diff --git a/.github/workflows/build-cross-compile.yml b/.github/workflows/build-cross-compile.yml new file mode 100644 index 00000000000..742f27a4ff8 --- /dev/null +++ b/.github/workflows/build-cross-compile.yml @@ -0,0 +1,146 @@ +# +# 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. +# + +name: 'Build (cross-compile)' + +on: + workflow_call: + inputs: + gcc-major-version: + required: false + type: string + default: '10' + +jobs: + build-cross-compile: + name: build + runs-on: ubuntu-20.04 + + strategy: + fail-fast: false + matrix: + target-cpu: + - aarch64 + - arm + - s390x + - ppc64le + include: + - target-cpu: aarch64 + debian-arch: arm64 + gnu-arch: aarch64 + - target-cpu: arm + debian-arch: armhf + gnu-arch: arm + gnu-abi: eabihf + - target-cpu: s390x + debian-arch: s390x + gnu-arch: s390x + - target-cpu: ppc64le + debian-arch: ppc64el + gnu-arch: powerpc64le + + steps: + - name: 'Checkout the JDK source' + uses: actions/checkout@v3 + + - name: 'Get the BootJDK' + id: bootjdk + uses: ./.github/actions/get-bootjdk + with: + platform: linux-x64 + + # Use linux-x64 JDK bundle as build JDK + - name: 'Get build JDK' + id: buildjdk + uses: ./.github/actions/get-bundles + with: + platform: linux-x64 + + # Upgrading apt to solve libc6 installation bugs, see JDK-8260460. + - name: 'Install toolchain and dependencies' + run: | + # Install dependencies using apt-get + sudo apt-get update + sudo apt-get install --only-upgrade apt + sudo apt-get install \ + gcc-${{ inputs.gcc-major-version }} \ + g++-${{ inputs.gcc-major-version }} \ + gcc-${{ inputs.gcc-major-version }}-${{ matrix.gnu-arch }}-linux-gnu${{ matrix.gnu-abi}} \ + g++-${{ inputs.gcc-major-version }}-${{ matrix.gnu-arch }}-linux-gnu${{ matrix.gnu-abi}} \ + libxrandr-dev libxtst-dev libcups2-dev libasound2-dev + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${{ inputs.gcc-major-version }} 100 --slave /usr/bin/g++ g++ /usr/bin/g++-${{ inputs.gcc-major-version }} + + - name: 'Check cache for sysroot' + id: get-cached-sysroot + uses: actions/cache@v3 + with: + path: sysroot + key: sysroot-${{ matrix.debian-arch }}-${{ hashFiles('./.github/workflows/build-cross-compile.yml') }} + + - name: 'Install sysroot dependencies' + run: sudo apt-get install debootstrap qemu-user-static + if: steps.get-cached-sysroot.outputs.cache-hit != 'true' + + - name: 'Create sysroot' + run: > + sudo qemu-debootstrap + --arch=${{ matrix.debian-arch }} + --verbose + --include=fakeroot,symlinks,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxrandr-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng-dev + --resolve-deps + buster + sysroot + https://httpredir.debian.org/debian/ + if: steps.get-cached-sysroot.outputs.cache-hit != 'true' + + - name: 'Prepare sysroot' + run: | + # Prepare sysroot and remove unused files to minimize cache + sudo chroot sysroot symlinks -cr . + sudo chown ${USER} -R sysroot + rm -rf sysroot/{dev,proc,run,sys} + if: steps.get-cached-sysroot.outputs.cache-hit != 'true' + + - name: 'Configure' + run: > + bash configure + --with-conf-name=linux-${{ matrix.target-cpu }} + --with-version-opt=${GITHUB_ACTOR}-${GITHUB_SHA} + --with-boot-jdk=${{ steps.bootjdk.outputs.path }} + --with-zlib=system + --enable-debug + --disable-precompiled-headers + --openjdk-target=${{ matrix.gnu-arch }}-linux-gnu${{ matrix.gnu-abi}} + --with-sysroot=sysroot + --with-build-jdk=${{ steps.buildjdk.outputs.jdk-path }} + CC=${{ matrix.gnu-arch }}-linux-gnu${{ matrix.gnu-abi}}-gcc-10 + CXX=${{ matrix.gnu-arch }}-linux-gnu${{ matrix.gnu-abi}}-g++-10 + + - name: 'Build' + id: build + uses: ./.github/actions/do-build + with: + make-target: 'hotspot' + platform: linux-${{ matrix.target-cpu }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 525f6d27f69..b59bc48b805 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -71,19 +71,17 @@ jobs: # 'false' otherwise. # arg $1: platform name or names to look for function check_platform() { - if [[ '${{ !secrets.JDK_SUBMIT_FILTER || startsWith(github.ref, 'refs/heads/submit/') }}' == 'false' ]]; then - # If JDK_SUBMIT_FILTER is set, and this is not a "submit/" branch, don't run anything - echo 'false' - return - fi - if [[ $GITHUB_EVENT_NAME == workflow_dispatch ]]; then input='${{ github.event.inputs.platforms }}' elif [[ $GITHUB_EVENT_NAME == push ]]; then - input='${{ secrets.JDK_SUBMIT_PLATFORMS }}' - else - echo 'Internal error in GHA' - exit 1 + if [[ '${{ !secrets.JDK_SUBMIT_FILTER || startsWith(github.ref, 'refs/heads/submit/') }}' == 'false' ]]; then + # If JDK_SUBMIT_FILTER is set, and this is not a "submit/" branch, don't run anything + >&2 echo 'JDK_SUBMIT_FILTER is set and not a "submit/" branch' + echo 'false' + return + else + input='${{ secrets.JDK_SUBMIT_PLATFORMS }}' + fi fi normalized_input="$(echo ,$input, | tr -d ' ')" @@ -123,7 +121,7 @@ jobs: uses: ./.github/workflows/build-linux.yml with: platform: linux-x64 - apt-gcc-version: '10=10.3.0-1ubuntu1~20.04' + apt-gcc-version: '10' # The linux-x64 jdk bundle is used as buildjdk for the cross-compile job if: needs.select.outputs.linux-x64 == 'true' || needs.select.outputs.linux-cross-compile == 'true' @@ -149,7 +147,7 @@ jobs: platform: linux-x64 make-target: 'hotspot' debug-levels: '[ "debug" ]' - apt-gcc-version: '10=10.3.0-1ubuntu1~20.04' + apt-gcc-version: '10' extra-conf-options: '--disable-precompiled-headers' if: needs.select.outputs.linux-x64-variants == 'true' @@ -161,7 +159,7 @@ jobs: platform: linux-x64 make-target: 'hotspot' debug-levels: '[ "debug" ]' - apt-gcc-version: '10=10.3.0-1ubuntu1~20.04' + apt-gcc-version: '10' extra-conf-options: '--with-jvm-variants=zero --disable-precompiled-headers' if: needs.select.outputs.linux-x64-variants == 'true' @@ -173,7 +171,7 @@ jobs: platform: linux-x64 make-target: 'hotspot' debug-levels: '[ "debug" ]' - apt-gcc-version: '10=10.3.0-1ubuntu1~20.04' + apt-gcc-version: '10' extra-conf-options: '--with-jvm-variants=minimal --disable-precompiled-headers' if: needs.select.outputs.linux-x64-variants == 'true' @@ -186,7 +184,7 @@ jobs: make-target: 'hotspot' # Technically this is not the "debug" level, but we can't inject a new matrix state for just this job debug-levels: '[ "debug" ]' - apt-gcc-version: '10=10.3.0-1ubuntu1~20.04' + apt-gcc-version: '10' extra-conf-options: '--with-debug-level=optimized --disable-precompiled-headers' if: needs.select.outputs.linux-x64-variants == 'true' diff --git a/.jcheck/conf b/.jcheck/conf index 888eec4671f..5b8b093c86f 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -1,7 +1,7 @@ [general] project=jdk-updates jbs=JDK -version=11.0.20 +version=11.0.21 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace diff --git a/make/autoconf/hotspot.m4 b/make/autoconf/hotspot.m4 index b78bb10f0a7..3a1d1efd19a 100644 --- a/make/autoconf/hotspot.m4 +++ b/make/autoconf/hotspot.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -165,8 +165,11 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_DTRACE], DTRACE_DEP_MISSING=false - AC_MSG_CHECKING([for dtrace tool]) - if test "x$DTRACE" != "x" && test -x "$DTRACE"; then + AC_MSG_CHECKING([for dtrace tool and platform support]) + if test "x$OPENJDK_TARGET_CPU_ARCH" = "xppc"; then + AC_MSG_RESULT([no, $OPENJDK_TARGET_CPU_ARCH]) + DTRACE_DEP_MISSING=true + elif test "x$DTRACE" != "x" && test -x "$DTRACE"; then AC_MSG_RESULT([$DTRACE]) else AC_MSG_RESULT([not found, cannot build dtrace]) diff --git a/make/autoconf/version-numbers b/make/autoconf/version-numbers index f6618777ecf..e6d1afbbc53 100644 --- a/make/autoconf/version-numbers +++ b/make/autoconf/version-numbers @@ -28,12 +28,12 @@ DEFAULT_VERSION_FEATURE=11 DEFAULT_VERSION_INTERIM=0 -DEFAULT_VERSION_UPDATE=20 +DEFAULT_VERSION_UPDATE=21 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2023-07-18 +DEFAULT_VERSION_DATE=2023-10-17 DEFAULT_VERSION_CLASSFILE_MAJOR=55 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_ACCEPTABLE_BOOT_VERSIONS="10 11" diff --git a/make/data/cacerts/certignarootca b/make/data/cacerts/certignarootca new file mode 100644 index 00000000000..b79092d0cb5 --- /dev/null +++ b/make/data/cacerts/certignarootca @@ -0,0 +1,43 @@ +Owner: CN=Certigna Root CA, OU=0002 48146308100036, O=Dhimyotis, C=FR +Issuer: CN=Certigna Root CA, OU=0002 48146308100036, O=Dhimyotis, C=FR +Serial number: cae91b89f155030da3e6416dc4e3a6e1 +Valid from: Tue Oct 01 08:32:27 GMT 2013 until: Sat Oct 01 08:32:27 GMT 2033 +Signature algorithm name: SHA256withRSA +Subject Public Key Algorithm: 4096-bit RSA key +Version: 3 +-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw +WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw +MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x +MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD +VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX +BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO +ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M +CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu +I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm +TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh +C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf +ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz +IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT +Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k +JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 +hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB +GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov +L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo +dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr +aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq +hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L +6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG +HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 +0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB +lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi +o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 +gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v +faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 +Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh +jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw +3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- diff --git a/make/data/cacerts/secomscrootca1 b/make/data/cacerts/secomscrootca1 deleted file mode 100644 index d300e31195d..00000000000 --- a/make/data/cacerts/secomscrootca1 +++ /dev/null @@ -1,27 +0,0 @@ -Owner: OU=Security Communication RootCA1, O=SECOM Trust.net, C=JP -Issuer: OU=Security Communication RootCA1, O=SECOM Trust.net, C=JP -Serial number: 0 -Valid from: Tue Sep 30 04:20:49 GMT 2003 until: Sat Sep 30 04:20:49 GMT 2023 -Signature algorithm name: SHA1withRSA -Subject Public Key Algorithm: 2048-bit RSA key -Version: 3 ------BEGIN CERTIFICATE----- -MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY -MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t -dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 -WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD -VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 -9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ -DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 -Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N -QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ -xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G -A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T -AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG -kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr -Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 -Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU -JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot -RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== ------END CERTIFICATE----- diff --git a/make/data/publicsuffixlist/VERSION b/make/data/publicsuffixlist/VERSION index be9290a33fc..4ffc88dbd83 100644 --- a/make/data/publicsuffixlist/VERSION +++ b/make/data/publicsuffixlist/VERSION @@ -1,2 +1,2 @@ -Github: https://raw.githubusercontent.com/publicsuffix/list/3c213aab32b3c014f171b1673d4ce9b5cd72bf1c/public_suffix_list.dat -Date: 2021-11-27 +Github: https://raw.githubusercontent.com/publicsuffix/list/88467c960d6cdad2ca1623e892e5e17506bc269f/public_suffix_list.dat +Date: 2023-04-14 diff --git a/make/data/publicsuffixlist/public_suffix_list.dat b/make/data/publicsuffixlist/public_suffix_list.dat index 5529554d82d..d9f0c71dbb4 100644 --- a/make/data/publicsuffixlist/public_suffix_list.dat +++ b/make/data/publicsuffixlist/public_suffix_list.dat @@ -9,7 +9,7 @@ // ===BEGIN ICANN DOMAINS=== -// ac : https://en.wikipedia.org/wiki/.ac +// ac : http://nic.ac/rules.htm ac com.ac edu.ac @@ -22,8 +22,7 @@ org.ac ad nom.ad -// ae : https://en.wikipedia.org/wiki/.ae -// see also: "Domain Name Eligibility Policy" at http://www.aeda.ae/eng/aepolicy.php +// ae : https://tdra.gov.ae/en/aeda/ae-policies ae co.ae net.ae @@ -381,11 +380,29 @@ org.bi // biz : https://en.wikipedia.org/wiki/.biz biz -// bj : https://en.wikipedia.org/wiki/.bj +// bj : https://nic.bj/bj-suffixes.txt +// submitted by registry bj -asso.bj -barreau.bj -gouv.bj +africa.bj +agro.bj +architectes.bj +assur.bj +avocats.bj +co.bj +com.bj +eco.bj +econo.bj +edu.bj +info.bj +loisirs.bj +money.bj +net.bj +org.bj +ote.bj +resto.bj +restaurant.bj +tourism.bj +univ.bj // bm : http://www.bermudanic.bm/dnr-text.txt bm @@ -865,6 +882,7 @@ gov.cx // cy : http://www.nic.cy/ // Submitted by registry Panayiotou Fotia +// namespace policies URL https://www.nic.cy/portal//sites/default/files/symfonia_gia_eggrafi.pdf cy ac.cy biz.cy @@ -872,10 +890,9 @@ com.cy ekloges.cy gov.cy ltd.cy -name.cy +mil.cy net.cy org.cy -parliament.cy press.cy pro.cy tm.cy @@ -1034,8 +1051,7 @@ fm // fo : https://en.wikipedia.org/wiki/.fo fo -// fr : http://www.afnic.fr/ -// domaines descriptifs : https://www.afnic.fr/medias/documents/Cadre_legal/Afnic_Naming_Policy_12122016_VEN.pdf +// fr : https://www.afnic.fr/ https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf fr asso.fr com.fr @@ -1043,7 +1059,7 @@ gouv.fr nom.fr prd.fr tm.fr -// domaines sectoriels : https://www.afnic.fr/en/products-and-services/the-fr-tld/sector-based-fr-domains-4.html +// Former "domaines sectoriels", still registration suffixes aeroport.fr avocat.fr avoues.fr @@ -1316,7 +1332,9 @@ web.id ie gov.ie -// il : http://www.isoc.org.il/domains/ +// il : http://www.isoc.org.il/domains/ +// see also: https://en.isoc.org.il/il-cctld/registration-rules +// ISOC-IL (operated by .il Registry) il ac.il co.il @@ -1326,6 +1344,16 @@ k12.il muni.il net.il org.il +// xn--4dbrk0ce ("Israel", Hebrew) : IL +ישראל +// xn--4dbgdty6c.xn--4dbrk0ce. +אקדמיה.ישראל +// xn--5dbhl8d.xn--4dbrk0ce. +ישוב.ישראל +// xn--8dbq2a.xn--4dbrk0ce. +צהל.ישראל +// xn--hebda8b.xn--4dbrk0ce. +ממשל.ישראל // im : https://www.nic.im/ // Submitted by registry @@ -1341,22 +1369,51 @@ tt.im tv.im // in : https://en.wikipedia.org/wiki/.in -// see also: https://registry.in/Policies +// see also: https://registry.in/policies // Please note, that nic.in is not an official eTLD, but used by most // government institutions. in +5g.in +6g.in +ac.in +ai.in +am.in +bihar.in +biz.in +business.in +ca.in +cn.in co.in +com.in +coop.in +cs.in +delhi.in +dr.in +edu.in +er.in firm.in -net.in -org.in gen.in +gov.in +gujarat.in ind.in +info.in +int.in +internet.in +io.in +me.in +mil.in +net.in nic.in -ac.in -edu.in +org.in +pg.in +post.in +pro.in res.in -gov.in -mil.in +travel.in +tv.in +uk.in +up.in +us.in // info : https://en.wikipedia.org/wiki/.info info @@ -1366,7 +1423,7 @@ info int eu.int -// io : http://www.nic.io/rules.html +// io : http://www.nic.io/rules.htm // list of other 2nd level tlds ? io com.io @@ -3765,11 +3822,10 @@ org.kw // ky : http://www.icta.ky/da_ky_reg_dom.php // Confirmed by registry 2008-06-17 ky -edu.ky -gov.ky com.ky -org.ky +edu.ky net.ky +org.ky // kz : https://en.wikipedia.org/wiki/.kz // see also: http://www.nic.kz/rules/index.jsp @@ -4013,555 +4069,8 @@ ac.mu co.mu or.mu -// museum : http://about.museum/naming/ -// http://index.museum/ +// museum : https://welcome.museum/wp-content/uploads/2018/05/20180525-Registration-Policy-MUSEUM-EN_VF-2.pdf https://welcome.museum/buy-your-dot-museum-2/ museum -academy.museum -agriculture.museum -air.museum -airguard.museum -alabama.museum -alaska.museum -amber.museum -ambulance.museum -american.museum -americana.museum -americanantiques.museum -americanart.museum -amsterdam.museum -and.museum -annefrank.museum -anthro.museum -anthropology.museum -antiques.museum -aquarium.museum -arboretum.museum -archaeological.museum -archaeology.museum -architecture.museum -art.museum -artanddesign.museum -artcenter.museum -artdeco.museum -arteducation.museum -artgallery.museum -arts.museum -artsandcrafts.museum -asmatart.museum -assassination.museum -assisi.museum -association.museum -astronomy.museum -atlanta.museum -austin.museum -australia.museum -automotive.museum -aviation.museum -axis.museum -badajoz.museum -baghdad.museum -bahn.museum -bale.museum -baltimore.museum -barcelona.museum -baseball.museum -basel.museum -baths.museum -bauern.museum -beauxarts.museum -beeldengeluid.museum -bellevue.museum -bergbau.museum -berkeley.museum -berlin.museum -bern.museum -bible.museum -bilbao.museum -bill.museum -birdart.museum -birthplace.museum -bonn.museum -boston.museum -botanical.museum -botanicalgarden.museum -botanicgarden.museum -botany.museum -brandywinevalley.museum -brasil.museum -bristol.museum -british.museum -britishcolumbia.museum -broadcast.museum -brunel.museum -brussel.museum -brussels.museum -bruxelles.museum -building.museum -burghof.museum -bus.museum -bushey.museum -cadaques.museum -california.museum -cambridge.museum -can.museum -canada.museum -capebreton.museum -carrier.museum -cartoonart.museum -casadelamoneda.museum -castle.museum -castres.museum -celtic.museum -center.museum -chattanooga.museum -cheltenham.museum -chesapeakebay.museum -chicago.museum -children.museum -childrens.museum -childrensgarden.museum -chiropractic.museum -chocolate.museum -christiansburg.museum -cincinnati.museum -cinema.museum -circus.museum -civilisation.museum -civilization.museum -civilwar.museum -clinton.museum -clock.museum -coal.museum -coastaldefence.museum -cody.museum -coldwar.museum -collection.museum -colonialwilliamsburg.museum -coloradoplateau.museum -columbia.museum -columbus.museum -communication.museum -communications.museum -community.museum -computer.museum -computerhistory.museum -comunicações.museum -contemporary.museum -contemporaryart.museum -convent.museum -copenhagen.museum -corporation.museum -correios-e-telecomunicações.museum -corvette.museum -costume.museum -countryestate.museum -county.museum -crafts.museum -cranbrook.museum -creation.museum -cultural.museum -culturalcenter.museum -culture.museum -cyber.museum -cymru.museum -dali.museum -dallas.museum -database.museum -ddr.museum -decorativearts.museum -delaware.museum -delmenhorst.museum -denmark.museum -depot.museum -design.museum -detroit.museum -dinosaur.museum -discovery.museum -dolls.museum -donostia.museum -durham.museum -eastafrica.museum -eastcoast.museum -education.museum -educational.museum -egyptian.museum -eisenbahn.museum -elburg.museum -elvendrell.museum -embroidery.museum -encyclopedic.museum -england.museum -entomology.museum -environment.museum -environmentalconservation.museum -epilepsy.museum -essex.museum -estate.museum -ethnology.museum -exeter.museum -exhibition.museum -family.museum -farm.museum -farmequipment.museum -farmers.museum -farmstead.museum -field.museum -figueres.museum -filatelia.museum -film.museum -fineart.museum -finearts.museum -finland.museum -flanders.museum -florida.museum -force.museum -fortmissoula.museum -fortworth.museum -foundation.museum -francaise.museum -frankfurt.museum -franziskaner.museum -freemasonry.museum -freiburg.museum -fribourg.museum -frog.museum -fundacio.museum -furniture.museum -gallery.museum -garden.museum -gateway.museum -geelvinck.museum -gemological.museum -geology.museum -georgia.museum -giessen.museum -glas.museum -glass.museum -gorge.museum -grandrapids.museum -graz.museum -guernsey.museum -halloffame.museum -hamburg.museum -handson.museum -harvestcelebration.museum -hawaii.museum -health.museum -heimatunduhren.museum -hellas.museum -helsinki.museum -hembygdsforbund.museum -heritage.museum -histoire.museum -historical.museum -historicalsociety.museum -historichouses.museum -historisch.museum -historisches.museum -history.museum -historyofscience.museum -horology.museum -house.museum -humanities.museum -illustration.museum -imageandsound.museum -indian.museum -indiana.museum -indianapolis.museum -indianmarket.museum -intelligence.museum -interactive.museum -iraq.museum -iron.museum -isleofman.museum -jamison.museum -jefferson.museum -jerusalem.museum -jewelry.museum -jewish.museum -jewishart.museum -jfk.museum -journalism.museum -judaica.museum -judygarland.museum -juedisches.museum -juif.museum -karate.museum -karikatur.museum -kids.museum -koebenhavn.museum -koeln.museum -kunst.museum -kunstsammlung.museum -kunstunddesign.museum -labor.museum -labour.museum -lajolla.museum -lancashire.museum -landes.museum -lans.museum -läns.museum -larsson.museum -lewismiller.museum -lincoln.museum -linz.museum -living.museum -livinghistory.museum -localhistory.museum -london.museum -losangeles.museum -louvre.museum -loyalist.museum -lucerne.museum -luxembourg.museum -luzern.museum -mad.museum -madrid.museum -mallorca.museum -manchester.museum -mansion.museum -mansions.museum -manx.museum -marburg.museum -maritime.museum -maritimo.museum -maryland.museum -marylhurst.museum -media.museum -medical.museum -medizinhistorisches.museum -meeres.museum -memorial.museum -mesaverde.museum -michigan.museum -midatlantic.museum -military.museum -mill.museum -miners.museum -mining.museum -minnesota.museum -missile.museum -missoula.museum -modern.museum -moma.museum -money.museum -monmouth.museum -monticello.museum -montreal.museum -moscow.museum -motorcycle.museum -muenchen.museum -muenster.museum -mulhouse.museum -muncie.museum -museet.museum -museumcenter.museum -museumvereniging.museum -music.museum -national.museum -nationalfirearms.museum -nationalheritage.museum -nativeamerican.museum -naturalhistory.museum -naturalhistorymuseum.museum -naturalsciences.museum -nature.museum -naturhistorisches.museum -natuurwetenschappen.museum -naumburg.museum -naval.museum -nebraska.museum -neues.museum -newhampshire.museum -newjersey.museum -newmexico.museum -newport.museum -newspaper.museum -newyork.museum -niepce.museum -norfolk.museum -north.museum -nrw.museum -nyc.museum -nyny.museum -oceanographic.museum -oceanographique.museum -omaha.museum -online.museum -ontario.museum -openair.museum -oregon.museum -oregontrail.museum -otago.museum -oxford.museum -pacific.museum -paderborn.museum -palace.museum -paleo.museum -palmsprings.museum -panama.museum -paris.museum -pasadena.museum -pharmacy.museum -philadelphia.museum -philadelphiaarea.museum -philately.museum -phoenix.museum -photography.museum -pilots.museum -pittsburgh.museum -planetarium.museum -plantation.museum -plants.museum -plaza.museum -portal.museum -portland.museum -portlligat.museum -posts-and-telecommunications.museum -preservation.museum -presidio.museum -press.museum -project.museum -public.museum -pubol.museum -quebec.museum -railroad.museum -railway.museum -research.museum -resistance.museum -riodejaneiro.museum -rochester.museum -rockart.museum -roma.museum -russia.museum -saintlouis.museum -salem.museum -salvadordali.museum -salzburg.museum -sandiego.museum -sanfrancisco.museum -santabarbara.museum -santacruz.museum -santafe.museum -saskatchewan.museum -satx.museum -savannahga.museum -schlesisches.museum -schoenbrunn.museum -schokoladen.museum -school.museum -schweiz.museum -science.museum -scienceandhistory.museum -scienceandindustry.museum -sciencecenter.museum -sciencecenters.museum -science-fiction.museum -sciencehistory.museum -sciences.museum -sciencesnaturelles.museum -scotland.museum -seaport.museum -settlement.museum -settlers.museum -shell.museum -sherbrooke.museum -sibenik.museum -silk.museum -ski.museum -skole.museum -society.museum -sologne.museum -soundandvision.museum -southcarolina.museum -southwest.museum -space.museum -spy.museum -square.museum -stadt.museum -stalbans.museum -starnberg.museum -state.museum -stateofdelaware.museum -station.museum -steam.museum -steiermark.museum -stjohn.museum -stockholm.museum -stpetersburg.museum -stuttgart.museum -suisse.museum -surgeonshall.museum -surrey.museum -svizzera.museum -sweden.museum -sydney.museum -tank.museum -tcm.museum -technology.museum -telekommunikation.museum -television.museum -texas.museum -textile.museum -theater.museum -time.museum -timekeeping.museum -topology.museum -torino.museum -touch.museum -town.museum -transport.museum -tree.museum -trolley.museum -trust.museum -trustee.museum -uhren.museum -ulm.museum -undersea.museum -university.museum -usa.museum -usantiques.museum -usarts.museum -uscountryestate.museum -usculture.museum -usdecorativearts.museum -usgarden.museum -ushistory.museum -ushuaia.museum -uslivinghistory.museum -utah.museum -uvic.museum -valley.museum -vantaa.museum -versailles.museum -viking.museum -village.museum -virginia.museum -virtual.museum -virtuel.museum -vlaanderen.museum -volkenkunde.museum -wales.museum -wallonie.museum -war.museum -washingtondc.museum -watchandclock.museum -watch-and-clock.museum -western.museum -westfalen.museum -whaling.museum -wildlife.museum -williamsburg.museum -windmill.museum -workshop.museum -york.museum -yorkshire.museum -yosemite.museum -youth.museum -zoological.museum -zoology.museum -ירושלים.museum -иком.museum // mv : https://en.wikipedia.org/wiki/.mv // "mv" included because, contra Wikipedia, google.mv exists. @@ -5804,7 +5313,7 @@ zarow.pl zgora.pl zgorzelec.pl -// pm : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf +// pm : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf pm // pn : http://www.government.pn/PnRegistry/policies.htm @@ -5902,7 +5411,7 @@ net.qa org.qa sch.qa -// re : http://www.afnic.re/obtenir/chartes/nommage-re/annexe-descriptifs +// re : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf re asso.re com.re @@ -6037,7 +5546,7 @@ gov.sg edu.sg per.sg -// sh : http://www.nic.sh/registrar.html +// sh : http://nic.sh/rules.htm sh com.sh net.sh @@ -6159,7 +5668,7 @@ td // http://www.telnic.org/ tel -// tf : https://en.wikipedia.org/wiki/.tf +// tf : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf tf // tg : https://en.wikipedia.org/wiki/.tg @@ -6778,7 +6287,7 @@ edu.vu net.vu org.vu -// wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf +// wf : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf wf // ws : https://en.wikipedia.org/wiki/.ws @@ -6790,7 +6299,7 @@ org.ws gov.ws edu.ws -// yt : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf +// yt : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf yt // IDN ccTLDs @@ -7132,7 +6641,7 @@ org.zw // newGTLDs -// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2021-11-13T15:12:42Z +// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2023-04-14T15:13:16Z // This list is auto-generated, don't edit it manually. // aaa : 2015-02-26 American Automobile Association, Inc. aaa @@ -7182,9 +6691,6 @@ aco // actor : 2013-12-12 Dog Beach, LLC actor -// adac : 2015-07-16 Allgemeiner Deutscher Automobil-Club e.V. (ADAC) -adac - // ads : 2014-12-04 Charleston Road Registry Inc. ads @@ -7197,9 +6703,6 @@ aeg // aetna : 2015-05-21 Aetna Life Insurance Company aetna -// afamilycompany : 2015-07-23 Johnson Shareholdings, Inc. -afamilycompany - // afl : 2014-10-02 Australian Football League afl @@ -7305,7 +6808,7 @@ arab // aramco : 2014-11-20 Aramco Services Company aramco -// archi : 2014-02-06 Afilias Limited +// archi : 2014-02-06 Identity Digital Limited archi // army : 2014-03-06 Dog Beach, LLC @@ -7338,7 +6841,7 @@ audi // audible : 2015-06-25 Amazon Registry Services, Inc. audible -// audio : 2014-03-20 UNR Corp. +// audio : 2014-03-20 XYZ.COM LLC audio // auspost : 2015-08-13 Australian Postal Corporation @@ -7353,7 +6856,7 @@ auto // autos : 2014-01-09 XYZ.COM LLC autos -// avianca : 2015-01-08 Avianca Holdings S.A. +// avianca : 2015-01-08 Avianca Inc. avianca // aws : 2015-06-25 AWS Registry LLC @@ -7449,7 +6952,7 @@ best // bestbuy : 2015-07-31 BBY Solutions, Inc. bestbuy -// bet : 2015-05-07 Afilias Limited +// bet : 2015-05-07 Identity Digital Limited bet // bharti : 2014-01-09 Bharti Enterprises (Holding) Private Limited @@ -7470,13 +6973,13 @@ bing // bingo : 2014-12-04 Binky Moon, LLC bingo -// bio : 2014-03-06 Afilias Limited +// bio : 2014-03-06 Identity Digital Limited bio -// black : 2014-01-16 Afilias Limited +// black : 2014-01-16 Identity Digital Limited black -// blackfriday : 2014-01-16 UNR Corp. +// blackfriday : 2014-01-16 Registry Services, LLC blackfriday // blockbuster : 2015-07-30 Dish DBS Corporation @@ -7488,7 +6991,7 @@ blog // bloomberg : 2014-07-17 Bloomberg IP Holdings LLC bloomberg -// blue : 2013-11-07 Afilias Limited +// blue : 2013-11-07 Identity Digital Limited blue // bms : 2014-10-30 Bristol-Myers Squibb Company @@ -7530,7 +7033,7 @@ bosch // bostik : 2015-05-28 Bostik SA bostik -// boston : 2015-12-10 Boston TLD Management, LLC +// boston : 2015-12-10 Registry Services, LLC boston // bot : 2014-12-18 Amazon Registry Services, Inc. @@ -7560,12 +7063,6 @@ brother // brussels : 2014-02-06 DNS.be vzw brussels -// budapest : 2013-11-21 Minds + Machines Group Limited -budapest - -// bugatti : 2015-07-23 Bugatti International SA -bugatti - // build : 2013-11-07 Plan Bee LLC build @@ -7599,7 +7096,7 @@ call // calvinklein : 2015-07-30 PVH gTLD Holdings LLC calvinklein -// cam : 2016-04-21 AC Webconnecting Holding B.V. +// cam : 2016-04-21 Cam Connecting SARL cam // camera : 2013-08-27 Binky Moon, LLC @@ -7608,9 +7105,6 @@ camera // camp : 2013-11-07 Binky Moon, LLC camp -// cancerresearch : 2014-05-15 Australian Cancer Research Foundation -cancerresearch - // canon : 2014-09-12 Canon Inc. canon @@ -7647,7 +7141,7 @@ cars // casa : 2013-11-21 Registry Services, LLC casa -// case : 2015-09-03 Helium TLDs Ltd +// case : 2015-09-03 Digity, LLC case // cash : 2014-03-06 Binky Moon, LLC @@ -7695,7 +7189,7 @@ chanel // channel : 2014-05-08 Charleston Road Registry Inc. channel -// charity : 2018-04-11 Binky Moon, LLC +// charity : 2018-04-11 Public Interest Registry charity // chase : 2015-04-30 JPMorgan Chase Bank, National Association @@ -7710,7 +7204,7 @@ cheap // chintai : 2015-06-11 CHINTAI Corporation chintai -// christmas : 2013-11-21 UNR Corp. +// christmas : 2013-11-21 XYZ.COM LLC christmas // chrome : 2014-07-24 Charleston Road Registry Inc. @@ -7749,7 +7243,7 @@ claims // cleaning : 2013-12-05 Binky Moon, LLC cleaning -// click : 2014-06-05 UNR Corp. +// click : 2014-06-05 Internet Naming Company LLC click // clinic : 2014-03-20 Binky Moon, LLC @@ -7833,7 +7327,7 @@ cool // corsica : 2014-09-25 Collectivité de Corse corsica -// country : 2013-12-19 DotCountry LLC +// country : 2013-12-19 Internet Naming Company LLC country // coupon : 2015-02-26 Amazon Registry Services, Inc. @@ -7842,7 +7336,7 @@ coupon // coupons : 2015-03-26 Binky Moon, LLC coupons -// courses : 2014-12-04 OPEN UNIVERSITIES AUSTRALIA PTY LTD +// courses : 2014-12-04 Registry Services, LLC courses // cpa : 2019-06-10 American Institute of Certified Public Accountants @@ -7872,9 +7366,6 @@ cruise // cruises : 2013-12-05 Binky Moon, LLC cruises -// csc : 2014-09-25 Alliance-One Services, Inc. -csc - // cuisinella : 2014-04-03 SCHMIDT GROUPE S.A.S. cuisinella @@ -7962,7 +7453,7 @@ dhl // diamonds : 2013-09-22 Binky Moon, LLC diamonds -// diet : 2014-06-26 UNR Corp. +// diet : 2014-06-26 XYZ.COM LLC diet // digital : 2014-03-06 Binky Moon, LLC @@ -8016,9 +7507,6 @@ dtv // dubai : 2015-01-01 Dubai Smart Government Department dubai -// duck : 2015-07-23 Johnson Shareholdings, Inc. -duck - // dunlop : 2015-07-02 The Goodyear Tire & Rubber Company dunlop @@ -8034,7 +7522,7 @@ dvag // dvr : 2016-05-26 DISH Technologies L.L.C. dvr -// earth : 2014-12-04 Interlink Co., Ltd. +// earth : 2014-12-04 Interlink Systems Innovation Institute K.K. earth // eat : 2014-01-23 Charleston Road Registry Inc. @@ -8211,7 +7699,7 @@ flir // florist : 2013-11-07 Binky Moon, LLC florist -// flowers : 2014-10-09 UNR Corp. +// flowers : 2014-10-09 XYZ.COM LLC flowers // fly : 2014-05-08 Charleston Road Registry Inc. @@ -8241,7 +7729,7 @@ forsale // forum : 2015-04-02 Fegistry, LLC forum -// foundation : 2013-12-05 Binky Moon, LLC +// foundation : 2013-12-05 Public Interest Registry foundation // fox : 2015-09-11 FOX Registry, LLC @@ -8298,7 +7786,7 @@ gallo // gallup : 2015-02-19 Gallup, Inc. gallup -// game : 2015-05-28 UNR Corp. +// game : 2015-05-28 XYZ.COM LLC game // games : 2015-05-28 Dog Beach, LLC @@ -8322,7 +7810,7 @@ gdn // gea : 2014-12-04 GEA Group Aktiengesellschaft gea -// gent : 2014-01-23 COMBELL NV +// gent : 2014-01-23 Easyhost BV gent // genting : 2015-03-12 Resorts World Inc Pte. Ltd. @@ -8340,22 +7828,19 @@ gift // gifts : 2014-07-03 Binky Moon, LLC gifts -// gives : 2014-03-06 Dog Beach, LLC +// gives : 2014-03-06 Public Interest Registry gives -// giving : 2014-11-13 Giving Limited +// giving : 2014-11-13 Public Interest Registry giving -// glade : 2015-07-23 Johnson Shareholdings, Inc. -glade - // glass : 2013-11-07 Binky Moon, LLC glass // gle : 2014-07-24 Charleston Road Registry Inc. gle -// global : 2014-04-17 Dot Global Domain Registry Limited +// global : 2014-04-17 Identity Digital Limited global // globo : 2013-12-19 Globo Comunicação e Participações S.A @@ -8412,7 +7897,7 @@ graphics // gratis : 2014-03-20 Binky Moon, LLC gratis -// green : 2014-05-08 Afilias Limited +// green : 2014-05-08 Identity Digital Limited green // gripe : 2014-03-06 Binky Moon, LLC @@ -8436,7 +7921,7 @@ guge // guide : 2013-09-13 Binky Moon, LLC guide -// guitars : 2013-11-14 UNR Corp. +// guitars : 2013-11-14 XYZ.COM LLC guitars // guru : 2013-08-27 Binky Moon, LLC @@ -8469,7 +7954,7 @@ health // healthcare : 2014-06-12 Binky Moon, LLC healthcare -// help : 2014-06-26 UNR Corp. +// help : 2014-06-26 Innovation service Limited help // helsinki : 2015-02-05 City of Helsinki @@ -8484,7 +7969,7 @@ hermes // hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc. hgtv -// hiphop : 2014-03-06 UNR Corp. +// hiphop : 2014-03-06 Dot Hip Hop, LLC hiphop // hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc. @@ -8493,7 +7978,7 @@ hisamitsu // hitachi : 2014-10-31 Hitachi, Ltd. hitachi -// hiv : 2014-03-13 UNR Corp. +// hiv : 2014-03-13 Internet Naming Company LLC hiv // hkt : 2015-05-14 PCCW-HKT DataCom Services Limited @@ -8532,7 +8017,7 @@ hospital // host : 2014-04-17 Radix FZC host -// hosting : 2014-05-29 UNR Corp. +// hosting : 2014-05-29 XYZ.COM LLC hosting // hot : 2015-08-27 Amazon Registry Services, Inc. @@ -8697,7 +8182,7 @@ jpmorgan // jprs : 2014-09-18 Japan Registry Services Co., Ltd. jprs -// juegos : 2014-03-20 UNR Corp. +// juegos : 2014-03-20 Internet Naming Company LLC juegos // juniper : 2015-07-30 JUNIPER NETWORKS, INC. @@ -8727,7 +8212,7 @@ kia // kids : 2021-08-13 DotKids Foundation Limited kids -// kim : 2013-09-23 Afilias Limited +// kim : 2013-09-23 Identity Digital Limited kim // kinder : 2014-11-07 Ferrero Trading Lux S.A. @@ -8796,7 +8281,7 @@ lanxess // lasalle : 2015-04-02 Jones Lang LaSalle Incorporated lasalle -// lat : 2014-10-16 ECOM-LAC Federaciòn de Latinoamèrica y el Caribe para Internet y el Comercio Electrònico +// lat : 2014-10-16 XYZ.COM LLC lat // latino : 2015-07-30 Dish DBS Corporation @@ -8832,7 +8317,7 @@ lego // lexus : 2015-04-23 TOYOTA MOTOR CORPORATION lexus -// lgbt : 2014-05-08 Afilias Limited +// lgbt : 2014-05-08 Identity Digital Limited lgbt // lidl : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG @@ -8865,10 +8350,7 @@ limo // lincoln : 2014-11-13 Ford Motor Company lincoln -// linde : 2014-12-04 Linde Aktiengesellschaft -linde - -// link : 2013-11-14 UNR Corp. +// link : 2013-11-14 Nova Registry Ltd link // lipsy : 2015-06-25 Lipsy Ltd @@ -8880,13 +8362,10 @@ live // living : 2015-07-30 Lifestyle Domain Holdings, Inc. living -// lixil : 2015-03-19 LIXIL Group Corporation -lixil - -// llc : 2017-12-14 Afilias Limited +// llc : 2017-12-14 Identity Digital Limited llc -// llp : 2019-08-26 UNR Corp. +// llp : 2019-08-26 Intercap Registry Inc. llp // loan : 2014-11-20 dot Loan Limited @@ -8901,10 +8380,7 @@ locker // locus : 2015-06-25 Locus Analytics LLC locus -// loft : 2015-07-30 Annco, Inc. -loft - -// lol : 2015-01-30 UNR Corp. +// lol : 2015-01-30 XYZ.COM LLC lol // london : 2013-11-14 Dot London Domains Limited @@ -8913,7 +8389,7 @@ london // lotte : 2014-11-07 Lotte Holdings Co., Ltd. lotte -// lotto : 2014-04-10 Afilias Limited +// lotto : 2014-04-10 Identity Digital Limited lotto // love : 2014-12-22 Merchant Law Group LLP @@ -8940,9 +8416,6 @@ luxe // luxury : 2013-10-17 Luxury Partners, LLC luxury -// macys : 2015-07-31 Macys, Inc. -macys - // madrid : 2014-05-01 Comunidad de Madrid madrid @@ -9021,7 +8494,7 @@ menu // merckmsd : 2016-07-14 MSD Registry Holdings, Inc. merckmsd -// miami : 2013-12-19 Minds + Machines Group Limited +// miami : 2013-12-19 Registry Services, LLC miami // microsoft : 2014-12-18 Microsoft Corporation @@ -9054,13 +8527,13 @@ mobile // moda : 2013-11-07 Dog Beach, LLC moda -// moe : 2013-11-13 Interlink Co., Ltd. +// moe : 2013-11-13 Interlink Systems Innovation Institute K.K. moe // moi : 2014-12-18 Amazon Registry Services, Inc. moi -// mom : 2015-04-16 UNR Corp. +// mom : 2015-04-16 XYZ.COM LLC mom // monash : 2013-09-30 Monash University @@ -9216,9 +8689,6 @@ obi // observer : 2015-04-30 Dog Beach, LLC observer -// off : 2015-07-23 Johnson Shareholdings, Inc. -off - // office : 2015-03-12 Microsoft Corporation office @@ -9264,7 +8734,7 @@ oracle // orange : 2015-03-12 Orange Brand Services Limited orange -// organic : 2014-03-27 Afilias Limited +// organic : 2014-03-27 Identity Digital Limited organic // origins : 2015-10-01 The Estée Lauder Companies Inc. @@ -9285,7 +8755,7 @@ ovh // page : 2014-12-04 Charleston Road Registry Inc. page -// panasonic : 2015-07-30 Panasonic Corporation +// panasonic : 2015-07-30 Panasonic Holdings Corporation panasonic // paris : 2014-01-30 City of Paris @@ -9312,7 +8782,7 @@ pay // pccw : 2015-05-14 PCCW Enterprises Limited pccw -// pet : 2015-05-07 Afilias Limited +// pet : 2015-05-07 Identity Digital Limited pet // pfizer : 2015-09-11 Pfizer Inc. @@ -9330,7 +8800,7 @@ philips // phone : 2016-06-02 Dish DBS Corporation phone -// photo : 2013-11-14 UNR Corp. +// photo : 2013-11-14 Registry Services, LLC photo // photography : 2013-09-20 Binky Moon, LLC @@ -9342,7 +8812,7 @@ photos // physio : 2014-05-01 PhysBiz Pty Ltd physio -// pics : 2013-11-14 UNR Corp. +// pics : 2013-11-14 XYZ.COM LLC pics // pictet : 2014-06-26 Pictet Europe S.A. @@ -9360,7 +8830,7 @@ pin // ping : 2015-06-11 Ping Registry Provider, Inc. ping -// pink : 2013-10-01 Afilias Limited +// pink : 2013-10-01 Identity Digital Limited pink // pioneer : 2015-07-16 Pioneer Corporation @@ -9390,7 +8860,7 @@ pnc // pohl : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG pohl -// poker : 2014-07-03 Afilias Limited +// poker : 2014-07-03 Identity Digital Limited poker // politie : 2015-08-20 Politie Nederland @@ -9423,13 +8893,13 @@ prof // progressive : 2015-07-23 Progressive Casualty Insurance Company progressive -// promo : 2014-12-18 Afilias Limited +// promo : 2014-12-18 Identity Digital Limited promo // properties : 2013-12-05 Binky Moon, LLC properties -// property : 2014-05-22 UNR Corp. +// property : 2014-05-22 Internet Naming Company LLC property // protection : 2015-04-23 XYZ.COM LLC @@ -9447,7 +8917,7 @@ pub // pwc : 2015-10-29 PricewaterhouseCoopers LLP pwc -// qpon : 2013-11-14 dotCOOL, Inc. +// qpon : 2013-11-14 dotQPON LLC qpon // quebec : 2013-12-19 PointQuébec Inc @@ -9462,9 +8932,6 @@ racing // radio : 2016-07-21 European Broadcasting Union (EBU) radio -// raid : 2015-07-23 Johnson Shareholdings, Inc. -raid - // read : 2014-12-18 Amazon Registry Services, Inc. read @@ -9480,7 +8947,7 @@ realty // recipes : 2013-10-17 Binky Moon, LLC recipes -// red : 2013-11-07 Afilias Limited +// red : 2013-11-07 Identity Digital Limited red // redstone : 2014-10-31 Redstone Haute Couture Co., Ltd. @@ -9576,7 +9043,7 @@ rsvp // rugby : 2016-12-15 World Rugby Strategic Developments Limited rugby -// ruhr : 2013-10-02 regiodot GmbH & Co. KG +// ruhr : 2013-10-02 dotSaarland GmbH ruhr // run : 2015-03-19 Binky Moon, LLC @@ -9669,9 +9136,6 @@ schwarz // science : 2014-09-11 dot Science Limited science -// scjohnson : 2015-07-23 Johnson Shareholdings, Inc. -scjohnson - // scot : 2014-01-23 Dot Scot Registry Limited scot @@ -9699,9 +9163,6 @@ sener // services : 2014-02-27 Binky Moon, LLC services -// ses : 2015-07-23 SES -ses - // seven : 2015-08-06 Seven West Media Ltd seven @@ -9711,7 +9172,7 @@ sew // sex : 2014-11-13 ICM Registry SX LLC sex -// sexy : 2013-09-11 UNR Corp. +// sexy : 2013-09-11 Internet Naming Company LLC sexy // sfr : 2015-08-13 Societe Francaise du Radiotelephone - SFR @@ -9732,7 +9193,7 @@ shell // shia : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. shia -// shiksha : 2013-11-14 Afilias Limited +// shiksha : 2013-11-14 Identity Digital Limited shiksha // shoes : 2013-10-02 Binky Moon, LLC @@ -9765,7 +9226,7 @@ singles // site : 2015-01-15 Radix FZC site -// ski : 2015-04-09 Afilias Limited +// ski : 2015-04-09 Identity Digital Limited ski // skin : 2015-01-15 XYZ.COM LLC @@ -9786,7 +9247,7 @@ smart // smile : 2014-12-18 Amazon Registry Services, Inc. smile -// sncf : 2015-02-19 Société Nationale des Chemins de fer Francais S N C F +// sncf : 2015-02-19 Société Nationale SNCF sncf // soccer : 2015-03-26 Binky Moon, LLC @@ -9870,7 +9331,7 @@ stream // studio : 2015-02-11 Dog Beach, LLC studio -// study : 2014-12-11 OPEN UNIVERSITIES AUSTRALIA PTY LTD +// study : 2014-12-11 Registry Services, LLC study // style : 2014-12-04 Binky Moon, LLC @@ -9930,7 +9391,7 @@ tatamotors // tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic" tatar -// tattoo : 2013-08-30 UNR Corp. +// tattoo : 2013-08-30 Top Level Design, LLC tattoo // tax : 2014-03-20 Binky Moon, LLC @@ -10023,7 +9484,7 @@ toray // toshiba : 2014-04-10 TOSHIBA Corporation toshiba -// total : 2015-08-06 Total SA +// total : 2015-08-06 TotalEnergies SE total // tours : 2015-01-22 Binky Moon, LLC @@ -10059,7 +9520,7 @@ travelers // travelersinsurance : 2015-03-26 Travelers TLD, LLC travelersinsurance -// trust : 2014-10-16 UNR Corp. +// trust : 2014-10-16 Internet Naming Company LLC trust // trv : 2015-03-26 Travelers TLD, LLC @@ -10206,7 +9667,7 @@ wanggou // watch : 2013-11-14 Binky Moon, LLC watch -// watches : 2014-12-22 Afilias Limited +// watches : 2014-12-22 Identity Digital Limited watches // weather : 2015-01-08 International Business Machines Corporation @@ -10341,7 +9802,7 @@ xin // xn--5tzm5g : 2014-12-22 Global Website TLD Asia Limited 网站 -// xn--6frz82g : 2013-09-23 Afilias Limited +// xn--6frz82g : 2013-09-23 Identity Digital Limited 移动 // xn--6qq986b3xl : 2013-09-13 Tycoon Treasure Limited @@ -10458,9 +9919,6 @@ xin // xn--jlq480n2rg : 2019-12-19 Amazon Registry Services, Inc. 亚马逊 -// xn--jlq61u9w7b : 2015-01-08 Nokia Corporation -诺基亚 - // xn--jvr189m : 2015-02-26 Amazon Registry Services, Inc. 食品 @@ -10648,6 +10106,14 @@ graphox.us // Submitted by accesso Team *.devcdnaccesso.com +// Acorn Labs : https://acorn.io +// Submitted by Craig Jellick +*.on-acorn.io + +// ActiveTrail: https://www.activetrail.biz/ +// Submitted by Ofer Kalaora +activetrail.biz + // Adobe : https://www.adobe.com/ // Submitted by Ian Boston and Lars Trieloff adobeaemcloud.com @@ -10657,10 +10123,43 @@ adobeaemcloud.net hlx.page hlx3.page +// Adobe Developer Platform : https://developer.adobe.com +// Submitted by Jesse MacFadyen +adobeio-static.net +adobeioruntime.net + // Agnat sp. z o.o. : https://domena.pl // Submitted by Przemyslaw Plewa beep.pl +// Airkit : https://www.airkit.com/ +// Submitted by Grant Cooksey +airkitapps.com +airkitapps-au.com +airkitapps.eu + +// Aiven: https://aiven.io/ +// Submitted by Etienne Stalmans +aivencloud.com + +// Akamai : https://www.akamai.com/ +// Submitted by Akamai Team +akadns.net +akamai.net +akamai-staging.net +akamaiedge.net +akamaiedge-staging.net +akamaihd.net +akamaihd-staging.net +akamaiorigin.net +akamaiorigin-staging.net +akamaized.net +akamaized-staging.net +edgekey.net +edgekey-staging.net +edgesuite.net +edgesuite-staging.net + // alboto.ca : http://alboto.ca // Submitted by Anton Avramov barsy.ca @@ -10682,19 +10181,134 @@ altervista.org // Submitted by Cyril alwaysdata.net -// Amazon CloudFront : https://aws.amazon.com/cloudfront/ +// Amaze Software : https://amaze.co +// Submitted by Domain Admin +myamaze.net + +// Amazon : https://www.amazon.com/ +// Submitted by AWS Security +// Subsections of Amazon/subsidiaries will appear until "concludes" tag + +// Amazon CloudFront // Submitted by Donavan Miller +// Reference: 54144616-fd49-4435-8535-19c6a601bdb3 cloudfront.net -// Amazon Elastic Compute Cloud : https://aws.amazon.com/ec2/ +// Amazon EC2 // Submitted by Luke Wells +// Reference: 4c38fa71-58ac-4768-99e5-689c1767e537 *.compute.amazonaws.com *.compute-1.amazonaws.com *.compute.amazonaws.com.cn us-east-1.amazonaws.com -// Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/ +// Amazon S3 +// Submitted by Luke Wells +// Reference: d068bd97-f0a9-4838-a6d8-954b622ef4ae +s3.cn-north-1.amazonaws.com.cn +s3.dualstack.ap-northeast-1.amazonaws.com +s3.dualstack.ap-northeast-2.amazonaws.com +s3.ap-northeast-2.amazonaws.com +s3-website.ap-northeast-2.amazonaws.com +s3.dualstack.ap-south-1.amazonaws.com +s3.ap-south-1.amazonaws.com +s3-website.ap-south-1.amazonaws.com +s3.dualstack.ap-southeast-1.amazonaws.com +s3.dualstack.ap-southeast-2.amazonaws.com +s3.dualstack.ca-central-1.amazonaws.com +s3.ca-central-1.amazonaws.com +s3-website.ca-central-1.amazonaws.com +s3.dualstack.eu-central-1.amazonaws.com +s3.eu-central-1.amazonaws.com +s3-website.eu-central-1.amazonaws.com +s3.dualstack.eu-west-1.amazonaws.com +s3.dualstack.eu-west-2.amazonaws.com +s3.eu-west-2.amazonaws.com +s3-website.eu-west-2.amazonaws.com +s3.dualstack.eu-west-3.amazonaws.com +s3.eu-west-3.amazonaws.com +s3-website.eu-west-3.amazonaws.com +s3.amazonaws.com +s3-ap-northeast-1.amazonaws.com +s3-ap-northeast-2.amazonaws.com +s3-ap-south-1.amazonaws.com +s3-ap-southeast-1.amazonaws.com +s3-ap-southeast-2.amazonaws.com +s3-ca-central-1.amazonaws.com +s3-eu-central-1.amazonaws.com +s3-eu-west-1.amazonaws.com +s3-eu-west-2.amazonaws.com +s3-eu-west-3.amazonaws.com +s3-external-1.amazonaws.com +s3-fips-us-gov-west-1.amazonaws.com +s3-sa-east-1.amazonaws.com +s3-us-east-2.amazonaws.com +s3-us-gov-west-1.amazonaws.com +s3-us-west-1.amazonaws.com +s3-us-west-2.amazonaws.com +s3-website-ap-northeast-1.amazonaws.com +s3-website-ap-southeast-1.amazonaws.com +s3-website-ap-southeast-2.amazonaws.com +s3-website-eu-west-1.amazonaws.com +s3-website-sa-east-1.amazonaws.com +s3-website-us-east-1.amazonaws.com +s3-website-us-west-1.amazonaws.com +s3-website-us-west-2.amazonaws.com +s3.dualstack.sa-east-1.amazonaws.com +s3.dualstack.us-east-1.amazonaws.com +s3.dualstack.us-east-2.amazonaws.com +s3.us-east-2.amazonaws.com +s3-website.us-east-2.amazonaws.com + +// AWS Cloud9 +// Submitted by: AWS Security +// Reference: 2b6dfa9a-3a7f-4367-b2e7-0321e77c0d59 +vfs.cloud9.af-south-1.amazonaws.com +webview-assets.cloud9.af-south-1.amazonaws.com +vfs.cloud9.ap-east-1.amazonaws.com +webview-assets.cloud9.ap-east-1.amazonaws.com +vfs.cloud9.ap-northeast-1.amazonaws.com +webview-assets.cloud9.ap-northeast-1.amazonaws.com +vfs.cloud9.ap-northeast-2.amazonaws.com +webview-assets.cloud9.ap-northeast-2.amazonaws.com +vfs.cloud9.ap-northeast-3.amazonaws.com +webview-assets.cloud9.ap-northeast-3.amazonaws.com +vfs.cloud9.ap-south-1.amazonaws.com +webview-assets.cloud9.ap-south-1.amazonaws.com +vfs.cloud9.ap-southeast-1.amazonaws.com +webview-assets.cloud9.ap-southeast-1.amazonaws.com +vfs.cloud9.ap-southeast-2.amazonaws.com +webview-assets.cloud9.ap-southeast-2.amazonaws.com +vfs.cloud9.ca-central-1.amazonaws.com +webview-assets.cloud9.ca-central-1.amazonaws.com +vfs.cloud9.eu-central-1.amazonaws.com +webview-assets.cloud9.eu-central-1.amazonaws.com +vfs.cloud9.eu-north-1.amazonaws.com +webview-assets.cloud9.eu-north-1.amazonaws.com +vfs.cloud9.eu-south-1.amazonaws.com +webview-assets.cloud9.eu-south-1.amazonaws.com +vfs.cloud9.eu-west-1.amazonaws.com +webview-assets.cloud9.eu-west-1.amazonaws.com +vfs.cloud9.eu-west-2.amazonaws.com +webview-assets.cloud9.eu-west-2.amazonaws.com +vfs.cloud9.eu-west-3.amazonaws.com +webview-assets.cloud9.eu-west-3.amazonaws.com +vfs.cloud9.me-south-1.amazonaws.com +webview-assets.cloud9.me-south-1.amazonaws.com +vfs.cloud9.sa-east-1.amazonaws.com +webview-assets.cloud9.sa-east-1.amazonaws.com +vfs.cloud9.us-east-1.amazonaws.com +webview-assets.cloud9.us-east-1.amazonaws.com +vfs.cloud9.us-east-2.amazonaws.com +webview-assets.cloud9.us-east-2.amazonaws.com +vfs.cloud9.us-west-1.amazonaws.com +webview-assets.cloud9.us-west-1.amazonaws.com +vfs.cloud9.us-west-2.amazonaws.com +webview-assets.cloud9.us-west-2.amazonaws.com + +// AWS Elastic Beanstalk // Submitted by Luke Wells +// Reference: aa202394-43a0-4857-b245-8db04549137e cn-north-1.eb.amazonaws.com.cn cn-northwest-1.eb.amazonaws.com.cn elasticbeanstalk.com @@ -10716,71 +10330,24 @@ us-gov-west-1.elasticbeanstalk.com us-west-1.elasticbeanstalk.com us-west-2.elasticbeanstalk.com -// Amazon Elastic Load Balancing : https://aws.amazon.com/elasticloadbalancing/ +// (AWS) Elastic Load Balancing // Submitted by Luke Wells -*.elb.amazonaws.com +// Reference: 12a3d528-1bac-4433-a359-a395867ffed2 *.elb.amazonaws.com.cn +*.elb.amazonaws.com -// Amazon Global Accelerator : https://aws.amazon.com/global-accelerator/ +// AWS Global Accelerator // Submitted by Daniel Massaguer +// Reference: d916759d-a08b-4241-b536-4db887383a6a awsglobalaccelerator.com -// Amazon S3 : https://aws.amazon.com/s3/ -// Submitted by Luke Wells -s3.amazonaws.com -s3-ap-northeast-1.amazonaws.com -s3-ap-northeast-2.amazonaws.com -s3-ap-south-1.amazonaws.com -s3-ap-southeast-1.amazonaws.com -s3-ap-southeast-2.amazonaws.com -s3-ca-central-1.amazonaws.com -s3-eu-central-1.amazonaws.com -s3-eu-west-1.amazonaws.com -s3-eu-west-2.amazonaws.com -s3-eu-west-3.amazonaws.com -s3-external-1.amazonaws.com -s3-fips-us-gov-west-1.amazonaws.com -s3-sa-east-1.amazonaws.com -s3-us-gov-west-1.amazonaws.com -s3-us-east-2.amazonaws.com -s3-us-west-1.amazonaws.com -s3-us-west-2.amazonaws.com -s3.ap-northeast-2.amazonaws.com -s3.ap-south-1.amazonaws.com -s3.cn-north-1.amazonaws.com.cn -s3.ca-central-1.amazonaws.com -s3.eu-central-1.amazonaws.com -s3.eu-west-2.amazonaws.com -s3.eu-west-3.amazonaws.com -s3.us-east-2.amazonaws.com -s3.dualstack.ap-northeast-1.amazonaws.com -s3.dualstack.ap-northeast-2.amazonaws.com -s3.dualstack.ap-south-1.amazonaws.com -s3.dualstack.ap-southeast-1.amazonaws.com -s3.dualstack.ap-southeast-2.amazonaws.com -s3.dualstack.ca-central-1.amazonaws.com -s3.dualstack.eu-central-1.amazonaws.com -s3.dualstack.eu-west-1.amazonaws.com -s3.dualstack.eu-west-2.amazonaws.com -s3.dualstack.eu-west-3.amazonaws.com -s3.dualstack.sa-east-1.amazonaws.com -s3.dualstack.us-east-1.amazonaws.com -s3.dualstack.us-east-2.amazonaws.com -s3-website-us-east-1.amazonaws.com -s3-website-us-west-1.amazonaws.com -s3-website-us-west-2.amazonaws.com -s3-website-ap-northeast-1.amazonaws.com -s3-website-ap-southeast-1.amazonaws.com -s3-website-ap-southeast-2.amazonaws.com -s3-website-eu-west-1.amazonaws.com -s3-website-sa-east-1.amazonaws.com -s3-website.ap-northeast-2.amazonaws.com -s3-website.ap-south-1.amazonaws.com -s3-website.ca-central-1.amazonaws.com -s3-website.eu-central-1.amazonaws.com -s3-website.eu-west-2.amazonaws.com -s3-website.eu-west-3.amazonaws.com -s3-website.us-east-2.amazonaws.com +// eero +// Submitted by Yue Kang +// Reference: 264afe70-f62c-4c02-8ab9-b5281ed24461 +eero.online +eero-stage.online + +// concludes Amazon // Amune : https://amune.org/ // Submitted by Team Amune @@ -10833,6 +10400,14 @@ myasustor.com // Submitted by Sam Smyth cdn.prod.atlassian-dev.net +// Authentick UG (haftungsbeschränkt) : https://authentick.net +// Submitted by Lukas Reschke +translated.page + +// Autocode : https://autocode.com +// Submitted by Jacob Lee +autocode.dev + // AVM : https://avm.de // Submitted by Andreas Weise myfritz.net @@ -10847,7 +10422,7 @@ onavstack.net *.advisor.ws // AZ.pl sp. z.o.o: https://az.pl -// Submited by Krzysztof Wolski +// Submitted by Krzysztof Wolski ecommerce-shop.pl // b-data GmbH : https://www.b-data.io @@ -10873,6 +10448,26 @@ rs.ba app.banzaicloud.io *.backyards.banzaicloud.io +// BASE, Inc. : https://binc.jp +// Submitted by Yuya NAGASAWA +base.ec +official.ec +buyshop.jp +fashionstore.jp +handcrafted.jp +kawaiishop.jp +supersale.jp +theshop.jp +shopselect.net +base.shop + +// BeagleBoard.org Foundation : https://beagleboard.org +// Submitted by Jason Kridner +beagleboard.io + +// Beget Ltd +// Submitted by Lev Nekrasov +*.beget.app // BetaInABox // Submitted by Adrian @@ -10941,6 +10536,11 @@ cafjs.com // Submitted by Marcus Popp mycd.eu +// Canva Pty Ltd : https://canva.com/ +// Submitted by Joel Aquilina +canva-apps.cn +canva-apps.com + // Carrd : https://carrd.co // Submitted by AJ drr.ac @@ -11070,8 +10670,11 @@ cloudcontrolapp.com // Cloudflare, Inc. : https://www.cloudflare.com/ // Submitted by Cloudflare Team -pages.dev +cf-ipfs.com +cloudflare-ipfs.com trycloudflare.com +pages.dev +r2.dev workers.dev // Clovyr : https://clovyr.io @@ -11115,6 +10718,10 @@ cloudns.us // Submitted by Angelo Gladding cnpy.gdn +// Codeberg e. V. : https://codeberg.org +// Submitted by Moritz Marquardt +codeberg.page + // CoDNS B.V. co.nl co.no @@ -11241,11 +10848,21 @@ deno-staging.dev // Submitted by Peter Thomassen dedyn.io +// Deta: https://www.deta.sh/ +// Submitted by Aavash Shrestha +deta.app +deta.dev + // Diher Solutions : https://diher.solutions // Submitted by Didi Hermawan *.rss.my.id *.diher.solutions +// Discord Inc : https://discord.com +// Submitted by Sahn Lam +discordsays.com +discordsez.com + // DNS Africa Ltd https://dns.business // Submitted by Calvin Browne jozi.biz @@ -11634,10 +11251,10 @@ dynv6.net // Submitted by Vladimir Dudr e4.cz -// eero : https://eero.com/ -// Submitted by Yue Kang -eero.online -eero-stage.online +// Easypanel : https://easypanel.io +// Submitted by Andrei Canta +easypanel.app +easypanel.host // Elementor : Elementor Ltd. // Submitted by Anton Barkan @@ -11653,11 +11270,20 @@ en-root.fr mytuleap.com tuleap-partners.com +// Encoretivity AB: https://encore.dev +// Submitted by André Eriksson +encr.app +encoreapi.com + // ECG Robotics, Inc: https://ecgrobotics.org // Submitted by onred.one staging.onred.one +// encoway GmbH : https://www.encoway.de +// Submitted by Marcel Daus +eu.encoway.cloud + // EU.org https://eu.org/ // Submitted by Pierre Beyssac eu.org @@ -11832,6 +11458,7 @@ u.channelsdvr.net // Fastly Inc. : http://www.fastly.com/ // Submitted by Fastly Security edgecompute.app +fastly-edge.com fastly-terrarium.com fastlylb.net map.fastlylb.net @@ -11843,6 +11470,10 @@ a.ssl.fastly.net b.ssl.fastly.net global.ssl.fastly.net +// Fastmail : https://www.fastmail.com/ +// Submitted by Marc Bradshaw +*.user.fm + // FASTVPS EESTI OU : https://fastvps.ru/ // Submitted by Likhachev Vasiliy fastvps-server.com @@ -11861,8 +11492,6 @@ app.os.stg.fedoraproject.org // FearWorks Media Ltd. : https://fearworksmedia.co.uk // submitted by Keith Fairley -couk.me -ukco.me conn.uk copro.uk hosp.uk @@ -11921,6 +11550,10 @@ id.forgerock.io // Submitted by Koen Rouwhorst framer.app framercanvas.com +framer.media +framer.photos +framer.website +framer.wiki // Frusky MEDIA&PR : https://www.frusky.de // Submitted by Victor Pupynin @@ -11966,10 +11599,22 @@ futuremailing.at *.kunden.ortsinfo.at *.statics.cloud -// GDS : https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains -// Submitted by David Illsley +// GDS : https://www.gov.uk/service-manual/technology/managing-domain-names +// Submitted by Stephen Ford +independent-commission.uk +independent-inquest.uk +independent-inquiry.uk +independent-panel.uk +independent-review.uk +public-inquiry.uk +royal-commission.uk +campaign.gov.uk service.gov.uk +// CDDO : https://www.gov.uk/guidance/get-an-api-domain-on-govuk +// Submitted by Jamie Tanna +api.gov.uk + // Gehirn Inc. : https://www.gehirn.co.jp/ // Submitted by Kohei YOSHIDA gehirn.ne.jp @@ -12019,8 +11664,114 @@ co.ro shop.ro // GMO Pepabo, Inc. : https://pepabo.com/ -// Submitted by dojineko +// Submitted by Hosting Div lolipop.io +angry.jp +babyblue.jp +babymilk.jp +backdrop.jp +bambina.jp +bitter.jp +blush.jp +boo.jp +boy.jp +boyfriend.jp +but.jp +candypop.jp +capoo.jp +catfood.jp +cheap.jp +chicappa.jp +chillout.jp +chips.jp +chowder.jp +chu.jp +ciao.jp +cocotte.jp +coolblog.jp +cranky.jp +cutegirl.jp +daa.jp +deca.jp +deci.jp +digick.jp +egoism.jp +fakefur.jp +fem.jp +flier.jp +floppy.jp +fool.jp +frenchkiss.jp +girlfriend.jp +girly.jp +gloomy.jp +gonna.jp +greater.jp +hacca.jp +heavy.jp +her.jp +hiho.jp +hippy.jp +holy.jp +hungry.jp +icurus.jp +itigo.jp +jellybean.jp +kikirara.jp +kill.jp +kilo.jp +kuron.jp +littlestar.jp +lolipopmc.jp +lolitapunk.jp +lomo.jp +lovepop.jp +lovesick.jp +main.jp +mods.jp +mond.jp +mongolian.jp +moo.jp +namaste.jp +nikita.jp +nobushi.jp +noor.jp +oops.jp +parallel.jp +parasite.jp +pecori.jp +peewee.jp +penne.jp +pepper.jp +perma.jp +pigboat.jp +pinoko.jp +punyu.jp +pupu.jp +pussycat.jp +pya.jp +raindrop.jp +readymade.jp +sadist.jp +schoolbus.jp +secret.jp +staba.jp +stripper.jp +sub.jp +sunnyday.jp +thick.jp +tonkotsu.jp +under.jp +upper.jp +velvet.jp +verse.jp +versus.jp +vivian.jp +watson.jp +weblike.jp +whitesnow.jp +zombie.jp +heteml.net // GOV.UK Platform as a Service : https://www.cloud.service.gov.uk/ // Submitted by Tom Whitwell @@ -12142,6 +11893,10 @@ blogspot.vn // Submitted by Niels Martignene goupile.fr +// Government of the Netherlands: https://www.government.nl +// Submitted by +gov.nl + // Group 53, LLC : https://www.group53.com // Submitted by Tyler Todd awsmppl.com @@ -12152,7 +11907,7 @@ günstigbestellen.de günstigliefern.de // Hakaran group: http://hakaran.cz -// Submited by Arseniy Sokolov +// Submitted by Arseniy Sokolov fin.ci free.hr caa.li @@ -12187,20 +11942,25 @@ herokussl.com // Hibernating Rhinos // Submitted by Oren Eini -myravendb.com +ravendb.cloud ravendb.community ravendb.me development.run ravendb.run // home.pl S.A.: https://home.pl -// Submited by Krzysztof Wolski +// Submitted by Krzysztof Wolski homesklep.pl // Hong Kong Productivity Council: https://www.hkpc.org/ // Submitted by SECaaS Team secaas.hk +// Hoplix : https://www.hoplix.com +// Submitted by Danilo De Franco +hoplix.shop + + // HOSTBIP REGISTRY : https://www.hostbip.com/ // Submitted by Atanunu Igbunuroghene orx.biz @@ -12212,7 +11972,10 @@ ltd.ng ngo.ng edu.scot sch.so -org.yt + +// HostFly : https://www.ie.ua +// Submitted by Bohdan Dub +ie.ua // HostyHosting (hostyhosting.com) hostyhosting.io @@ -12230,6 +11993,11 @@ moonscale.net // Submitted by Hannu Aronsson iki.fi +// iliad italia: https://www.iliad.it +// Submitted by Marios Makassikis +ibxos.it +iliadboxos.it + // Impertrix Solutions : // Submitted by Zhixiang Zhao impertrixcdn.com @@ -12299,7 +12067,7 @@ to.leg.br pixolino.com // Internet-Pro, LLP: https://netangels.ru/ -// Submited by Vasiliy Sheredeko +// Submitted by Vasiliy Sheredeko na4u.ru // iopsys software solutions AB : https://iopsys.eu/ @@ -12310,9 +12078,11 @@ iopsys.se // Submitted by Matthew Hardeman ipifony.net -// IServ GmbH : https://iserv.eu -// Submitted by Kim-Alexander Brodowski +// IServ GmbH : https://iserv.de +// Submitted by Mario Hoberg +iservschule.de mein-iserv.de +schulplattform.de schulserver.de test-iserv.de iserv.dev @@ -12322,7 +12092,7 @@ iserv.dev iobb.net // Jelastic, Inc. : https://jelastic.com/ -// Submited by Ihor Kolodyuk +// Submitted by Ihor Kolodyuk mel.cloudlets.com.au cloud.interhostsolutions.be users.scale.virtualcloud.com.br @@ -12433,6 +12203,14 @@ js.org kaas.gg khplay.nl +// Kakao : https://www.kakaocorp.com/ +// Submitted by JaeYoong Lee +ktistory.com + +// Kapsi : https://kapsi.fi +// Submitted by Tomi Juntunen +kapsi.fi + // Keyweb AG : https://www.keyweb.de // Submitted by Martin Dannehl keymachine.de @@ -12446,6 +12224,10 @@ uni5.net // Submitted by Roy Keene knightpoint.systems +// KoobinEvent, SL: https://www.koobin.com +// Submitted by Iván Oliva +koobin.events + // KUROKU LTD : https://kuroku.ltd/ // Submitted by DisposaBoy oya.to @@ -12510,6 +12292,10 @@ ip.linodeusercontent.com // Submitted by Victor Velchev we.bs +// Localcert : https://localcert.dev +// Submitted by Lann Martin +*.user.localcert.dev + // localzone.xyz // Submitted by Kenny Niehage localzone.xyz @@ -12618,6 +12404,10 @@ hra.health miniserver.com memset.net +// Messerli Informatik AG : https://www.messerli.ch/ +// Submitted by Ruben Schmidmeister +messerli.app + // MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ // Submitted by Zdeněk Šustr *.cloud.metacentrum.cz @@ -12637,12 +12427,15 @@ eu.meteorapp.com co.pl // Microsoft Corporation : http://microsoft.com -// Submitted by Mitch Webster +// Submitted by Public Suffix List Admin *.azurecontainer.io azurewebsites.net azure-mobile.net cloudapp.net azurestaticapps.net +1.azurestaticapps.net +2.azurestaticapps.net +3.azurestaticapps.net centralus.azurestaticapps.net eastasia.azurestaticapps.net eastus2.azurestaticapps.net @@ -12695,24 +12488,9 @@ cust.retrosnub.co.uk // Submitted by Paulus Schoutsen ui.nabu.casa -// Names.of.London : https://names.of.london/ -// Submitted by James Stevens or -pony.club -of.fashion -in.london -of.london -from.marketing -with.marketing -for.men -repair.men -and.mom -for.mom -for.one -under.one -for.sale -that.win -from.work -to.work +// Net at Work Gmbh : https://www.netatwork.de +// Submitted by Jan Jaeschke +cloud.nospamproxy.com // Netlify : https://www.netlify.com // Submitted by Jessica Parsons @@ -12724,7 +12502,19 @@ netlify.app // ngrok : https://ngrok.com/ // Submitted by Alan Shreve +ngrok.app +ngrok-free.app +ngrok.dev +ngrok-free.dev ngrok.io +ap.ngrok.io +au.ngrok.io +eu.ngrok.io +in.ngrok.io +jp.ngrok.io +sa.ngrok.io +us.ngrok.io +ngrok.pizza // Nimbus Hosting Ltd. : https://www.nimbushosting.co.uk/ // Submitted by Nicholas Ford @@ -12742,7 +12532,10 @@ noop.app // Northflank Ltd. : https://northflank.com/ // Submitted by Marco Suter *.northflank.app +*.build.run *.code.run +*.database.run +*.migration.run // Noticeable : https://noticeable.io // Submitted by Laurent Pellegrino @@ -12873,11 +12666,6 @@ zapto.org // Submitted by Konstantin Nosov stage.nodeart.io -// Nodum B.V. : https://nodum.io/ -// Submitted by Wietse Wind -nodum.co -nodum.io - // Nucleos Inc. : https://nucleos.com // Submitted by Piotr Zduniak pcloud.host @@ -12908,7 +12696,26 @@ omniwe.site // One.com: https://www.one.com/ // Submitted by Jacob Bunk Nielsen +123hjemmeside.dk +123hjemmeside.no +123homepage.it +123kotisivu.fi +123minsida.se +123miweb.es +123paginaweb.pt +123sait.ru +123siteweb.fr +123webseite.at +123webseite.de +123website.be +123website.ch +123website.lu +123website.nl service.one +simplesite.com +simplesite.com.br +simplesite.gr +simplesite.pl // One Fold Media : http://www.onefoldmedia.com/ // Submitted by Eddie Jones @@ -12930,8 +12737,12 @@ orsites.com // Submitted by Yngve Pettersen operaunite.com +// Orange : https://www.orange.com +// Submitted by Alexandre Linte +tech.orange + // Oursky Limited : https://authgear.com/, https://skygear.io/ -// Submited by Authgear Team , Skygear Developer +// Submitted by Authgear Team , Skygear Developer authgear-staging.com authgearapps.com skygearapp.com @@ -13039,6 +12850,10 @@ pleskns.com // Submitted by Maximilian Schieder dyn53.io +// Porter : https://porter.run/ +// Submitted by Rudraksh MK +onporter.run + // Positive Codes Technology Company : http://co.bn/faq.html // Submitted by Zulfais co.bn @@ -13096,6 +12911,10 @@ qoto.io // Submitted by Xavier De Cock qualifioapp.com +// Quality Unit: https://qualityunit.com +// Submitted by Vasyl Tsalko +ladesk.com + // QuickBackend: https://www.quickbackend.com // Submitted by Dani Biro qbuser.com @@ -13169,7 +12988,9 @@ app.render.com onrender.com // Repl.it : https://repl.it -// Submitted by Mason Clayton +// Submitted by Lincoln Bergeson +firewalledreplit.co +id.firewalledreplit.co repl.co id.repl.co repl.run @@ -13200,6 +13021,10 @@ itcouldbewor.se // Submitted by Jennifer Herting git-pages.rit.edu +// Rocky Enterprise Software Foundation : https://resf.org +// Submitted by Neil Hanlon +rocky.page + // Rusnames Limited: http://rusnames.ru/ // Submitted by Sergey Zotov биз.рус @@ -13213,6 +13038,62 @@ git-pages.rit.edu спб.рус я.рус +// SAKURA Internet Inc. : https://www.sakura.ad.jp/ +// Submitted by Internet Service Department +180r.com +dojin.com +sakuratan.com +sakuraweb.com +x0.com +2-d.jp +bona.jp +crap.jp +daynight.jp +eek.jp +flop.jp +halfmoon.jp +jeez.jp +matrix.jp +mimoza.jp +ivory.ne.jp +mail-box.ne.jp +mints.ne.jp +mokuren.ne.jp +opal.ne.jp +sakura.ne.jp +sumomo.ne.jp +topaz.ne.jp +netgamers.jp +nyanta.jp +o0o0.jp +rdy.jp +rgr.jp +rulez.jp +s3.isk01.sakurastorage.jp +s3.isk02.sakurastorage.jp +saloon.jp +sblo.jp +skr.jp +tank.jp +uh-oh.jp +undo.jp +rs.webaccel.jp +user.webaccel.jp +websozai.jp +xii.jp +squares.net +jpn.org +kirara.st +x0.to +from.tv +sakura.tv + +// Salesforce.com, Inc. https://salesforce.com/ +// Submitted by Michael Biven +*.builder.code.com +*.dev-builder.code.com +*.stg-builder.code.com + // Sandstorm Development Group, Inc. : https://sandcats.io/ // Submitted by Asheesh Laroia sandcats.io @@ -13222,6 +13103,34 @@ sandcats.io logoip.de logoip.com +// Scaleway : https://www.scaleway.com/ +// Submitted by Rémy Léone +fr-par-1.baremetal.scw.cloud +fr-par-2.baremetal.scw.cloud +nl-ams-1.baremetal.scw.cloud +fnc.fr-par.scw.cloud +functions.fnc.fr-par.scw.cloud +k8s.fr-par.scw.cloud +nodes.k8s.fr-par.scw.cloud +s3.fr-par.scw.cloud +s3-website.fr-par.scw.cloud +whm.fr-par.scw.cloud +priv.instances.scw.cloud +pub.instances.scw.cloud +k8s.scw.cloud +k8s.nl-ams.scw.cloud +nodes.k8s.nl-ams.scw.cloud +s3.nl-ams.scw.cloud +s3-website.nl-ams.scw.cloud +whm.nl-ams.scw.cloud +k8s.pl-waw.scw.cloud +nodes.k8s.pl-waw.scw.cloud +s3.pl-waw.scw.cloud +s3-website.pl-waw.scw.cloud +scalebook.scw.cloud +smartlabeling.scw.cloud +dedibox.fr + // schokokeks.org GbR : https://schokokeks.org/ // Submitted by Hanno Böck schokokeks.net @@ -13329,6 +13238,13 @@ small-web.org // Submitted by Dan Kozak vp4.me +// Snowflake Inc : https://www.snowflake.com/ +// Submitted by Faith Olapade +snowflake.app +privatelink.snowflake.app +streamlit.app +streamlitapp.com + // Snowplow Analytics : https://snowplowanalytics.com/ // Submitted by Ian Streeter try-snowplow.com @@ -13342,6 +13258,8 @@ srht.site stackhero-network.com // Staclar : https://staclar.com +// Submitted by Q Misell +musician.io // Submitted by Matthias Merkel novecore.site @@ -13440,25 +13358,28 @@ syncloud.it // Synology, Inc. : https://www.synology.com/ // Submitted by Rony Weng -diskstation.me dscloud.biz -dscloud.me -dscloud.mobi +direct.quickconnect.cn dsmynas.com -dsmynas.net -dsmynas.org familyds.com -familyds.net -familyds.org +diskstation.me +dscloud.me i234.me myds.me synology.me +dscloud.mobi +dsmynas.net +familyds.net +dsmynas.org +familyds.org vpnplus.to direct.quickconnect.to // Tabit Technologies Ltd. : https://tabit.cloud/ // Submitted by Oren Agiv tabitorder.co.il +mytabit.co.il +mytabit.com // TAIFUN Software AG : http://taifun-software.de // Submitted by Bjoern Henke @@ -13476,9 +13397,14 @@ gdynia.pl med.pl sopot.pl +// team.blue https://team.blue +// Submitted by Cedric Dubois +site.tb-hosting.com + // Teckids e.V. : https://www.teckids.org // Submitted by Dominik George -edugit.org +edugit.io +s3.teckids.org // Telebit : https://telebit.cloud // Submitted by AJ ONeal @@ -13486,10 +13412,6 @@ telebit.app telebit.io *.telebit.xyz -// The Gwiddle Foundation : https://gwiddlefoundation.org.uk -// Submitted by Joshua Bayfield -gwiddle.co.uk - // Thingdust AG : https://thingdust.com/ // Submitted by Adrian Imboden *.firenet.ch @@ -13524,10 +13446,6 @@ pages.torproject.net 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 @@ -13556,6 +13474,10 @@ lima.zone *.transurl.eu *.transurl.nl +// TransIP: https://www.transip.nl +// Submitted by Cedric Dubois +site.transip.me + // TuxFamily : http://tuxfamily.org // Submitted by TuxFamily administrators tuxfamily.org @@ -13576,6 +13498,14 @@ syno-ds.de synology-diskstation.de synology-ds.de +// Typedream : https://typedream.com +// Submitted by Putri Karunia +typedream.app + +// Typeform : https://www.typeform.com +// Submitted by Sergi Ferriz +pro.typeform.com + // Uberspace : https://uberspace.de // Submitted by Moritz Werner uber.space @@ -13588,6 +13518,19 @@ hk.org ltd.hk inc.hk +// UK Intis Telecom LTD : https://it.com +// Submitted by ITComdomains +it.com + +// UNIVERSAL DOMAIN REGISTRY : https://www.udr.org.yt/ +// see also: whois -h whois.udr.org.yt help +// Submitted by Atanunu Igbunuroghene +name.pm +sch.tf +biz.wf +sch.wf +org.yt + // United Gameserver GmbH : https://united-gameserver.de // Submitted by Stefan Schwarz virtualuser.de @@ -13674,19 +13617,14 @@ me.vu // Submitted by Serhii Rostilo v.ua +// Vultr Objects : https://www.vultr.com/products/object-storage/ +// Submitted by Niels Maumenee +*.vultrobjects.com + // Waffle Computer Inc., Ltd. : https://docs.waffleinfo.com // 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 @@ -13723,6 +13661,10 @@ wmcloud.org panel.gg daemon.panel.gg +// Wizard Zines : https://wizardzines.com +// Submitted by Julia Evans +messwithdns.com + // WoltLab GmbH : https://www.woltlab.com // Submitted by Tim Düsterhus woltlab-demo.com diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk index e7b5ab4e187..35afe9439b2 100644 --- a/make/lib/Awt2dLibraries.gmk +++ b/make/lib/Awt2dLibraries.gmk @@ -527,6 +527,7 @@ else E_END_OF_LOOP_CODE_NOT_REACHED, \ DISABLED_WARNINGS_microsoft := 4018 4267 4244 4312 4819, \ DISABLED_WARNINGS_gcc := implicit-fallthrough cast-function-type bad-function-cast, \ + DISABLED_WARNINGS_clang := missing-declarations, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ )) @@ -559,10 +560,12 @@ else # hb-ft.cc is not presently needed, and requires freetype 2.4.2 or later. LIBFONTMANAGER_EXCLUDE_FILES += libharfbuzz/hb-ft.cc - HARFBUZZ_DISABLED_WARNINGS_gcc := type-limits missing-field-initializers strict-aliasing + HARFBUZZ_DISABLED_WARNINGS_gcc := type-limits missing-field-initializers strict-aliasing \ + array-bounds # noexcept-type required for GCC 7 builds. Not required for GCC 8+. + # expansion-to-defined required for GCC 9 builds. Not required for GCC 10+. HARFBUZZ_DISABLED_WARNINGS_CXX_gcc := reorder delete-non-virtual-dtor strict-overflow \ - maybe-uninitialized class-memaccess unused-result extra noexcept-type + maybe-uninitialized class-memaccess unused-result extra noexcept-type expansion-to-defined HARFBUZZ_DISABLED_WARNINGS_clang := unused-value incompatible-pointer-types \ tautological-constant-out-of-range-compare int-to-pointer-cast \ undef missing-field-initializers deprecated-declarations c++11-narrowing range-loop-analysis diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index a29b1a48668..c15ca6299f3 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -991,6 +991,7 @@ reg_class v7_reg( V7, V7_H ); +<<<<<<< HEAD // Class for 128 bit register v8 reg_class v8_reg( V8, V8_H @@ -1111,6 +1112,8 @@ reg_class v31_reg( V31, V31_H ); +======= +>>>>>>> dragonwell_extended_upstream/master // Singleton class for condition codes reg_class int_flags(RFLAGS); @@ -5121,6 +5124,7 @@ operand vRegD_V7() interface(REG_INTER); %} +<<<<<<< HEAD operand vRegD_V8() %{ constraint(ALLOC_IN_RC(v8_reg)); @@ -5337,6 +5341,8 @@ operand vRegD_V31() interface(REG_INTER); %} +======= +>>>>>>> dragonwell_extended_upstream/master // Flags register, used as output of signed compare instructions // note that on AArch64 we also use this register as the output for @@ -15845,14 +15851,17 @@ instruct string_compareLU(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 %} instruct string_indexofUU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2, - iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, - iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, rFlagsReg cr) + iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, + iRegINoSp tmp3, iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, + vRegD_V0 vtmp0, vRegD_V1 vtmp1, rFlagsReg cr) %{ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, - TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, KILL cr); - format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (UU)" %} + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, + TEMP vtmp0, TEMP vtmp1, KILL cr); + format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (UU) " + "# KILL $str1 $cnt1 $str2 $cnt2 $tmp1 $tmp2 $tmp3 $tmp4 $tmp5 $tmp6 V0-V1 cr" %} ins_encode %{ __ string_indexof($str1$$Register, $str2$$Register, @@ -15866,14 +15875,17 @@ instruct string_indexofUU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 %} instruct string_indexofLL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2, - iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, - iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, rFlagsReg cr) + iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, + iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, + vRegD_V0 vtmp0, vRegD_V1 vtmp1, rFlagsReg cr) %{ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, - TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, KILL cr); - format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (LL)" %} + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, + TEMP vtmp0, TEMP vtmp1, KILL cr); + format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (LL) " + "# KILL $str1 $cnt1 $str2 $cnt2 $tmp1 $tmp2 $tmp3 $tmp4 $tmp5 $tmp6 V0-V1 cr" %} ins_encode %{ __ string_indexof($str1$$Register, $str2$$Register, @@ -15887,14 +15899,17 @@ instruct string_indexofLL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 %} instruct string_indexofUL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2, - iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, - iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, rFlagsReg cr) + iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, + iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, + vRegD_V0 vtmp0, vRegD_V1 vtmp1, rFlagsReg cr) %{ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, - TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, KILL cr); - format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (UL)" %} + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, + TEMP tmp6, TEMP vtmp0, TEMP vtmp1, KILL cr); + format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (UL) " + "# KILL $str1 cnt1 $str2 $cnt2 $tmp1 $tmp2 $tmp3 $tmp4 $tmp5 $tmp6 V0-V1 cr" %} ins_encode %{ __ string_indexof($str1$$Register, $str2$$Register, @@ -15908,14 +15923,15 @@ instruct string_indexofUL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 %} instruct string_indexof_conUU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, - immI_le_4 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, - iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) + immI_le_4 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, + iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) %{ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); - format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (UU)" %} + format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (UU) " + "# KILL $str1 $cnt1 $str2 $tmp1 $tmp2 $tmp3 $tmp4 cr" %} ins_encode %{ int icnt2 = (int)$int_cnt2$$constant; @@ -15929,14 +15945,15 @@ instruct string_indexof_conUU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, %} instruct string_indexof_conLL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, - immI_le_4 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, - iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) + immI_le_4 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, + iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) %{ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); - format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (LL)" %} + format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (LL) " + "# KILL $str1 $cnt1 $str2 $tmp1 $tmp2 $tmp3 $tmp4 cr" %} ins_encode %{ int icnt2 = (int)$int_cnt2$$constant; @@ -15950,14 +15967,15 @@ instruct string_indexof_conLL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, %} instruct string_indexof_conUL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, - immI_1 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, - iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) + immI_1 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, + iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) %{ predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); - format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (UL)" %} + format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (UL) " + "# KILL $str1 $cnt1 $str2 $tmp1 $tmp2 $tmp3 $tmp4 cr" %} ins_encode %{ int icnt2 = (int)$int_cnt2$$constant; @@ -16022,13 +16040,17 @@ instruct string_equalsU(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt, instruct array_equalsB(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, iRegP_R3 tmp1, iRegP_R4 tmp2, iRegP_R5 tmp3, + vRegD_V0 vtmp0, vRegD_V1 vtmp1, vRegD_V2 vtmp2, vRegD_V3 vtmp3, + vRegD_V4 vtmp4, vRegD_V5 vtmp5, vRegD_V6 vtmp6, vRegD_V7 vtmp7, iRegP_R10 tmp, rFlagsReg cr) %{ predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); match(Set result (AryEq ary1 ary2)); - effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr); + effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, + TEMP vtmp0, TEMP vtmp1, TEMP vtmp2, TEMP vtmp3, TEMP vtmp4, TEMP vtmp5, + TEMP vtmp6, TEMP vtmp7, KILL cr); - format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %} + format %{ "Array Equals $ary1,ary2 -> $result # KILL $ary1 $ary2 $tmp $tmp1 $tmp2 $tmp3 V0-V7 cr" %} ins_encode %{ address tpc = __ arrays_equals($ary1$$Register, $ary2$$Register, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, @@ -16043,13 +16065,17 @@ instruct array_equalsB(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, instruct array_equalsC(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, iRegP_R3 tmp1, iRegP_R4 tmp2, iRegP_R5 tmp3, + vRegD_V0 vtmp0, vRegD_V1 vtmp1, vRegD_V2 vtmp2, vRegD_V3 vtmp3, + vRegD_V4 vtmp4, vRegD_V5 vtmp5, vRegD_V6 vtmp6, vRegD_V7 vtmp7, iRegP_R10 tmp, rFlagsReg cr) %{ predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); match(Set result (AryEq ary1 ary2)); - effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr); + effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, + TEMP vtmp0, TEMP vtmp1, TEMP vtmp2, TEMP vtmp3, TEMP vtmp4, TEMP vtmp5, + TEMP vtmp6, TEMP vtmp7, KILL cr); - format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %} + format %{ "Array Equals $ary1,ary2 -> $result # KILL $ary1 $ary2 $tmp $tmp1 $tmp2 $tmp3 V0-V7 cr" %} ins_encode %{ address tpc = __ arrays_equals($ary1$$Register, $ary2$$Register, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, @@ -16079,35 +16105,40 @@ instruct has_negatives(iRegP_R1 ary1, iRegI_R2 len, iRegI_R0 result, rFlagsReg c // fast char[] to byte[] compression instruct string_compress(iRegP_R2 src, iRegP_R1 dst, iRegI_R3 len, - vRegD_V0 tmp1, vRegD_V1 tmp2, - vRegD_V2 tmp3, vRegD_V3 tmp4, + vRegD_V0 vtmp0, vRegD_V1 vtmp1, vRegD_V2 vtmp2, + vRegD_V3 vtmp3, vRegD_V4 vtmp4, vRegD_V5 vtmp5, iRegI_R0 result, rFlagsReg cr) %{ match(Set result (StrCompressedCopy src (Binary dst len))); - effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr); + effect(TEMP vtmp0, TEMP vtmp1, TEMP vtmp2, TEMP vtmp3, TEMP vtmp4, TEMP vtmp5, + USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr); - format %{ "String Compress $src,$dst -> $result // KILL R1, R2, R3, R4" %} + format %{ "String Compress $src,$dst -> $result # KILL $src $dst $len V0-V5 cr" %} ins_encode %{ __ char_array_compress($src$$Register, $dst$$Register, $len$$Register, - $tmp1$$FloatRegister, $tmp2$$FloatRegister, - $tmp3$$FloatRegister, $tmp4$$FloatRegister, + $vtmp0$$FloatRegister, $vtmp1$$FloatRegister, + $vtmp2$$FloatRegister, $vtmp3$$FloatRegister, + $vtmp4$$FloatRegister, $vtmp5$$FloatRegister, $result$$Register); %} ins_pipe( pipe_slow ); %} // fast byte[] to char[] inflation -instruct string_inflate(Universe dummy, iRegP_R0 src, iRegP_R1 dst, iRegI_R2 len, - vRegD_V0 tmp1, vRegD_V1 tmp2, vRegD_V2 tmp3, iRegP_R3 tmp4, rFlagsReg cr) +instruct string_inflate(Universe dummy, iRegP_R0 src, iRegP_R1 dst, iRegI_R2 len, iRegP_R3 tmp, + vRegD_V0 vtmp0, vRegD_V1 vtmp1, vRegD_V2 vtmp2, vRegD_V3 vtmp3, + vRegD_V4 vtmp4, vRegD_V5 vtmp5, vRegD_V6 vtmp6, rFlagsReg cr) %{ match(Set dummy (StrInflatedCopy src (Binary dst len))); - effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr); + effect(TEMP vtmp0, TEMP vtmp1, TEMP vtmp2, TEMP vtmp3, + TEMP vtmp4, TEMP vtmp5, TEMP vtmp6, TEMP tmp, + USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr); - format %{ "String Inflate $src,$dst // KILL $tmp1, $tmp2" %} + format %{ "String Inflate $src,$dst # KILL $tmp $src $dst $len V0-V6 cr" %} ins_encode %{ address tpc = __ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register, - $tmp1$$FloatRegister, $tmp2$$FloatRegister, - $tmp3$$FloatRegister, $tmp4$$Register); + $vtmp0$$FloatRegister, $vtmp1$$FloatRegister, + $vtmp2$$FloatRegister, $tmp$$Register); if (tpc == NULL) { ciEnv::current()->record_failure("CodeCache is full"); return; @@ -16118,19 +16149,20 @@ instruct string_inflate(Universe dummy, iRegP_R0 src, iRegP_R1 dst, iRegI_R2 len // encode char[] to byte[] in ISO_8859_1 instruct encode_iso_array(iRegP_R2 src, iRegP_R1 dst, iRegI_R3 len, - vRegD_V0 Vtmp1, vRegD_V1 Vtmp2, - vRegD_V2 Vtmp3, vRegD_V3 Vtmp4, + vRegD_V0 vtmp0, vRegD_V1 vtmp1, vRegD_V2 vtmp2, + vRegD_V3 vtmp3, vRegD_V4 vtmp4, vRegD_V5 vtmp5, iRegI_R0 result, rFlagsReg cr) %{ match(Set result (EncodeISOArray src (Binary dst len))); - effect(USE_KILL src, USE_KILL dst, USE_KILL len, - KILL Vtmp1, KILL Vtmp2, KILL Vtmp3, KILL Vtmp4, KILL cr); + effect(USE_KILL src, USE_KILL dst, USE_KILL len, KILL vtmp0, KILL vtmp1, + KILL vtmp2, KILL vtmp3, KILL vtmp4, KILL vtmp5, KILL cr); - format %{ "Encode array $src,$dst,$len -> $result" %} + format %{ "Encode array $src,$dst,$len -> $result # KILL $src $dst $len V0-V5 cr" %} ins_encode %{ __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register, - $result$$Register, $Vtmp1$$FloatRegister, $Vtmp2$$FloatRegister, - $Vtmp3$$FloatRegister, $Vtmp4$$FloatRegister); + $result$$Register, $vtmp0$$FloatRegister, $vtmp1$$FloatRegister, + $vtmp2$$FloatRegister, $vtmp3$$FloatRegister, + $vtmp4$$FloatRegister, $vtmp5$$FloatRegister); %} ins_pipe( pipe_class_memory ); %} diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp index 383c5b9973b..de369a1b6cd 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp @@ -542,7 +542,7 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { // first the method - Method* m = *interpreter_frame_method_addr(); + Method* m = safe_interpreter_frame_method(); // validate the method we'd find in this potential sender if (!Method::is_valid_method(m)) return false; diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 5803af77147..893fc050799 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -4455,6 +4455,7 @@ void MacroAssembler::remove_frame(int framesize) { typedef void (MacroAssembler::* chr_insn)(Register Rt, const Address &adr); // Search for str1 in str2 and return index or -1 +// Clobbers: rscratch1, rscratch2, rflags. May also clobber v0-v1, when icnt1==-1. void MacroAssembler::string_indexof(Register str2, Register str1, Register cnt2, Register cnt1, Register tmp1, Register tmp2, @@ -5246,6 +5247,8 @@ address MacroAssembler::has_negatives(Register ary1, Register len, Register resu return pc(); } +// Clobbers: rscratch1, rscratch2, rflags +// May also clobber v0-v7 when (!UseSimpleArrayEquals && UseSIMDForArrayEquals) address MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3, Register tmp4, Register tmp5, Register result, Register cnt1, int elem_size) { @@ -5738,10 +5741,13 @@ void MacroAssembler::fill_words(Register base, Register cnt, Register value) // Intrinsic for sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray and // java/lang/StringUTF16.compress. +// +// Clobbers: src, dst, res, rscratch1, rscratch2, rflags void MacroAssembler::encode_iso_array(Register src, Register dst, - Register len, Register result, - FloatRegister Vtmp1, FloatRegister Vtmp2, - FloatRegister Vtmp3, FloatRegister Vtmp4) + Register len, Register result, + FloatRegister Vtmp1, FloatRegister Vtmp2, + FloatRegister Vtmp3, FloatRegister Vtmp4, + FloatRegister Vtmp5, FloatRegister Vtmp6) { Label DONE, SET_RESULT, NEXT_32, NEXT_32_PRFM, LOOP_8, NEXT_8, LOOP_1, NEXT_1, NEXT_32_START, NEXT_32_PRFM_START; @@ -5764,13 +5770,13 @@ void MacroAssembler::encode_iso_array(Register src, Register dst, ld1(Vtmp1, Vtmp2, Vtmp3, Vtmp4, T8H, src); BIND(NEXT_32_PRFM_START); prfm(Address(src, SoftwarePrefetchHintDistance)); - orr(v4, T16B, Vtmp1, Vtmp2); - orr(v5, T16B, Vtmp3, Vtmp4); + orr(Vtmp5, T16B, Vtmp1, Vtmp2); + orr(Vtmp6, T16B, Vtmp3, Vtmp4); uzp1(Vtmp1, T16B, Vtmp1, Vtmp2); uzp1(Vtmp3, T16B, Vtmp3, Vtmp4); - uzp2(v5, T16B, v4, v5); // high bytes - umov(tmp2, v5, D, 1); - fmovd(tmp1, v5); + uzp2(Vtmp6, T16B, Vtmp5, Vtmp6); // high bytes + umov(tmp2, Vtmp6, D, 1); + fmovd(tmp1, Vtmp6); orr(tmp1, tmp1, tmp2); cbnz(tmp1, LOOP_8); stpq(Vtmp1, Vtmp3, dst); @@ -5789,8 +5795,8 @@ void MacroAssembler::encode_iso_array(Register src, Register dst, ld1(Vtmp1, Vtmp2, Vtmp3, Vtmp4, T8H, src); } prfm(Address(src, SoftwarePrefetchHintDistance)); - uzp1(v4, T16B, Vtmp1, Vtmp2); - uzp1(v5, T16B, Vtmp3, Vtmp4); + uzp1(Vtmp5, T16B, Vtmp1, Vtmp2); + uzp1(Vtmp6, T16B, Vtmp3, Vtmp4); orr(Vtmp1, T16B, Vtmp1, Vtmp2); orr(Vtmp3, T16B, Vtmp3, Vtmp4); uzp2(Vtmp1, T16B, Vtmp1, Vtmp3); // high bytes @@ -5798,7 +5804,7 @@ void MacroAssembler::encode_iso_array(Register src, Register dst, fmovd(tmp1, Vtmp1); orr(tmp1, tmp1, tmp2); cbnz(tmp1, LOOP_8); - stpq(v4, v5, dst); + stpq(Vtmp5, Vtmp6, dst); sub(len, len, 32); add(dst, dst, 32); add(src, src, 64); @@ -5843,6 +5849,7 @@ void MacroAssembler::encode_iso_array(Register src, Register dst, // Inflate byte[] array to char[]. +// Clobbers: src, dst, len, rflags, rscratch1, v0-v6 address MacroAssembler::byte_array_inflate(Register src, Register dst, Register len, FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3, Register tmp4) { @@ -5951,9 +5958,10 @@ address MacroAssembler::byte_array_inflate(Register src, Register dst, Register void MacroAssembler::char_array_compress(Register src, Register dst, Register len, FloatRegister tmp1Reg, FloatRegister tmp2Reg, FloatRegister tmp3Reg, FloatRegister tmp4Reg, + FloatRegister tmp5Reg, FloatRegister tmp6Reg, Register result) { encode_iso_array(src, dst, len, result, - tmp1Reg, tmp2Reg, tmp3Reg, tmp4Reg); + tmp1Reg, tmp2Reg, tmp3Reg, tmp4Reg, tmp5Reg, tmp6Reg); cmp(len, zr); csel(result, result, zr, EQ); } diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index 2c8037678b3..fa2f6f2586e 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -1264,12 +1264,14 @@ class MacroAssembler: public Assembler { void char_array_compress(Register src, Register dst, Register len, FloatRegister tmp1Reg, FloatRegister tmp2Reg, FloatRegister tmp3Reg, FloatRegister tmp4Reg, + FloatRegister tmp5Reg, FloatRegister tmp6Reg, Register result); void encode_iso_array(Register src, Register dst, Register len, Register result, FloatRegister Vtmp1, FloatRegister Vtmp2, - FloatRegister Vtmp3, FloatRegister Vtmp4); + FloatRegister Vtmp3, FloatRegister Vtmp4, + FloatRegister Vtmp5, FloatRegister Vtmp6); void string_indexof(Register str1, Register str2, Register cnt1, Register cnt2, Register tmp1, Register tmp2, diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index a7227c81aae..05dd928511c 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -4145,6 +4145,7 @@ class StubGenerator: public StubCodeGenerator { // result = r0 - return value. Already contains "false" // cnt1 = r10 - amount of elements left to check, reduced by wordSize // r3-r5 are reserved temporary registers + // Clobbers: v0-v7 when UseSIMDForArrayEquals, rscratch1, rscratch2 address generate_large_array_equals() { Register a1 = r1, a2 = r2, result = r0, cnt1 = r10, tmp1 = rscratch1, tmp2 = rscratch2, tmp3 = r3, tmp4 = r4, tmp5 = r5, tmp6 = r11, @@ -4549,6 +4550,8 @@ class StubGenerator: public StubCodeGenerator { // R2 = cnt1 // R3 = str1 // R4 = cnt2 + // Clobbers: rscratch1, rscratch2, v0, v1, rflags + // // This generic linear code use few additional ideas, which makes it faster: // 1) we can safely keep at least 1st register of pattern(since length >= 8) // in order to skip initial loading(help in systems with 1 ld pipeline) @@ -4863,6 +4866,7 @@ class StubGenerator: public StubCodeGenerator { // R3 = len >> 3 // V0 = 0 // v1 = loaded 8 bytes + // Clobbers: r0, r1, r3, rscratch1, rflags, v0-v6 address generate_large_byte_array_inflate() { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", "large_byte_array_inflate"); diff --git a/src/hotspot/cpu/arm/frame_arm.cpp b/src/hotspot/cpu/arm/frame_arm.cpp index 7b3515eeb36..e59afff6dd9 100644 --- a/src/hotspot/cpu/arm/frame_arm.cpp +++ b/src/hotspot/cpu/arm/frame_arm.cpp @@ -497,7 +497,7 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { // first the method - Method* m = *interpreter_frame_method_addr(); + Method* m = safe_interpreter_frame_method(); // validate the method we'd find in this potential sender if (!Method::is_valid_method(m)) return false; diff --git a/src/hotspot/cpu/ppc/frame_ppc.cpp b/src/hotspot/cpu/ppc/frame_ppc.cpp index c9fc6f25686..149ffd17d25 100644 --- a/src/hotspot/cpu/ppc/frame_ppc.cpp +++ b/src/hotspot/cpu/ppc/frame_ppc.cpp @@ -302,7 +302,7 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { // first the method - Method* m = *interpreter_frame_method_addr(); + Method* m = safe_interpreter_frame_method(); // validate the method we'd find in this potential sender if (!Method::is_valid_method(m)) return false; diff --git a/src/hotspot/cpu/x86/frame_x86.cpp b/src/hotspot/cpu/x86/frame_x86.cpp index 34a1a73b4c7..479ee6f3f83 100644 --- a/src/hotspot/cpu/x86/frame_x86.cpp +++ b/src/hotspot/cpu/x86/frame_x86.cpp @@ -523,7 +523,7 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { // do some validation of frame elements // first the method - Method* m = *interpreter_frame_method_addr(); + Method* m = safe_interpreter_frame_method(); // validate the method we'd find in this potential sender if (!Method::is_valid_method(m)) return false; diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 888f80a2ad5..a4fe046e77f 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -836,6 +836,106 @@ static void *thread_native_entry(Thread *thread) { return 0; } +// On Linux, glibc places static TLS blocks (for __thread variables) on +// the thread stack. This decreases the stack size actually available +// to threads. +// +// For large static TLS sizes, this may cause threads to malfunction due +// to insufficient stack space. This is a well-known issue in glibc: +// http://sourceware.org/bugzilla/show_bug.cgi?id=11787. +// +// As a workaround, we call a private but assumed-stable glibc function, +// __pthread_get_minstack() to obtain the minstack size and derive the +// static TLS size from it. We then increase the user requested stack +// size by this TLS size. The same function is used to determine whether +// adjustStackSizeForGuardPages() needs to be true. +// +// Due to compatibility concerns, this size adjustment is opt-in and +// controlled via AdjustStackSizeForTLS. +typedef size_t (*GetMinStack)(const pthread_attr_t *attr); + +GetMinStack _get_minstack_func = NULL; // Initialized via os::init_2() + +// Returns the size of the static TLS area glibc puts on thread stacks. +// The value is cached on first use, which occurs when the first thread +// is created during VM initialization. +static size_t get_static_tls_area_size(const pthread_attr_t *attr) { + size_t tls_size = 0; + if (_get_minstack_func != NULL) { + // Obtain the pthread minstack size by calling __pthread_get_minstack. + size_t minstack_size = _get_minstack_func(attr); + + // Remove non-TLS area size included in minstack size returned + // by __pthread_get_minstack() to get the static TLS size. + // If adjustStackSizeForGuardPages() is true, minstack size includes + // guard_size. Otherwise guard_size is automatically added + // to the stack size by pthread_create and is no longer included + // in minstack size. In both cases, the guard_size is taken into + // account, so there is no need to adjust the result for that. + // + // Although __pthread_get_minstack() is a private glibc function, + // it is expected to have a stable behavior across future glibc + // versions while glibc still allocates the static TLS blocks off + // the stack. Following is glibc 2.28 __pthread_get_minstack(): + // + // size_t + // __pthread_get_minstack (const pthread_attr_t *attr) + // { + // return GLRO(dl_pagesize) + __static_tls_size + PTHREAD_STACK_MIN; + // } + // + // + // The following 'minstack_size > os::vm_page_size() + PTHREAD_STACK_MIN' + // if check is done for precaution. + if (minstack_size > (size_t)os::vm_page_size() + PTHREAD_STACK_MIN) { + tls_size = minstack_size - (size_t)os::vm_page_size() - PTHREAD_STACK_MIN; + } + } + + log_info(os, thread)("Stack size adjustment for TLS is " SIZE_FORMAT, + tls_size); + return tls_size; +} + +// In glibc versions prior to 2.27 the guard size mechanism +// was not implemented properly. The POSIX standard requires adding +// the size of the guard pages to the stack size, instead glibc +// took the space out of 'stacksize'. Thus we need to adapt the requested +// stack_size by the size of the guard pages to mimic proper behaviour. +// The fix in glibc 2.27 has now been backported to numerous earlier +// glibc versions so we need to do a dynamic runtime check. +static bool _adjustStackSizeForGuardPages = true; +bool os::Linux::adjustStackSizeForGuardPages() { + return _adjustStackSizeForGuardPages; +} + +// Dummy decl as substitute for cmdline parameter. TLS not in jdk11. +static const bool AdjustStackSizeForTLS = false; + +#if defined(__GLIBC__) +static void init_adjust_stacksize_for_guard_pages() { + assert(_get_minstack_func == NULL, "initialization error"); + _get_minstack_func =(GetMinStack)dlsym(RTLD_DEFAULT, "__pthread_get_minstack"); + log_info(os, thread)("Lookup of __pthread_get_minstack %s", + _get_minstack_func == NULL ? "failed" : "succeeded"); + + if (_get_minstack_func != NULL) { + pthread_attr_t attr; + pthread_attr_init(&attr); + size_t min_stack = _get_minstack_func(&attr); + size_t guard = 16 * K; // Actual value doesn't matter as it is not examined + pthread_attr_setguardsize(&attr, guard); + size_t min_stack2 = _get_minstack_func(&attr); + pthread_attr_destroy(&attr); + // If the minimum stack size changed when we added the guard page space + // then we need to perform the adjustment. + _adjustStackSizeForGuardPages = (min_stack2 != min_stack); + log_info(os)("Glibc stack size guard page adjustment is %sneeded", + _adjustStackSizeForGuardPages ? "" : "not "); + } +} +#endif // GLIBC + bool os::create_thread(Thread* thread, ThreadType thr_type, size_t req_stack_size) { assert(thread->osthread() == NULL, "caller responsible"); @@ -861,16 +961,24 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, // Calculate stack size if it's not specified by caller. size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size); - // In the Linux NPTL pthread implementation the guard size mechanism - // is not implemented properly. The posix standard requires adding - // the size of the guard pages to the stack size, instead Linux - // takes the space out of 'stacksize'. Thus we adapt the requested - // stack_size by the size of the guard pages to mimick proper - // behaviour. However, be careful not to end up with a size - // of zero due to overflow. Don't add the guard page in that case. size_t guard_size = os::Linux::default_guard_size(thr_type); - if (stack_size <= SIZE_MAX - guard_size) { - stack_size += guard_size; + // Configure glibc guard page. Must happen before calling + // get_static_tls_area_size(), which uses the guard_size. + pthread_attr_setguardsize(&attr, guard_size); + + // Apply stack size adjustments if needed. However, be careful not to end up + // with a size of zero due to overflow. Don't add the adjustment in that case. + size_t stack_adjust_size = 0; + if (AdjustStackSizeForTLS) { + // Adjust the stack_size for on-stack TLS - see get_static_tls_area_size(). + stack_adjust_size += get_static_tls_area_size(&attr); + } else if (os::Linux::adjustStackSizeForGuardPages()) { + stack_adjust_size += guard_size; + } + + stack_adjust_size = align_up(stack_adjust_size, os::vm_page_size()); + if (stack_size <= SIZE_MAX - stack_adjust_size) { + stack_size += stack_adjust_size; } assert(is_aligned(stack_size, os::vm_page_size()), "stack_size not aligned"); @@ -1016,8 +1124,10 @@ bool os::create_attached_thread(JavaThread* thread) { // and save the caller's signal mask os::Linux::hotspot_sigmask(thread); - log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", - os::current_thread_id(), (uintx) pthread_self()); + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT + ", stack: " PTR_FORMAT " - " PTR_FORMAT " (" SIZE_FORMAT "k) ).", + os::current_thread_id(), (uintx) pthread_self(), + p2i(thread->stack_base()), p2i(thread->stack_end()), thread->stack_size() / K); return true; } @@ -1432,7 +1542,7 @@ void os::Linux::fast_thread_clock_init() { // Note, that some kernels may support the current thread // clock (CLOCK_THREAD_CPUTIME_ID) but not the clocks // returned by the pthread_getcpuclockid(). - // If the fast Posix clocks are supported then the sys_clock_getres() + // If the fast POSIX clocks are supported then the clock_getres() // must return at least tp.tv_sec == 0 which means a resolution // better than 1 sec. This is extra check for reliability. @@ -5541,6 +5651,11 @@ jint os::init_2(void) { log_info(os)("HotSpot is running with %s, %s", Linux::libc_version(), Linux::libpthread_version()); +#ifdef __GLIBC__ + // Check if we need to adjust the stack size for glibc guard pages. + init_adjust_stacksize_for_guard_pages(); +#endif + if (UseNUMA) { if (!Linux::libnuma_init()) { UseNUMA = false; @@ -6469,9 +6584,9 @@ bool os::start_debugging(char *buf, int buflen) { // // ** P1 (aka bottom) and size (P2 = P1 - size) are the address and stack size // returned from pthread_attr_getstack(). -// ** Due to NPTL implementation error, linux takes the glibc guard page out -// of the stack size given in pthread_attr. We work around this for -// threads created by the VM. (We adapt bottom to be P1 and size accordingly.) +// ** If adjustStackSizeForGuardPages() is true the guard pages have been taken +// out of the stack size given in pthread_attr. We work around this for +// threads created by the VM. We adjust bottom to be P1 and size accordingly. // #ifndef ZERO static void current_stack_region(address * bottom, size_t * size) { @@ -6498,14 +6613,15 @@ static void current_stack_region(address * bottom, size_t * size) { fatal("Cannot locate current stack attributes!"); } - // Work around NPTL stack guard error. - size_t guard_size = 0; - rslt = pthread_attr_getguardsize(&attr, &guard_size); - if (rslt != 0) { - fatal("pthread_attr_getguardsize failed with error = %d", rslt); - } - *bottom += guard_size; - *size -= guard_size; + if (os::Linux::adjustStackSizeForGuardPages()) { + size_t guard_size = 0; + rslt = pthread_attr_getguardsize(&attr, &guard_size); + if (rslt != 0) { + fatal("pthread_attr_getguardsize failed with error = %d", rslt); + } + *bottom += guard_size; + *size -= guard_size; + } pthread_attr_destroy(&attr); diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp index f74611625cf..ed53c686dc5 100644 --- a/src/hotspot/os/linux/os_linux.hpp +++ b/src/hotspot/os/linux/os_linux.hpp @@ -198,6 +198,8 @@ class Linux { // Return default guard size for the specified thread type static size_t default_guard_size(os::ThreadType thr_type); + static bool adjustStackSizeForGuardPages(); // See comments in os_linux.cpp + static void capture_initial_stack(size_t max_size); // Stack overflow handling diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 53b5f742578..e8363fd617a 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -1436,8 +1436,8 @@ char* os::Posix::describe_pthread_attr(char* buf, size_t buflen, const pthread_a int detachstate = 0; pthread_attr_getstacksize(attr, &stack_size); pthread_attr_getguardsize(attr, &guard_size); - // Work around linux NPTL implementation error, see also os::create_thread() in os_linux.cpp. - LINUX_ONLY(stack_size -= guard_size); + // Work around glibc stack guard issue, see os::create_thread() in os_linux.cpp. + LINUX_ONLY(if (os::Linux::adjustStackSizeForGuardPages()) stack_size -= guard_size;) pthread_attr_getdetachstate(attr, &detachstate); jio_snprintf(buf, buflen, "stacksize: " SIZE_FORMAT "k, guardsize: " SIZE_FORMAT "k, %s", stack_size / 1024, guard_size / 1024, diff --git a/src/hotspot/share/c1/c1_LinearScan.cpp b/src/hotspot/share/c1/c1_LinearScan.cpp index cc0bc9deabb..ef5a01003eb 100644 --- a/src/hotspot/share/c1/c1_LinearScan.cpp +++ b/src/hotspot/share/c1/c1_LinearScan.cpp @@ -1947,6 +1947,14 @@ void LinearScan::resolve_exception_edge(XHandler* handler, int throwing_op_id, i // interval at the throwing instruction must be searched using the operands // of the phi function Value from_value = phi->operand_at(handler->phi_operand()); + if (from_value == NULL) { + // We have reached here in a kotlin application running with JVMTI + // capability "can_access_local_variables". + // The illegal state is not yet propagated to this phi. Do it here. + phi->make_illegal(); + // We can skip the illegal phi edge. + return; + } // with phi functions it can happen that the same from_value is used in // multiple mappings, so notify move-resolver that this is allowed diff --git a/src/hotspot/share/classfile/altHashing.cpp b/src/hotspot/share/classfile/altHashing.cpp index 25d2728b445..253266c16f1 100644 --- a/src/hotspot/share/classfile/altHashing.cpp +++ b/src/hotspot/share/classfile/altHashing.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,9 +31,7 @@ /* SipHash reference C implementation - Copyright (c) 2012-2021 Jean-Philippe Aumasson - - Copyright (c) 2012-2014 Daniel J. Bernstein + Copyright (c) 2016 Jean-Philippe Aumasson To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain diff --git a/src/hotspot/share/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp index d842cbd5f72..9b6b01bd78f 100644 --- a/src/hotspot/share/classfile/dictionary.cpp +++ b/src/hotspot/share/classfile/dictionary.cpp @@ -207,6 +207,7 @@ void DictionaryEntry::add_protection_domain(Dictionary* dict, Handle protection_ if (lt.is_enabled()) { LogStream ls(lt); print_count(&ls); + ls.cr(); } } diff --git a/src/hotspot/share/classfile/dictionary.hpp b/src/hotspot/share/classfile/dictionary.hpp index a3e251424f7..1beb28f91dd 100644 --- a/src/hotspot/share/classfile/dictionary.hpp +++ b/src/hotspot/share/classfile/dictionary.hpp @@ -195,7 +195,7 @@ class DictionaryEntry : public HashtableEntry { current = current->_next) { count++; } - st->print_cr("pd set count = #%d", count); + st->print("pd set count = #%d", count); } void verify(); diff --git a/src/hotspot/share/classfile/loaderConstraints.cpp b/src/hotspot/share/classfile/loaderConstraints.cpp index 7cccf23efb7..b7d339dd222 100644 --- a/src/hotspot/share/classfile/loaderConstraints.cpp +++ b/src/hotspot/share/classfile/loaderConstraints.cpp @@ -189,6 +189,7 @@ void log_ldr_constraint_msg(Symbol* class_name, const char* reason, bool LoaderConstraintTable::add_entry(Symbol* class_name, InstanceKlass* klass1, Handle class_loader1, InstanceKlass* klass2, Handle class_loader2) { + LogTarget(Info, class, loader, constraints) lt; if (klass1 != NULL && klass2 != NULL) { if (klass1 == klass2) { @@ -242,9 +243,8 @@ bool LoaderConstraintTable::add_entry(Symbol* class_name, p->set_loaders(NEW_C_HEAP_ARRAY(ClassLoaderData*, 2, mtClass)); p->set_loader(0, class_loader1()); p->set_loader(1, class_loader2()); - p->set_klass(klass); - p->set_next(bucket(index)); - set_entry(index, p); + Hashtable::add_entry(index, p); + if (lt.is_enabled()) { ResourceMark rm; lt.print("adding new constraint for name: %s, loader[0]: %s," @@ -478,13 +478,15 @@ void LoaderConstraintTable::print_on(outputStream* st) const { probe != NULL; probe = probe->next()) { st->print("%4d: ", cindex); - probe->name()->print_on(st); - st->print(" , loaders:"); + st->print("Symbol: %s loaders:", probe->name()->as_C_string()); for (int n = 0; n < probe->num_loaders(); n++) { + st->cr(); + st->print(" "); probe->loader_data(n)->print_value_on(st); - st->print(", "); } st->cr(); } } } + +void LoaderConstraintTable::print() const { print_on(tty); } diff --git a/src/hotspot/share/classfile/loaderConstraints.hpp b/src/hotspot/share/classfile/loaderConstraints.hpp index 8a7a1248e62..8d706a8b0e9 100644 --- a/src/hotspot/share/classfile/loaderConstraints.hpp +++ b/src/hotspot/share/classfile/loaderConstraints.hpp @@ -79,6 +79,7 @@ class LoaderConstraintTable : public Hashtable { void purge_loader_constraints(); void verify(PlaceholderTable* placeholders); + void print() const; void print_on(outputStream* st) const; }; diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp index d6e1a2aa71d..1fc41b183a5 100644 --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp @@ -5837,6 +5837,9 @@ void CMSMarkStack::expand() { if (!_virtual_space.initialize(rs, rs.size())) { fatal("Not enough swap for expanded marking stack"); } + // Record NMT memory type + MemTracker::record_virtual_memory_type(rs.base(), mtGC); + _base = (oop*)(_virtual_space.low()); _index = 0; _capacity = new_capacity; diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp index 7b94f6fb888..a987c1ad8d4 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp @@ -506,6 +506,7 @@ uintx StringDedupTable::unlink_or_oops_do(StringDedupUnlinkOrOopsDoClosure* cl, while (*entry != NULL) { oop* p = (oop*)(*entry)->obj_addr(); if (cl->is_alive(*p)) { + typeArrayOop value = (typeArrayOop)*p; cl->keep_alive(p); if (is_resizing()) { // We are resizing the table, transfer entry to the new table @@ -517,7 +518,6 @@ uintx StringDedupTable::unlink_or_oops_do(StringDedupUnlinkOrOopsDoClosure* cl, // at this point since we don't have exclusive access to all // destination partitions. finish_rehash() will do a single // threaded transfer of all entries. - typeArrayOop value = (typeArrayOop)*p; bool latin1 = (*entry)->latin1(); unsigned int hash = hash_code(value, latin1); (*entry)->set_hash(hash); diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index 6df6ad24425..493697f2310 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -897,24 +897,17 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte CallInfo info; constantPoolHandle pool(thread, last_frame.method()->constants()); + methodHandle resolved_method; + { JvmtiHideSingleStepping jhss(thread); LinkResolver::resolve_invoke(info, receiver, pool, last_frame.get_index_u2_cpcache(bytecode), bytecode, CHECK); - if (JvmtiExport::can_hotswap_or_post_breakpoint()) { - int retry_count = 0; - while (info.resolved_method()->is_old()) { - // It is very unlikely that method is redefined more than 100 times - // in the middle of resolve. If it is looping here more than 100 times - // means then there could be a bug here. - guarantee((retry_count++ < 100), - "Could not resolve to latest version of redefined method"); - // method is redefined in the middle of resolve so re-try. - LinkResolver::resolve_invoke(info, receiver, pool, - last_frame.get_index_u2_cpcache(bytecode), bytecode, - CHECK); - } + if (JvmtiExport::can_hotswap_or_post_breakpoint() && info.resolved_method()->is_old()) { + resolved_method = methodHandle(thread, info.resolved_method()->get_new_method()); + } else { + resolved_method = info.resolved_method(); } } // end JvmtiHideSingleStepping @@ -924,22 +917,20 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte #ifdef ASSERT if (bytecode == Bytecodes::_invokeinterface) { - if (info.resolved_method()->method_holder() == - SystemDictionary::Object_klass()) { + if (resolved_method->method_holder() == SystemDictionary::Object_klass()) { // NOTE: THIS IS A FIX FOR A CORNER CASE in the JVM spec // (see also CallInfo::set_interface for details) assert(info.call_kind() == CallInfo::vtable_call || info.call_kind() == CallInfo::direct_call, ""); - methodHandle rm = info.resolved_method(); - assert(rm->is_final() || info.has_vtable_index(), + assert(resolved_method->is_final() || info.has_vtable_index(), "should have been set already"); - } else if (!info.resolved_method()->has_itable_index()) { + } else if (!resolved_method->has_itable_index()) { // Resolved something like CharSequence.toString. Use vtable not itable. assert(info.call_kind() != CallInfo::itable_call, ""); } else { // Setup itable entry assert(info.call_kind() == CallInfo::itable_call, ""); - int index = info.resolved_method()->itable_index(); + int index = resolved_method->itable_index(); assert(info.itable_index() == index, ""); } } else if (bytecode == Bytecodes::_invokespecial) { @@ -959,20 +950,20 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte case CallInfo::direct_call: cp_cache_entry->set_direct_call( bytecode, - info.resolved_method(), + resolved_method, sender->is_interface()); break; case CallInfo::vtable_call: cp_cache_entry->set_vtable_call( bytecode, - info.resolved_method(), + resolved_method, info.vtable_index()); break; case CallInfo::itable_call: cp_cache_entry->set_itable_call( bytecode, info.resolved_klass(), - info.resolved_method(), + resolved_method, info.itable_index()); break; default: ShouldNotReachHere(); diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index e484bb85eaf..c4d59765686 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -758,6 +758,7 @@ void MetaspaceUtils::print_report(outputStream* out, size_t scale, int flags) { out->print_cr(" Non-Class:"); } Metaspace::space_list()->print_on(out, scale); + out->cr(); if (Metaspace::using_class_space()) { out->print_cr(" Class:"); Metaspace::class_space_list()->print_on(out, scale); diff --git a/src/hotspot/share/memory/metaspaceShared.cpp b/src/hotspot/share/memory/metaspaceShared.cpp index fe7a98fc334..9212cd53a7f 100644 --- a/src/hotspot/share/memory/metaspaceShared.cpp +++ b/src/hotspot/share/memory/metaspaceShared.cpp @@ -1401,12 +1401,6 @@ void VM_PopulateDumpSharedSpace::doit() { FileMapInfo::check_nonempty_dir_in_shared_path_table(); NOT_PRODUCT(SystemDictionary::verify();) - // The following guarantee is meant to ensure that no loader constraints - // exist yet, since the constraints table is not shared. This becomes - // more important now that we don't re-initialize vtables/itables for - // shared classes at runtime, where constraints were previously created. - guarantee(SystemDictionary::constraints()->number_of_entries() == 0, - "loader constraints are not saved"); guarantee(SystemDictionary::placeholders()->number_of_entries() == 0, "placeholders are not saved"); // Revisit and implement this if we prelink method handle call sites: diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index 88f4ab076aa..cc018c2ee77 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -25,7 +25,7 @@ #include "precompiled.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/dictionary.hpp" -#include "classfile/javaClasses.hpp" +#include "classfile/javaClasses.inline.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "gc/shared/collectedHeap.inline.hpp" @@ -738,7 +738,7 @@ void Klass::verify_on(outputStream* st) { } if (java_mirror_no_keepalive() != NULL) { - guarantee(oopDesc::is_oop(java_mirror_no_keepalive()), "should be instance"); + guarantee(java_lang_Class::is_instance(java_mirror_no_keepalive()), "should be instance"); } } diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index 91e13651f31..c67be65fdae 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -274,9 +274,8 @@ class Klass : public Metadata { // Both mirrors are on the ClassLoaderData::_handles list already so no // barriers are needed. void set_java_mirror_handle(OopHandle mirror) { _java_mirror = mirror; } - OopHandle java_mirror_handle() const { - return _java_mirror; - } + OopHandle java_mirror_handle() const { return _java_mirror; } + void swap_java_mirror_handle(OopHandle& mirror) { _java_mirror.swap(mirror); } // modifier flags jint modifier_flags() const { return _modifier_flags; } diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp index da8468dead4..63c656f52f4 100644 --- a/src/hotspot/share/oops/method.hpp +++ b/src/hotspot/share/oops/method.hpp @@ -984,6 +984,15 @@ class Method : public Metadata { // Deallocation function for redefine classes or if an error occurs void deallocate_contents(ClassLoaderData* loader_data); + Method* get_new_method() const { + InstanceKlass* holder = method_holder(); + Method* new_method = holder->method_with_idnum(orig_method_idnum()); + + assert(new_method != NULL, "method_with_idnum() should not be null"); + assert(this != new_method, "sanity check"); + return new_method; + } + // Printing #ifndef PRODUCT void print_on(outputStream* st) const; diff --git a/src/hotspot/share/oops/oopHandle.hpp b/src/hotspot/share/oops/oopHandle.hpp index e822d3710c9..1b7dea9413c 100644 --- a/src/hotspot/share/oops/oopHandle.hpp +++ b/src/hotspot/share/oops/oopHandle.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, 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 @@ -43,6 +43,10 @@ class OopHandle { OopHandle() : _obj(NULL) {} OopHandle(oop* w) : _obj(w) {} + void swap(OopHandle& copy) { + ::swap(_obj, copy._obj); + } + inline oop resolve() const; inline oop peek() const; diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index c7a71aa95cb..e76812892e5 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -57,6 +57,296 @@ #include "utilities/macros.hpp" +<<<<<<< HEAD +======= +class LibraryIntrinsic : public InlineCallGenerator { + // Extend the set of intrinsics known to the runtime: + public: + private: + bool _is_virtual; + bool _does_virtual_dispatch; + int8_t _predicates_count; // Intrinsic is predicated by several conditions + int8_t _last_predicate; // Last generated predicate + vmIntrinsics::ID _intrinsic_id; + + public: + LibraryIntrinsic(ciMethod* m, bool is_virtual, int predicates_count, bool does_virtual_dispatch, vmIntrinsics::ID id) + : InlineCallGenerator(m), + _is_virtual(is_virtual), + _does_virtual_dispatch(does_virtual_dispatch), + _predicates_count((int8_t)predicates_count), + _last_predicate((int8_t)-1), + _intrinsic_id(id) + { + } + virtual bool is_intrinsic() const { return true; } + virtual bool is_virtual() const { return _is_virtual; } + virtual bool is_predicated() const { return _predicates_count > 0; } + virtual int predicates_count() const { return _predicates_count; } + virtual bool does_virtual_dispatch() const { return _does_virtual_dispatch; } + virtual JVMState* generate(JVMState* jvms); + virtual Node* generate_predicate(JVMState* jvms, int predicate); + vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; } +}; + + +// Local helper class for LibraryIntrinsic: +class LibraryCallKit : public GraphKit { + private: + LibraryIntrinsic* _intrinsic; // the library intrinsic being called + Node* _result; // the result node, if any + int _reexecute_sp; // the stack pointer when bytecode needs to be reexecuted + + const TypeOopPtr* sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type); + + public: + LibraryCallKit(JVMState* jvms, LibraryIntrinsic* intrinsic) + : GraphKit(jvms), + _intrinsic(intrinsic), + _result(NULL) + { + // Check if this is a root compile. In that case we don't have a caller. + if (!jvms->has_method()) { + _reexecute_sp = sp(); + } else { + // Find out how many arguments the interpreter needs when deoptimizing + // and save the stack pointer value so it can used by uncommon_trap. + // We find the argument count by looking at the declared signature. + bool ignored_will_link; + ciSignature* declared_signature = NULL; + ciMethod* ignored_callee = caller()->get_method_at_bci(bci(), ignored_will_link, &declared_signature); + const int nargs = declared_signature->arg_size_for_bc(caller()->java_code_at_bci(bci())); + _reexecute_sp = sp() + nargs; // "push" arguments back on stack + } + } + + virtual LibraryCallKit* is_LibraryCallKit() const { return (LibraryCallKit*)this; } + + ciMethod* caller() const { return jvms()->method(); } + int bci() const { return jvms()->bci(); } + LibraryIntrinsic* intrinsic() const { return _intrinsic; } + vmIntrinsics::ID intrinsic_id() const { return _intrinsic->intrinsic_id(); } + ciMethod* callee() const { return _intrinsic->method(); } + + bool try_to_inline(int predicate); + Node* try_to_predicate(int predicate); + + void push_result() { + // Push the result onto the stack. + if (!stopped() && result() != NULL) { + BasicType bt = result()->bottom_type()->basic_type(); + push_node(bt, result()); + } + } + + private: + void fatal_unexpected_iid(vmIntrinsics::ID iid) { + fatal("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)); + } + + void set_result(Node* n) { assert(_result == NULL, "only set once"); _result = n; } + void set_result(RegionNode* region, PhiNode* value); + Node* result() { return _result; } + + virtual int reexecute_sp() { return _reexecute_sp; } + + // Helper functions to inline natives + Node* generate_guard(Node* test, RegionNode* region, float true_prob); + Node* generate_slow_guard(Node* test, RegionNode* region); + Node* generate_fair_guard(Node* test, RegionNode* region); + Node* generate_negative_guard(Node* index, RegionNode* region, + // resulting CastII of index: + Node* *pos_index = NULL); + Node* generate_limit_guard(Node* offset, Node* subseq_length, + Node* array_length, + RegionNode* region); + void generate_string_range_check(Node* array, Node* offset, + Node* length, bool char_count); + Node* generate_current_thread(Node* &tls_output); + Node* load_mirror_from_klass(Node* klass); + Node* load_klass_from_mirror_common(Node* mirror, bool never_see_null, + RegionNode* region, int null_path, + int offset); + Node* load_klass_from_mirror(Node* mirror, bool never_see_null, + RegionNode* region, int null_path) { + int offset = java_lang_Class::klass_offset_in_bytes(); + return load_klass_from_mirror_common(mirror, never_see_null, + region, null_path, + offset); + } + Node* load_array_klass_from_mirror(Node* mirror, bool never_see_null, + RegionNode* region, int null_path) { + int offset = java_lang_Class::array_klass_offset_in_bytes(); + return load_klass_from_mirror_common(mirror, never_see_null, + region, null_path, + offset); + } + Node* generate_access_flags_guard(Node* kls, + int modifier_mask, int modifier_bits, + RegionNode* region); + Node* generate_interface_guard(Node* kls, RegionNode* region); + Node* generate_array_guard(Node* kls, RegionNode* region) { + return generate_array_guard_common(kls, region, false, false); + } + Node* generate_non_array_guard(Node* kls, RegionNode* region) { + return generate_array_guard_common(kls, region, false, true); + } + Node* generate_objArray_guard(Node* kls, RegionNode* region) { + return generate_array_guard_common(kls, region, true, false); + } + Node* generate_non_objArray_guard(Node* kls, RegionNode* region) { + return generate_array_guard_common(kls, region, true, true); + } + Node* generate_array_guard_common(Node* kls, RegionNode* region, + bool obj_array, bool not_array); + Node* generate_virtual_guard(Node* obj_klass, RegionNode* slow_region); + CallJavaNode* generate_method_call(vmIntrinsics::ID method_id, + bool is_virtual = false, bool is_static = false); + CallJavaNode* generate_method_call_static(vmIntrinsics::ID method_id) { + return generate_method_call(method_id, false, true); + } + CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) { + return generate_method_call(method_id, true, false); + } + Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static, ciInstanceKlass * fromKls); + Node * field_address_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static, ciInstanceKlass * fromKls); + + Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2, StrIntrinsicNode::ArgEnc ae); + bool inline_string_compareTo(StrIntrinsicNode::ArgEnc ae); + bool inline_string_indexOf(StrIntrinsicNode::ArgEnc ae); + bool inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae); + Node* make_indexOf_node(Node* src_start, Node* src_count, Node* tgt_start, Node* tgt_count, + RegionNode* region, Node* phi, StrIntrinsicNode::ArgEnc ae); + bool inline_string_indexOfChar(); + bool inline_string_equals(StrIntrinsicNode::ArgEnc ae); + bool inline_string_toBytesU(); + bool inline_string_getCharsU(); + bool inline_string_copy(bool compress); + bool inline_string_char_access(bool is_store); + Node* round_double_node(Node* n); + bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName); + bool inline_math_native(vmIntrinsics::ID id); + bool inline_math(vmIntrinsics::ID id); + bool inline_double_math(vmIntrinsics::ID id); + template + bool inline_math_overflow(Node* arg1, Node* arg2); + void inline_math_mathExact(Node* math, Node* test); + bool inline_math_addExactI(bool is_increment); + bool inline_math_addExactL(bool is_increment); + bool inline_math_multiplyExactI(); + bool inline_math_multiplyExactL(); + bool inline_math_multiplyHigh(); + bool inline_math_negateExactI(); + bool inline_math_negateExactL(); + bool inline_math_subtractExactI(bool is_decrement); + bool inline_math_subtractExactL(bool is_decrement); + bool inline_min_max(vmIntrinsics::ID id); + bool inline_notify(vmIntrinsics::ID id); + Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y); + // This returns Type::AnyPtr, RawPtr, or OopPtr. + int classify_unsafe_addr(Node* &base, Node* &offset, BasicType type); + Node* make_unsafe_address(Node*& base, Node* offset, BasicType type = T_ILLEGAL, bool can_cast = false); + + typedef enum { Relaxed, Opaque, Volatile, Acquire, Release } AccessKind; + DecoratorSet mo_decorator_for_access_kind(AccessKind kind); + bool inline_unsafe_access(bool is_store, BasicType type, AccessKind kind, bool is_unaligned); + static bool klass_needs_init_guard(Node* kls); + bool inline_unsafe_allocate(); + bool inline_unsafe_newArray(bool uninitialized); + bool inline_unsafe_copyMemory(); + bool inline_native_currentThread(); + + bool inline_native_time_funcs(address method, const char* funcName); +#ifdef JFR_HAVE_INTRINSICS + bool inline_native_classID(); + bool inline_native_getEventWriter(); +#endif + bool inline_native_isInterrupted(); + bool inline_native_Class_query(vmIntrinsics::ID id); + bool inline_native_subtype_check(); + bool inline_native_getLength(); + bool inline_array_copyOf(bool is_copyOfRange); + bool inline_array_equals(StrIntrinsicNode::ArgEnc ae); + bool inline_preconditions_checkIndex(); + void copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array); + bool inline_native_clone(bool is_virtual); + bool inline_native_Reflection_getCallerClass(); + // Helper function for inlining native object hash method + bool inline_native_hashcode(bool is_virtual, bool is_static); + bool inline_native_getClass(); + + // Helper functions for inlining arraycopy + bool inline_arraycopy(); + AllocateArrayNode* tightly_coupled_allocation(Node* ptr, + RegionNode* slow_region); + static CallStaticJavaNode* get_uncommon_trap_from_success_proj(Node* node); + SafePointNode* create_safepoint_with_state_before_array_allocation(const AllocateArrayNode* alloc) const; + void replace_unrelated_uncommon_traps_with_alloc_state(AllocateArrayNode* alloc, JVMState* saved_jvms_before_guards); + void replace_unrelated_uncommon_traps_with_alloc_state(JVMState* saved_jvms_before_guards); + void create_new_uncommon_trap(CallStaticJavaNode* uncommon_trap_call); + JVMState* arraycopy_restore_alloc_state(AllocateArrayNode* alloc, int& saved_reexecute_sp); + void arraycopy_move_allocation_here(AllocateArrayNode* alloc, Node* dest, JVMState* saved_jvms_before_guards, int saved_reexecute_sp, + uint new_idx); + + typedef enum { LS_get_add, LS_get_set, LS_cmp_swap, LS_cmp_swap_weak, LS_cmp_exchange } LoadStoreKind; + bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind, AccessKind access_kind); + bool inline_unsafe_fence(vmIntrinsics::ID id); + bool inline_onspinwait(); + bool inline_fp_conversions(vmIntrinsics::ID id); + bool inline_number_methods(vmIntrinsics::ID id); + bool inline_reference_get(); + bool inline_Class_cast(); + bool inline_aescrypt_Block(vmIntrinsics::ID id); + bool inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id); + bool inline_electronicCodeBook_AESCrypt(vmIntrinsics::ID id); + bool inline_counterMode_AESCrypt(vmIntrinsics::ID id); + Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting); + Node* inline_electronicCodeBook_AESCrypt_predicate(bool decrypting); + Node* inline_counterMode_AESCrypt_predicate(); + Node* get_key_start_from_aescrypt_object(Node* aescrypt_object); + Node* get_original_key_start_from_aescrypt_object(Node* aescrypt_object); + bool inline_ghash_processBlocks(); + bool inline_base64_encodeBlock(); + bool inline_sha_implCompress(vmIntrinsics::ID id); + bool inline_digestBase_implCompressMB(int predicate); + bool inline_sha_implCompressMB(Node* digestBaseObj, ciInstanceKlass* instklass_SHA, + bool long_state, address stubAddr, const char *stubName, + Node* src_start, Node* ofs, Node* limit); + Node* get_state_from_sha_object(Node *sha_object); + Node* get_state_from_sha5_object(Node *sha_object); + Node* inline_digestBase_implCompressMB_predicate(int predicate); + bool inline_encodeISOArray(); + bool inline_updateCRC32(); + bool inline_updateBytesCRC32(); + bool inline_updateByteBufferCRC32(); + Node* get_table_from_crc32c_class(ciInstanceKlass *crc32c_class); + bool inline_updateBytesCRC32C(); + bool inline_updateDirectByteBufferCRC32C(); + bool inline_updateBytesAdler32(); + bool inline_updateByteBufferAdler32(); + bool inline_multiplyToLen(); + bool inline_hasNegatives(); + bool inline_squareToLen(); + bool inline_mulAdd(); + bool inline_montgomeryMultiply(); + bool inline_montgomerySquare(); + bool inline_vectorizedMismatch(); + bool inline_fma(vmIntrinsics::ID id); + bool inline_character_compare(vmIntrinsics::ID id); + bool inline_fp_min_max(vmIntrinsics::ID id); + + bool inline_profileBoolean(); + bool inline_isCompileConstant(); + void clear_upper_avx() { +#ifdef X86 + if (UseAVX >= 2) { + C->set_clear_upper_avx(true); + } +#endif + } +}; + +>>>>>>> dragonwell_extended_upstream/master //---------------------------make_vm_intrinsic---------------------------- CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { vmIntrinsics::ID id = m->intrinsic_id(); @@ -1183,7 +1473,7 @@ bool LibraryCallKit::inline_string_indexOfChar() { } assert(callee()->signature()->size() == 4, "String.indexOfChar() has 4 arguments"); Node* src = argument(0); // byte[] - Node* tgt = argument(1); // tgt is int ch + Node* int_ch = argument(1); Node* from_index = argument(2); Node* max = argument(3); @@ -1195,6 +1485,15 @@ bool LibraryCallKit::inline_string_indexOfChar() { // Range checks generate_string_range_check(src, src_offset, src_count, true); + + // Check for int_ch >= 0 + Node* int_ch_cmp = _gvn.transform(new CmpINode(int_ch, intcon(0))); + Node* int_ch_bol = _gvn.transform(new BoolNode(int_ch_cmp, BoolTest::ge)); + { + BuildCutout unless(this, int_ch_bol, PROB_MAX); + uncommon_trap(Deoptimization::Reason_intrinsic, + Deoptimization::Action_maybe_recompile); + } if (stopped()) { return true; } @@ -1202,7 +1501,7 @@ bool LibraryCallKit::inline_string_indexOfChar() { RegionNode* region = new RegionNode(3); Node* phi = new PhiNode(region, TypeInt::INT); - Node* result = new StrIndexOfCharNode(control(), memory(TypeAryPtr::BYTES), src_start, src_count, tgt, StrIntrinsicNode::none); + Node* result = new StrIndexOfCharNode(control(), memory(TypeAryPtr::BYTES), src_start, src_count, int_ch, StrIntrinsicNode::none); C->set_has_split_ifs(true); // Has chance for split-if optimization _gvn.transform(result); @@ -4289,24 +4588,7 @@ JVMState* LibraryCallKit::arraycopy_restore_alloc_state(AllocateArrayNode* alloc } if (no_interfering_store) { - JVMState* old_jvms = alloc->jvms()->clone_shallow(C); - uint size = alloc->req(); - SafePointNode* sfpt = new SafePointNode(size, old_jvms); - old_jvms->set_map(sfpt); - for (uint i = 0; i < size; i++) { - sfpt->init_req(i, alloc->in(i)); - } - // re-push array length for deoptimization - sfpt->ins_req(old_jvms->stkoff() + old_jvms->sp(), alloc->in(AllocateNode::ALength)); - old_jvms->set_sp(old_jvms->sp()+1); - old_jvms->set_monoff(old_jvms->monoff()+1); - old_jvms->set_scloff(old_jvms->scloff()+1); - old_jvms->set_endoff(old_jvms->endoff()+1); - old_jvms->set_should_reexecute(true); - - sfpt->set_i_o(map()->i_o()); - sfpt->set_memory(map()->memory()); - sfpt->set_control(map()->control()); + SafePointNode* sfpt = create_safepoint_with_state_before_array_allocation(alloc); JVMState* saved_jvms = jvms(); saved_reexecute_sp = _reexecute_sp; @@ -4321,6 +4603,30 @@ JVMState* LibraryCallKit::arraycopy_restore_alloc_state(AllocateArrayNode* alloc return NULL; } +// Clone the JVMState of the array allocation and create a new safepoint with it. Re-push the array length to the stack +// such that uncommon traps can be emitted to re-execute the array allocation in the interpreter. +SafePointNode* LibraryCallKit::create_safepoint_with_state_before_array_allocation(const AllocateArrayNode* alloc) const { + JVMState* old_jvms = alloc->jvms()->clone_shallow(C); + uint size = alloc->req(); + SafePointNode* sfpt = new SafePointNode(size, old_jvms); + old_jvms->set_map(sfpt); + for (uint i = 0; i < size; i++) { + sfpt->init_req(i, alloc->in(i)); + } + // re-push array length for deoptimization + sfpt->ins_req(old_jvms->stkoff() + old_jvms->sp(), alloc->in(AllocateNode::ALength)); + old_jvms->set_sp(old_jvms->sp()+1); + old_jvms->set_monoff(old_jvms->monoff()+1); + old_jvms->set_scloff(old_jvms->scloff()+1); + old_jvms->set_endoff(old_jvms->endoff()+1); + old_jvms->set_should_reexecute(true); + + sfpt->set_i_o(map()->i_o()); + sfpt->set_memory(map()->memory()); + sfpt->set_control(map()->control()); + return sfpt; +} + // In case of a deoptimization, we restart execution at the // allocation, allocating a new array. We would leave an uninitialized // array in the heap that GCs wouldn't expect. Move the allocation @@ -4328,18 +4634,20 @@ JVMState* LibraryCallKit::arraycopy_restore_alloc_state(AllocateArrayNode* alloc // deoptimize. This is possible because tightly_coupled_allocation() // guarantees there's no observer of the allocated array at this point // and the control flow is simple enough. -void LibraryCallKit::arraycopy_move_allocation_here(AllocateArrayNode* alloc, Node* dest, JVMState* saved_jvms, +void LibraryCallKit::arraycopy_move_allocation_here(AllocateArrayNode* alloc, Node* dest, JVMState* saved_jvms_before_guards, int saved_reexecute_sp, uint new_idx) { - if (saved_jvms != NULL && !stopped()) { + if (saved_jvms_before_guards != NULL && !stopped()) { + replace_unrelated_uncommon_traps_with_alloc_state(alloc, saved_jvms_before_guards); + assert(alloc != NULL, "only with a tightly coupled allocation"); // restore JVM state to the state at the arraycopy - saved_jvms->map()->set_control(map()->control()); - assert(saved_jvms->map()->memory() == map()->memory(), "memory state changed?"); - assert(saved_jvms->map()->i_o() == map()->i_o(), "IO state changed?"); + saved_jvms_before_guards->map()->set_control(map()->control()); + assert(saved_jvms_before_guards->map()->memory() == map()->memory(), "memory state changed?"); + assert(saved_jvms_before_guards->map()->i_o() == map()->i_o(), "IO state changed?"); // If we've improved the types of some nodes (null check) while // emitting the guards, propagate them to the current state - map()->replaced_nodes().apply(saved_jvms->map(), new_idx); - set_jvms(saved_jvms); + map()->replaced_nodes().apply(saved_jvms_before_guards->map(), new_idx); + set_jvms(saved_jvms_before_guards); _reexecute_sp = saved_reexecute_sp; // Remove the allocation from above the guards @@ -4415,6 +4723,58 @@ void LibraryCallKit::arraycopy_move_allocation_here(AllocateArrayNode* alloc, No } } +// Unrelated UCTs between the array allocation and the array copy, which are considered safe by tightly_coupled_allocation(), +// need to be replaced by an UCT with a state before the array allocation (including the array length). This is necessary +// because we could hit one of these UCTs (which are executed before the emitted array copy guards and the actual array +// allocation which is moved down in arraycopy_move_allocation_here()). When later resuming execution in the interpreter, +// we would have wrongly skipped the array allocation. To prevent this, we resume execution at the array allocation in +// the interpreter similar to what we are doing for the newly emitted guards for the array copy. +void LibraryCallKit::replace_unrelated_uncommon_traps_with_alloc_state(AllocateArrayNode* alloc, + JVMState* saved_jvms_before_guards) { + if (saved_jvms_before_guards->map()->control()->is_IfProj()) { + // There is at least one unrelated uncommon trap which needs to be replaced. + SafePointNode* sfpt = create_safepoint_with_state_before_array_allocation(alloc); + + JVMState* saved_jvms = jvms(); + const int saved_reexecute_sp = _reexecute_sp; + set_jvms(sfpt->jvms()); + _reexecute_sp = jvms()->sp(); + + replace_unrelated_uncommon_traps_with_alloc_state(saved_jvms_before_guards); + + // Restore state + set_jvms(saved_jvms); + _reexecute_sp = saved_reexecute_sp; + } +} + +// Replace the unrelated uncommon traps with new uncommon trap nodes by reusing the action and reason. The new uncommon +// traps will have the state of the array allocation. Let the old uncommon trap nodes die. +void LibraryCallKit::replace_unrelated_uncommon_traps_with_alloc_state(JVMState* saved_jvms_before_guards) { + Node* if_proj = saved_jvms_before_guards->map()->control(); // Start the search right before the newly emitted guards + while (if_proj->is_IfProj()) { + CallStaticJavaNode* uncommon_trap = get_uncommon_trap_from_success_proj(if_proj); + if (uncommon_trap != NULL) { + create_new_uncommon_trap(uncommon_trap); + } + assert(if_proj->in(0)->is_If(), "must be If"); + if_proj = if_proj->in(0)->in(0); + } + assert(if_proj->is_Proj() && if_proj->in(0)->is_Initialize(), + "must have reached control projection of init node"); +} + +void LibraryCallKit::create_new_uncommon_trap(CallStaticJavaNode* uncommon_trap_call) { + const int trap_request = uncommon_trap_call->uncommon_trap_request(); + assert(trap_request != 0, "no valid UCT trap request"); + PreserveJVMState pjvms(this); + set_control(uncommon_trap_call->in(0)); + uncommon_trap(Deoptimization::trap_request_reason(trap_request), + Deoptimization::trap_request_action(trap_request)); + assert(stopped(), "Should be stopped"); + _gvn.hash_delete(uncommon_trap_call); + uncommon_trap_call->set_req(0, top()); // not used anymore, kill it +} //------------------------------inline_arraycopy----------------------- // public static native void java.lang.System.arraycopy(Object src, int srcPos, @@ -4435,12 +4795,12 @@ bool LibraryCallKit::inline_arraycopy() { AllocateArrayNode* alloc = tightly_coupled_allocation(dest, NULL); int saved_reexecute_sp = -1; - JVMState* saved_jvms = arraycopy_restore_alloc_state(alloc, saved_reexecute_sp); + JVMState* saved_jvms_before_guards = arraycopy_restore_alloc_state(alloc, saved_reexecute_sp); // See arraycopy_restore_alloc_state() comment // if alloc == NULL we don't have to worry about a tightly coupled allocation so we can emit all needed guards - // if saved_jvms != NULL (then alloc != NULL) then we can handle guards and a tightly coupled allocation - // if saved_jvms == NULL and alloc != NULL, we can't emit any guards - bool can_emit_guards = (alloc == NULL || saved_jvms != NULL); + // if saved_jvms_before_guards != NULL (then alloc != NULL) then we can handle guards and a tightly coupled allocation + // if saved_jvms_before_guards == NULL and alloc != NULL, we can't emit any guards + bool can_emit_guards = (alloc == NULL || saved_jvms_before_guards != NULL); // The following tests must be performed // (1) src and dest are arrays. @@ -4456,12 +4816,12 @@ bool LibraryCallKit::inline_arraycopy() { // (3) src and dest must not be null. // always do this here because we need the JVM state for uncommon traps Node* null_ctl = top(); - src = saved_jvms != NULL ? null_check_oop(src, &null_ctl, true, true) : null_check(src, T_ARRAY); + src = saved_jvms_before_guards != NULL ? null_check_oop(src, &null_ctl, true, true) : null_check(src, T_ARRAY); assert(null_ctl->is_top(), "no null control here"); dest = null_check(dest, T_ARRAY); if (!can_emit_guards) { - // if saved_jvms == NULL and alloc != NULL, we don't emit any + // if saved_jvms_before_guards == NULL and alloc != NULL, we don't emit any // guards but the arraycopy node could still take advantage of a // tightly allocated allocation. tightly_coupled_allocation() is // called again to make sure it takes the null check above into @@ -4575,7 +4935,7 @@ bool LibraryCallKit::inline_arraycopy() { ciMethod* trap_method = method(); int trap_bci = bci(); - if (saved_jvms != NULL) { + if (saved_jvms_before_guards != NULL) { trap_method = alloc->jvms()->method(); trap_bci = alloc->jvms()->bci(); } @@ -4646,10 +5006,9 @@ bool LibraryCallKit::inline_arraycopy() { const TypeKlassPtr* dest_klass_t = _gvn.type(dest_klass)->is_klassptr(); const Type *toop = TypeOopPtr::make_from_klass(dest_klass_t->klass()); src = _gvn.transform(new CheckCastPPNode(control(), src, toop)); + arraycopy_move_allocation_here(alloc, dest, saved_jvms_before_guards, saved_reexecute_sp, new_idx); } - arraycopy_move_allocation_here(alloc, dest, saved_jvms, saved_reexecute_sp, new_idx); - if (stopped()) { return true; } @@ -4715,32 +5074,27 @@ LibraryCallKit::tightly_coupled_allocation(Node* ptr, // There may be guards which feed into the slow_region. // Any other control flow means that we might not get a chance // to finish initializing the allocated object. - if ((ctl->is_IfFalse() || ctl->is_IfTrue()) && ctl->in(0)->is_If()) { - IfNode* iff = ctl->in(0)->as_If(); - Node* not_ctl = iff->proj_out_or_null(1 - ctl->as_Proj()->_con); - assert(not_ctl != NULL && not_ctl != ctl, "found alternate"); - if (slow_region != NULL && slow_region->find_edge(not_ctl) >= 1) { - ctl = iff->in(0); // This test feeds the known slow_region. - continue; - } - // One more try: Various low-level checks bottom out in - // uncommon traps. If the debug-info of the trap omits - // any reference to the allocation, as we've already - // observed, then there can be no objection to the trap. - bool found_trap = false; - for (DUIterator_Fast jmax, j = not_ctl->fast_outs(jmax); j < jmax; j++) { - Node* obs = not_ctl->fast_out(j); - if (obs->in(0) == not_ctl && obs->is_Call() && - (obs->as_Call()->entry_point() == SharedRuntime::uncommon_trap_blob()->entry_point())) { - found_trap = true; break; + // This code is removed by "8263615: Cleanup tightly_coupled_allocation" + // I had to adapt it when backporting "8297730: C2: Arraycopy intrinsic throws incorrect exception" + if (slow_region != NULL) { + if ((ctl->is_IfFalse() || ctl->is_IfTrue()) && ctl->in(0)->is_If()) { + IfNode* iff = ctl->in(0)->as_If(); + Node* not_ctl = iff->proj_out_or_null(1 - ctl->as_Proj()->_con); + if (slow_region->find_edge(not_ctl) >= 1) { + ctl = iff->in(0); // This test feeds the known slow_region. + continue; } } - if (found_trap) { - ctl = iff->in(0); // This test feeds a harmless uncommon trap. - continue; - } } - return NULL; + // Various low-level checks bottom out in uncommon traps. These + // are considered safe since we've already checked above that + // there is no unexpected observer of this allocation. + if (get_uncommon_trap_from_success_proj(ctl) != NULL) { + assert(ctl->in(0)->is_If(), "must be If"); + ctl = ctl->in(0)->in(0); + } else { + return NULL; + } } // If we get this far, we have an allocation which immediately @@ -4751,6 +5105,20 @@ LibraryCallKit::tightly_coupled_allocation(Node* ptr, return alloc; } +CallStaticJavaNode* LibraryCallKit::get_uncommon_trap_from_success_proj(Node* node) { + if (node->is_IfProj()) { + Node* other_proj = node->as_IfProj()->other_if_proj(); + for (DUIterator_Fast jmax, j = other_proj->fast_outs(jmax); j < jmax; j++) { + Node* obs = other_proj->fast_out(j); + if (obs->in(0) == other_proj && obs->is_CallStaticJava() && + (obs->as_CallStaticJava()->entry_point() == SharedRuntime::uncommon_trap_blob()->entry_point())) { + return obs->as_CallStaticJava(); + } + } + } + return NULL; +} + //-------------inline_encodeISOArray----------------------------------- // encode char[] to byte[] in ISO_8859_1 bool LibraryCallKit::inline_encodeISOArray() { diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 044fd16d1a4..e401eb4460f 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -3240,7 +3240,12 @@ bool IdealLoopTree::do_remove_empty_loop(PhaseIdealLoop *phase) { // counted loop has limit check predicate. Node* phi = cl->phi(); Node* exact_limit = phase->exact_limit(this); - Node* final_iv = new SubINode(exact_limit, cl->stride()); + + // We need to pin the exact limit to prevent it from floating above the zero trip guard. + Node * cast_ii = ConstraintCastNode::make_cast(Op_CastII, cl->in(LoopNode::EntryControl), exact_limit, phase->_igvn.type(exact_limit), true); + phase->register_new_node(cast_ii, cl->in(LoopNode::EntryControl)); + + Node* final_iv = new SubINode(cast_ii, cl->stride()); phase->register_new_node(final_iv, cl->in(LoopNode::EntryControl)); phase->_igvn.replace_node(phi, final_iv); diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 10522d98c19..f1b7ff47656 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -501,7 +501,7 @@ Node *PhaseIdealLoop::remix_address_expressions( Node *n ) { n23_loop == n_loop ) { Node *add1 = new AddPNode( n->in(1), n->in(2)->in(2), n->in(3) ); // Stuff new AddP in the loop preheader - register_new_node( add1, n_loop->_head->in(LoopNode::EntryControl) ); + register_new_node( add1, n_loop->_head->as_Loop()->skip_strip_mined(1)->in(LoopNode::EntryControl) ); Node *add2 = new AddPNode( n->in(1), add1, n->in(2)->in(3) ); register_new_node( add2, n_ctrl ); _igvn.replace_node( n, add2 ); @@ -522,7 +522,7 @@ Node *PhaseIdealLoop::remix_address_expressions( Node *n ) { if (!is_member(n_loop,get_ctrl(I))) { Node *add1 = new AddPNode(n->in(1), n->in(2), I); // Stuff new AddP in the loop preheader - register_new_node(add1, n_loop->_head->in(LoopNode::EntryControl)); + register_new_node(add1, n_loop->_head->as_Loop()->skip_strip_mined(1)->in(LoopNode::EntryControl)); Node *add2 = new AddPNode(n->in(1), add1, V); register_new_node(add2, n_ctrl); _igvn.replace_node(n, add2); diff --git a/src/hotspot/share/opto/parse1.cpp b/src/hotspot/share/opto/parse1.cpp index 27228e31911..86ab2eea105 100644 --- a/src/hotspot/share/opto/parse1.cpp +++ b/src/hotspot/share/opto/parse1.cpp @@ -610,8 +610,6 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) // Parse all the basic blocks. do_all_blocks(); - C->set_default_node_notes(caller_nn); - // Check for bailouts during conversion to graph if (failing()) { if (log) log->done("parse"); @@ -622,6 +620,10 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) set_map(entry_map); do_exits(); + // Only reset this now, to make sure that debug information emitted + // for exiting control flow still refers to the inlined method. + C->set_default_node_notes(caller_nn); + if (log) log->done("parse nodes='%d' live='%d' memory='" SIZE_FORMAT "'", C->unique(), C->live_nodes(), C->node_arena()->used()); } diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 344334a82a9..5aec3b953b6 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -482,6 +482,14 @@ PhaseRenumberLive::PhaseRenumberLive(PhaseGVN* gvn, uint worklist_size = worklist->size(); + GrowableArray* old_node_note_array = C->node_note_array(); + if (old_node_note_array != NULL) { + int new_size = (_useful.size() >> 8) + 1; // The node note array uses blocks, see C->_log2_node_notes_block_size + new_size = MAX2(8, new_size); + C->set_node_note_array(new (C->comp_arena()) GrowableArray (C->comp_arena(), new_size, 0, NULL)); + C->grow_node_notes(C->node_note_array(), new_size); + } + // Iterate over the set of live nodes. for (uint current_idx = 0; current_idx < _useful.size(); current_idx++) { Node* n = _useful.at(current_idx); @@ -497,6 +505,11 @@ PhaseRenumberLive::PhaseRenumberLive(PhaseGVN* gvn, assert(_old2new_map.at(n->_idx) == -1, "already seen"); _old2new_map.at_put(n->_idx, current_idx); + if (old_node_note_array != NULL) { + Node_Notes* nn = C->locate_node_notes(old_node_note_array, n->_idx); + C->set_node_notes_at(current_idx, nn); + } + n->set_idx(current_idx); // Update node ID. if (in_worklist) { diff --git a/src/hotspot/share/prims/jvmtiThreadState.hpp b/src/hotspot/share/prims/jvmtiThreadState.hpp index 5eeb88a8601..e6caf6a24eb 100644 --- a/src/hotspot/share/prims/jvmtiThreadState.hpp +++ b/src/hotspot/share/prims/jvmtiThreadState.hpp @@ -411,14 +411,14 @@ class RedefineVerifyMark : public StackObj { JvmtiThreadState *state) : _state(state), _scratch_class(scratch_class) { _state->set_class_versions_map(the_class, scratch_class); - _scratch_mirror = _scratch_class->java_mirror_handle(); - _scratch_class->set_java_mirror_handle(the_class->java_mirror_handle()); + _scratch_mirror = the_class->java_mirror_handle(); // this is a copy that is swapped + _scratch_class->swap_java_mirror_handle(_scratch_mirror); } ~RedefineVerifyMark() { // Restore the scratch class's mirror, so when scratch_class is removed // the correct mirror pointing to it can be cleared. - _scratch_class->set_java_mirror_handle(_scratch_mirror); + _scratch_class->swap_java_mirror_handle(_scratch_mirror); _state->clear_class_versions_map(); } }; diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 2dc69195748..a56758eb5c4 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -94,6 +94,7 @@ #endif // INCLUDE_AOT #ifdef LINUX +#include "os_linux.hpp" #include "osContainer_linux.hpp" #include "cgroupSubsystem_linux.hpp" #endif @@ -1832,7 +1833,7 @@ WB_ENTRY(jboolean, WB_AreOpenArchiveHeapObjectsMapped(JNIEnv* env)) return MetaspaceShared::open_archive_heap_region_mapped(); WB_END -WB_ENTRY(jboolean, WB_IsCDSIncludedInVmBuild(JNIEnv* env)) +WB_ENTRY(jboolean, WB_IsCDSIncluded(JNIEnv* env)) #if INCLUDE_CDS # ifdef _LP64 if (!UseCompressedOops || !UseCompressedClassPointers) { @@ -1851,7 +1852,7 @@ WB_ENTRY(jboolean, WB_IsJavaHeapArchiveSupported(JNIEnv* env)) WB_END -WB_ENTRY(jboolean, WB_IsJFRIncludedInVmBuild(JNIEnv* env)) +WB_ENTRY(jboolean, WB_IsJFRIncluded(JNIEnv* env)) #if INCLUDE_JFR return true; #else @@ -2026,6 +2027,18 @@ WB_ENTRY(jboolean, WB_IsContainerized(JNIEnv* env, jobject o)) return false; WB_END +// Physical memory of the host machine (including containers) +WB_ENTRY(jlong, WB_HostPhysicalMemory(JNIEnv* env, jobject o)) + LINUX_ONLY(return os::Linux::physical_memory();) + return os::physical_memory(); +WB_END + +// Physical swap of the host machine (including containers), Linux only. +WB_ENTRY(jlong, WB_HostPhysicalSwap(JNIEnv* env, jobject o)) + LINUX_ONLY(return (jlong)os::Linux::host_swap();) + return -1; // Not used/implemented on other platforms +WB_END + WB_ENTRY(jint, WB_ValidateCgroup(JNIEnv* env, jobject o, jstring proc_cgroups, @@ -2282,8 +2295,8 @@ static JNINativeMethod methods[] = { {CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored }, {CC"getResolvedReferences", CC"(Ljava/lang/Class;)Ljava/lang/Object;", (void*)&WB_GetResolvedReferences}, {CC"areOpenArchiveHeapObjectsMapped", CC"()Z", (void*)&WB_AreOpenArchiveHeapObjectsMapped}, - {CC"isCDSIncludedInVmBuild", CC"()Z", (void*)&WB_IsCDSIncludedInVmBuild }, - {CC"isJFRIncludedInVmBuild", CC"()Z", (void*)&WB_IsJFRIncludedInVmBuild }, + {CC"isCDSIncluded", CC"()Z", (void*)&WB_IsCDSIncluded }, + {CC"isJFRIncluded", CC"()Z", (void*)&WB_IsJFRIncluded }, {CC"isJavaHeapArchiveSupported", CC"()Z", (void*)&WB_IsJavaHeapArchiveSupported }, {CC"clearInlineCaches0", CC"(Z)V", (void*)&WB_ClearInlineCaches }, @@ -2305,6 +2318,8 @@ static JNINativeMethod methods[] = { {CC"validateCgroup", CC"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", (void*)&WB_ValidateCgroup }, + {CC"hostPhysicalMemory", CC"()J", (void*)&WB_HostPhysicalMemory }, + {CC"hostPhysicalSwap", CC"()J", (void*)&WB_HostPhysicalSwap }, {CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo }, {CC"disableElfSectionCache", CC"()V", (void*)&WB_DisableElfSectionCache }, {CC"aotLibrariesCount", CC"()I", (void*)&WB_AotLibrariesCount }, diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index 26590bac21a..b3c3ef65636 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -44,6 +44,7 @@ #include "runtime/monitorChunk.hpp" #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/safefetch.inline.hpp" #include "runtime/signature.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" @@ -240,6 +241,14 @@ bool frame::is_entry_frame_valid(JavaThread* thread) const { return (jfa->last_Java_sp() > sp()); } +Method* frame::safe_interpreter_frame_method() const { + Method** m_addr = interpreter_frame_method_addr(); + if (m_addr == NULL) { + return NULL; + } + return (Method*) SafeFetchN((intptr_t*) m_addr, 0); +} + bool frame::should_be_deoptimized() const { if (_deopt_state == is_deoptimized || !is_compiled_frame() ) return false; diff --git a/src/hotspot/share/runtime/frame.hpp b/src/hotspot/share/runtime/frame.hpp index a3b89bcbffb..d4776ffecb6 100644 --- a/src/hotspot/share/runtime/frame.hpp +++ b/src/hotspot/share/runtime/frame.hpp @@ -168,6 +168,8 @@ class frame { bool is_entry_frame_valid(JavaThread* thread) const; + Method* safe_interpreter_frame_method() const; + // All frames: // A low-level interface for vframes: diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 4ccdacde6cb..348afb866ca 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -133,8 +133,8 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G); // notproduct flags are settable / visible only during development and are not declared in the PRODUCT version // A flag must be declared with one of the following types: -// bool, int, uint, intx, uintx, size_t, ccstr, double, or uint64_t. -// The type "ccstr" is an alias for "const char*" and is used +// bool, int, uint, intx, uintx, size_t, ccstr, ccstrlist, double, or uint64_t. +// The type "ccstr" and "ccstrlist" are an alias for "const char*" and is used // only in this file, because the macrology requires single-token type names. // Note: Diagnostic options not meant for VM tuning or for product modes. diff --git a/src/java.base/macosx/classes/apple/security/KeychainStore.java b/src/java.base/macosx/classes/apple/security/KeychainStore.java index e2647118b09..9f00cf81a9c 100644 --- a/src/java.base/macosx/classes/apple/security/KeychainStore.java +++ b/src/java.base/macosx/classes/apple/security/KeychainStore.java @@ -108,12 +108,13 @@ class TrustedCertEntry { private Hashtable entries = new Hashtable<>(); /** - * Algorithm identifiers and corresponding OIDs for the contents of the PKCS12 bag we get from the Keychain. + * Algorithm identifiers and corresponding OIDs for the contents of the + * PKCS12 bag we get from the Keychain. */ - private static final int keyBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 2}; - private static final int pbeWithSHAAnd3KeyTripleDESCBC[] = {1, 2, 840, 113549, 1, 12, 1, 3}; - private static ObjectIdentifier PKCS8ShroudedKeyBag_OID; - private static ObjectIdentifier pbeWithSHAAnd3KeyTripleDESCBC_OID; + private static ObjectIdentifier PKCS8ShroudedKeyBag_OID = + ObjectIdentifier.of(KnownOIDs.PKCS8ShroudedKeyBag); + private static ObjectIdentifier pbeWithSHAAnd3KeyTripleDESCBC_OID = + ObjectIdentifier.of(KnownOIDs.PBEWithSHA1AndDESede); /** * Constnats used in PBE decryption. @@ -131,12 +132,6 @@ public Void run() { return null; } }); - try { - PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag); - pbeWithSHAAnd3KeyTripleDESCBC_OID = new ObjectIdentifier(pbeWithSHAAnd3KeyTripleDESCBC); - } catch (IOException ioe) { - // should not happen - } } private static void permissionCheck() { diff --git a/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c b/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c index bc64cd1ae62..30fa8eea206 100644 --- a/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c +++ b/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c @@ -272,7 +272,8 @@ void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) { mib[2] = pid; size = (size_t) maxargs; if (sysctl(mib, 3, args, &size, NULL, 0) == -1) { - if (errno != EINVAL) { + if (errno != EINVAL && errno != EIO) { + // If the pid is invalid, the information returned is empty and no exception JNU_ThrowByNameWithLastError(env, "java/lang/RuntimeException", "sysctl failed"); } @@ -300,4 +301,3 @@ void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) { // Free the arg buffer free(args); } - diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DESKey.java b/src/java.base/share/classes/com/sun/crypto/provider/DESKey.java index 7e032058f30..6bbbb0e3b11 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/DESKey.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/DESKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package com.sun.crypto.provider; +import java.io.IOException; +import java.io.InvalidObjectException; import java.lang.ref.Reference; import java.security.MessageDigest; import java.security.KeyRep; @@ -43,7 +45,7 @@ final class DESKey implements SecretKey { - static final long serialVersionUID = 7724971015953279128L; + private static final long serialVersionUID = 7724971015953279128L; private byte[] key; @@ -112,7 +114,7 @@ public int hashCode() { for (int i = 1; i < this.key.length; i++) { retval += this.key[i] * i; } - return(retval ^= "des".hashCode()); + return(retval ^ "des".hashCode()); } public boolean equals(Object obj) { @@ -133,14 +135,27 @@ public boolean equals(Object obj) { } /** - * readObject is called to restore the state of this key from - * a stream. + * Restores the state of this object from the stream. + * + * @param s the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded */ private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException + throws IOException, ClassNotFoundException { s.defaultReadObject(); + if ((key == null) || (key.length != DESKeySpec.DES_KEY_LEN)) { + throw new InvalidObjectException("Wrong key size"); + } key = key.clone(); + + DESKeyGenerator.setParityBit(key, 0); + + // Use the cleaner to zero the key when no longer referenced + final byte[] k = key; + CleanerFactory.cleaner().register(this, + () -> java.util.Arrays.fill(k, (byte)0x00)); } /** diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.java b/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.java index 89970c467df..06fb7b6ae6b 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package com.sun.crypto.provider; +import java.io.IOException; +import java.io.InvalidObjectException; import java.lang.ref.Reference; import java.security.MessageDigest; import java.security.KeyRep; @@ -43,7 +45,7 @@ final class DESedeKey implements SecretKey { - static final long serialVersionUID = 2463986565756745178L; + private static final long serialVersionUID = 2463986565756745178L; private byte[] key; @@ -111,7 +113,7 @@ public int hashCode() { for (int i = 1; i < this.key.length; i++) { retval += this.key[i] * i; } - return(retval ^= "desede".hashCode()); + return(retval ^ "desede".hashCode()); } public boolean equals(Object obj) { @@ -133,14 +135,29 @@ public boolean equals(Object obj) { } /** - * readObject is called to restore the state of this key from - * a stream. + * Restores the state of this object from the stream. + * + * @param s the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded */ private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException + throws IOException, ClassNotFoundException { s.defaultReadObject(); + if ((key == null) || (key.length != DESedeKeySpec.DES_EDE_KEY_LEN)) { + throw new InvalidObjectException("Wrong key size"); + } key = key.clone(); + + DESKeyGenerator.setParityBit(key, 0); + DESKeyGenerator.setParityBit(key, 8); + DESKeyGenerator.setParityBit(key, 16); + + // Use the cleaner to zero the key when no longer referenced + final byte[] k = key; + CleanerFactory.cleaner().register(this, + () -> java.util.Arrays.fill(k, (byte)0x00)); } /** diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DHPrivateKey.java b/src/java.base/share/classes/com/sun/crypto/provider/DHPrivateKey.java index c87cc1c5d62..c7e70df9561 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/DHPrivateKey.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/DHPrivateKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,15 +40,13 @@ * algorithm. * * @author Jan Luehe - * - * * @see DHPublicKey * @see java.security.KeyAgreement */ final class DHPrivateKey implements PrivateKey, javax.crypto.interfaces.DHPrivateKey, Serializable { - static final long serialVersionUID = 7565477590005668886L; + private static final long serialVersionUID = 7565477590005668886L; // only supported version of PKCS#8 PrivateKeyInfo private static final BigInteger PKCS8_VERSION = BigInteger.ZERO; @@ -63,16 +61,14 @@ final class DHPrivateKey implements PrivateKey, private byte[] encodedKey; // the prime modulus - private BigInteger p; + private final BigInteger p; // the base generator - private BigInteger g; + private final BigInteger g; // the private-value length (optional) private int l; - private int DH_data[] = { 1, 2, 840, 113549, 1, 3, 1 }; - /** * Make a DH private key out of a private value x, a prime * modulus p, and a base generator g. @@ -219,7 +215,7 @@ public synchronized byte[] getEncoded() { DerOutputStream algid = new DerOutputStream(); // store OID - algid.putOID(new ObjectIdentifier(DH_data)); + algid.putOID(DHPublicKey.DH_OID); // encode parameters DerOutputStream params = new DerOutputStream(); params.putInteger(this.p); @@ -319,4 +315,27 @@ private Object writeReplace() throws java.io.ObjectStreamException { getFormat(), getEncoded()); } + + /** + * Restores the state of this object from the stream. + *

+ * JDK 1.5+ objects use KeyReps instead. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if ((key == null) || (key.length == 0)) { + throw new InvalidObjectException("key not deserializable"); + } + this.key = key.clone(); + if ((encodedKey == null) || (encodedKey.length == 0)) { + throw new InvalidObjectException( + "encoded key not deserializable"); + } + this.encodedKey = encodedKey.clone(); + } } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DHPublicKey.java b/src/java.base/share/classes/com/sun/crypto/provider/DHPublicKey.java index f2264ad43b0..dd2d652a2c8 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/DHPublicKey.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/DHPublicKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,15 +40,13 @@ * A public key in X.509 format for the Diffie-Hellman key agreement algorithm. * * @author Jan Luehe - * - * * @see DHPrivateKey * @see javax.crypto.KeyAgreement */ final class DHPublicKey implements PublicKey, javax.crypto.interfaces.DHPublicKey, Serializable { - static final long serialVersionUID = 7647557958927458271L; + private static final long serialVersionUID = 7647557958927458271L; // the public key private BigInteger y; @@ -60,15 +58,17 @@ final class DHPublicKey implements PublicKey, private byte[] encodedKey; // the prime modulus - private BigInteger p; + private final BigInteger p; // the base generator - private BigInteger g; + private final BigInteger g; // the private-value length (optional) private int l; - private int DH_data[] = { 1, 2, 840, 113549, 1, 3, 1 }; + // Note: this OID is used by DHPrivateKey as well. + static ObjectIdentifier DH_OID = + ObjectIdentifier.of(KnownOIDs.DiffieHellman); /** * Make a DH public key out of a public value y, a prime @@ -202,7 +202,7 @@ public synchronized byte[] getEncoded() { DerOutputStream algid = new DerOutputStream(); // store oid in algid - algid.putOID(new ObjectIdentifier(DH_data)); + algid.putOID(DH_OID); // encode parameters DerOutputStream params = new DerOutputStream(); @@ -320,4 +320,27 @@ private Object writeReplace() throws java.io.ObjectStreamException { getFormat(), getEncoded()); } + + /** + * Restores the state of this object from the stream. + *

+ * JDK 1.5+ objects use KeyReps instead. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if ((key == null) || (key.length == 0)) { + throw new InvalidObjectException("key not deserializable"); + } + this.key = key.clone(); + if ((encodedKey == null) || (encodedKey.length == 0)) { + throw new InvalidObjectException( + "encoded key not deserializable"); + } + this.encodedKey = encodedKey.clone(); + } } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java b/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java index e8a3399d8f1..9eb6b5f28ca 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java @@ -48,6 +48,7 @@ import sun.security.x509.AlgorithmId; import sun.security.util.ObjectIdentifier; +import sun.security.util.KnownOIDs; import sun.security.util.SecurityProperties; /** @@ -67,14 +68,6 @@ final class KeyProtector { - // defined by SunSoft (SKI project) - private static final String PBE_WITH_MD5_AND_DES3_CBC_OID - = "1.3.6.1.4.1.42.2.19.1"; - - // JavaSoft proprietary key-protection algorithm (used to protect private - // keys in the keystore implementation that comes with JDK 1.2) - private static final String KEY_PROTECTOR_OID = "1.3.6.1.4.1.42.2.17.1.1"; - private static final int MAX_ITERATION_COUNT = 5000000; private static final int MIN_ITERATION_COUNT = 10000; private static final int DEFAULT_ITERATION_COUNT = 200000; @@ -154,7 +147,8 @@ byte[] protect(PrivateKey key) pbeParams.init(pbeSpec); AlgorithmId encrAlg = new AlgorithmId - (new ObjectIdentifier(PBE_WITH_MD5_AND_DES3_CBC_OID), pbeParams); + (ObjectIdentifier.of(KnownOIDs.JAVASOFT_JCEKeyProtector), + pbeParams); return new EncryptedPrivateKeyInfo(encrAlg,encrKey).getEncoded(); } @@ -169,13 +163,13 @@ Key recover(EncryptedPrivateKeyInfo encrInfo) SecretKey sKey = null; try { String encrAlg = encrInfo.getAlgorithm().getOID().toString(); - if (!encrAlg.equals(PBE_WITH_MD5_AND_DES3_CBC_OID) - && !encrAlg.equals(KEY_PROTECTOR_OID)) { + if (!encrAlg.equals(KnownOIDs.JAVASOFT_JCEKeyProtector.value()) + && !encrAlg.equals(KnownOIDs.JAVASOFT_JDKKeyProtector.value())) { throw new UnrecoverableKeyException("Unsupported encryption " + "algorithm"); } - if (encrAlg.equals(KEY_PROTECTOR_OID)) { + if (encrAlg.equals(KnownOIDs.JAVASOFT_JDKKeyProtector.value())) { // JDK 1.2 style recovery plain = recover(encrInfo.getEncryptedData()); } else { diff --git a/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java b/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java index 6e90f3fe15d..e4879b50dc4 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/OAEPParameters.java @@ -55,24 +55,10 @@ public final class OAEPParameters extends AlgorithmParametersSpi { private String mdName; private MGF1ParameterSpec mgfSpec; private byte[] p; - private static ObjectIdentifier OID_MGF1; - private static ObjectIdentifier OID_PSpecified; - - static { - try { - OID_MGF1 = new ObjectIdentifier(new int[] {1,2,840,113549,1,1,8}); - } catch (IOException ioe) { - // should not happen - OID_MGF1 = null; - } - try { - OID_PSpecified = - new ObjectIdentifier(new int[] {1,2,840,113549,1,1,9}); - } catch (IOException ioe) { - // should not happen - OID_PSpecified = null; - } - } + private static ObjectIdentifier OID_MGF1 = + ObjectIdentifier.of(KnownOIDs.MGF1); + private static ObjectIdentifier OID_PSpecified = + ObjectIdentifier.of(KnownOIDs.PSpecified); public OAEPParameters() { } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java b/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java index 93be05f08d7..2d43c34f20f 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package com.sun.crypto.provider; +import java.io.IOException; +import java.io.InvalidObjectException; import java.lang.ref.Reference; import java.security.MessageDigest; import java.security.KeyRep; @@ -44,11 +46,11 @@ */ final class PBEKey implements SecretKey { - static final long serialVersionUID = -2234768909660948176L; + private static final long serialVersionUID = -2234768909660948176L; private byte[] key; - private String type; + private final String type; /** * Creates a PBE key from a given PBE key specification. @@ -109,7 +111,7 @@ public int hashCode() { for (int i = 1; i < this.key.length; i++) { retval += this.key[i] * i; } - return(retval ^= getAlgorithm().toLowerCase(Locale.ENGLISH).hashCode()); + return(retval ^ getAlgorithm().toLowerCase(Locale.ENGLISH).hashCode()); } public boolean equals(Object obj) { @@ -143,14 +145,37 @@ public void destroy() { } /** - * readObject is called to restore the state of this key from - * a stream. + * Restores the state of this object from the stream. + * + * @param s the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded */ private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException + throws IOException, ClassNotFoundException { s.defaultReadObject(); + if (key == null) { + throw new InvalidObjectException( + "PBEKey couldn't be deserialized"); + } key = key.clone(); + + // Accept "\0" to signify "zero-length password with no terminator". + if (!(key.length == 1 && key[0] == 0)) { + for (int i = 0; i < key.length; i++) { + if ((key[i] < '\u0020') || (key[i] > '\u007E')) { + throw new InvalidObjectException( + "PBEKey had non-ASCII chars"); + } + } + } + + // Use the cleaner to zero the key when no longer referenced + final byte[] k = this.key; + CleanerFactory.cleaner().register(this, + () -> Arrays.fill(k, (byte) 0x00)); + } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java b/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java index 968d591ac6c..8b199f7abd2 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,57 +90,18 @@ * * */ - abstract class PBES2Parameters extends AlgorithmParametersSpi { - private static final int pkcs5PBKDF2[] = - {1, 2, 840, 113549, 1, 5, 12}; - private static final int pkcs5PBES2[] = - {1, 2, 840, 113549, 1, 5, 13}; - private static final int hmacWithSHA1[] = - {1, 2, 840, 113549, 2, 7}; - private static final int hmacWithSHA224[] = - {1, 2, 840, 113549, 2, 8}; - private static final int hmacWithSHA256[] = - {1, 2, 840, 113549, 2, 9}; - private static final int hmacWithSHA384[] = - {1, 2, 840, 113549, 2, 10}; - private static final int hmacWithSHA512[] = - {1, 2, 840, 113549, 2, 11}; - private static final int aes128CBC[] = - {2, 16, 840, 1, 101, 3, 4, 1, 2}; - private static final int aes192CBC[] = - {2, 16, 840, 1, 101, 3, 4, 1, 22}; - private static final int aes256CBC[] = - {2, 16, 840, 1, 101, 3, 4, 1, 42}; - - private static ObjectIdentifier pkcs5PBKDF2_OID; - private static ObjectIdentifier pkcs5PBES2_OID; - private static ObjectIdentifier hmacWithSHA1_OID; - private static ObjectIdentifier hmacWithSHA224_OID; - private static ObjectIdentifier hmacWithSHA256_OID; - private static ObjectIdentifier hmacWithSHA384_OID; - private static ObjectIdentifier hmacWithSHA512_OID; - private static ObjectIdentifier aes128CBC_OID; - private static ObjectIdentifier aes192CBC_OID; - private static ObjectIdentifier aes256CBC_OID; - - static { - try { - pkcs5PBKDF2_OID = new ObjectIdentifier(pkcs5PBKDF2); - pkcs5PBES2_OID = new ObjectIdentifier(pkcs5PBES2); - hmacWithSHA1_OID = new ObjectIdentifier(hmacWithSHA1); - hmacWithSHA224_OID = new ObjectIdentifier(hmacWithSHA224); - hmacWithSHA256_OID = new ObjectIdentifier(hmacWithSHA256); - hmacWithSHA384_OID = new ObjectIdentifier(hmacWithSHA384); - hmacWithSHA512_OID = new ObjectIdentifier(hmacWithSHA512); - aes128CBC_OID = new ObjectIdentifier(aes128CBC); - aes192CBC_OID = new ObjectIdentifier(aes192CBC); - aes256CBC_OID = new ObjectIdentifier(aes256CBC); - } catch (IOException ioe) { - // should not happen - } - } + private static ObjectIdentifier pkcs5PBKDF2_OID = + ObjectIdentifier.of(KnownOIDs.PBKDF2WithHmacSHA1); + private static ObjectIdentifier pkcs5PBES2_OID = + ObjectIdentifier.of(KnownOIDs.PBES2); + private static ObjectIdentifier aes128CBC_OID = + ObjectIdentifier.of(KnownOIDs.AES_128$CBC$NoPadding); + private static ObjectIdentifier aes192CBC_OID = + ObjectIdentifier.of(KnownOIDs.AES_192$CBC$NoPadding); + private static ObjectIdentifier aes256CBC_OID = + ObjectIdentifier.of(KnownOIDs.AES_256$CBC$NoPadding); // the PBES2 algorithm name private String pbes2AlgorithmName = null; @@ -155,7 +116,8 @@ abstract class PBES2Parameters extends AlgorithmParametersSpi { private AlgorithmParameterSpec cipherParam = null; // the key derivation function (default is HmacSHA1) - private ObjectIdentifier kdfAlgo_OID = hmacWithSHA1_OID; + private ObjectIdentifier kdfAlgo_OID = + ObjectIdentifier.of(KnownOIDs.HmacSHA1); // the encryption function private ObjectIdentifier cipherAlgo_OID = null; @@ -200,19 +162,11 @@ abstract class PBES2Parameters extends AlgorithmParametersSpi { switch (kdfAlgo) { case "HmacSHA1": - kdfAlgo_OID = hmacWithSHA1_OID; - break; case "HmacSHA224": - kdfAlgo_OID = hmacWithSHA224_OID; - break; case "HmacSHA256": - kdfAlgo_OID = hmacWithSHA256_OID; - break; case "HmacSHA384": - kdfAlgo_OID = hmacWithSHA384_OID; - break; case "HmacSHA512": - kdfAlgo_OID = hmacWithSHA512_OID; + kdfAlgo_OID = ObjectIdentifier.of(KnownOIDs.findMatch(kdfAlgo)); break; default: throw new NoSuchAlgorithmException( @@ -284,7 +238,7 @@ protected void engineInit(byte[] encoded) } cipherAlgo = parseES(pBES2_params.data.getDerValue()); - pbes2AlgorithmName = new StringBuilder().append("PBEWith") + this.pbes2AlgorithmName = new StringBuilder().append("PBEWith") .append(kdfAlgo).append("And").append(cipherAlgo).toString(); } @@ -335,21 +289,18 @@ private String parseKDF(DerValue keyDerivationFunc) throws IOException { } if (prf != null) { kdfAlgo_OID = prf.data.getOID(); - if (hmacWithSHA1_OID.equals(kdfAlgo_OID)) { - kdfAlgo = "HmacSHA1"; - } else if (hmacWithSHA224_OID.equals(kdfAlgo_OID)) { - kdfAlgo = "HmacSHA224"; - } else if (hmacWithSHA256_OID.equals(kdfAlgo_OID)) { - kdfAlgo = "HmacSHA256"; - } else if (hmacWithSHA384_OID.equals(kdfAlgo_OID)) { - kdfAlgo = "HmacSHA384"; - } else if (hmacWithSHA512_OID.equals(kdfAlgo_OID)) { - kdfAlgo = "HmacSHA512"; - } else { + KnownOIDs o = KnownOIDs.findMatch(kdfAlgo_OID.toString()); + if (o == null || (!o.stdName().equals("HmacSHA1") && + !o.stdName().equals("HmacSHA224") && + !o.stdName().equals("HmacSHA256") && + !o.stdName().equals("HmacSHA384") && + !o.stdName().equals("HmacSHA512"))) { throw new IOException("PBE parameter parsing error: " + "expecting the object identifier for a HmacSHA key " + "derivation function"); } + kdfAlgo = o.stdName(); + if (prf.data.available() != 0) { // parameter is 'NULL' for all HmacSHA KDFs DerValue parameter = prf.data.getDerValue(); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java index 6ea08796d8b..8e30cdf02aa 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java @@ -25,7 +25,7 @@ package com.sun.crypto.provider; -import java.io.ObjectStreamException; +import java.io.*; import java.lang.ref.Reference; import java.nio.ByteBuffer; import java.nio.CharBuffer; @@ -55,14 +55,14 @@ */ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey { - static final long serialVersionUID = -2234868909660948157L; + private static final long serialVersionUID = -2234868909660948157L; - private char[] passwd; - private byte[] salt; - private int iterCount; + private final char[] passwd; + private final byte[] salt; + private final int iterCount; private byte[] key; - private Mac prf; + private final Mac prf; private static byte[] getPasswordBytes(char[] passwd) { Charset utf8 = Charset.forName("UTF-8"); @@ -144,12 +144,13 @@ private static byte[] deriveKey(final Mac prf, final byte[] password, int intR = keyLength - (intL - 1)*hlen; // residue byte[] ui = new byte[hlen]; byte[] ti = new byte[hlen]; + String algName = prf.getAlgorithm(); // SecretKeySpec cannot be used, since password can be empty here. SecretKey macKey = new SecretKey() { private static final long serialVersionUID = 7874493593505141603L; @Override public String getAlgorithm() { - return prf.getAlgorithm(); + return algName; } @Override public String getFormat() { @@ -162,18 +163,26 @@ public byte[] getEncoded() { @Override public int hashCode() { return Arrays.hashCode(password) * 41 + - prf.getAlgorithm().toLowerCase(Locale.ENGLISH).hashCode(); + algName.toLowerCase(Locale.ENGLISH).hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (this.getClass() != obj.getClass()) return false; SecretKey sk = (SecretKey)obj; - return prf.getAlgorithm().equalsIgnoreCase( + return algName.equalsIgnoreCase( sk.getAlgorithm()) && MessageDigest.isEqual(password, sk.getEncoded()); } + // This derived key can't be deserialized. + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "PBKDF2KeyImpl SecretKeys are not " + + "directly deserializable"); + } }; + prf.init(macKey); byte[] ibytes = new byte[4]; @@ -282,4 +291,19 @@ private Object writeReplace() throws ObjectStreamException { return new KeyRep(KeyRep.Type.SECRET, getAlgorithm(), getFormat(), getEncoded()); } + + /** + * Restores the state of this object from the stream. + *

+ * Deserialization of this class is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "PBKDF2KeyImpl keys are not directly deserializable"); + } } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java index 414e2c5c6c4..815968bf3f0 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java @@ -32,8 +32,7 @@ import java.util.HashMap; import java.util.List; import static sun.security.util.SecurityConstants.PROVIDER_VER; -import static sun.security.provider.SunEntries.createAliases; -import static sun.security.provider.SunEntries.createAliasesWithOid; +import static sun.security.util.SecurityProviderConstants.*; /** * The "SunJCE" Cryptographic Service Provider. @@ -99,9 +98,22 @@ private static class SecureRandomHolder { } static SecureRandom getRandom() { return SecureRandomHolder.RANDOM; } - private void ps(String type, String algo, String cn, - List aliases, HashMap attrs) { - putService(new Provider.Service(this, type, algo, cn, aliases, attrs)); + // ps: putService + private void ps(String type, String algo, String cn) { + putService(new Provider.Service(this, type, algo, cn, null, null)); + } + + private void ps(String type, String algo, String cn, List als, + HashMap attrs) { + putService(new Provider.Service(this, type, algo, cn, als, + attrs)); + } + + // psA: putService with default aliases + private void psA(String type, String algo, String cn, + HashMap attrs) { + putService(new Provider.Service(this, type, algo, cn, getAliases(algo), + attrs)); } public SunJCE() { @@ -127,57 +139,6 @@ public Void run() { } void putEntries() { - // common aliases and oids - List aesAliases = createAliases("Rijndael"); - List desEdeAliases = createAliases("TripleDES"); - List arcFourAliases = createAliases("RC4"); - List sunTlsMSAliases = createAliases( - "SunTls12MasterSecret", "SunTlsExtendedMasterSecret" - ); - List sunTlsKMAliases = createAliases("SunTls12KeyMaterial"); - List sunTlsRsaPMSAliases = createAliases("SunTls12RsaPremasterSecret"); - - String aes128Oid = "2.16.840.1.101.3.4.1."; - String aes192Oid = "2.16.840.1.101.3.4.1.2"; - String aes256Oid = "2.16.840.1.101.3.4.1.4"; - - List pkcs12RC4_128Aliases = - createAliasesWithOid("1.2.840.113549.1.12.1.1"); - - List pkcs12RC4_40Aliases = - createAliasesWithOid("1.2.840.113549.1.12.1.2"); - - List pkcs12DESedeAliases = - createAliasesWithOid("1.2.840.113549.1.12.1.3"); - - List pkcs12RC2_128Aliases = - createAliasesWithOid("1.2.840.113549.1.12.1.5"); - - List pkcs12RC2_40Aliases = - createAliasesWithOid("1.2.840.113549.1.12.1.6"); - - List pkcs5MD5_DESAliases = - createAliasesWithOid("1.2.840.113549.1.5.3", "PBE"); - - List pkcs5PBKDF2Aliases = - createAliasesWithOid("1.2.840.113549.1.5.12"); - - List pkcs5PBES2Aliases = - createAliasesWithOid("1.2.840.113549.1.5.13"); - - List diffieHellmanAliases = - createAliasesWithOid("1.2.840.113549.1.3.1", "DH"); - - List chachaPolyAliases = - createAliasesWithOid("1.2.840.113549.1.9.16.3.18"); - - String macOidBase = "1.2.840.113549.2."; - List macSHA1Aliases = createAliasesWithOid(macOidBase + "7"); - List macSHA224Aliases = createAliasesWithOid(macOidBase + "8"); - List macSHA256Aliases = createAliasesWithOid(macOidBase + "9"); - List macSHA384Aliases = createAliasesWithOid(macOidBase + "10"); - List macSHA512Aliases = createAliasesWithOid(macOidBase + "11"); - // reuse attribute map and reset before each reuse HashMap attrs = new HashMap<>(3); attrs.put("SupportedModes", "ECB"); @@ -212,8 +173,8 @@ void putEntries() { attrs.put("SupportedKeyFormats", "RAW"); ps("Cipher", "DES", "com.sun.crypto.provider.DESCipher", null, attrs); - ps("Cipher", "DESede", "com.sun.crypto.provider.DESedeCipher", - desEdeAliases, attrs); + psA("Cipher", "DESede", "com.sun.crypto.provider.DESedeCipher", + attrs); ps("Cipher", "Blowfish", "com.sun.crypto.provider.BlowfishCipher", null, attrs); @@ -224,58 +185,58 @@ void putEntries() { attrs.put("SupportedModes", BLOCK_MODES128); attrs.put("SupportedPaddings", BLOCK_PADS); attrs.put("SupportedKeyFormats", "RAW"); - ps("Cipher", "AES", "com.sun.crypto.provider.AESCipher$General", - aesAliases, attrs); + psA("Cipher", "AES", + "com.sun.crypto.provider.AESCipher$General", attrs); attrs.clear(); attrs.put("SupportedKeyFormats", "RAW"); - ps("Cipher", "AES_128/ECB/NoPadding", + psA("Cipher", "AES_128/ECB/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_ECB_NoPadding", - createAliasesWithOid(aes128Oid+"1"), attrs); - ps("Cipher", "AES_128/CBC/NoPadding", + attrs); + psA("Cipher", "AES_128/CBC/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_CBC_NoPadding", - createAliasesWithOid(aes128Oid+"2"), attrs); - ps("Cipher", "AES_128/OFB/NoPadding", + attrs); + psA("Cipher", "AES_128/OFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_OFB_NoPadding", - createAliasesWithOid(aes128Oid+"3"), attrs); - ps("Cipher", "AES_128/CFB/NoPadding", + attrs); + psA("Cipher", "AES_128/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_CFB_NoPadding", - createAliasesWithOid(aes128Oid+"4"), attrs); - ps("Cipher", "AES_128/GCM/NoPadding", + attrs); + psA("Cipher", "AES_128/GCM/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_GCM_NoPadding", - createAliasesWithOid(aes128Oid+"6"), attrs); + attrs); - ps("Cipher", "AES_192/ECB/NoPadding", + psA("Cipher", "AES_192/ECB/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_ECB_NoPadding", - createAliasesWithOid(aes192Oid+"1"), attrs); - ps("Cipher", "AES_192/CBC/NoPadding", + attrs); + psA("Cipher", "AES_192/CBC/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_CBC_NoPadding", - createAliasesWithOid(aes192Oid+"2"), attrs); - ps("Cipher", "AES_192/OFB/NoPadding", + attrs); + psA("Cipher", "AES_192/OFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_OFB_NoPadding", - createAliasesWithOid(aes192Oid+"3"), attrs); - ps("Cipher", "AES_192/CFB/NoPadding", + attrs); + psA("Cipher", "AES_192/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_CFB_NoPadding", - createAliasesWithOid(aes192Oid+"4"), attrs); - ps("Cipher", "AES_192/GCM/NoPadding", + attrs); + psA("Cipher", "AES_192/GCM/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_GCM_NoPadding", - createAliasesWithOid(aes192Oid+"6"), attrs); + attrs); - ps("Cipher", "AES_256/ECB/NoPadding", + psA("Cipher", "AES_256/ECB/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_ECB_NoPadding", - createAliasesWithOid(aes256Oid+"1"), attrs); - ps("Cipher", "AES_256/CBC/NoPadding", + attrs); + psA("Cipher", "AES_256/CBC/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_CBC_NoPadding", - createAliasesWithOid(aes256Oid+"2"), attrs); - ps("Cipher", "AES_256/OFB/NoPadding", + attrs); + psA("Cipher", "AES_256/OFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_OFB_NoPadding", - createAliasesWithOid(aes256Oid+"3"), attrs); - ps("Cipher", "AES_256/CFB/NoPadding", + attrs); + psA("Cipher", "AES_256/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_CFB_NoPadding", - createAliasesWithOid(aes256Oid+"4"), attrs); - ps("Cipher", "AES_256/GCM/NoPadding", + attrs); + psA("Cipher", "AES_256/GCM/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_GCM_NoPadding", - createAliasesWithOid(aes256Oid+"6"), attrs); + attrs); attrs.clear(); attrs.put("SupportedModes", "CBC"); @@ -288,148 +249,131 @@ void putEntries() { attrs.put("SupportedModes", "ECB"); attrs.put("SupportedPaddings", "NOPADDING"); attrs.put("SupportedKeyFormats", "RAW"); - ps("Cipher", "ARCFOUR", "com.sun.crypto.provider.ARCFOURCipher", - arcFourAliases, attrs); + psA("Cipher", "ARCFOUR", + "com.sun.crypto.provider.ARCFOURCipher", attrs); ps("Cipher", "AESWrap", "com.sun.crypto.provider.AESWrapCipher$General", null, attrs); - ps("Cipher", "AESWrap_128", + psA("Cipher", "AESWrap_128", "com.sun.crypto.provider.AESWrapCipher$AES128", - createAliasesWithOid(aes128Oid+"5"), attrs); - ps("Cipher", "AESWrap_192", + attrs); + psA("Cipher", "AESWrap_192", "com.sun.crypto.provider.AESWrapCipher$AES192", - createAliasesWithOid(aes192Oid+"5"), attrs); - ps("Cipher", "AESWrap_256", + attrs); + psA("Cipher", "AESWrap_256", "com.sun.crypto.provider.AESWrapCipher$AES256", - createAliasesWithOid(aes256Oid+"5"), attrs); + attrs); attrs.clear(); attrs.put("SupportedKeyFormats", "RAW"); ps("Cipher", "ChaCha20", "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Only", null, attrs); - ps("Cipher", "ChaCha20-Poly1305", + psA("Cipher", "ChaCha20-Poly1305", "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", - chachaPolyAliases, attrs); + attrs); // PBES1 - ps("Cipher", "PBEWithMD5AndDES", + psA("Cipher", "PBEWithMD5AndDES", "com.sun.crypto.provider.PBEWithMD5AndDESCipher", - pkcs5MD5_DESAliases, null); + null); ps("Cipher", "PBEWithMD5AndTripleDES", - "com.sun.crypto.provider.PBEWithMD5AndTripleDESCipher", - null, null); - ps("Cipher", "PBEWithSHA1AndDESede", + "com.sun.crypto.provider.PBEWithMD5AndTripleDESCipher"); + psA("Cipher", "PBEWithSHA1AndDESede", "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndDESede", - pkcs12DESedeAliases, null); - ps("Cipher", "PBEWithSHA1AndRC2_40", + null); + psA("Cipher", "PBEWithSHA1AndRC2_40", "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC2_40", - pkcs12RC2_40Aliases, null); - ps("Cipher", "PBEWithSHA1AndRC2_128", + null); + psA("Cipher", "PBEWithSHA1AndRC2_128", "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC2_128", - pkcs12RC2_128Aliases, null); - ps("Cipher", "PBEWithSHA1AndRC4_40", + null); + psA("Cipher", "PBEWithSHA1AndRC4_40", "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC4_40", - pkcs12RC4_40Aliases, null); + null); - ps("Cipher", "PBEWithSHA1AndRC4_128", + psA("Cipher", "PBEWithSHA1AndRC4_128", "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC4_128", - pkcs12RC4_128Aliases, null); + null); // PBES2 ps("Cipher", "PBEWithHmacSHA1AndAES_128", - "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_128", - null, null); + "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_128"); ps("Cipher", "PBEWithHmacSHA224AndAES_128", - "com.sun.crypto.provider.PBES2Core$HmacSHA224AndAES_128", - null, null); + "com.sun.crypto.provider.PBES2Core$HmacSHA224AndAES_128"); ps("Cipher", "PBEWithHmacSHA256AndAES_128", - "com.sun.crypto.provider.PBES2Core$HmacSHA256AndAES_128", - null, null); + "com.sun.crypto.provider.PBES2Core$HmacSHA256AndAES_128"); ps("Cipher", "PBEWithHmacSHA384AndAES_128", - "com.sun.crypto.provider.PBES2Core$HmacSHA384AndAES_128", - null, null); + "com.sun.crypto.provider.PBES2Core$HmacSHA384AndAES_128"); ps("Cipher", "PBEWithHmacSHA512AndAES_128", - "com.sun.crypto.provider.PBES2Core$HmacSHA512AndAES_128", - null, null); + "com.sun.crypto.provider.PBES2Core$HmacSHA512AndAES_128"); ps("Cipher", "PBEWithHmacSHA1AndAES_256", - "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_256", - null, null); + "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_256"); ps("Cipher", "PBEWithHmacSHA224AndAES_256", - "com.sun.crypto.provider.PBES2Core$HmacSHA224AndAES_256", - null, null); + "com.sun.crypto.provider.PBES2Core$HmacSHA224AndAES_256"); ps("Cipher", "PBEWithHmacSHA256AndAES_256", - "com.sun.crypto.provider.PBES2Core$HmacSHA256AndAES_256", - null, null); + "com.sun.crypto.provider.PBES2Core$HmacSHA256AndAES_256"); ps("Cipher", "PBEWithHmacSHA384AndAES_256", - "com.sun.crypto.provider.PBES2Core$HmacSHA384AndAES_256", - null, null); + "com.sun.crypto.provider.PBES2Core$HmacSHA384AndAES_256"); ps("Cipher", "PBEWithHmacSHA512AndAES_256", - "com.sun.crypto.provider.PBES2Core$HmacSHA512AndAES_256", - null, null); + "com.sun.crypto.provider.PBES2Core$HmacSHA512AndAES_256"); /* * Key(pair) Generator engines */ ps("KeyGenerator", "DES", - "com.sun.crypto.provider.DESKeyGenerator", - null, null); - ps("KeyGenerator", "DESede", + "com.sun.crypto.provider.DESKeyGenerator"); + psA("KeyGenerator", "DESede", "com.sun.crypto.provider.DESedeKeyGenerator", - desEdeAliases, null); + null); ps("KeyGenerator", "Blowfish", - "com.sun.crypto.provider.BlowfishKeyGenerator", - null, null); - ps("KeyGenerator", "AES", + "com.sun.crypto.provider.BlowfishKeyGenerator"); + psA("KeyGenerator", "AES", "com.sun.crypto.provider.AESKeyGenerator", - aesAliases, null); + null); ps("KeyGenerator", "RC2", - "com.sun.crypto.provider.KeyGeneratorCore$RC2KeyGenerator", - null, null); - ps("KeyGenerator", "ARCFOUR", + "com.sun.crypto.provider.KeyGeneratorCore$RC2KeyGenerator"); + psA("KeyGenerator", "ARCFOUR", "com.sun.crypto.provider.KeyGeneratorCore$ARCFOURKeyGenerator", - arcFourAliases, null); + null); ps("KeyGenerator", "ChaCha20", - "com.sun.crypto.provider.KeyGeneratorCore$ChaCha20KeyGenerator", - null, null); + "com.sun.crypto.provider.KeyGeneratorCore$ChaCha20KeyGenerator"); ps("KeyGenerator", "HmacMD5", - "com.sun.crypto.provider.HmacMD5KeyGenerator", - null, null); + "com.sun.crypto.provider.HmacMD5KeyGenerator"); - ps("KeyGenerator", "HmacSHA1", - "com.sun.crypto.provider.HmacSHA1KeyGenerator", - macSHA1Aliases, null); - ps("KeyGenerator", "HmacSHA224", + psA("KeyGenerator", "HmacSHA1", + "com.sun.crypto.provider.HmacSHA1KeyGenerator", null); + psA("KeyGenerator", "HmacSHA224", "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA224", - macSHA224Aliases, null); - ps("KeyGenerator", "HmacSHA256", + null); + psA("KeyGenerator", "HmacSHA256", "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA256", - macSHA256Aliases, null); - ps("KeyGenerator", "HmacSHA384", + null); + psA("KeyGenerator", "HmacSHA384", "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA384", - macSHA384Aliases, null); - ps("KeyGenerator", "HmacSHA512", + null); + psA("KeyGenerator", "HmacSHA512", "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA512", - macSHA512Aliases, null); + null); - ps("KeyPairGenerator", "DiffieHellman", + psA("KeyPairGenerator", "DiffieHellman", "com.sun.crypto.provider.DHKeyPairGenerator", - diffieHellmanAliases, null); + null); /* * Algorithm parameter generation engines */ - ps("AlgorithmParameterGenerator", + psA("AlgorithmParameterGenerator", "DiffieHellman", "com.sun.crypto.provider.DHParameterGenerator", - diffieHellmanAliases, null); + null); /* * Key Agreement engines @@ -437,142 +381,120 @@ void putEntries() { attrs.clear(); attrs.put("SupportedKeyClasses", "javax.crypto.interfaces.DHPublicKey" + "|javax.crypto.interfaces.DHPrivateKey"); - ps("KeyAgreement", "DiffieHellman", + psA("KeyAgreement", "DiffieHellman", "com.sun.crypto.provider.DHKeyAgreement", - diffieHellmanAliases, attrs); + attrs); /* * Algorithm Parameter engines */ - ps("AlgorithmParameters", "DiffieHellman", - "com.sun.crypto.provider.DHParameters", - diffieHellmanAliases, null); + psA("AlgorithmParameters", "DiffieHellman", + "com.sun.crypto.provider.DHParameters", null); ps("AlgorithmParameters", "DES", - "com.sun.crypto.provider.DESParameters", - null, null); + "com.sun.crypto.provider.DESParameters"); - ps("AlgorithmParameters", "DESede", - "com.sun.crypto.provider.DESedeParameters", - desEdeAliases, null); + psA("AlgorithmParameters", "DESede", + "com.sun.crypto.provider.DESedeParameters", null); - ps("AlgorithmParameters", "PBEWithMD5AndDES", + psA("AlgorithmParameters", "PBEWithMD5AndDES", "com.sun.crypto.provider.PBEParameters", - pkcs5MD5_DESAliases, null); + null); ps("AlgorithmParameters", "PBEWithMD5AndTripleDES", - "com.sun.crypto.provider.PBEParameters", - null, null); + "com.sun.crypto.provider.PBEParameters"); - ps("AlgorithmParameters", "PBEWithSHA1AndDESede", + psA("AlgorithmParameters", "PBEWithSHA1AndDESede", "com.sun.crypto.provider.PBEParameters", - pkcs12DESedeAliases, null); + null); - ps("AlgorithmParameters", "PBEWithSHA1AndRC2_40", + psA("AlgorithmParameters", "PBEWithSHA1AndRC2_40", "com.sun.crypto.provider.PBEParameters", - pkcs12RC2_40Aliases, null); + null); - ps("AlgorithmParameters", "PBEWithSHA1AndRC2_128", + psA("AlgorithmParameters", "PBEWithSHA1AndRC2_128", "com.sun.crypto.provider.PBEParameters", - pkcs12RC2_128Aliases, null); + null); - ps("AlgorithmParameters", "PBEWithSHA1AndRC4_40", + psA("AlgorithmParameters", "PBEWithSHA1AndRC4_40", "com.sun.crypto.provider.PBEParameters", - pkcs12RC4_40Aliases, null); + null); - ps("AlgorithmParameters", "PBEWithSHA1AndRC4_128", + psA("AlgorithmParameters", "PBEWithSHA1AndRC4_128", "com.sun.crypto.provider.PBEParameters", - pkcs12RC4_128Aliases, null); + null); - ps("AlgorithmParameters", "PBES2", + psA("AlgorithmParameters", "PBES2", "com.sun.crypto.provider.PBES2Parameters$General", - pkcs5PBES2Aliases, null); + null); ps("AlgorithmParameters", "PBEWithHmacSHA1AndAES_128", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA1AndAES_128", - null, null); + "com.sun.crypto.provider.PBES2Parameters$HmacSHA1AndAES_128"); ps("AlgorithmParameters", "PBEWithHmacSHA224AndAES_128", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA224AndAES_128", - null, null); + "com.sun.crypto.provider.PBES2Parameters$HmacSHA224AndAES_128"); ps("AlgorithmParameters", "PBEWithHmacSHA256AndAES_128", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA256AndAES_128", - null, null); + "com.sun.crypto.provider.PBES2Parameters$HmacSHA256AndAES_128"); ps("AlgorithmParameters", "PBEWithHmacSHA384AndAES_128", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA384AndAES_128", - null, null); + "com.sun.crypto.provider.PBES2Parameters$HmacSHA384AndAES_128"); ps("AlgorithmParameters", "PBEWithHmacSHA512AndAES_128", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA512AndAES_128", - null, null); + "com.sun.crypto.provider.PBES2Parameters$HmacSHA512AndAES_128"); ps("AlgorithmParameters", "PBEWithHmacSHA1AndAES_256", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA1AndAES_256", - null, null); + "com.sun.crypto.provider.PBES2Parameters$HmacSHA1AndAES_256"); ps("AlgorithmParameters", "PBEWithHmacSHA224AndAES_256", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA224AndAES_256", - null, null); + "com.sun.crypto.provider.PBES2Parameters$HmacSHA224AndAES_256"); ps("AlgorithmParameters", "PBEWithHmacSHA256AndAES_256", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA256AndAES_256", - null, null); + "com.sun.crypto.provider.PBES2Parameters$HmacSHA256AndAES_256"); ps("AlgorithmParameters", "PBEWithHmacSHA384AndAES_256", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA384AndAES_256", - null, null); + "com.sun.crypto.provider.PBES2Parameters$HmacSHA384AndAES_256"); ps("AlgorithmParameters", "PBEWithHmacSHA512AndAES_256", - "com.sun.crypto.provider.PBES2Parameters$HmacSHA512AndAES_256", - null, null); + "com.sun.crypto.provider.PBES2Parameters$HmacSHA512AndAES_256"); ps("AlgorithmParameters", "Blowfish", - "com.sun.crypto.provider.BlowfishParameters", - null, null); + "com.sun.crypto.provider.BlowfishParameters"); - ps("AlgorithmParameters", "AES", - "com.sun.crypto.provider.AESParameters", - aesAliases, null); + psA("AlgorithmParameters", "AES", + "com.sun.crypto.provider.AESParameters", null); ps("AlgorithmParameters", "GCM", - "com.sun.crypto.provider.GCMParameters", - null, null); + "com.sun.crypto.provider.GCMParameters"); ps("AlgorithmParameters", "RC2", - "com.sun.crypto.provider.RC2Parameters", - null, null); + "com.sun.crypto.provider.RC2Parameters"); ps("AlgorithmParameters", "OAEP", - "com.sun.crypto.provider.OAEPParameters", - null, null); + "com.sun.crypto.provider.OAEPParameters"); - ps("AlgorithmParameters", "ChaCha20-Poly1305", - "com.sun.crypto.provider.ChaCha20Poly1305Parameters", - chachaPolyAliases, null); + psA("AlgorithmParameters", "ChaCha20-Poly1305", + "com.sun.crypto.provider.ChaCha20Poly1305Parameters", null); /* * Key factories */ - ps("KeyFactory", "DiffieHellman", + psA("KeyFactory", "DiffieHellman", "com.sun.crypto.provider.DHKeyFactory", - diffieHellmanAliases, null); + null); /* * Secret-key factories */ ps("SecretKeyFactory", "DES", - "com.sun.crypto.provider.DESKeyFactory", - null, null); + "com.sun.crypto.provider.DESKeyFactory"); - ps("SecretKeyFactory", "DESede", - "com.sun.crypto.provider.DESedeKeyFactory", - desEdeAliases, null); + psA("SecretKeyFactory", "DESede", + "com.sun.crypto.provider.DESedeKeyFactory", null); - ps("SecretKeyFactory", "PBEWithMD5AndDES", + psA("SecretKeyFactory", "PBEWithMD5AndDES", "com.sun.crypto.provider.PBEKeyFactory$PBEWithMD5AndDES", - pkcs5MD5_DESAliases, null); + null); /* * Internal in-house crypto algorithm used for @@ -581,85 +503,70 @@ void putEntries() { * algorithm. */ ps("SecretKeyFactory", "PBEWithMD5AndTripleDES", - "com.sun.crypto.provider.PBEKeyFactory$PBEWithMD5AndTripleDES", - null, null); + "com.sun.crypto.provider.PBEKeyFactory$PBEWithMD5AndTripleDES"); - ps("SecretKeyFactory", "PBEWithSHA1AndDESede", + psA("SecretKeyFactory", "PBEWithSHA1AndDESede", "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndDESede", - pkcs12DESedeAliases, null); + null); - ps("SecretKeyFactory", "PBEWithSHA1AndRC2_40", + psA("SecretKeyFactory", "PBEWithSHA1AndRC2_40", "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC2_40", - pkcs12RC2_40Aliases, null); + null); - ps("SecretKeyFactory", "PBEWithSHA1AndRC2_128", + psA("SecretKeyFactory", "PBEWithSHA1AndRC2_128", "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC2_128", - pkcs12RC2_128Aliases, null); + null); - ps("SecretKeyFactory", "PBEWithSHA1AndRC4_40", + psA("SecretKeyFactory", "PBEWithSHA1AndRC4_40", "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC4_40", - pkcs12RC4_40Aliases,null); + null); - ps("SecretKeyFactory", "PBEWithSHA1AndRC4_128", + psA("SecretKeyFactory", "PBEWithSHA1AndRC4_128", "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC4_128", - pkcs12RC4_128Aliases, null); + null); ps("SecretKeyFactory", "PBEWithHmacSHA1AndAES_128", - "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA1AndAES_128", - null, null); + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA1AndAES_128"); ps("SecretKeyFactory", "PBEWithHmacSHA224AndAES_128", - "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA224AndAES_128", - null, null); + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA224AndAES_128"); ps("SecretKeyFactory", "PBEWithHmacSHA256AndAES_128", - "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA256AndAES_128", - null, null); + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA256AndAES_128"); ps("SecretKeyFactory", "PBEWithHmacSHA384AndAES_128", - "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA384AndAES_128", - null, null); + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA384AndAES_128"); ps("SecretKeyFactory", "PBEWithHmacSHA512AndAES_128", - "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA512AndAES_128", - null, null); + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA512AndAES_128"); ps("SecretKeyFactory", "PBEWithHmacSHA1AndAES_256", - "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA1AndAES_256", - null, null); + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA1AndAES_256"); ps("SecretKeyFactory", "PBEWithHmacSHA224AndAES_256", - "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA224AndAES_256", - null, null); + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA224AndAES_256"); ps("SecretKeyFactory", "PBEWithHmacSHA256AndAES_256", - "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA256AndAES_256", - null, null); + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA256AndAES_256"); ps("SecretKeyFactory", "PBEWithHmacSHA384AndAES_256", - "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA384AndAES_256", - null, null); + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA384AndAES_256"); ps("SecretKeyFactory", "PBEWithHmacSHA512AndAES_256", - "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA512AndAES_256", - null, null); + "com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA512AndAES_256"); // PBKDF2 - ps("SecretKeyFactory", "PBKDF2WithHmacSHA1", + psA("SecretKeyFactory", "PBKDF2WithHmacSHA1", "com.sun.crypto.provider.PBKDF2Core$HmacSHA1", - pkcs5PBKDF2Aliases, null); + null); ps("SecretKeyFactory", "PBKDF2WithHmacSHA224", - "com.sun.crypto.provider.PBKDF2Core$HmacSHA224", - null, null); + "com.sun.crypto.provider.PBKDF2Core$HmacSHA224"); ps("SecretKeyFactory", "PBKDF2WithHmacSHA256", - "com.sun.crypto.provider.PBKDF2Core$HmacSHA256", - null, null); + "com.sun.crypto.provider.PBKDF2Core$HmacSHA256"); ps("SecretKeyFactory", "PBKDF2WithHmacSHA384", - "com.sun.crypto.provider.PBKDF2Core$HmacSHA384", - null, null); + "com.sun.crypto.provider.PBKDF2Core$HmacSHA384"); ps("SecretKeyFactory", "PBKDF2WithHmacSHA512", - "com.sun.crypto.provider.PBKDF2Core$HmacSHA512", - null, null); + "com.sun.crypto.provider.PBKDF2Core$HmacSHA512"); /* * MAC @@ -667,23 +574,20 @@ void putEntries() { attrs.clear(); attrs.put("SupportedKeyFormats", "RAW"); ps("Mac", "HmacMD5", "com.sun.crypto.provider.HmacMD5", null, attrs); - ps("Mac", "HmacSHA1", "com.sun.crypto.provider.HmacSHA1", - macSHA1Aliases, attrs); - ps("Mac", "HmacSHA224", "com.sun.crypto.provider.HmacCore$HmacSHA224", - macSHA224Aliases, attrs); - ps("Mac", "HmacSHA256", "com.sun.crypto.provider.HmacCore$HmacSHA256", - macSHA256Aliases, attrs); - ps("Mac", "HmacSHA384", "com.sun.crypto.provider.HmacCore$HmacSHA384", - macSHA384Aliases, attrs); - ps("Mac", "HmacSHA512", "com.sun.crypto.provider.HmacCore$HmacSHA512", - macSHA512Aliases, attrs); - // TODO: aliases with OIDs - ps("Mac", "HmacSHA512/224", - "com.sun.crypto.provider.HmacCore$HmacSHA512_224", - null, attrs); - ps("Mac", "HmacSHA512/256", - "com.sun.crypto.provider.HmacCore$HmacSHA512_256", - null, attrs); + psA("Mac", "HmacSHA1", "com.sun.crypto.provider.HmacSHA1", + attrs); + psA("Mac", "HmacSHA224", + "com.sun.crypto.provider.HmacCore$HmacSHA224", attrs); + psA("Mac", "HmacSHA256", + "com.sun.crypto.provider.HmacCore$HmacSHA256", attrs); + psA("Mac", "HmacSHA384", + "com.sun.crypto.provider.HmacCore$HmacSHA384", attrs); + psA("Mac", "HmacSHA512", + "com.sun.crypto.provider.HmacCore$HmacSHA512", attrs); + psA("Mac", "HmacSHA512/224", + "com.sun.crypto.provider.HmacCore$HmacSHA512_224", attrs); + psA("Mac", "HmacSHA512/256", + "com.sun.crypto.provider.HmacCore$HmacSHA512_256", attrs); ps("Mac", "HmacPBESHA1", "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA1", null, attrs); @@ -727,8 +631,7 @@ void putEntries() { * KeyStore */ ps("KeyStore", "JCEKS", - "com.sun.crypto.provider.JceKeyStore", - null, null); + "com.sun.crypto.provider.JceKeyStore"); /* * SSL/TLS mechanisms @@ -739,24 +642,22 @@ void putEntries() { * mechanisms, and it will cause calls to come here. */ ps("KeyGenerator", "SunTlsPrf", - "com.sun.crypto.provider.TlsPrfGenerator$V10", - null, null); + "com.sun.crypto.provider.TlsPrfGenerator$V10"); ps("KeyGenerator", "SunTls12Prf", - "com.sun.crypto.provider.TlsPrfGenerator$V12", - null, null); + "com.sun.crypto.provider.TlsPrfGenerator$V12"); ps("KeyGenerator", "SunTlsMasterSecret", "com.sun.crypto.provider.TlsMasterSecretGenerator", - createAliases("SunTls12MasterSecret", - "SunTlsExtendedMasterSecret"), null); + List.of("SunTls12MasterSecret", "SunTlsExtendedMasterSecret"), + null); ps("KeyGenerator", "SunTlsKeyMaterial", "com.sun.crypto.provider.TlsKeyMaterialGenerator", - createAliases("SunTls12KeyMaterial"), null); + List.of("SunTls12KeyMaterial"), null); ps("KeyGenerator", "SunTlsRsaPremasterSecret", "com.sun.crypto.provider.TlsRsaPremasterSecretGenerator", - createAliases("SunTls12RsaPremasterSecret"), null); + List.of("SunTls12RsaPremasterSecret"), null); } // Return the instance of this class or create one if needed. diff --git a/src/java.base/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java b/src/java.base/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java index be0b28a891a..5028e4bb3c4 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package com.sun.crypto.provider; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.security.*; import java.security.spec.AlgorithmParameterSpec; @@ -61,11 +64,11 @@ protected void engineInit(SecureRandom random) { @SuppressWarnings("deprecation") protected void engineInit(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { - if (params instanceof TlsMasterSecretParameterSpec == false) { + if (!(params instanceof TlsMasterSecretParameterSpec)) { throw new InvalidAlgorithmParameterException(MSG); } this.spec = (TlsMasterSecretParameterSpec)params; - if ("RAW".equals(spec.getPremasterSecret().getFormat()) == false) { + if (!"RAW".equals(spec.getPremasterSecret().getFormat())) { throw new InvalidAlgorithmParameterException( "Key format must be RAW"); } @@ -185,6 +188,21 @@ public byte[] getEncoded() { return key.clone(); } - } + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if ((key == null) || (key.length == 0)) { + throw new InvalidObjectException("TlsMasterSecretKey is null"); + } + key = key.clone(); + } + } } diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java index 86392160c9e..212a612c1f7 100644 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java +++ b/src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java @@ -61,7 +61,7 @@ class NativeUnpack { // Resets the engine and frees all resources. // Returns total number of bytes consumed by the engine. - private synchronized native long finish(); + synchronized native long finish(); // Setting state in the unpacker. protected synchronized native boolean setOption(String opt, String value); diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java index e5942075fbf..9ff1369295c 100644 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java +++ b/src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java @@ -116,6 +116,11 @@ public synchronized void unpack(InputStream in, JarOutputStream out) throws IOEx } catch (UnsatisfiedLinkError | NoClassDefFoundError ex) { // failover to java implementation (new DoUnpack()).run(in0, out); + } finally { + if (_nunp != null) { + // Free up native memory and JNI handles to prevent leaks + ((NativeUnpack) _nunp).finish(); + } } in0.close(); Utils.markJarFile(out); diff --git a/src/java.base/share/classes/java/net/URI.java b/src/java.base/share/classes/java/net/URI.java index 863bb771350..7d1bf935363 100644 --- a/src/java.base/share/classes/java/net/URI.java +++ b/src/java.base/share/classes/java/net/URI.java @@ -3193,6 +3193,7 @@ private int parseAuthority(int start, int n) boolean serverChars; boolean regChars; + boolean skipParseException; if (scan(p, n, "]") > p) { // contains a literal IPv6 address, therefore % is allowed @@ -3208,15 +3209,28 @@ private int parseAuthority(int start, int n) return n; } + // When parsing a URI, skip creating exception objects if the server-based + // authority is not required and the registry parse is successful. + // + skipParseException = (!requireServerAuthority && regChars); if (serverChars) { // Might be (probably is) a server-based authority, so attempt // to parse it as such. If the attempt fails, try to treat it // as a registry-based authority. try { - q = parseServer(p, n); - if (q < n) - failExpecting("end of authority", q); - authority = input.substring(p, n); + q = parseServer(p, n, skipParseException); + if (q < n) { + if (skipParseException) { + userInfo = null; + host = null; + port = -1; + q = p; + } else { + failExpecting("end of authority", q); + } + } else { + authority = input.substring(p, n); + } } catch (URISyntaxException x) { // Undo results of failed parse userInfo = null; @@ -3254,7 +3268,7 @@ private int parseAuthority(int start, int n) // [@][:] // - private int parseServer(int start, int n) + private int parseServer(int start, int n, boolean skipParseException) throws URISyntaxException { int p = start; @@ -3294,7 +3308,7 @@ private int parseServer(int start, int n) } else { q = parseIPv4Address(p, n); if (q <= p) - q = parseHostname(p, n); + q = parseHostname(p, n, skipParseException); p = q; } @@ -3311,7 +3325,10 @@ private int parseServer(int start, int n) } p = q; } + } else if (p < n && skipParseException) { + return p; } + if (p < n) failExpecting("port number", p); @@ -3416,7 +3433,7 @@ private int parseIPv4Address(int start, int n) { // domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum // toplabel = alpha | alpha *( alphanum | "-" ) alphanum // - private int parseHostname(int start, int n) + private int parseHostname(int start, int n, boolean skipParseException) throws URISyntaxException { int p = start; @@ -3444,9 +3461,12 @@ private int parseHostname(int start, int n) p = q; } while (p < n); - if ((p < n) && !at(p, n, ':')) + if ((p < n) && !at(p, n, ':')) { + if (skipParseException) { + return p; + } fail("Illegal character in hostname", p); - + } if (l < 0) failExpecting("hostname", start); diff --git a/src/java.base/share/classes/java/security/AlgorithmParameterGenerator.java b/src/java.base/share/classes/java/security/AlgorithmParameterGenerator.java index 9f3cabc78ea..af8bdd545aa 100644 --- a/src/java.base/share/classes/java/security/AlgorithmParameterGenerator.java +++ b/src/java.base/share/classes/java/security/AlgorithmParameterGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -309,7 +309,7 @@ public final Provider getProvider() { * @param size the size (number of bits). */ public final void init(int size) { - paramGenSpi.engineInit(size, JCAUtil.getSecureRandom()); + paramGenSpi.engineInit(size, JCAUtil.getDefSecureRandom()); } /** @@ -340,7 +340,7 @@ public final void init(int size, SecureRandom random) { */ public final void init(AlgorithmParameterSpec genParamSpec) throws InvalidAlgorithmParameterException { - paramGenSpi.engineInit(genParamSpec, JCAUtil.getSecureRandom()); + paramGenSpi.engineInit(genParamSpec, JCAUtil.getDefSecureRandom()); } /** diff --git a/src/java.base/share/classes/java/security/CodeSigner.java b/src/java.base/share/classes/java/security/CodeSigner.java index a1d37ee208a..26793a7c15d 100644 --- a/src/java.base/share/classes/java/security/CodeSigner.java +++ b/src/java.base/share/classes/java/security/CodeSigner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -156,9 +156,9 @@ public boolean equals(Object obj) { public String toString() { StringBuilder sb = new StringBuilder(); sb.append("("); - sb.append("Signer: " + signerCertPath.getCertificates().get(0)); + sb.append("Signer: ").append(signerCertPath.getCertificates().get(0)); if (timestamp != null) { - sb.append("timestamp: " + timestamp); + sb.append("timestamp: ").append(timestamp); } sb.append(")"); return sb.toString(); @@ -166,8 +166,11 @@ public String toString() { // Explicitly reset hash code value to -1 private void readObject(ObjectInputStream ois) - throws IOException, ClassNotFoundException { - ois.defaultReadObject(); - myhash = -1; + throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + if (signerCertPath == null) { + throw new InvalidObjectException("signerCertPath is null"); + } + myhash = -1; } } diff --git a/src/java.base/share/classes/java/security/KeyPairGenerator.java b/src/java.base/share/classes/java/security/KeyPairGenerator.java index eee081ae51e..4c564989482 100644 --- a/src/java.base/share/classes/java/security/KeyPairGenerator.java +++ b/src/java.base/share/classes/java/security/KeyPairGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -373,7 +373,7 @@ void disableFailover() { * supported by this KeyPairGenerator object. */ public void initialize(int keysize) { - initialize(keysize, JCAUtil.getSecureRandom()); + initialize(keysize, JCAUtil.getDefSecureRandom()); } /** @@ -433,7 +433,7 @@ public void initialize(int keysize, SecureRandom random) { */ public void initialize(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { - initialize(params, JCAUtil.getSecureRandom()); + initialize(params, JCAUtil.getDefSecureRandom()); } /** diff --git a/src/java.base/share/classes/java/security/PKCS12Attribute.java b/src/java.base/share/classes/java/security/PKCS12Attribute.java index 4a8ebfb64c0..ffce09318e3 100644 --- a/src/java.base/share/classes/java/security/PKCS12Attribute.java +++ b/src/java.base/share/classes/java/security/PKCS12Attribute.java @@ -76,7 +76,7 @@ public PKCS12Attribute(String name, String value) { // Validate name ObjectIdentifier type; try { - type = new ObjectIdentifier(name); + type = ObjectIdentifier.of(name); } catch (IOException e) { throw new IllegalArgumentException("Incorrect format: name", e); } diff --git a/src/java.base/share/classes/java/security/Security.java b/src/java.base/share/classes/java/security/Security.java index b36510a376b..5b9552058b5 100644 --- a/src/java.base/share/classes/java/security/Security.java +++ b/src/java.base/share/classes/java/security/Security.java @@ -47,6 +47,9 @@ * implementation-specific location, which is typically the properties file * {@code conf/security/java.security} in the Java installation directory. * + * @implNote If the properties file fails to load, the JDK implementation will + * throw an unspecified error when initializing the {@code Security} class. + * * @author Benjamin Renaud * @since 1.1 */ @@ -81,130 +84,83 @@ public Void run() { private static void initialize() { props = new Properties(); - boolean loadedProps = false; boolean overrideAll = false; // first load the system properties file // to determine the value of security.overridePropertiesFile File propFile = securityPropFile("java.security"); - if (propFile.exists()) { - InputStream is = null; - try { - FileInputStream fis = new FileInputStream(propFile); - is = new BufferedInputStream(fis); - props.load(is); - loadedProps = true; - - if (sdebug != null) { - sdebug.println("reading security properties file: " + - propFile); - } - } catch (IOException e) { - if (sdebug != null) { - sdebug.println("unable to load security properties from " + - propFile); - e.printStackTrace(); - } - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException ioe) { - if (sdebug != null) { - sdebug.println("unable to close input stream"); - } - } - } - } + boolean success = loadProps(propFile, null, false); + if (!success) { + throw new InternalError("Error loading java.security file"); } if ("true".equalsIgnoreCase(props.getProperty ("security.overridePropertiesFile"))) { String extraPropFile = System.getProperty - ("java.security.properties"); + ("java.security.properties"); if (extraPropFile != null && extraPropFile.startsWith("=")) { overrideAll = true; extraPropFile = extraPropFile.substring(1); } + loadProps(null, extraPropFile, overrideAll); + } + } - if (overrideAll) { - props = new Properties(); - if (sdebug != null) { - sdebug.println - ("overriding other security properties files!"); + private static boolean loadProps(File masterFile, String extraPropFile, boolean overrideAll) { + InputStream is = null; + try { + if (masterFile != null && masterFile.exists()) { + is = new FileInputStream(masterFile); + } else if (extraPropFile != null) { + extraPropFile = PropertyExpander.expand(extraPropFile); + File propFile = new File(extraPropFile); + URL propURL; + if (propFile.exists()) { + propURL = new URL + ("file:" + propFile.getCanonicalPath()); + } else { + propURL = new URL(extraPropFile); } - } - - // now load the user-specified file so its values - // will win if they conflict with the earlier values - if (extraPropFile != null) { - BufferedInputStream bis = null; - try { - URL propURL; - - extraPropFile = PropertyExpander.expand(extraPropFile); - propFile = new File(extraPropFile); - if (propFile.exists()) { - propURL = new URL - ("file:" + propFile.getCanonicalPath()); - } else { - propURL = new URL(extraPropFile); - } - bis = new BufferedInputStream(propURL.openStream()); - props.load(bis); - loadedProps = true; - if (sdebug != null) { - sdebug.println("reading security properties file: " + - propURL); - if (overrideAll) { - sdebug.println - ("overriding other security properties files!"); - } - } - } catch (Exception e) { + is = propURL.openStream(); + if (overrideAll) { + props = new Properties(); if (sdebug != null) { sdebug.println - ("unable to load security properties from " + - extraPropFile); - e.printStackTrace(); - } - } finally { - if (bis != null) { - try { - bis.close(); - } catch (IOException ioe) { - if (sdebug != null) { - sdebug.println("unable to close input stream"); - } - } + ("overriding other security properties files!"); } } + } else { + // unexpected + return false; } - } - - if (!loadedProps) { - initializeStatic(); + props.load(is); if (sdebug != null) { - sdebug.println("unable to load security properties " + - "-- using defaults"); + // ExceptionInInitializerError if masterFile.getName() is + // called here (NPE!). Leave as is (and few lines down) + sdebug.println("reading security properties file: " + + masterFile == null ? extraPropFile : "java.security"); + } + return true; + } catch (IOException | PropertyExpander.ExpandException e) { + if (sdebug != null) { + sdebug.println("unable to load security properties from " + + masterFile == null ? extraPropFile : "java.security"); + e.printStackTrace(); + } + return false; + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException ioe) { + if (sdebug != null) { + sdebug.println("unable to close input stream"); + } + } } } - - } - - /* - * Initialize to default values, if /lib/java.security - * is not found. - */ - private static void initializeStatic() { - props.put("security.provider.1", "sun.security.provider.Sun"); - props.put("security.provider.2", "sun.security.rsa.SunRsaSign"); - props.put("security.provider.3", "com.sun.net.ssl.internal.ssl.Provider"); - props.put("security.provider.4", "com.sun.crypto.provider.SunJCE"); - props.put("security.provider.5", "sun.security.jgss.SunProvider"); - props.put("security.provider.6", "com.sun.security.sasl.Provider"); } /** diff --git a/src/java.base/share/classes/java/security/cert/CertPathHelperImpl.java b/src/java.base/share/classes/java/security/cert/CertPathHelperImpl.java index bd6545a7357..3da6cb3dd4f 100644 --- a/src/java.base/share/classes/java/security/cert/CertPathHelperImpl.java +++ b/src/java.base/share/classes/java/security/cert/CertPathHelperImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,10 @@ package java.security.cert; -import java.util.*; +import java.util.Date; import sun.security.provider.certpath.CertPathHelper; -import sun.security.x509.GeneralNameInterface; - /** * Helper class that allows the Sun CertPath provider to access * implementation dependent APIs in CertPath framework. @@ -55,11 +53,6 @@ static synchronized void initialize() { } } - protected void implSetPathToNames(X509CertSelector sel, - Set names) { - sel.setPathToNamesInternal(names); - } - protected void implSetDateAndTime(X509CRLSelector sel, Date date, long skew) { sel.setDateAndTime(date, skew); } diff --git a/src/java.base/share/classes/java/security/cert/CertificateFactory.java b/src/java.base/share/classes/java/security/cert/CertificateFactory.java index ae4e8bd05c4..40870fce541 100644 --- a/src/java.base/share/classes/java/security/cert/CertificateFactory.java +++ b/src/java.base/share/classes/java/security/cert/CertificateFactory.java @@ -26,14 +26,14 @@ package java.security.cert; import java.io.InputStream; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; import java.security.Provider; import java.security.Security; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; @@ -352,7 +352,9 @@ public final String getType() { public final Certificate generateCertificate(InputStream inStream) throws CertificateException { - return certFacSpi.engineGenerateCertificate(inStream); + Certificate c = certFacSpi.engineGenerateCertificate(inStream); + JCAUtil.tryCommitCertEvent(c); + return c; } /** diff --git a/src/java.base/share/classes/java/security/cert/CertificateRevokedException.java b/src/java.base/share/classes/java/security/cert/CertificateRevokedException.java index 0bac9a64870..bd8bdb11fb8 100644 --- a/src/java.base/share/classes/java/security/cert/CertificateRevokedException.java +++ b/src/java.base/share/classes/java/security/cert/CertificateRevokedException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -243,7 +243,7 @@ private void readObject(ObjectInputStream ois) boolean critical = ois.readBoolean(); byte[] extVal = IOUtils.readExactlyNBytes(ois, ois.readInt()); Extension ext = sun.security.x509.Extension.newExtension - (new ObjectIdentifier(oid), critical, extVal); + (ObjectIdentifier.of(oid), critical, extVal); extensions.put(oid, ext); } } diff --git a/src/java.base/share/classes/java/security/cert/X509CertSelector.java b/src/java.base/share/classes/java/security/cert/X509CertSelector.java index 70c77258ad0..55b0732ccef 100644 --- a/src/java.base/share/classes/java/security/cert/X509CertSelector.java +++ b/src/java.base/share/classes/java/security/cert/X509CertSelector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,11 +31,7 @@ import java.util.*; import javax.security.auth.x500.X500Principal; -import sun.security.util.HexDumpEncoder; -import sun.security.util.Debug; -import sun.security.util.DerInputStream; -import sun.security.util.DerValue; -import sun.security.util.ObjectIdentifier; +import sun.security.util.*; import sun.security.x509.*; /** @@ -88,11 +84,7 @@ public class X509CertSelector implements CertSelector { private static final Debug debug = Debug.getInstance("certpath"); private static final ObjectIdentifier ANY_EXTENDED_KEY_USAGE = - ObjectIdentifier.newInternal(new int[] {2, 5, 29, 37, 0}); - - static { - CertPathHelperImpl.initialize(); - } + ObjectIdentifier.of(KnownOIDs.anyExtendedKeyUsage); private BigInteger serialNumber; private X500Principal issuer; @@ -506,7 +498,7 @@ public void setSubjectPublicKeyAlgID(String oid) throws IOException { if (oid == null) { subjectPublicKeyAlgID = null; } else { - subjectPublicKeyAlgID = new ObjectIdentifier(oid); + subjectPublicKeyAlgID = ObjectIdentifier.of(oid); } } @@ -622,7 +614,7 @@ public void setExtendedKeyUsage(Set keyPurposeSet) throws IOException { Collections.unmodifiableSet(new HashSet<>(keyPurposeSet)); keyPurposeOIDSet = new HashSet<>(); for (String s : this.keyPurposeSet) { - keyPurposeOIDSet.add(new ObjectIdentifier(s)); + keyPurposeOIDSet.add(ObjectIdentifier.of(s)); } } } @@ -1105,8 +1097,8 @@ public void setPolicy(Set certPolicySet) throws IOException { if (!(o instanceof String)) { throw new IOException("non String in certPolicySet"); } - polIdVector.add(new CertificatePolicyId(new ObjectIdentifier( - (String)o))); + polIdVector.add(new CertificatePolicyId + (ObjectIdentifier.of((String)o))); } // If everything went OK, make the changes policySet = tempSet; @@ -1177,14 +1169,6 @@ public void setPathToNames(Collection> names) throws IOException { } } - // called from CertPathHelper - void setPathToNamesInternal(Set names) { - // set names to non-null dummy value - // this breaks getPathToNames() - pathToNames = Collections.>emptySet(); - pathToGeneralNames = names; - } - /** * Adds a name to the pathToNames criterion. The {@code X509Certificate} * must not include name constraints that would prohibit building a diff --git a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java index 4c8e9b159fc..4015d5697d5 100644 --- a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java +++ b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java @@ -1807,6 +1807,8 @@ public boolean block() { * interrupted. */ private Object waitingGet(boolean interruptible) { + if (interruptible && Thread.interrupted()) + return null; Signaller q = null; boolean queued = false; Object r; @@ -1818,25 +1820,25 @@ private Object waitingGet(boolean interruptible) { } else if (!queued) queued = tryPushStack(q); + else if (interruptible && q.interrupted) { + q.thread = null; + cleanStack(); + return null; + } else { try { ForkJoinPool.managedBlock(q); } catch (InterruptedException ie) { // currently cannot happen q.interrupted = true; } - if (q.interrupted && interruptible) - break; } } - if (q != null && queued) { + if (q != null) { q.thread = null; - if (!interruptible && q.interrupted) + if (q.interrupted) Thread.currentThread().interrupt(); - if (r == null) - cleanStack(); } - if (r != null || (r = result) != null) - postComplete(); + postComplete(); return r; } @@ -1845,45 +1847,49 @@ else if (!queued) * throws TimeoutException on timeout. */ private Object timedGet(long nanos) throws TimeoutException { - if (Thread.interrupted()) - return null; - if (nanos > 0L) { - long d = System.nanoTime() + nanos; - long deadline = (d == 0L) ? 1L : d; // avoid 0 - Signaller q = null; - boolean queued = false; - Object r; - while ((r = result) == null) { // similar to untimed - if (q == null) { - q = new Signaller(true, nanos, deadline); - if (Thread.currentThread() instanceof ForkJoinWorkerThread) - ForkJoinPool.helpAsyncBlocker(defaultExecutor(), q); - } - else if (!queued) - queued = tryPushStack(q); - else if (q.nanos <= 0L) - break; - else { - try { - ForkJoinPool.managedBlock(q); - } catch (InterruptedException ie) { - q.interrupted = true; - } - if (q.interrupted) - break; - } + long d = System.nanoTime() + nanos; + long deadline = (d == 0L) ? 1L : d; // avoid 0 + boolean interrupted = false, queued = false; + Signaller q = null; + Object r = null; + for (;;) { // order of checking interrupt, result, timeout matters + if (interrupted || (interrupted = Thread.interrupted())) + break; + else if ((r = result) != null) + break; + else if (nanos <= 0L) + break; + else if (q == null) { + q = new Signaller(true, nanos, deadline); + if (Thread.currentThread() instanceof ForkJoinWorkerThread) + ForkJoinPool.helpAsyncBlocker(defaultExecutor(), q); } - if (q != null && queued) { - q.thread = null; - if (r == null) - cleanStack(); + else if (!queued) + queued = tryPushStack(q); + else { + try { + ForkJoinPool.managedBlock(q); + interrupted = q.interrupted; + nanos = q.nanos; + } catch (InterruptedException ie) { + interrupted = true; + } } - if (r != null || (r = result) != null) - postComplete(); - if (r != null || (q != null && q.interrupted)) - return r; } - throw new TimeoutException(); + if (q != null) { + q.thread = null; + if (r == null) + cleanStack(); + } + if (r != null) { + if (interrupted) + Thread.currentThread().interrupt(); + postComplete(); + return r; + } else if (interrupted) + return null; + else + throw new TimeoutException(); } /* ------------- public methods -------------- */ diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java index 56c52fb4ffa..bb969b5d2bd 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -2852,22 +2852,20 @@ private final void unlockRoot() { * Possibly blocks awaiting root lock. */ private final void contendedLock() { - boolean waiting = false; + Thread current = Thread.currentThread(), w; for (int s;;) { if (((s = lockState) & ~WAITER) == 0) { if (U.compareAndSetInt(this, LOCKSTATE, s, WRITER)) { - if (waiting) - waiter = null; + if (waiter == current) + U.compareAndSetObject(this, WAITERTHREAD, current, null); return; } } - else if ((s & WAITER) == 0) { - if (U.compareAndSetInt(this, LOCKSTATE, s, s | WAITER)) { - waiting = true; - waiter = Thread.currentThread(); - } - } - else if (waiting) + else if ((s & WAITER) == 0) + U.compareAndSetInt(this, LOCKSTATE, s, s | WAITER); + else if ((w = waiter) == null) + U.compareAndSetObject(this, WAITERTHREAD, null, current); + else if (w == current) LockSupport.park(this); } } @@ -3287,6 +3285,8 @@ static boolean checkInvariants(TreeNode t) { private static final Unsafe U = Unsafe.getUnsafe(); private static final long LOCKSTATE = U.objectFieldOffset(TreeBin.class, "lockState"); + private static final long WAITERTHREAD + = U.objectFieldOffset(TreeBin.class, "waiter"); } /* ----------------Table Traversal -------------- */ diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java index 85da9318815..2b58547a6ae 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -66,7 +66,7 @@ import jdk.internal.ref.CleanerFactory; import jdk.internal.vm.annotation.Stable; import sun.nio.cs.UTF_8; -import sun.security.action.GetBooleanAction; +import sun.security.action.GetPropertyAction; import java.security.AccessController; import static java.util.zip.ZipConstants64.*; @@ -120,12 +120,12 @@ class ZipFile implements ZipConstants, Closeable { public static final int OPEN_READ = 0x1; /** - * Flag which specifies whether the validation of the Zip64 extra - * fields should be disabled + * Flag to specify whether the Extra ZIP64 validation should be + * disabled. */ - private static final boolean disableZip64ExtraFieldValidation = - AccessController.doPrivileged - (new GetBooleanAction("jdk.util.zip.disableZip64ExtraFieldValidation")); + private static final boolean DISABLE_ZIP64_EXTRA_VALIDATION = + getDisableZip64ExtraFieldValidation(); + /** * Mode flag to open a zip file and mark it for deletion. The file will be * deleted some time between the moment that it is opened and the moment @@ -1131,6 +1131,22 @@ private String[] getMetaInfEntryNames() { private static boolean isWindows; private static final JavaLangAccess JLA; + /** + * Returns the value of the System property which indicates whether the + * Extra ZIP64 validation should be disabled. + */ + static boolean getDisableZip64ExtraFieldValidation() { + boolean result; + String value = GetPropertyAction.privilegedGetProperty( + "jdk.util.zip.disableZip64ExtraFieldValidation"); + if (value == null) { + result = false; + } else { + result = value.isEmpty() || value.equalsIgnoreCase("true"); + } + return result; + } + static { SharedSecrets.setJavaUtilZipFileAccess( new JavaUtilZipFileAccess() { @@ -1241,25 +1257,32 @@ private void checkExtraFields(int cenPos, int startingOffset, zerror("Invalid CEN header (extra data field size too long)"); } int currentOffset = startingOffset; - while (currentOffset < extraEndOffset) { + // Walk through each Extra Header. Each Extra Header Must consist of: + // Header ID - 2 bytes + // Data Size - 2 bytes: + while (currentOffset + Integer.BYTES <= extraEndOffset) { int tag = get16(cen, currentOffset); currentOffset += Short.BYTES; int tagBlockSize = get16(cen, currentOffset); + currentOffset += Short.BYTES; int tagBlockEndingOffset = currentOffset + tagBlockSize; // The ending offset for this tag block should not go past the // offset for the end of the extra field if (tagBlockEndingOffset > extraEndOffset) { - zerror("Invalid CEN header (invalid zip64 extra data field size)"); + zerror(String.format( + "Invalid CEN header (invalid extra data field size for " + + "tag: 0x%04x at %d)", + tag, cenPos)); } - currentOffset += Short.BYTES; if (tag == ZIP64_EXTID) { // Get the compressed size; long csize = CENSIZ(cen, cenPos); // Get the uncompressed size; long size = CENLEN(cen, cenPos); + checkZip64ExtraFieldValues(currentOffset, tagBlockSize, csize, size); } @@ -1283,6 +1306,16 @@ private void checkZip64ExtraFieldValues(int off, int blockSize, long csize, long size) throws ZipException { byte[] cen = this.cen; + // if ZIP64_EXTID blocksize == 0, which may occur with some older + // versions of Apache Ant and Commons Compress, validate csize and size + // to make sure neither field == ZIP64_MAGICVAL + if (blockSize == 0) { + if (csize == ZIP64_MAGICVAL || size == ZIP64_MAGICVAL) { + zerror("Invalid CEN header (invalid zip64 extra data field size)"); + } + // Only validate the ZIP64_EXTID data if the block size > 0 + return; + } // Validate the Zip64 Extended Information Extra Field (0x0001) // length. if (!isZip64ExtBlockSizeValid(blockSize)) { @@ -1693,7 +1726,7 @@ private void initCEN(int knownTotal, ZipCoder zc) throws IOException { } else { checkEncoding(zc, cen, pos + CENHDR, nlen); } - if (elen > 0 && !disableZip64ExtraFieldValidation) { + if (elen > 0 && !DISABLE_ZIP64_EXTRA_VALIDATION) { long extraStartingOffset = pos + CENHDR + nlen; if ((int)extraStartingOffset != extraStartingOffset) { zerror("invalid CEN header (bad extra offset)"); diff --git a/src/java.base/share/classes/javax/crypto/Cipher.java b/src/java.base/share/classes/javax/crypto/Cipher.java index ce5c63e7d31..b6194a8715b 100644 --- a/src/java.base/share/classes/javax/crypto/Cipher.java +++ b/src/java.base/share/classes/javax/crypto/Cipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -1220,7 +1220,7 @@ private static String getOpmodeString(int opmode) { * by the underlying {@code CipherSpi}. */ public final void init(int opmode, Key key) throws InvalidKeyException { - init(opmode, key, JCAUtil.getSecureRandom()); + init(opmode, key, JCAUtil.getDefSecureRandom()); } /** @@ -1361,7 +1361,7 @@ public final void init(int opmode, Key key, SecureRandom random) public final void init(int opmode, Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException { - init(opmode, key, params, JCAUtil.getSecureRandom()); + init(opmode, key, params, JCAUtil.getDefSecureRandom()); } /** @@ -1504,7 +1504,7 @@ public final void init(int opmode, Key key, AlgorithmParameterSpec params, public final void init(int opmode, Key key, AlgorithmParameters params) throws InvalidKeyException, InvalidAlgorithmParameterException { - init(opmode, key, params, JCAUtil.getSecureRandom()); + init(opmode, key, params, JCAUtil.getDefSecureRandom()); } /** @@ -1652,7 +1652,7 @@ public final void init(int opmode, Key key, AlgorithmParameters params, public final void init(int opmode, Certificate certificate) throws InvalidKeyException { - init(opmode, certificate, JCAUtil.getSecureRandom()); + init(opmode, certificate, JCAUtil.getDefSecureRandom()); } /** diff --git a/src/java.base/share/classes/javax/crypto/KeyAgreement.java b/src/java.base/share/classes/javax/crypto/KeyAgreement.java index 88ecf67eedb..ad38418363b 100644 --- a/src/java.base/share/classes/javax/crypto/KeyAgreement.java +++ b/src/java.base/share/classes/javax/crypto/KeyAgreement.java @@ -446,7 +446,7 @@ public final Provider getProvider() { * has an incompatible algorithm type. */ public final void init(Key key) throws InvalidKeyException { - init(key, JCAUtil.getSecureRandom()); + init(key, JCAUtil.getDefSecureRandom()); } /** @@ -514,7 +514,7 @@ public final void init(Key key, SecureRandom random) public final void init(Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException { - init(key, params, JCAUtil.getSecureRandom()); + init(key, params, JCAUtil.getDefSecureRandom()); } private String getProviderName() { diff --git a/src/java.base/share/classes/javax/crypto/KeyGenerator.java b/src/java.base/share/classes/javax/crypto/KeyGenerator.java index 3e83f8f30c5..2f8af71cec5 100644 --- a/src/java.base/share/classes/javax/crypto/KeyGenerator.java +++ b/src/java.base/share/classes/javax/crypto/KeyGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -450,7 +450,7 @@ public final void init(SecureRandom random) { public final void init(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { - init(params, JCAUtil.getSecureRandom()); + init(params, JCAUtil.getDefSecureRandom()); } /** @@ -514,7 +514,7 @@ public final void init(AlgorithmParameterSpec params, SecureRandom random) * supported. */ public final void init(int keysize) { - init(keysize, JCAUtil.getSecureRandom()); + init(keysize, JCAUtil.getDefSecureRandom()); } /** diff --git a/src/java.base/share/classes/javax/crypto/spec/SecretKeySpec.java b/src/java.base/share/classes/javax/crypto/spec/SecretKeySpec.java index ba29c757144..c85f4b6287a 100644 --- a/src/java.base/share/classes/javax/crypto/spec/SecretKeySpec.java +++ b/src/java.base/share/classes/javax/crypto/spec/SecretKeySpec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package javax.crypto.spec; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.security.MessageDigest; import java.security.spec.KeySpec; import java.util.Locale; @@ -232,4 +235,25 @@ public boolean equals(Object obj) { return MessageDigest.isEqual(this.key, thatKey); } + + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + + if (key == null || algorithm == null) { + throw new InvalidObjectException("Missing argument"); + } + + this.key = key.clone(); + if (key.length == 0) { + throw new InvalidObjectException("Invalid key length"); + } + } } diff --git a/src/java.base/share/classes/javax/net/ssl/SSLContextSpi.java b/src/java.base/share/classes/javax/net/ssl/SSLContextSpi.java index f0b0dc33832..7f70c613d49 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLContextSpi.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLContextSpi.java @@ -210,10 +210,9 @@ protected SSLParameters engineGetDefaultSSLParameters() { */ protected SSLParameters engineGetSupportedSSLParameters() { SSLSocket socket = getDefaultSocket(); - SSLParameters params = new SSLParameters(); + SSLParameters params = socket.getSSLParameters(); params.setCipherSuites(socket.getSupportedCipherSuites()); params.setProtocols(socket.getSupportedProtocols()); return params; } - } diff --git a/src/java.base/share/classes/javax/security/auth/callback/ChoiceCallback.java b/src/java.base/share/classes/javax/security/auth/callback/ChoiceCallback.java index b11f8943a15..1c6befedf39 100644 --- a/src/java.base/share/classes/javax/security/auth/callback/ChoiceCallback.java +++ b/src/java.base/share/classes/javax/security/auth/callback/ChoiceCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,10 @@ package javax.security.auth.callback; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; + /** *

Underlying security services instantiate and pass a * {@code ChoiceCallback} to the {@code handle} @@ -42,7 +46,7 @@ public class ChoiceCallback implements Callback, java.io.Serializable { * @serial * @since 1.4 */ - private String prompt; + private final String prompt; /** * @serial the list of choices * @since 1.4 @@ -52,13 +56,13 @@ public class ChoiceCallback implements Callback, java.io.Serializable { * @serial the choice to be used as the default choice * @since 1.4 */ - private int defaultChoice; + private final int defaultChoice; /** * @serial whether multiple selections are allowed from the list of * choices * @since 1.4 */ - private boolean multipleSelectionsAllowed; + private final boolean multipleSelectionsAllowed; /** * @serial the selected choices, represented as indexes into the * {@code choices} list. @@ -71,7 +75,6 @@ public class ChoiceCallback implements Callback, java.io.Serializable { * a list of choices, a default choice, and a boolean specifying * whether or not multiple selections from the list of choices are allowed. * - * * @param prompt the prompt used to describe the list of choices. * * @param choices the list of choices. @@ -103,15 +106,15 @@ public ChoiceCallback(String prompt, String[] choices, defaultChoice < 0 || defaultChoice >= choices.length) throw new IllegalArgumentException(); + this.prompt = prompt; + this.defaultChoice = defaultChoice; + this.multipleSelectionsAllowed = multipleSelectionsAllowed; + + this.choices = choices.clone(); for (int i = 0; i < choices.length; i++) { if (choices[i] == null || choices[i].isEmpty()) throw new IllegalArgumentException(); } - - this.prompt = prompt; - this.choices = choices; - this.defaultChoice = defaultChoice; - this.multipleSelectionsAllowed = multipleSelectionsAllowed; } /** @@ -129,7 +132,7 @@ public String getPrompt() { * @return the list of choices. */ public String[] getChoices() { - return choices; + return choices.clone(); } /** @@ -180,7 +183,7 @@ public void setSelectedIndex(int selection) { public void setSelectedIndexes(int[] selections) { if (!multipleSelectionsAllowed) throw new UnsupportedOperationException(); - this.selections = selections; + this.selections = selections == null ? null : selections.clone(); } /** @@ -192,6 +195,39 @@ public void setSelectedIndexes(int[] selections) { * @see #setSelectedIndexes */ public int[] getSelectedIndexes() { - return selections; + return selections == null ? null : selections.clone(); + } + + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + + if ((prompt == null) || prompt.isEmpty() || + (choices == null) || (choices.length == 0) || + (defaultChoice < 0) || (defaultChoice >= choices.length)) { + throw new InvalidObjectException( + "Missing/invalid prompt/choices"); + } + + choices = choices.clone(); + for (int i = 0; i < choices.length; i++) { + if ((choices[i] == null) || choices[i].isEmpty()) + throw new InvalidObjectException("Null/empty choices"); + } + + if (selections != null) { + selections = selections.clone(); + if (!multipleSelectionsAllowed && (selections.length != 1)) { + throw new InvalidObjectException( + "Multiple selections not allowed"); + } + } } } diff --git a/src/java.base/share/classes/javax/security/auth/callback/ConfirmationCallback.java b/src/java.base/share/classes/javax/security/auth/callback/ConfirmationCallback.java index 78113195ebf..33752f2aa8b 100644 --- a/src/java.base/share/classes/javax/security/auth/callback/ConfirmationCallback.java +++ b/src/java.base/share/classes/javax/security/auth/callback/ConfirmationCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package javax.security.auth.callback; +import java.io.IOException; +import java.io.ObjectInputStream; + /** *

Underlying security services instantiate and pass a * {@code ConfirmationCallback} to the {@code handle} @@ -121,26 +124,27 @@ public class ConfirmationCallback implements Callback, java.io.Serializable { /** ERROR message type. */ public static final int ERROR = 2; + /** * @serial * @since 1.4 */ - private String prompt; + private final String prompt; /** * @serial * @since 1.4 */ - private int messageType; + private final int messageType; /** * @serial * @since 1.4 */ - private int optionType = UNSPECIFIED_OPTION; + private final int optionType; /** * @serial * @since 1.4 */ - private int defaultOption; + private final int defaultOption; /** * @serial * @since 1.4 @@ -205,8 +209,10 @@ public ConfirmationCallback(int messageType, break; } + this.prompt = null; this.messageType = messageType; this.optionType = optionType; + this.options = null; this.defaultOption = defaultOption; } @@ -247,14 +253,16 @@ public ConfirmationCallback(int messageType, defaultOption < 0 || defaultOption >= options.length) throw new IllegalArgumentException(); + this.prompt = null; + this.messageType = messageType; + this.optionType = UNSPECIFIED_OPTION; + this.defaultOption = defaultOption; + + this.options = options.clone(); for (int i = 0; i < options.length; i++) { if (options[i] == null || options[i].isEmpty()) throw new IllegalArgumentException(); } - - this.messageType = messageType; - this.options = options; - this.defaultOption = defaultOption; } /** @@ -318,6 +326,7 @@ public ConfirmationCallback(String prompt, int messageType, this.prompt = prompt; this.messageType = messageType; this.optionType = optionType; + this.options = null; this.defaultOption = defaultOption; } @@ -363,15 +372,16 @@ public ConfirmationCallback(String prompt, int messageType, defaultOption < 0 || defaultOption >= options.length) throw new IllegalArgumentException(); + this.prompt = prompt; + this.messageType = messageType; + this.optionType = UNSPECIFIED_OPTION; + this.defaultOption = defaultOption; + + this.options = options.clone(); for (int i = 0; i < options.length; i++) { if (options[i] == null || options[i].isEmpty()) throw new IllegalArgumentException(); } - - this.prompt = prompt; - this.messageType = messageType; - this.options = options; - this.defaultOption = defaultOption; } /** @@ -422,7 +432,7 @@ public int getOptionType() { * an {@code optionType} instead of {@code options}. */ public String[] getOptions() { - return options; + return options == null ? null : options.clone(); } /** @@ -477,4 +487,19 @@ public void setSelectedIndex(int selection) { public int getSelectedIndex() { return selection; } + + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if (options != null) { + options = options.clone(); + } + } } diff --git a/src/java.base/share/classes/javax/security/auth/callback/PasswordCallback.java b/src/java.base/share/classes/javax/security/auth/callback/PasswordCallback.java index 0611d7f0f99..02612b1815f 100644 --- a/src/java.base/share/classes/javax/security/auth/callback/PasswordCallback.java +++ b/src/java.base/share/classes/javax/security/auth/callback/PasswordCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,15 @@ package javax.security.auth.callback; +import java.lang.ref.Cleaner; +import java.util.Arrays; + +import jdk.internal.ref.CleanerFactory; + +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; + /** *

Underlying security services instantiate and pass a * {@code PasswordCallback} to the {@code handle} @@ -37,16 +46,20 @@ public class PasswordCallback implements Callback, java.io.Serializable { private static final long serialVersionUID = 2267422647454909926L; + private transient Cleaner.Cleanable cleanable; + /** * @serial * @since 1.4 */ - private String prompt; + private final String prompt; + /** * @serial * @since 1.4 */ - private boolean echoOn; + private final boolean echoOn; + /** * @serial * @since 1.4 @@ -105,7 +118,19 @@ public boolean isEchoOn() { * @see #getPassword */ public void setPassword(char[] password) { + // Cleanup the last buffered password copy. + if (cleanable != null) { + cleanable.clean(); + cleanable = null; + } + + // Set the retrieved password. this.inputPassword = (password == null ? null : password.clone()); + + if (this.inputPassword != null) { + cleanable = CleanerFactory.cleaner().register( + this, cleanerFor(inputPassword)); + } } /** @@ -125,9 +150,38 @@ public char[] getPassword() { * Clear the retrieved password. */ public void clearPassword() { + // Cleanup the last retrieved password copy. + if (cleanable != null) { + cleanable.clean(); + cleanable = null; + } + } + + private static Runnable cleanerFor(char[] password) { + return () -> { + Arrays.fill(password, ' '); + }; + } + + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + + if (prompt == null || prompt.isEmpty()) { + throw new InvalidObjectException("Missing prompt"); + } + if (inputPassword != null) { - for (int i = 0; i < inputPassword.length; i++) - inputPassword[i] = ' '; + inputPassword = inputPassword.clone(); + cleanable = CleanerFactory.cleaner().register( + this, cleanerFor(inputPassword)); } } } diff --git a/src/java.base/share/classes/jdk/internal/event/X509CertificateEvent.java b/src/java.base/share/classes/jdk/internal/event/X509CertificateEvent.java index b145abceb69..5b668ca2a05 100644 --- a/src/java.base/share/classes/jdk/internal/event/X509CertificateEvent.java +++ b/src/java.base/share/classes/jdk/internal/event/X509CertificateEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 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 @@ -31,6 +31,15 @@ */ public final class X509CertificateEvent extends Event { + private static final X509CertificateEvent EVENT = new X509CertificateEvent(); + + /** + * Returns {@code true} if event is enabled, {@code false} otherwise. + */ + public static boolean isTurnedOn() { + return EVENT.isEnabled(); + } + public String algorithm; public String serialNumber; public String subject; diff --git a/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/src/java.base/share/classes/sun/launcher/LauncherHelper.java index eefb5bb712b..e8b7dd4693a 100644 --- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java +++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,6 +87,7 @@ import jdk.internal.module.Modules; import jdk.internal.platform.Container; import jdk.internal.platform.Metrics; +import sun.util.calendar.ZoneInfoFile; public final class LauncherHelper { @@ -280,6 +281,8 @@ private static void printLocale() { Locale.getDefault(Category.DISPLAY).getDisplayName()); ostream.println(INDENT + "default format locale = " + Locale.getDefault(Category.FORMAT).getDisplayName()); + ostream.println(INDENT + "tzdata version = " + + ZoneInfoFile.getVersion()); printLocales(); ostream.println(); } diff --git a/src/java.base/share/classes/sun/net/www/http/KeepAliveCache.java b/src/java.base/share/classes/sun/net/www/http/KeepAliveCache.java index a36b90ca8fc..e717d5b8698 100644 --- a/src/java.base/share/classes/sun/net/www/http/KeepAliveCache.java +++ b/src/java.base/share/classes/sun/net/www/http/KeepAliveCache.java @@ -113,38 +113,45 @@ public KeepAliveCache() {} * @param url The URL contains info about the host and port * @param http The HttpClient to be cached */ - public synchronized void put(final URL url, Object obj, HttpClient http) { - boolean startThread = (keepAliveTimer == null); - if (!startThread) { - if (!keepAliveTimer.isAlive()) { - startThread = true; - } - } - if (startThread) { - clear(); - /* Unfortunately, we can't always believe the keep-alive timeout we got - * back from the server. If I'm connected through a Netscape proxy - * to a server that sent me a keep-alive - * time of 15 sec, the proxy unilaterally terminates my connection - * The robustness to get around this is in HttpClient.parseHTTP() - */ - final KeepAliveCache cache = this; - AccessController.doPrivileged(new PrivilegedAction<>() { - public Void run() { - keepAliveTimer = InnocuousThread.newSystemThread("Keep-Alive-Timer", cache); - keepAliveTimer.setDaemon(true); - keepAliveTimer.setPriority(Thread.MAX_PRIORITY - 2); - keepAliveTimer.start(); - return null; + public void put(final URL url, Object obj, HttpClient http) { + // this method may need to close an HttpClient, either because + // it is not cacheable, or because the cache is at its capacity. + // In the latter case, we close the least recently used client. + // The client to close is stored in oldClient, and is closed + // after cacheLock is released. + HttpClient oldClient = null; + synchronized (this) { + boolean startThread = (keepAliveTimer == null); + if (!startThread) { + if (!keepAliveTimer.isAlive()) { + startThread = true; } - }); - } + } + if (startThread) { + clear(); + /* Unfortunately, we can't always believe the keep-alive timeout we got + * back from the server. If I'm connected through a Netscape proxy + * to a server that sent me a keep-alive + * time of 15 sec, the proxy unilaterally terminates my connection + * The robustness to get around this is in HttpClient.parseHTTP() + */ + final KeepAliveCache cache = this; + AccessController.doPrivileged(new PrivilegedAction<>() { + public Void run() { + keepAliveTimer = InnocuousThread.newSystemThread("Keep-Alive-Timer", cache); + keepAliveTimer.setDaemon(true); + keepAliveTimer.setPriority(Thread.MAX_PRIORITY - 2); + keepAliveTimer.start(); + return null; + } + }); + } - KeepAliveKey key = new KeepAliveKey(url, obj); - ClientVector v = super.get(key); + KeepAliveKey key = new KeepAliveKey(url, obj); + ClientVector v = super.get(key); - if (v == null) { - int keepAliveTimeout = http.getKeepAliveTimeout(); + if (v == null) { + int keepAliveTimeout = http.getKeepAliveTimeout(); if (keepAliveTimeout == 0) { keepAliveTimeout = getUserKeepAlive(http.getUsingProxy()); if (keepAliveTimeout == -1) { @@ -164,14 +171,19 @@ public Void run() { // alive, which could be 0, if the user specified 0 for the property assert keepAliveTimeout >= 0; if (keepAliveTimeout == 0) { - http.closeServer(); + oldClient = http; } else { v = new ClientVector(keepAliveTimeout * 1000); v.put(http); super.put(key, v); } - } else { - v.put(http); + } else { + oldClient = v.put(http); + } + } + // close after releasing locks + if (oldClient != null) { + oldClient.closeServer(); } } @@ -221,6 +233,7 @@ public void run() { try { Thread.sleep(LIFETIME); } catch (InterruptedException e) {} + List closeList = null; // Remove all outdated HttpClients. synchronized (this) { @@ -230,15 +243,18 @@ public void run() { for (KeepAliveKey key : keySet()) { ClientVector v = get(key); synchronized (v) { - KeepAliveEntry e = v.peek(); + KeepAliveEntry e = v.peekLast(); while (e != null) { if ((currentTime - e.idleStartTime) > v.nap) { - v.poll(); - e.hc.closeServer(); + v.pollLast(); + if (closeList == null) { + closeList = new ArrayList<>(); + } + closeList.add(e.hc); } else { break; } - e = v.peek(); + e = v.peekLast(); } if (v.isEmpty()) { @@ -251,6 +267,12 @@ public void run() { removeVector(key); } } + // close connections outside cacheLock + if (closeList != null) { + for (HttpClient hc : closeList) { + hc.closeServer(); + } + } } while (!isEmpty()); } @@ -268,8 +290,8 @@ private void readObject(ObjectInputStream stream) } } -/* FILO order for recycling HttpClients, should run in a thread - * to time them out. If > maxConns are in use, block. +/* LIFO order for reusing HttpClients. Most recent entries at the front. + * If > maxConns are in use, discard oldest. */ class ClientVector extends ArrayDeque { private static final long serialVersionUID = -8680532108106489459L; @@ -282,36 +304,37 @@ class ClientVector extends ArrayDeque { } synchronized HttpClient get() { - if (isEmpty()) { + // check the most recent connection, use if still valid + KeepAliveEntry e = peekFirst(); + if (e == null) { return null; } - // Loop until we find a connection that has not timed out - HttpClient hc = null; long currentTime = System.currentTimeMillis(); - do { - KeepAliveEntry e = pop(); - if ((currentTime - e.idleStartTime) > nap) { - e.hc.closeServer(); - } else { - hc = e.hc; - if (KeepAliveCache.logger.isLoggable(PlatformLogger.Level.FINEST)) { - String msg = "cached HttpClient was idle for " + if ((currentTime - e.idleStartTime) > nap) { + return null; // all connections stale - will be cleaned up later + } else { + pollFirst(); + if (KeepAliveCache.logger.isLoggable(PlatformLogger.Level.FINEST)) { + String msg = "cached HttpClient was idle for " + Long.toString(currentTime - e.idleStartTime); - KeepAliveCache.logger.finest(msg); - } + KeepAliveCache.logger.finest(msg); } - } while ((hc == null) && (!isEmpty())); - return hc; + return e.hc; + } } /* return a still valid, unused HttpClient */ - synchronized void put(HttpClient h) { + synchronized HttpClient put(HttpClient h) { + HttpClient staleClient = null; + assert KeepAliveCache.getMaxConnections() > 0; if (size() >= KeepAliveCache.getMaxConnections()) { - h.closeServer(); // otherwise the connection remains in limbo - } else { - push(new KeepAliveEntry(h, System.currentTimeMillis())); + // remove oldest connection + staleClient = removeLast().hc; } + addFirst(new KeepAliveEntry(h, System.currentTimeMillis())); + // close after releasing the locks + return staleClient; } /* remove an HttpClient */ @@ -339,10 +362,10 @@ private void readObject(ObjectInputStream stream) } class KeepAliveKey { - private String protocol = null; - private String host = null; - private int port = 0; - private Object obj = null; // additional key, such as socketfactory + private final String protocol; + private final String host; + private final int port; + private final Object obj; // additional key, such as socketfactory /** * Constructor @@ -383,8 +406,8 @@ public int hashCode() { } class KeepAliveEntry { - HttpClient hc; - long idleStartTime; + final HttpClient hc; + final long idleStartTime; KeepAliveEntry(HttpClient hc, long idleStartTime) { this.hc = hc; diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java b/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java index f4547a2c47a..1262d075015 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java @@ -517,4 +517,13 @@ private synchronized void writeObject(java.io.ObjectOutputStream s) s2 = new String (pw.getPassword()); s.defaultWriteObject (); } + + /** + * Releases any system or cryptographic resources. + * It is up to implementors to override disposeContext() + * to take necessary action. + */ + public void disposeContext() { + // do nothing + } } 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 9c1107f2a0a..85eee2c3bb6 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 @@ -1953,6 +1953,12 @@ private synchronized InputStream getInputStream0() throws IOException { if (serverAuthKey != null) { AuthenticationInfo.endAuthRequest(serverAuthKey); } + if (proxyAuthentication != null) { + proxyAuthentication.disposeContext(); + } + if (serverAuthentication != null) { + serverAuthentication.disposeContext(); + } } } @@ -2182,6 +2188,9 @@ public synchronized void doTunneling() throws IOException { if (proxyAuthKey != null) { AuthenticationInfo.endAuthRequest(proxyAuthKey); } + if (proxyAuthentication != null) { + proxyAuthentication.disposeContext(); + } } // restore original request headers @@ -2428,6 +2437,7 @@ public InetAddress run() } if (ret != null) { if (!ret.setHeaders(this, p, raw)) { + ret.disposeContext(); ret = null; } } @@ -2596,6 +2606,7 @@ private AuthenticationInfo getServerAuthentication (AuthenticationHeader authhdr if (ret != null ) { if (!ret.setHeaders(this, p, raw)) { + ret.disposeContext(); ret = null; } } @@ -2622,6 +2633,7 @@ private void checkResponseCredentials (boolean inClose) throws IOException { DigestAuthentication da = (DigestAuthentication) currentProxyCredentials; da.checkResponse (raw, method, getRequestURI()); + currentProxyCredentials.disposeContext(); currentProxyCredentials = null; } } @@ -2632,6 +2644,7 @@ private void checkResponseCredentials (boolean inClose) throws IOException { DigestAuthentication da = (DigestAuthentication) currentServerCredentials; da.checkResponse (raw, method, url); + currentServerCredentials.disposeContext(); currentServerCredentials = null; } } diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java b/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java index f3b9f94fa1a..cd5c1f8b35f 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java @@ -225,6 +225,22 @@ private byte[] nextToken(byte[] token) throws IOException { return negotiator.nextToken(token); } + /** + * Releases any system resources and cryptographic information stored in + * the context object and invalidates the context. + */ + @Override + public void disposeContext() { + if (negotiator != null) { + try { + negotiator.disposeContext(); + } catch (IOException ioEx) { + //do not rethrow IOException + } + negotiator = null; + } + } + // MS will send a final WWW-Authenticate even if the status is already // 200 OK. The token can be fed into initSecContext() again to determine // if the server can be trusted. This is not the same concept as Digest's diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/Negotiator.java b/src/java.base/share/classes/sun/net/www/protocol/http/Negotiator.java index 7993b9d284d..29be64d6f75 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/Negotiator.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/Negotiator.java @@ -82,5 +82,7 @@ private static void finest(Exception e) { logger.finest("NegotiateAuthentication: " + e); } } + + public void disposeContext() throws IOException { }; } diff --git a/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java b/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java index 72286b1c884..d70daef8714 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java +++ b/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java @@ -428,6 +428,14 @@ protected Socket createSocket() throws IOException { } } + @Override + public void closeServer() { + try { + // SSLSocket.close may block up to timeout. Make sure it's short. + serverSocket.setSoTimeout(1); + } catch (Exception e) {} + super.closeServer(); + } @Override public boolean needsTunneling() { diff --git a/src/java.base/share/classes/sun/security/jca/JCAUtil.java b/src/java.base/share/classes/sun/security/jca/JCAUtil.java index 59375cc220b..de02a1e6562 100644 --- a/src/java.base/share/classes/sun/security/jca/JCAUtil.java +++ b/src/java.base/share/classes/sun/security/jca/JCAUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, 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 @@ -26,8 +26,14 @@ package sun.security.jca; import java.lang.ref.*; - import java.security.*; +import java.security.PublicKey; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; + +import jdk.internal.event.EventHelper; +import jdk.internal.event.X509CertificateEvent; +import sun.security.util.KeyUtil; /** * Collection of static utility methods used by the security framework. @@ -59,6 +65,8 @@ private static class CachedSecureRandomHolder { public static SecureRandom instance = new SecureRandom(); } + private static volatile SecureRandom def = null; + /** * Get a SecureRandom instance. This method should be used by JDK * internal code in favor of calling "new SecureRandom()". That needs to @@ -69,4 +77,69 @@ public static SecureRandom getSecureRandom() { return CachedSecureRandomHolder.instance; } + // called by sun.security.jca.Providers class when provider list is changed + static void clearDefSecureRandom() { + def = null; + } + + /** + * Get the default SecureRandom instance. This method is the + * optimized version of "new SecureRandom()" which re-uses the default + * SecureRandom impl if the provider table is the same. + */ + public static SecureRandom getDefSecureRandom() { + SecureRandom result = def; + if (result == null) { + synchronized (JCAUtil.class) { + result = def; + if (result == null) { + def = result = new SecureRandom(); + } + } + } + return result; + + } + + public static void tryCommitCertEvent(Certificate cert) { + if ((X509CertificateEvent.isTurnedOn() || EventHelper.isLoggingSecurity())) { + if (cert instanceof X509Certificate) { + X509Certificate x509 = (X509Certificate) cert; + PublicKey pKey = x509.getPublicKey(); + String algId = x509.getSigAlgName(); + String serNum = x509.getSerialNumber().toString(16); + String subject = x509.getSubjectX500Principal().toString(); + String issuer = x509.getIssuerX500Principal().toString(); + String keyType = pKey.getAlgorithm(); + int length = KeyUtil.getKeySize(pKey); + int hashCode = x509.hashCode(); + long beginDate = x509.getNotBefore().getTime(); + long endDate = x509.getNotAfter().getTime(); + if (X509CertificateEvent.isTurnedOn()) { + X509CertificateEvent xce = new X509CertificateEvent(); + xce.algorithm = algId; + xce.serialNumber = serNum; + xce.subject = subject; + xce.issuer = issuer; + xce.keyType = keyType; + xce.keyLength = length; + xce.certificateId = hashCode; + xce.validFrom = beginDate; + xce.validUntil = endDate; + xce.commit(); + } + if (EventHelper.isLoggingSecurity()) { + EventHelper.logX509CertificateEvent(algId, + serNum, + subject, + issuer, + keyType, + length, + hashCode, + beginDate, + endDate); + } + } + } + } } diff --git a/src/java.base/share/classes/sun/security/jca/Providers.java b/src/java.base/share/classes/sun/security/jca/Providers.java index 817c8f2af06..7256308c12c 100644 --- a/src/java.base/share/classes/sun/security/jca/Providers.java +++ b/src/java.base/share/classes/sun/security/jca/Providers.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 @@ -150,6 +150,7 @@ public static void setProviderList(ProviderList newList) { } else { changeThreadProviderList(newList); } + JCAUtil.clearDefSecureRandom(); } /** diff --git a/src/java.base/share/classes/sun/security/pkcs/ContentInfo.java b/src/java.base/share/classes/sun/security/pkcs/ContentInfo.java index d3cdf3aead0..44256b83980 100644 --- a/src/java.base/share/classes/sun/security/pkcs/ContentInfo.java +++ b/src/java.base/share/classes/sun/security/pkcs/ContentInfo.java @@ -38,50 +38,36 @@ public class ContentInfo { // pkcs7 pre-defined content types - private static int[] pkcs7 = {1, 2, 840, 113549, 1, 7}; - private static int[] data = {1, 2, 840, 113549, 1, 7, 1}; - private static int[] sdata = {1, 2, 840, 113549, 1, 7, 2}; - private static int[] edata = {1, 2, 840, 113549, 1, 7, 3}; - private static int[] sedata = {1, 2, 840, 113549, 1, 7, 4}; - private static int[] ddata = {1, 2, 840, 113549, 1, 7, 5}; - private static int[] crdata = {1, 2, 840, 113549, 1, 7, 6}; - private static int[] nsdata = {2, 16, 840, 1, 113730, 2, 5}; - // timestamp token (id-ct-TSTInfo) from RFC 3161 - private static int[] tstInfo = {1, 2, 840, 113549, 1, 9, 16, 1, 4}; + public static ObjectIdentifier PKCS7_OID = + ObjectIdentifier.of(KnownOIDs.PKCS7); + public static ObjectIdentifier DATA_OID = + ObjectIdentifier.of(KnownOIDs.Data); + public static ObjectIdentifier SIGNED_DATA_OID = + ObjectIdentifier.of(KnownOIDs.SignedData); + public static ObjectIdentifier ENVELOPED_DATA_OID = + ObjectIdentifier.of(KnownOIDs.EnvelopedData); + public static ObjectIdentifier SIGNED_AND_ENVELOPED_DATA_OID = + ObjectIdentifier.of(KnownOIDs.SignedAndEnvelopedData); + public static ObjectIdentifier DIGESTED_DATA_OID = + ObjectIdentifier.of(KnownOIDs.DigestedData); + public static ObjectIdentifier ENCRYPTED_DATA_OID = + ObjectIdentifier.of(KnownOIDs.EncryptedData); + // this is for backwards-compatibility with JDK 1.1.x - private static final int[] OLD_SDATA = {1, 2, 840, 1113549, 1, 7, 2}; - private static final int[] OLD_DATA = {1, 2, 840, 1113549, 1, 7, 1}; - public static ObjectIdentifier PKCS7_OID; - public static ObjectIdentifier DATA_OID; - public static ObjectIdentifier SIGNED_DATA_OID; - public static ObjectIdentifier ENVELOPED_DATA_OID; - public static ObjectIdentifier SIGNED_AND_ENVELOPED_DATA_OID; - public static ObjectIdentifier DIGESTED_DATA_OID; - public static ObjectIdentifier ENCRYPTED_DATA_OID; - public static ObjectIdentifier OLD_SIGNED_DATA_OID; - public static ObjectIdentifier OLD_DATA_OID; - public static ObjectIdentifier NETSCAPE_CERT_SEQUENCE_OID; - public static ObjectIdentifier TIMESTAMP_TOKEN_INFO_OID; - - static { - PKCS7_OID = ObjectIdentifier.newInternal(pkcs7); - DATA_OID = ObjectIdentifier.newInternal(data); - SIGNED_DATA_OID = ObjectIdentifier.newInternal(sdata); - ENVELOPED_DATA_OID = ObjectIdentifier.newInternal(edata); - SIGNED_AND_ENVELOPED_DATA_OID = ObjectIdentifier.newInternal(sedata); - DIGESTED_DATA_OID = ObjectIdentifier.newInternal(ddata); - ENCRYPTED_DATA_OID = ObjectIdentifier.newInternal(crdata); - OLD_SIGNED_DATA_OID = ObjectIdentifier.newInternal(OLD_SDATA); - OLD_DATA_OID = ObjectIdentifier.newInternal(OLD_DATA); - /** - * The ASN.1 systax for the Netscape Certificate Sequence - * data type is defined - * - * here. - */ - NETSCAPE_CERT_SEQUENCE_OID = ObjectIdentifier.newInternal(nsdata); - TIMESTAMP_TOKEN_INFO_OID = ObjectIdentifier.newInternal(tstInfo); - } + public static ObjectIdentifier OLD_SIGNED_DATA_OID = + ObjectIdentifier.of(KnownOIDs.JDK_OLD_SignedData); + public static ObjectIdentifier OLD_DATA_OID = + ObjectIdentifier.of(KnownOIDs.JDK_OLD_Data); + + // The ASN.1 systax for the Netscape Certificate Sequence data type is + // defined at: + // http://wp.netscape.com/eng/security/comm4-cert-download.html + public static ObjectIdentifier NETSCAPE_CERT_SEQUENCE_OID = + ObjectIdentifier.of(KnownOIDs.NETSCAPE_CertSequence); + + // timestamp token (id-ct-TSTInfo) from RFC 3161 + public static ObjectIdentifier TIMESTAMP_TOKEN_INFO_OID = + ObjectIdentifier.of(KnownOIDs.TimeStampTokenInfo); ObjectIdentifier contentType; DerValue content; // OPTIONAL diff --git a/src/java.base/share/classes/sun/security/pkcs/PKCS7.java b/src/java.base/share/classes/sun/security/pkcs/PKCS7.java index 042dfd13333..603167e2279 100644 --- a/src/java.base/share/classes/sun/security/pkcs/PKCS7.java +++ b/src/java.base/share/classes/sun/security/pkcs/PKCS7.java @@ -36,6 +36,7 @@ import java.security.cert.CertificateFactory; import java.security.*; +import sun.security.jca.JCAUtil; import sun.security.timestamp.*; import sun.security.util.*; import sun.security.x509.AlgorithmId; @@ -69,23 +70,6 @@ public class PKCS7 { private Principal[] certIssuerNames; - /* - * Random number generator for creating nonce values - * (Lazy initialization) - */ - private static class SecureRandomHolder { - static final SecureRandom RANDOM; - static { - SecureRandom tmp = null; - try { - tmp = SecureRandom.getInstance("SHA1PRNG"); - } catch (NoSuchAlgorithmException e) { - // should not happen - } - RANDOM = tmp; - } - } - /* * Object identifier for the timestamping key purpose. */ @@ -885,11 +869,9 @@ private static byte[] generateTimestampToken(Timestamper tsa, } // Generate a nonce - BigInteger nonce = null; - if (SecureRandomHolder.RANDOM != null) { - nonce = new BigInteger(64, SecureRandomHolder.RANDOM); - tsQuery.setNonce(nonce); - } + BigInteger nonce = new BigInteger(64, JCAUtil.getDefSecureRandom()); + tsQuery.setNonce(nonce); + tsQuery.requestCertificate(true); TSResponse tsReply = tsa.generateTimestamp(tsQuery); diff --git a/src/java.base/share/classes/sun/security/pkcs/PKCS9Attribute.java b/src/java.base/share/classes/sun/security/pkcs/PKCS9Attribute.java index c6a1bc1778a..fb2fa121f14 100644 --- a/src/java.base/share/classes/sun/security/pkcs/PKCS9Attribute.java +++ b/src/java.base/share/classes/sun/security/pkcs/PKCS9Attribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -28,9 +28,7 @@ import java.io.IOException; import java.io.OutputStream; import java.security.cert.CertificateException; -import java.util.Locale; import java.util.Date; -import java.util.Hashtable; import sun.security.x509.CertificateExtensions; import sun.security.util.*; diff --git a/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java b/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java index be8722d8cdf..684c68c72ce 100644 --- a/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java +++ b/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java @@ -64,17 +64,11 @@ import javax.security.auth.x500.X500Principal; import sun.security.action.GetPropertyAction; -import sun.security.util.Debug; -import sun.security.util.DerInputStream; -import sun.security.util.DerOutputStream; -import sun.security.util.DerValue; -import sun.security.util.ObjectIdentifier; +import sun.security.util.*; import sun.security.pkcs.ContentInfo; -import sun.security.util.SecurityProperties; import sun.security.x509.AlgorithmId; import sun.security.pkcs.EncryptedPrivateKeyInfo; import sun.security.provider.JavaKeyStore.JKS; -import sun.security.util.KeyStoreDelegator; /** @@ -133,43 +127,42 @@ public DualFormatPKCS12() { private static final int MAX_ITERATION_COUNT = 5000000; private static final int SALT_LEN = 20; - // friendlyName, localKeyId, trustedKeyUsage - private static final String[] CORE_ATTRIBUTES = { - "1.2.840.113549.1.9.20", - "1.2.840.113549.1.9.21", - "2.16.840.1.113894.746875.1.1" + private static final KnownOIDs[] CORE_ATTRIBUTES = { + KnownOIDs.FriendlyName, + KnownOIDs.LocalKeyID, + KnownOIDs.ORACLE_TrustedKeyUsage }; private static final Debug debug = Debug.getInstance("pkcs12"); - private static final int[] keyBag = {1, 2, 840, 113549, 1, 12, 10, 1, 2}; - private static final int[] certBag = {1, 2, 840, 113549, 1, 12, 10, 1, 3}; - private static final int[] secretBag = {1, 2, 840, 113549, 1, 12, 10, 1, 5}; + private static final ObjectIdentifier PKCS8ShroudedKeyBag_OID = + ObjectIdentifier.of(KnownOIDs.PKCS8ShroudedKeyBag); + private static final ObjectIdentifier CertBag_OID = + ObjectIdentifier.of(KnownOIDs.CertBag); + private static final ObjectIdentifier SecretBag_OID = + ObjectIdentifier.of(KnownOIDs.SecretBag); + + private static final ObjectIdentifier PKCS9FriendlyName_OID = + ObjectIdentifier.of(KnownOIDs.FriendlyName); + private static final ObjectIdentifier PKCS9LocalKeyId_OID = + ObjectIdentifier.of(KnownOIDs.LocalKeyID); + private static final ObjectIdentifier PKCS9CertType_OID = + ObjectIdentifier.of(KnownOIDs.CertTypeX509); + private static final ObjectIdentifier pbes2_OID = + ObjectIdentifier.of(KnownOIDs.PBES2); - private static final int[] pkcs9Name = {1, 2, 840, 113549, 1, 9, 20}; - private static final int[] pkcs9KeyId = {1, 2, 840, 113549, 1, 9, 21}; - - private static final int[] pkcs9certType = {1, 2, 840, 113549, 1, 9, 22, 1}; - - private static final int[] pbes2 = {1, 2, 840, 113549, 1, 5, 13}; - // TODO: temporary Oracle OID /* - * { joint-iso-itu-t(2) country(16) us(840) organization(1) oracle(113894) - * jdk(746875) crypto(1) id-at-trustedKeyUsage(1) } + * Temporary Oracle OID + * + * {joint-iso-itu-t(2) country(16) us(840) organization(1) + * oracle(113894) jdk(746875) crypto(1) id-at-trustedKeyUsage(1)} */ - private static final int[] TrustedKeyUsage = - {2, 16, 840, 1, 113894, 746875, 1, 1}; - private static final int[] AnyExtendedKeyUsage = {2, 5, 29, 37, 0}; - - private static final ObjectIdentifier PKCS8ShroudedKeyBag_OID; - private static final ObjectIdentifier CertBag_OID; - private static final ObjectIdentifier SecretBag_OID; - private static final ObjectIdentifier PKCS9FriendlyName_OID; - private static final ObjectIdentifier PKCS9LocalKeyId_OID; - private static final ObjectIdentifier PKCS9CertType_OID; - private static final ObjectIdentifier pbes2_OID; - private static final ObjectIdentifier TrustedKeyUsage_OID; - private static final ObjectIdentifier[] AnyUsage; + private static final ObjectIdentifier TrustedKeyUsage_OID = + ObjectIdentifier.of(KnownOIDs.ORACLE_TrustedKeyUsage); + + private static final ObjectIdentifier[] AnyUsage = new ObjectIdentifier[] { + ObjectIdentifier.of(KnownOIDs.anyExtendedKeyUsage) + }; private int counter = 0; @@ -198,23 +191,6 @@ public DualFormatPKCS12() { // the source of randomness private SecureRandom random; - static { - try { - PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag); - CertBag_OID = new ObjectIdentifier(certBag); - SecretBag_OID = new ObjectIdentifier(secretBag); - PKCS9FriendlyName_OID = new ObjectIdentifier(pkcs9Name); - PKCS9LocalKeyId_OID = new ObjectIdentifier(pkcs9KeyId); - PKCS9CertType_OID = new ObjectIdentifier(pkcs9certType); - pbes2_OID = new ObjectIdentifier(pbes2); - TrustedKeyUsage_OID = new ObjectIdentifier(TrustedKeyUsage); - AnyUsage = new ObjectIdentifier[]{ - new ObjectIdentifier(AnyExtendedKeyUsage)}; - } catch (IOException ioe) { - throw new AssertionError("OID not initialized", ioe); - } - } - // A keystore entry and associated attributes private static class Entry { Date date; // the creation date of this entry @@ -1655,9 +1631,9 @@ private byte[] getBagAttributes(String alias, byte[] keyId, for (KeyStore.Entry.Attribute attribute : attributes) { String attributeName = attribute.getName(); // skip friendlyName, localKeyId and trustedKeyUsage - if (CORE_ATTRIBUTES[0].equals(attributeName) || - CORE_ATTRIBUTES[1].equals(attributeName) || - CORE_ATTRIBUTES[2].equals(attributeName)) { + if (CORE_ATTRIBUTES[0].value().equals(attributeName) || + CORE_ATTRIBUTES[1].value().equals(attributeName) || + CORE_ATTRIBUTES[2].value().equals(attributeName)) { continue; } attrs.write(((PKCS12Attribute) attribute).getEncoded()); diff --git a/src/java.base/share/classes/sun/security/provider/DSAPublicKeyImpl.java b/src/java.base/share/classes/sun/security/provider/DSAPublicKeyImpl.java index 7ccc1c0239f..a97a901f87f 100644 --- a/src/java.base/share/classes/sun/security/provider/DSAPublicKeyImpl.java +++ b/src/java.base/share/classes/sun/security/provider/DSAPublicKeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,17 +25,20 @@ package sun.security.provider; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.math.BigInteger; import java.security.KeyRep; import java.security.InvalidKeyException; /** * An X.509 public key for the Digital Signature Algorithm. - * + *

* The difference between DSAPublicKeyImpl and DSAPublicKey is that * DSAPublicKeyImpl calls writeReplace with KeyRep, and DSAPublicKey * calls writeObject. - * + *

* See the comments in DSAKeyFactory, 4532506, and 6232513. * */ @@ -70,10 +73,25 @@ public DSAPublicKeyImpl(byte[] encoded) throws InvalidKeyException { super(encoded); } - protected Object writeReplace() throws java.io.ObjectStreamException { + private Object writeReplace() throws java.io.ObjectStreamException { return new KeyRep(KeyRep.Type.PUBLIC, getAlgorithm(), getFormat(), getEncoded()); } + + /** + * Restores the state of this object from the stream. + *

+ * Deserialization of this object is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "DSAPublicKeyImpl keys are not directly deserializable"); + } } diff --git a/src/java.base/share/classes/sun/security/provider/KeyProtector.java b/src/java.base/share/classes/sun/security/provider/KeyProtector.java index 18405cca9c3..0404247621a 100644 --- a/src/java.base/share/classes/sun/security/provider/KeyProtector.java +++ b/src/java.base/share/classes/sun/security/provider/KeyProtector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -39,6 +39,7 @@ import sun.security.pkcs.EncryptedPrivateKeyInfo; import sun.security.x509.AlgorithmId; import sun.security.util.ObjectIdentifier; +import sun.security.util.KnownOIDs; import sun.security.util.DerValue; /** @@ -106,9 +107,6 @@ final class KeyProtector { private static final String DIGEST_ALG = "SHA"; private static final int DIGEST_LEN = 20; - // defined by JavaSoft - private static final String KEY_PROTECTOR_OID = "1.3.6.1.4.1.42.2.17.1.1"; - // The password used for protecting/recovering keys passed through this // key protector. We store it as a byte array, so that we can digest it. private byte[] passwdBytes; @@ -214,7 +212,8 @@ public byte[] protect(Key key) throws KeyStoreException // EncryptedPrivateKeyInfo, and returns its encoding AlgorithmId encrAlg; try { - encrAlg = new AlgorithmId(new ObjectIdentifier(KEY_PROTECTOR_OID)); + encrAlg = new AlgorithmId(ObjectIdentifier.of + (KnownOIDs.JAVASOFT_JDKKeyProtector)); return new EncryptedPrivateKeyInfo(encrAlg,encrKey).getEncoded(); } catch (IOException ioe) { throw new KeyStoreException(ioe.getMessage()); @@ -236,7 +235,8 @@ public Key recover(EncryptedPrivateKeyInfo encrInfo) // do we support the algorithm? AlgorithmId encrAlg = encrInfo.getAlgorithm(); - if (!(encrAlg.getOID().toString().equals(KEY_PROTECTOR_OID))) { + if (!(encrAlg.getOID().toString().equals + (KnownOIDs.JAVASOFT_JDKKeyProtector.value()))) { throw new UnrecoverableKeyException("Unsupported key protection " + "algorithm"); } diff --git a/src/java.base/share/classes/sun/security/provider/PolicyFile.java b/src/java.base/share/classes/sun/security/provider/PolicyFile.java index d2b46ab3c2a..fb795fe8472 100644 --- a/src/java.base/share/classes/sun/security/provider/PolicyFile.java +++ b/src/java.base/share/classes/sun/security/provider/PolicyFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2090,8 +2090,17 @@ public SelfPermission(String type, String name, String actions, this.actions.equals(that.actions))) return false; - if (this.certs.length != that.certs.length) + if ((this.certs == null) && (that.certs == null)) { + return true; + } + + if ((this.certs == null) || (that.certs == null)) { + return false; + } + + if (this.certs.length != that.certs.length) { return false; + } int i,j; boolean match; @@ -2161,7 +2170,7 @@ public String getSelfActions() { } public Certificate[] getCerts() { - return certs; + return (certs == null ? null : certs.clone()); } /** @@ -2174,6 +2183,21 @@ public Certificate[] getCerts() { @Override public String toString() { return "(SelfPermission " + type + " " + name + " " + actions + ")"; } + + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if (certs != null) { + this.certs = certs.clone(); + } + } } /** diff --git a/src/java.base/share/classes/sun/security/provider/SecureRandom.java b/src/java.base/share/classes/sun/security/provider/SecureRandom.java index 649e35cdea7..c55dba0ed0a 100644 --- a/src/java.base/share/classes/sun/security/provider/SecureRandom.java +++ b/src/java.base/share/classes/sun/security/provider/SecureRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package sun.security.provider; import java.io.IOException; +import java.io.InvalidObjectException; import java.security.MessageDigest; import java.security.SecureRandomSpi; import java.security.NoSuchAlgorithmException; @@ -187,7 +188,7 @@ private static void updateState(byte[] state, byte[] output) { /** * This static object will be seeded by SeedGenerator, and used * to seed future instances of SHA1PRNG SecureRandoms. - * + *

* Bloch, Effective Java Second Edition: Item 71 */ private static class SeederHolder { @@ -262,17 +263,23 @@ public synchronized void engineNextBytes(byte[] result) { } /* - * readObject is called to restore the state of the random object from - * a stream. We have to create a new instance of MessageDigest, because + * This method is called to restore the state of the random object from + * a stream. + *

+ * We have to create a new instance of {@code MessageDigest}, because * it is not included in the stream (it is marked "transient"). - * - * Note that the engineNextBytes() method invoked on the restored random - * object will yield the exact same (random) bytes as the original. + *

+ * Note that the {@code engineNextBytes()} method invoked on the restored + * random object will yield the exact same (random) bytes as the original. * If you do not want this behaviour, you should re-seed the restored - * random object, using engineSetSeed(). + * random object, using {@code engineSetSeed()}. + * + * @param s the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded */ private void readObject(java.io.ObjectInputStream s) - throws IOException, ClassNotFoundException { + throws IOException, ClassNotFoundException { s.defaultReadObject (); @@ -291,5 +298,34 @@ private void readObject(java.io.ObjectInputStream s) "internal error: SHA-1 not available.", exc); } } + + // Various consistency checks + if ((remainder == null) && (remCount > 0)) { + throw new InvalidObjectException( + "Remainder indicated, but no data available"); + } + + // Not yet allocated state + if (state == null) { + if (remainder == null) { + return; + } else { + throw new InvalidObjectException( + "Inconsistent buffer allocations"); + } + } + + // Sanity check on sizes/pointer + if ((state.length != DIGEST_SIZE) || + ((remainder != null) && (remainder.length != DIGEST_SIZE)) || + (remCount < 0 ) || (remCount >= DIGEST_SIZE)) { + throw new InvalidObjectException( + "Inconsistent buffer sizes/state"); + } + + state = state.clone(); + if (remainder != null) { + remainder = remainder.clone(); + } } } diff --git a/src/java.base/share/classes/sun/security/provider/SunEntries.java b/src/java.base/share/classes/sun/security/provider/SunEntries.java index 759f7d8e529..6fdc344b321 100644 --- a/src/java.base/share/classes/sun/security/provider/SunEntries.java +++ b/src/java.base/share/classes/sun/security/provider/SunEntries.java @@ -32,6 +32,8 @@ import jdk.internal.util.StaticProperty; import sun.security.action.GetPropertyAction; +import sun.security.util.SecurityProviderConstants; +import static sun.security.util.SecurityProviderConstants.getAliases; /** * Defines the entries of the SUN provider. @@ -80,18 +82,6 @@ public final class SunEntries { // the default algo used by SecureRandom class for new SecureRandom() calls public static final String DEF_SECURE_RANDOM_ALGO; - // create an aliases List from the specified aliases - public static List createAliases(String ... aliases) { - return Arrays.asList(aliases); - } - - // create an aliases List from the specified oid followed by other aliases - public static List createAliasesWithOid(String ... oids) { - String[] result = Arrays.copyOf(oids, oids.length + 1); - result[result.length - 1] = "OID." + oids[0]; - return Arrays.asList(result); - } - SunEntries(Provider p) { services = new LinkedHashSet<>(50, 0.9f); @@ -106,22 +96,20 @@ public static List createAliasesWithOid(String ... oids) { attrs.put("ThreadSafe", "true"); if (NativePRNG.isAvailable()) { add(p, "SecureRandom", "NativePRNG", - "sun.security.provider.NativePRNG", - null, attrs); + "sun.security.provider.NativePRNG", attrs); } if (NativePRNG.Blocking.isAvailable()) { add(p, "SecureRandom", "NativePRNGBlocking", - "sun.security.provider.NativePRNG$Blocking", null, attrs); + "sun.security.provider.NativePRNG$Blocking", attrs); } if (NativePRNG.NonBlocking.isAvailable()) { add(p, "SecureRandom", "NativePRNGNonBlocking", - "sun.security.provider.NativePRNG$NonBlocking", null, attrs); + "sun.security.provider.NativePRNG$NonBlocking", attrs); } attrs.put("ImplementedIn", "Software"); - add(p, "SecureRandom", "DRBG", "sun.security.provider.DRBG", - null, attrs); + add(p, "SecureRandom", "DRBG", "sun.security.provider.DRBG", attrs); add(p, "SecureRandom", "SHA1PRNG", - "sun.security.provider.SecureRandom", null, attrs); + "sun.security.provider.SecureRandom", attrs); /* * Signature engines @@ -134,37 +122,28 @@ public static List createAliasesWithOid(String ... oids) { attrs.put("KeySize", "1024"); // for NONE and SHA1 DSA signatures - add(p, "Signature", "SHA1withDSA", - "sun.security.provider.DSA$SHA1withDSA", - createAliasesWithOid("1.2.840.10040.4.3", "DSA", "DSS", - "SHA/DSA", "SHA-1/DSA", "SHA1/DSA", "SHAwithDSA", - "DSAWithSHA1", "1.3.14.3.2.13", "1.3.14.3.2.27"), attrs); - add(p, "Signature", "NONEwithDSA", "sun.security.provider.DSA$RawDSA", - createAliases("RawDSA"), attrs); + addWithAlias(p, "Signature", "SHA1withDSA", + "sun.security.provider.DSA$SHA1withDSA", attrs); + addWithAlias(p, "Signature", "NONEwithDSA", + "sun.security.provider.DSA$RawDSA", attrs); attrs.put("KeySize", "2048"); // for SHA224 and SHA256 DSA signatures - add(p, "Signature", "SHA224withDSA", - "sun.security.provider.DSA$SHA224withDSA", - createAliasesWithOid("2.16.840.1.101.3.4.3.1"), attrs); - add(p, "Signature", "SHA256withDSA", - "sun.security.provider.DSA$SHA256withDSA", - createAliasesWithOid("2.16.840.1.101.3.4.3.2"), attrs); + addWithAlias(p, "Signature", "SHA224withDSA", + "sun.security.provider.DSA$SHA224withDSA", attrs); + addWithAlias(p, "Signature", "SHA256withDSA", + "sun.security.provider.DSA$SHA256withDSA", attrs); attrs.remove("KeySize"); add(p, "Signature", "SHA1withDSAinP1363Format", - "sun.security.provider.DSA$SHA1withDSAinP1363Format", - null, null); + "sun.security.provider.DSA$SHA1withDSAinP1363Format"); add(p, "Signature", "NONEwithDSAinP1363Format", - "sun.security.provider.DSA$RawDSAinP1363Format", - null, null); + "sun.security.provider.DSA$RawDSAinP1363Format"); add(p, "Signature", "SHA224withDSAinP1363Format", - "sun.security.provider.DSA$SHA224withDSAinP1363Format", - null, null); + "sun.security.provider.DSA$SHA224withDSAinP1363Format"); add(p, "Signature", "SHA256withDSAinP1363Format", - "sun.security.provider.DSA$SHA256withDSAinP1363Format", - null, null); + "sun.security.provider.DSA$SHA256withDSAinP1363Format"); /* * Key Pair Generator engines @@ -173,85 +152,75 @@ public static List createAliasesWithOid(String ... oids) { attrs.put("ImplementedIn", "Software"); attrs.put("KeySize", "2048"); // for DSA KPG and APG only - String dsaOid = "1.2.840.10040.4.1"; - List dsaAliases = createAliasesWithOid(dsaOid, "1.3.14.3.2.12"); String dsaKPGImplClass = "sun.security.provider.DSAKeyPairGenerator$"; dsaKPGImplClass += (useLegacyDSA? "Legacy" : "Current"); - add(p, "KeyPairGenerator", "DSA", dsaKPGImplClass, dsaAliases, attrs); + addWithAlias(p, "KeyPairGenerator", "DSA", dsaKPGImplClass, attrs); /* * Algorithm Parameter Generator engines */ - add(p, "AlgorithmParameterGenerator", "DSA", - "sun.security.provider.DSAParameterGenerator", dsaAliases, - attrs); + addWithAlias(p, "AlgorithmParameterGenerator", "DSA", + "sun.security.provider.DSAParameterGenerator", attrs); attrs.remove("KeySize"); /* * Algorithm Parameter engines */ - add(p, "AlgorithmParameters", "DSA", - "sun.security.provider.DSAParameters", dsaAliases, attrs); + addWithAlias(p, "AlgorithmParameters", "DSA", + "sun.security.provider.DSAParameters", attrs); /* * Key factories */ - add(p, "KeyFactory", "DSA", "sun.security.provider.DSAKeyFactory", - dsaAliases, attrs); + addWithAlias(p, "KeyFactory", "DSA", + "sun.security.provider.DSAKeyFactory", attrs); /* * Digest engines */ - add(p, "MessageDigest", "MD2", "sun.security.provider.MD2", null, attrs); - add(p, "MessageDigest", "MD5", "sun.security.provider.MD5", null, attrs); - add(p, "MessageDigest", "SHA", "sun.security.provider.SHA", - createAliasesWithOid("1.3.14.3.2.26", "SHA-1", "SHA1"), attrs); - - String sha2BaseOid = "2.16.840.1.101.3.4.2"; - add(p, "MessageDigest", "SHA-224", "sun.security.provider.SHA2$SHA224", - createAliasesWithOid(sha2BaseOid + ".4"), attrs); - add(p, "MessageDigest", "SHA-256", "sun.security.provider.SHA2$SHA256", - createAliasesWithOid(sha2BaseOid + ".1"), attrs); - add(p, "MessageDigest", "SHA-384", "sun.security.provider.SHA5$SHA384", - createAliasesWithOid(sha2BaseOid + ".2"), attrs); - add(p, "MessageDigest", "SHA-512", "sun.security.provider.SHA5$SHA512", - createAliasesWithOid(sha2BaseOid + ".3"), attrs); - add(p, "MessageDigest", "SHA-512/224", - "sun.security.provider.SHA5$SHA512_224", - createAliasesWithOid(sha2BaseOid + ".5"), attrs); - add(p, "MessageDigest", "SHA-512/256", - "sun.security.provider.SHA5$SHA512_256", - createAliasesWithOid(sha2BaseOid + ".6"), attrs); - add(p, "MessageDigest", "SHA3-224", "sun.security.provider.SHA3$SHA224", - createAliasesWithOid(sha2BaseOid + ".7"), attrs); - add(p, "MessageDigest", "SHA3-256", "sun.security.provider.SHA3$SHA256", - createAliasesWithOid(sha2BaseOid + ".8"), attrs); - add(p, "MessageDigest", "SHA3-384", "sun.security.provider.SHA3$SHA384", - createAliasesWithOid(sha2BaseOid + ".9"), attrs); - add(p, "MessageDigest", "SHA3-512", "sun.security.provider.SHA3$SHA512", - createAliasesWithOid(sha2BaseOid + ".10"), attrs); + add(p, "MessageDigest", "MD2", "sun.security.provider.MD2", attrs); + add(p, "MessageDigest", "MD5", "sun.security.provider.MD5", attrs); + addWithAlias(p, "MessageDigest", "SHA-1", "sun.security.provider.SHA", + attrs); + + addWithAlias(p, "MessageDigest", "SHA-224", + "sun.security.provider.SHA2$SHA224", attrs); + addWithAlias(p, "MessageDigest", "SHA-256", + "sun.security.provider.SHA2$SHA256", attrs); + addWithAlias(p, "MessageDigest", "SHA-384", + "sun.security.provider.SHA5$SHA384", attrs); + addWithAlias(p, "MessageDigest", "SHA-512", + "sun.security.provider.SHA5$SHA512", attrs); + addWithAlias(p, "MessageDigest", "SHA-512/224", + "sun.security.provider.SHA5$SHA512_224", attrs); + addWithAlias(p, "MessageDigest", "SHA-512/256", + "sun.security.provider.SHA5$SHA512_256", attrs); + addWithAlias(p, "MessageDigest", "SHA3-224", + "sun.security.provider.SHA3$SHA224", attrs); + addWithAlias(p, "MessageDigest", "SHA3-256", + "sun.security.provider.SHA3$SHA256", attrs); + addWithAlias(p, "MessageDigest", "SHA3-384", + "sun.security.provider.SHA3$SHA384", attrs); + addWithAlias(p, "MessageDigest", "SHA3-512", + "sun.security.provider.SHA3$SHA512", attrs); /* * Certificates */ - add(p, "CertificateFactory", "X.509", - "sun.security.provider.X509Factory", - createAliases("X509"), attrs); + addWithAlias(p, "CertificateFactory", "X.509", + "sun.security.provider.X509Factory", attrs); /* * KeyStore */ add(p, "KeyStore", "PKCS12", - "sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", - null, null); + "sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12"); add(p, "KeyStore", "JKS", - "sun.security.provider.JavaKeyStore$DualFormatJKS", - null, attrs); + "sun.security.provider.JavaKeyStore$DualFormatJKS", attrs); add(p, "KeyStore", "CaseExactJKS", - "sun.security.provider.JavaKeyStore$CaseExactJKS", - null, attrs); + "sun.security.provider.JavaKeyStore$CaseExactJKS", attrs); add(p, "KeyStore", "DKS", "sun.security.provider.DomainKeyStore$DKS", - null, attrs); + attrs); /* @@ -259,22 +228,21 @@ public static List createAliasesWithOid(String ... oids) { */ add(p, "CertStore", "Collection", "sun.security.provider.certpath.CollectionCertStore", - null, attrs); + attrs); add(p, "CertStore", "com.sun.security.IndexedCollection", "sun.security.provider.certpath.IndexedCollectionCertStore", - null, attrs); + attrs); /* * Policy */ - add(p, "Policy", "JavaPolicy", "sun.security.provider.PolicySpiFile", - null, null); + add(p, "Policy", "JavaPolicy", "sun.security.provider.PolicySpiFile"); /* * Configuration */ add(p, "Configuration", "JavaLoginConfig", - "sun.security.provider.ConfigFile$Spi", null, null); + "sun.security.provider.ConfigFile$Spi"); /* * CertPathBuilder and CertPathValidator @@ -285,19 +253,29 @@ public static List createAliasesWithOid(String ... oids) { add(p, "CertPathBuilder", "PKIX", "sun.security.provider.certpath.SunCertPathBuilder", - null, attrs); + attrs); add(p, "CertPathValidator", "PKIX", "sun.security.provider.certpath.PKIXCertPathValidator", - null, attrs); + attrs); } Iterator iterator() { return services.iterator(); } + private void add(Provider p, String type, String algo, String cn) { + services.add(new Provider.Service(p, type, algo, cn, null, null)); + } + private void add(Provider p, String type, String algo, String cn, - List aliases, HashMap attrs) { - services.add(new Provider.Service(p, type, algo, cn, aliases, attrs)); + HashMap attrs) { + services.add(new Provider.Service(p, type, algo, cn, null, attrs)); + } + + private void addWithAlias(Provider p, String type, String algo, String cn, + HashMap attrs) { + services.add(new Provider.Service(p, type, algo, cn, + getAliases(algo), attrs)); } private LinkedHashSet services; diff --git a/src/java.base/share/classes/sun/security/provider/X509Factory.java b/src/java.base/share/classes/sun/security/provider/X509Factory.java index 47466820838..f30647126f4 100644 --- a/src/java.base/share/classes/sun/security/provider/X509Factory.java +++ b/src/java.base/share/classes/sun/security/provider/X509Factory.java @@ -26,12 +26,9 @@ package sun.security.provider; import java.io.*; -import java.security.PublicKey; import java.util.*; import java.security.cert.*; -import jdk.internal.event.EventHelper; -import jdk.internal.event.X509CertificateEvent; import sun.security.util.KeyUtil; import sun.security.util.Pem; import sun.security.x509.*; @@ -104,8 +101,6 @@ public Certificate engineGenerateCertificate(InputStream is) } cert = new X509CertImpl(encoding); addToCache(certCache, cert.getEncodedInternal(), cert); - // record cert details if necessary - commitEvent(cert); return cert; } else { throw new IOException("Empty input"); @@ -473,7 +468,7 @@ public Collection engineGenerateCRLs( } } catch (ParsingException e) { while (data != null) { - coll.add(new X509CertImpl(data)); + coll.add(X509CertImpl.newX509CertImpl(data)); data = readOneBlock(pbis); } } @@ -766,43 +761,4 @@ private static int readBERInternal(InputStream is, } return tag; } - - private void commitEvent(X509CertImpl info) { - X509CertificateEvent xce = new X509CertificateEvent(); - if (xce.shouldCommit() || EventHelper.isLoggingSecurity()) { - PublicKey pKey = info.getPublicKey(); - String algId = info.getSigAlgName(); - String serNum = info.getSerialNumber().toString(16); - String subject = info.getSubjectDN().getName(); - String issuer = info.getIssuerDN().getName(); - String keyType = pKey.getAlgorithm(); - int length = KeyUtil.getKeySize(pKey); - int hashCode = info.hashCode(); - long beginDate = info.getNotBefore().getTime(); - long endDate = info.getNotAfter().getTime(); - if (xce.shouldCommit()) { - xce.algorithm = algId; - xce.serialNumber = serNum; - xce.subject = subject; - xce.issuer = issuer; - xce.keyType = keyType; - xce.keyLength = length; - xce.certificateId = hashCode; - xce.validFrom = beginDate; - xce.validUntil = endDate; - xce.commit(); - } - if (EventHelper.isLoggingSecurity()) { - EventHelper.logX509CertificateEvent(algId, - serNum, - subject, - issuer, - keyType, - length, - hashCode, - beginDate, - endDate); - } - } - } } diff --git a/src/java.base/share/classes/sun/security/provider/certpath/CertPathHelper.java b/src/java.base/share/classes/sun/security/provider/certpath/CertPathHelper.java index 7c02007422d..ebc2200f0e6 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/CertPathHelper.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/CertPathHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,14 +26,10 @@ package sun.security.provider.certpath; import java.util.Date; -import java.util.Set; import java.security.cert.TrustAnchor; -import java.security.cert.X509CertSelector; import java.security.cert.X509CRLSelector; -import sun.security.x509.GeneralNameInterface; - /** * Helper class that allows access to JDK specific known-public methods in the * java.security.cert package. It relies on a subclass in the @@ -55,18 +51,10 @@ protected CertPathHelper() { // empty } - protected abstract void implSetPathToNames(X509CertSelector sel, - Set names); - protected abstract void implSetDateAndTime(X509CRLSelector sel, Date date, long skew); protected abstract boolean implIsJdkCA(TrustAnchor anchor); - static void setPathToNames(X509CertSelector sel, - Set names) { - instance.implSetPathToNames(sel, names); - } - public static void setDateAndTime(X509CRLSelector sel, Date date, long skew) { instance.implSetDateAndTime(sel, date, skew); } diff --git a/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java b/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java index 2afb2f9a85f..00351647349 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java @@ -48,7 +48,6 @@ import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.AuthorityKeyIdentifierExtension; import static sun.security.x509.PKIXExtensions.*; -import sun.security.x509.SubjectAlternativeNameExtension; import sun.security.x509.X500Name; import sun.security.x509.X509CertImpl; @@ -258,14 +257,6 @@ private void getMatchingCACerts(ForwardState currentState, */ caSelector.setSubject(currentState.issuerDN); - /* - * Match on subjectNamesTraversed (both DNs and AltNames) - * (checks that current cert's name constraints permit it - * to certify all the DNs and AltNames that have been traversed) - */ - CertPathHelper.setPathToNames - (caSelector, currentState.subjectNamesTraversed); - /* * check the validity period */ @@ -704,19 +695,6 @@ void verifyCert(X509Certificate cert, State currentState, // Don't bother to verify untrusted certificate more. currState.untrustedChecker.check(cert, Collections.emptySet()); - /* - * Abort if we encounter the same certificate or a certificate with - * the same public key, subject DN, and subjectAltNames as a cert - * that is already in path. - */ - for (X509Certificate cpListCert : certPathList) { - if (repeated(cpListCert, cert)) { - throw new CertPathValidatorException( - "cert with repeated subject, public key, and " + - "subjectAltNames detected"); - } - } - /* check if trusted cert */ boolean isTrustedCert = trustedCerts.contains(cert); @@ -794,49 +772,6 @@ void verifyCert(X509Certificate cert, State currentState, } } - /** - * Return true if two certificates are equal or have the same subject, - * public key, and subject alternative names. - */ - private static boolean repeated( - X509Certificate currCert, X509Certificate nextCert) { - if (currCert.equals(nextCert)) { - return true; - } - return (currCert.getSubjectX500Principal().equals( - nextCert.getSubjectX500Principal()) && - currCert.getPublicKey().equals(nextCert.getPublicKey()) && - altNamesEqual(currCert, nextCert)); - } - - /** - * Return true if two certificates have the same subject alternative names. - */ - private static boolean altNamesEqual( - X509Certificate currCert, X509Certificate nextCert) { - X509CertImpl curr, next; - try { - curr = X509CertImpl.toImpl(currCert); - next = X509CertImpl.toImpl(nextCert); - } catch (CertificateException ce) { - return false; - } - - SubjectAlternativeNameExtension currAltNameExt = - curr.getSubjectAlternativeNameExtension(); - SubjectAlternativeNameExtension nextAltNameExt = - next.getSubjectAlternativeNameExtension(); - if (currAltNameExt != null) { - if (nextAltNameExt == null) { - return false; - } - return Arrays.equals(currAltNameExt.getExtensionValue(), - nextAltNameExt.getExtensionValue()); - } else { - return (nextAltNameExt == null); - } - } - /** * Verifies whether the input certificate completes the path. * First checks the cert against each trust anchor that was specified, diff --git a/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java b/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java index 9d7af9b169b..9a5088babf2 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java @@ -31,17 +31,11 @@ import java.security.cert.PKIXCertPathChecker; import java.security.cert.X509Certificate; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.ListIterator; import javax.security.auth.x500.X500Principal; import sun.security.util.Debug; -import sun.security.x509.SubjectAlternativeNameExtension; -import sun.security.x509.GeneralNames; -import sun.security.x509.GeneralName; -import sun.security.x509.GeneralNameInterface; -import sun.security.x509.X500Name; import sun.security.x509.X509CertImpl; /** @@ -61,9 +55,6 @@ class ForwardState implements State { /* The last cert in the path */ X509CertImpl cert; - /* The set of subjectDNs and subjectAltNames of all certs in the path */ - HashSet subjectNamesTraversed; - /* * The number of intermediate CA certs which have been traversed so * far in the path @@ -73,7 +64,6 @@ class ForwardState implements State { /* Flag indicating if state is initial (path is just starting) */ private boolean init = true; - /* the untrusted certificates checker */ UntrustedChecker untrustedChecker; @@ -104,8 +94,6 @@ public String toString() { sb.append("\n issuerDN of last cert: ").append(issuerDN); sb.append("\n traversedCACerts: ").append(traversedCACerts); sb.append("\n init: ").append(String.valueOf(init)); - sb.append("\n subjectNamesTraversed: \n").append - (subjectNamesTraversed); sb.append("\n selfIssued: ").append (String.valueOf(selfIssued)); sb.append("]\n"); @@ -120,7 +108,6 @@ public String toString() { public void initState(List certPathCheckers) throws CertPathValidatorException { - subjectNamesTraversed = new HashSet(); traversedCACerts = 0; /* @@ -170,32 +157,6 @@ public void updateState(X509Certificate cert) } } - /* update subjectNamesTraversed only if this is the EE cert or if - this cert is not self-issued */ - if (init || !selfIssued) { - X500Principal subjName = cert.getSubjectX500Principal(); - subjectNamesTraversed.add(X500Name.asX500Name(subjName)); - - try { - SubjectAlternativeNameExtension subjAltNameExt - = icert.getSubjectAlternativeNameExtension(); - if (subjAltNameExt != null) { - GeneralNames gNames = subjAltNameExt.get( - SubjectAlternativeNameExtension.SUBJECT_NAME); - for (GeneralName gName : gNames.names()) { - subjectNamesTraversed.add(gName.getName()); - } - } - } catch (IOException e) { - if (debug != null) { - debug.println("ForwardState.updateState() unexpected " - + "exception"); - e.printStackTrace(); - } - throw new CertPathValidatorException(e); - } - } - init = false; } @@ -203,10 +164,6 @@ public void updateState(X509Certificate cert) * Clone current state. The state is cloned as each cert is * added to the path. This is necessary if backtracking occurs, * and a prior state needs to be restored. - * - * Note that this is a SMART clone. Not all fields are fully copied, - * because some of them will - * not have their contents modified by subsequent calls to updateState. */ @Override @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly @@ -226,13 +183,6 @@ public Object clone() { } } - /* - * Shallow copy traversed names. There is no need to - * deep copy contents, since the elements of the Set - * are never modified by subsequent calls to updateState(). - */ - clonedState.subjectNamesTraversed - = (HashSet)subjectNamesTraversed.clone(); return clonedState; } catch (CloneNotSupportedException e) { throw new InternalError(e.toString(), e); diff --git a/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java b/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java index 2cff9ead31e..f8b77988666 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java @@ -135,7 +135,7 @@ public enum ResponseStatus { private static final Debug debug = Debug.getInstance("certpath"); private static final boolean dump = debug != null && Debug.isOn("ocsp"); private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID = - ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1}); + ObjectIdentifier.of(KnownOIDs.OCSPBasicResponse); private static final int CERT_STATUS_GOOD = 0; private static final int CERT_STATUS_REVOKED = 1; private static final int CERT_STATUS_UNKNOWN = 2; @@ -144,9 +144,6 @@ public enum ResponseStatus { private static final int NAME_TAG = 1; private static final int KEY_TAG = 2; - // Object identifier for the OCSPSigning key purpose - private static final String KP_OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9"; - // Default maximum clock skew in milliseconds (15 minutes) // allowed when checking validity of OCSP responses private static final int DEFAULT_MAX_CLOCK_SKEW = 900000; @@ -357,7 +354,7 @@ public OCSPResponse(byte[] bytes) throws IOException { try { for (int i = 0; i < derCerts.length; i++) { X509CertImpl cert = - new X509CertImpl(derCerts[i].toByteArray()); + X509CertImpl.newX509CertImpl(derCerts[i].toByteArray()); certs.add(cert); if (debug != null) { @@ -495,7 +492,7 @@ void verify(List certIds, IssuerInfo issuerInfo, try { List keyPurposes = signerCert.getExtendedKeyUsage(); if (keyPurposes == null || - !keyPurposes.contains(KP_OCSP_SIGNING_OID)) { + !keyPurposes.contains(KnownOIDs.OCSPSigning.value())) { throw new CertPathValidatorException( "Responder's certificate not valid for signing " + "OCSP responses"); diff --git a/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java b/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java index 02425e86add..de3923bb3bc 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java @@ -228,13 +228,13 @@ private static PKIXCertPathValidatorResult validate(TrustAnchor anchor, X509ValidationEvent xve = new X509ValidationEvent(); if (xve.shouldCommit() || EventHelper.isLoggingSecurity()) { int[] certIds = params.certificates().stream() - .mapToInt(x -> x.hashCode()) + .mapToInt(Certificate::hashCode) .toArray(); - int anchorCertId = - anchor.getTrustedCert().hashCode(); + int anchorCertId = (anchorCert != null) ? + anchorCert.hashCode() : anchor.getCAPublicKey().hashCode(); if (xve.shouldCommit()) { xve.certificateId = anchorCertId; - int certificatePos = 1; //anchor cert + int certificatePos = 1; // most trusted CA xve.certificatePosition = certificatePos; xve.validationCounter = validationCounter.incrementAndGet(); xve.commit(); diff --git a/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java b/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java index 1e8f3294570..6d8e842419a 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java @@ -46,6 +46,7 @@ import sun.security.x509.*; import static sun.security.x509.PKIXExtensions.*; import sun.security.util.Debug; +import sun.security.util.KnownOIDs; class RevocationChecker extends PKIXRevocationChecker { @@ -723,7 +724,7 @@ private void checkOCSP(X509Certificate cert, // verify the response byte[] nonce = null; for (Extension ext : ocspExtensions) { - if (ext.getId().equals("1.3.6.1.5.5.7.48.1.2")) { + if (ext.getId().equals(KnownOIDs.OCSPNonceExt.value())) { nonce = ext.getValue(); } } diff --git a/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java b/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java index fd4eb9543e9..fd5a01a923d 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java @@ -33,6 +33,7 @@ import java.security.cert.CertPathValidatorException.BasicReason; import java.security.cert.PKIXReason; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -42,6 +43,7 @@ import sun.security.provider.certpath.PKIX.BuilderParams; import static sun.security.x509.PKIXExtensions.*; +import sun.security.x509.SubjectAlternativeNameExtension; import sun.security.x509.X509CertImpl; import sun.security.util.Debug; @@ -265,7 +267,7 @@ private void depthFirstSearchForward(X500Principal dN, */ Collection certs = builder.getMatchingCerts(currentState, buildParams.certStores()); - List vertices = addVertices(certs, adjList); + List vertices = addVertices(certs, adjList, cpList); if (debug != null) { debug.println("SunCertPathBuilder.depthFirstSearchForward(): " + "certs.size=" + vertices.size()); @@ -325,17 +327,32 @@ private void depthFirstSearchForward(X500Principal dN, * cert (which is signed by the trusted public key), but * don't add it yet to the cpList */ + PublicKey rootKey = cert.getPublicKey(); if (builder.trustAnchor.getTrustedCert() == null) { appendedCerts.add(0, cert); + rootKey = builder.trustAnchor.getCAPublicKey(); + if (debug != null) + debug.println( + "SunCertPathBuilder.depthFirstSearchForward " + + "using buildParams public key: " + + rootKey.toString()); } + TrustAnchor anchor = new TrustAnchor + (cert.getSubjectX500Principal(), rootKey, null); + // add the basic checker + List checkers = new ArrayList<>(); + BasicChecker basicChecker = new BasicChecker(anchor, + buildParams.date(), + buildParams.sigProvider(), + true); + checkers.add(basicChecker); Set initExpPolSet = Collections.singleton(PolicyChecker.ANY_POLICY); PolicyNodeImpl rootNode = new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false); - List checkers = new ArrayList<>(); PolicyChecker policyChecker = new PolicyChecker(buildParams.initialPolicies(), appendedCerts.size(), @@ -346,28 +363,13 @@ private void depthFirstSearchForward(X500Principal dN, rootNode); checkers.add(policyChecker); + // add the constraints checker + checkers.add(new ConstraintsChecker(appendedCerts.size())); + // add the algorithm checker checkers.add(new AlgorithmChecker(builder.trustAnchor, buildParams.timestamp(), buildParams.variant())); - PublicKey rootKey = cert.getPublicKey(); - if (builder.trustAnchor.getTrustedCert() == null) { - rootKey = builder.trustAnchor.getCAPublicKey(); - if (debug != null) - debug.println( - "SunCertPathBuilder.depthFirstSearchForward " + - "using buildParams public key: " + - rootKey.toString()); - } - TrustAnchor anchor = new TrustAnchor - (cert.getSubjectX500Principal(), rootKey, null); - - // add the basic checker - BasicChecker basicChecker = new BasicChecker(anchor, - buildParams.date(), - buildParams.sigProvider(), - true); - checkers.add(basicChecker); buildParams.setCertPath(cf.generateCertPath(appendedCerts)); @@ -563,18 +565,79 @@ private void depthFirstSearchForward(X500Principal dN, * adjacency list. */ private static List addVertices(Collection certs, - List> adjList) + List> adjList, + List cpList) { List l = adjList.get(adjList.size() - 1); for (X509Certificate cert : certs) { - Vertex v = new Vertex(cert); - l.add(v); + boolean repeated = false; + for (X509Certificate cpListCert : cpList) { + /* + * Ignore if we encounter the same certificate or a + * certificate with the same public key, subject DN, and + * subjectAltNames as a cert that is already in path. + */ + if (repeated(cpListCert, cert)) { + if (debug != null) { + debug.println("cert with repeated subject, " + + "public key, and subjectAltNames detected"); + } + repeated = true; + break; + } + } + if (!repeated) { + l.add(new Vertex(cert)); + } } return l; } + /** + * Return true if two certificates are equal or have the same subject, + * public key, and subject alternative names. + */ + private static boolean repeated( + X509Certificate currCert, X509Certificate nextCert) { + if (currCert.equals(nextCert)) { + return true; + } + return (currCert.getSubjectX500Principal().equals( + nextCert.getSubjectX500Principal()) && + currCert.getPublicKey().equals(nextCert.getPublicKey()) && + altNamesEqual(currCert, nextCert)); + } + + /** + * Return true if two certificates have the same subject alternative names. + */ + private static boolean altNamesEqual( + X509Certificate currCert, X509Certificate nextCert) { + X509CertImpl curr, next; + try { + curr = X509CertImpl.toImpl(currCert); + next = X509CertImpl.toImpl(nextCert); + } catch (CertificateException ce) { + return false; + } + + SubjectAlternativeNameExtension currAltNameExt = + curr.getSubjectAlternativeNameExtension(); + SubjectAlternativeNameExtension nextAltNameExt = + next.getSubjectAlternativeNameExtension(); + if (currAltNameExt != null) { + if (nextAltNameExt == null) { + return false; + } + return Arrays.equals(currAltNameExt.getExtensionValue(), + nextAltNameExt.getExtensionValue()); + } else { + return (nextAltNameExt == null); + } + } + /** * Returns true if trust anchor certificate matches specified * certificate constraints. diff --git a/src/java.base/share/classes/sun/security/provider/certpath/X509CertPath.java b/src/java.base/share/classes/sun/security/provider/certpath/X509CertPath.java index f738b5f5fe0..79cde0d72fd 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/X509CertPath.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/X509CertPath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,7 @@ package sun.security.provider.certpath; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.security.cert.CertificateEncodingException; import java.security.cert.Certificate; import java.security.cert.CertificateException; @@ -394,4 +391,19 @@ public Iterator getEncodings() { public List getCertificates() { return certs; } + + /** + * Restores the state of this object from the stream. + *

+ * Deserialization of this object is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "X509CertPaths are not directly deserializable"); + } } diff --git a/src/java.base/share/classes/sun/security/provider/certpath/X509CertificatePair.java b/src/java.base/share/classes/sun/security/provider/certpath/X509CertificatePair.java index ea139dd061d..35c64147e88 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/X509CertificatePair.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/X509CertificatePair.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, 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 @@ -240,7 +240,7 @@ private void parse(DerValue val) } opt = opt.data.getDerValue(); forward = X509Factory.intern - (new X509CertImpl(opt.toByteArray())); + (X509CertImpl.newX509CertImpl(opt.toByteArray())); } break; case TAG_REVERSE: @@ -251,7 +251,7 @@ private void parse(DerValue val) } opt = opt.data.getDerValue(); reverse = X509Factory.intern - (new X509CertImpl(opt.toByteArray())); + (X509CertImpl.newX509CertImpl(opt.toByteArray())); } break; default: diff --git a/src/java.base/share/classes/sun/security/rsa/PSSParameters.java b/src/java.base/share/classes/sun/security/rsa/PSSParameters.java index 22da2303923..163cdfcd126 100644 --- a/src/java.base/share/classes/sun/security/rsa/PSSParameters.java +++ b/src/java.base/share/classes/sun/security/rsa/PSSParameters.java @@ -99,7 +99,7 @@ protected void engineInit(byte[] encoded) throws IOException { } else if (d.isContextSpecific((byte) 0x01)) { // mgf algid AlgorithmId val = AlgorithmId.parse(d.data.getDerValue()); - if (!val.getOID().equals(AlgorithmId.mgf1_oid)) { + if (!val.getOID().equals(AlgorithmId.MGF1_oid)) { throw new IOException("Only MGF1 mgf is supported"); } @@ -247,7 +247,7 @@ public static byte[] getEncoded(PSSParameterSpec spec) throws IOException { if (!mgfDigestId.getOID().equals(AlgorithmId.SHA_oid)) { tmp2 = new DerOutputStream(); - tmp2.putOID(AlgorithmId.mgf1_oid); + tmp2.putOID(AlgorithmId.MGF1_oid); mgfDigestId.encode(tmp2); tmp3 = new DerOutputStream(); tmp3.write(DerValue.tag_Sequence, tmp2); diff --git a/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java b/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java index 927044c0c6c..eb8a7388616 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java +++ b/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java @@ -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 @@ -32,8 +32,7 @@ import java.security.spec.*; import sun.security.action.GetPropertyAction; -import sun.security.x509.AlgorithmId; -import static sun.security.rsa.RSAUtil.KeyType; +import sun.security.rsa.RSAUtil.KeyType; /** * KeyFactory for RSA keys, e.g. "RSA", "RSASSA-PSS". @@ -44,13 +43,15 @@ * between the following: * * For public keys: - * . PublicKey with an X.509 encoding + * . RSA PublicKey with an X.509 encoding + * . RSA PublicKey with an PKCS#1 encoding * . RSAPublicKey * . RSAPublicKeySpec * . X509EncodedKeySpec * * For private keys: - * . PrivateKey with a PKCS#8 encoding + * . RSA PrivateKey with a PKCS#8 encoding + * . RSA PrivateKey with a PKCS#1 encoding * . RSAPrivateKey * . RSAPrivateCrtKey * . RSAPrivateKeySpec @@ -96,8 +97,8 @@ static RSAKeyFactory getInstance(KeyType type) { return new RSAKeyFactory(type); } - // Internal utility method for checking key algorithm - private static void checkKeyAlgo(Key key, String expectedAlg) + // pkg-private utility method for checking key algorithm + static void checkKeyAlgo(Key key, String expectedAlg) throws InvalidKeyException { String keyAlg = key.getAlgorithm(); if (keyAlg == null || !(keyAlg.equalsIgnoreCase(expectedAlg))) { @@ -211,7 +212,7 @@ protected Key engineTranslateKey(Key key) throws InvalidKeyException { throw new InvalidKeyException("Key must not be null"); } // ensure the key algorithm matches the current KeyFactory instance - checkKeyAlgo(key, type.keyAlgo()); + checkKeyAlgo(key, type.keyAlgo); // no translation needed if the key is already our own impl if ((key instanceof RSAPrivateKeyImpl) || @@ -259,21 +260,17 @@ private PublicKey translatePublicKey(PublicKey key) RSAPublicKey rsaKey = (RSAPublicKey)key; try { return new RSAPublicKeyImpl( - RSAUtil.createAlgorithmId(type, rsaKey.getParams()), + type, rsaKey.getParams(), rsaKey.getModulus(), rsaKey.getPublicExponent()); } catch (ProviderException e) { // catch providers that incorrectly implement RSAPublicKey throw new InvalidKeyException("Invalid key", e); } - } else if ("X.509".equals(key.getFormat())) { - RSAPublicKey translated = new RSAPublicKeyImpl(key.getEncoded()); - // ensure the key algorithm matches the current KeyFactory instance - checkKeyAlgo(translated, type.keyAlgo()); - return translated; } else { - throw new InvalidKeyException("Public keys must be instance " - + "of RSAPublicKey or have X.509 encoding"); + // create new key based on the format and encoding of current 'key' + return RSAPublicKeyImpl.newKey(type, key.getFormat(), + key.getEncoded()); } } @@ -284,7 +281,7 @@ private PrivateKey translatePrivateKey(PrivateKey key) RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey)key; try { return new RSAPrivateCrtKeyImpl( - RSAUtil.createAlgorithmId(type, rsaKey.getParams()), + type, rsaKey.getParams(), rsaKey.getModulus(), rsaKey.getPublicExponent(), rsaKey.getPrivateExponent(), @@ -302,7 +299,7 @@ private PrivateKey translatePrivateKey(PrivateKey key) RSAPrivateKey rsaKey = (RSAPrivateKey)key; try { return new RSAPrivateKeyImpl( - RSAUtil.createAlgorithmId(type, rsaKey.getParams()), + type, rsaKey.getParams(), rsaKey.getModulus(), rsaKey.getPrivateExponent() ); @@ -310,15 +307,9 @@ private PrivateKey translatePrivateKey(PrivateKey key) // catch providers that incorrectly implement RSAPrivateKey throw new InvalidKeyException("Invalid key", e); } - } else if ("PKCS#8".equals(key.getFormat())) { - RSAPrivateKey translated = - RSAPrivateCrtKeyImpl.newKey(key.getEncoded()); - // ensure the key algorithm matches the current KeyFactory instance - checkKeyAlgo(translated, type.keyAlgo()); - return translated; } else { - throw new InvalidKeyException("Private keys must be instance " - + "of RSAPrivate(Crt)Key or have PKCS#8 encoding"); + return RSAPrivateCrtKeyImpl.newKey(type, key.getFormat(), + key.getEncoded()); } } @@ -326,16 +317,13 @@ private PrivateKey translatePrivateKey(PrivateKey key) private PublicKey generatePublic(KeySpec keySpec) throws GeneralSecurityException { if (keySpec instanceof X509EncodedKeySpec) { - X509EncodedKeySpec x509Spec = (X509EncodedKeySpec)keySpec; - RSAPublicKey generated = new RSAPublicKeyImpl(x509Spec.getEncoded()); - // ensure the key algorithm matches the current KeyFactory instance - checkKeyAlgo(generated, type.keyAlgo()); - return generated; + return RSAPublicKeyImpl.newKey(type, "X.509", + ((X509EncodedKeySpec)keySpec).getEncoded()); } else if (keySpec instanceof RSAPublicKeySpec) { RSAPublicKeySpec rsaSpec = (RSAPublicKeySpec)keySpec; try { return new RSAPublicKeyImpl( - RSAUtil.createAlgorithmId(type, rsaSpec.getParams()), + type, rsaSpec.getParams(), rsaSpec.getModulus(), rsaSpec.getPublicExponent() ); @@ -352,16 +340,13 @@ private PublicKey generatePublic(KeySpec keySpec) private PrivateKey generatePrivate(KeySpec keySpec) throws GeneralSecurityException { if (keySpec instanceof PKCS8EncodedKeySpec) { - PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec)keySpec; - RSAPrivateKey generated = RSAPrivateCrtKeyImpl.newKey(pkcsSpec.getEncoded()); - // ensure the key algorithm matches the current KeyFactory instance - checkKeyAlgo(generated, type.keyAlgo()); - return generated; + return RSAPrivateCrtKeyImpl.newKey(type, "PKCS#8", + ((PKCS8EncodedKeySpec)keySpec).getEncoded()); } else if (keySpec instanceof RSAPrivateCrtKeySpec) { RSAPrivateCrtKeySpec rsaSpec = (RSAPrivateCrtKeySpec)keySpec; try { return new RSAPrivateCrtKeyImpl( - RSAUtil.createAlgorithmId(type, rsaSpec.getParams()), + type, rsaSpec.getParams(), rsaSpec.getModulus(), rsaSpec.getPublicExponent(), rsaSpec.getPrivateExponent(), @@ -378,7 +363,7 @@ private PrivateKey generatePrivate(KeySpec keySpec) RSAPrivateKeySpec rsaSpec = (RSAPrivateKeySpec)keySpec; try { return new RSAPrivateKeyImpl( - RSAUtil.createAlgorithmId(type, rsaSpec.getParams()), + type, rsaSpec.getParams(), rsaSpec.getModulus(), rsaSpec.getPrivateExponent() ); @@ -396,7 +381,8 @@ protected T engineGetKeySpec(Key key, Class keySpec) try { // convert key to one of our keys // this also verifies that the key is a valid RSA key and ensures - // that the encoding is X.509/PKCS#8 for public/private keys + // that the encoding is X.509/PKCS#8 or PKCS#1 for public/private + // keys key = engineTranslateKey(key); } catch (InvalidKeyException e) { throw new InvalidKeySpecException(e); diff --git a/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java b/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java index 4d2f9952368..6bd041b60f1 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java +++ b/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java @@ -32,10 +32,10 @@ import java.security.spec.RSAKeyGenParameterSpec; import sun.security.jca.JCAUtil; +import sun.security.rsa.RSAUtil.KeyType; + import static sun.security.util.SecurityProviderConstants.DEF_RSA_KEY_SIZE; import static sun.security.util.SecurityProviderConstants.DEF_RSASSA_PSS_KEY_SIZE; -import sun.security.x509.AlgorithmId; -import static sun.security.rsa.RSAUtil.KeyType; /** * RSA keypair generation. Standard algorithm, minimum key length 512 bit. @@ -55,7 +55,7 @@ public abstract class RSAKeyPairGenerator extends KeyPairGeneratorSpi { private int keySize; private final KeyType type; - private AlgorithmId rsaId; + private AlgorithmParameterSpec keyParams; // PRNG to use private SecureRandom random; @@ -116,7 +116,7 @@ public void initialize(AlgorithmParameterSpec params, SecureRandom random) } try { - this.rsaId = RSAUtil.createAlgorithmId(type, tmpParams); + this.keyParams = RSAUtil.checkParamsAgainstType(type, tmpParams); } catch (ProviderException e) { throw new InvalidAlgorithmParameterException( "Invalid key parameters", e); @@ -177,9 +177,10 @@ public KeyPair generateKeyPair() { BigInteger coeff = q.modInverse(p); try { - PublicKey publicKey = new RSAPublicKeyImpl(rsaId, n, e); - PrivateKey privateKey = new RSAPrivateCrtKeyImpl( - rsaId, n, e, d, p, q, pe, qe, coeff); + PublicKey publicKey = new RSAPublicKeyImpl(type, keyParams, + n, e); + PrivateKey privateKey = new RSAPrivateCrtKeyImpl(type, + keyParams, n, e, d, p, q, pe, qe, coeff); return new KeyPair(publicKey, privateKey); } catch (InvalidKeyException exc) { // invalid key exception only thrown for keys < 512 bit, diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java b/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java index 7ba5fb93d64..c00f75b35d6 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java +++ b/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ package sun.security.rsa; import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.math.BigInteger; import java.security.*; @@ -34,16 +36,15 @@ import sun.security.util.*; -import sun.security.x509.AlgorithmId; import sun.security.pkcs.PKCS8Key; -import static sun.security.rsa.RSAUtil.KeyType; +import sun.security.rsa.RSAUtil.KeyType; /** * RSA private key implementation for "RSA", "RSASSA-PSS" algorithms in CRT form. * For non-CRT private keys, see RSAPrivateKeyImpl. We need separate classes * to ensure correct behavior in instanceof checks, etc. - * + *

* Note: RSA keys must be at least 512 bits long * * @see RSAPrivateKeyImpl @@ -66,27 +67,52 @@ public final class RSAPrivateCrtKeyImpl private BigInteger qe; // prime exponent q private BigInteger coeff; // CRT coeffcient + private transient KeyType type; + // Optional parameters associated with this RSA key // specified in the encoding of its AlgorithmId. // Must be null for "RSA" keys. - private AlgorithmParameterSpec keyParams; + private transient AlgorithmParameterSpec keyParams; /** - * Generate a new key from its encoding. Returns a CRT key if possible - * and a non-CRT key otherwise. Used by RSAKeyFactory. + * Generate a new RSAPrivate(Crt)Key from the specified type, + * format and encoding. Returns a CRT key if possible and a non-CRT + * key otherwise. + * Also used by SunPKCS11 provider. */ - public static RSAPrivateKey newKey(byte[] encoded) - throws InvalidKeyException { - RSAPrivateCrtKeyImpl key = new RSAPrivateCrtKeyImpl(encoded); - // check all CRT-specific components are available, if any one - // missing, return a non-CRT key instead - if (checkComponents(key)) { - return key; - } else { - return new RSAPrivateKeyImpl( - key.algid, - key.getModulus(), - key.getPrivateExponent()); + public static RSAPrivateKey newKey(KeyType type, String format, + byte[] encoded) throws InvalidKeyException { + switch (format) { + case "PKCS#8": + RSAPrivateCrtKeyImpl key = new RSAPrivateCrtKeyImpl(encoded); + RSAKeyFactory.checkKeyAlgo(key, type.keyAlgo); + // check all CRT-specific components are available, if any one + // missing, return a non-CRT key instead + if (checkComponents(key)) { + return key; + } else { + return new RSAPrivateKeyImpl(key.type, key.keyParams, + key.getModulus(), key.getPrivateExponent()); + } + case "PKCS#1": + try { + BigInteger[] comps = parseASN1(encoded); + if ((comps[1].signum() == 0) || (comps[3].signum() == 0) || + (comps[4].signum() == 0) || (comps[5].signum() == 0) || + (comps[6].signum() == 0) || (comps[7].signum() == 0)) { + return new RSAPrivateKeyImpl(type, null, comps[0], + comps[2]); + } else { + return new RSAPrivateCrtKeyImpl(type, null, comps[0], + comps[1], comps[2], comps[3], comps[4], comps[5], + comps[6], comps[7]); + } + } catch (IOException ioe) { + throw new InvalidKeyException("Invalid PKCS#1 encoding", ioe); + } + default: + throw new InvalidKeyException("Unsupported RSA Private(Crt)Key " + + "format: " + format); } } @@ -113,14 +139,13 @@ public static RSAPrivateKey newKey(KeyType type, BigInteger p, BigInteger q, BigInteger pe, BigInteger qe, BigInteger coeff) throws InvalidKeyException { RSAPrivateKey key; - AlgorithmId rsaId = RSAUtil.createAlgorithmId(type, params); if ((e.signum() == 0) || (p.signum() == 0) || (q.signum() == 0) || (pe.signum() == 0) || (qe.signum() == 0) || (coeff.signum() == 0)) { // if any component is missing, return a non-CRT key - return new RSAPrivateKeyImpl(rsaId, n, d); + return new RSAPrivateKeyImpl(type, params, n, d); } else { - return new RSAPrivateCrtKeyImpl(rsaId, n, e, d, + return new RSAPrivateCrtKeyImpl(type, params, n, e, d, p, q, pe, qe, coeff); } } @@ -128,7 +153,7 @@ public static RSAPrivateKey newKey(KeyType type, /** * Construct a key from its encoding. Called from newKey above. */ - RSAPrivateCrtKeyImpl(byte[] encoded) throws InvalidKeyException { + private RSAPrivateCrtKeyImpl(byte[] encoded) throws InvalidKeyException { if (encoded == null || encoded.length == 0) { throw new InvalidKeyException("Missing key encoding"); } @@ -136,8 +161,10 @@ public static RSAPrivateKey newKey(KeyType type, decode(encoded); RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e); try { - // this will check the validity of params - this.keyParams = RSAUtil.getParamSpec(algid); + // check the validity of oid and params + Object[] o = RSAUtil.getTypeAndParamSpec(algid); + this.type = (KeyType) o[0]; + this.keyParams = (AlgorithmParameterSpec) o[1]; } catch (ProviderException e) { throw new InvalidKeyException(e); } @@ -147,7 +174,7 @@ public static RSAPrivateKey newKey(KeyType type, * Construct a RSA key from its components. Used by the * RSAKeyFactory and the RSAKeyPairGenerator. */ - RSAPrivateCrtKeyImpl(AlgorithmId rsaId, + RSAPrivateCrtKeyImpl(KeyType type, AlgorithmParameterSpec keyParams, BigInteger n, BigInteger e, BigInteger d, BigInteger p, BigInteger q, BigInteger pe, BigInteger qe, BigInteger coeff) throws InvalidKeyException { @@ -161,11 +188,19 @@ public static RSAPrivateKey newKey(KeyType type, this.pe = pe; this.qe = qe; this.coeff = coeff; - this.keyParams = RSAUtil.getParamSpec(rsaId); - // generate the encoding - algid = rsaId; try { + // validate and generate the algid encoding + algid = RSAUtil.createAlgorithmId(type, keyParams); + } catch (ProviderException exc) { + throw new InvalidKeyException(exc); + } + + this.type = type; + this.keyParams = keyParams; + + try { + // generate the key encoding DerOutputStream out = new DerOutputStream(); out.putInteger(0); // version must be 0 out.putInteger(n); @@ -188,7 +223,7 @@ public static RSAPrivateKey newKey(KeyType type, // see JCA doc @Override public String getAlgorithm() { - return algid.getName(); + return type.keyAlgo; } // see JCA doc @@ -248,9 +283,39 @@ public AlgorithmParameterSpec getParams() { // return a string representation of this key for debugging @Override public String toString() { - return "SunRsaSign " + getAlgorithm() + " private CRT key, " + n.bitLength() - + " bits" + "\n params: " + keyParams + "\n modulus: " + n - + "\n private exponent: " + d; + return "SunRsaSign " + type.keyAlgo + " private CRT key, " + + n.bitLength() + " bits" + "\n params: " + keyParams + + "\n modulus: " + n + "\n private exponent: " + d; + } + + // utility method for parsing DER encoding of RSA private keys in PKCS#1 + // format as defined in RFC 8017 Appendix A.1.2, i.e. SEQ of version, n, + // e, d, p, q, pe, qe, and coeff, and return the parsed components. + private static BigInteger[] parseASN1(byte[] raw) throws IOException { + DerValue derValue = new DerValue(raw); + if (derValue.tag != DerValue.tag_Sequence) { + throw new IOException("Not a SEQUENCE"); + } + int version = derValue.data.getInteger(); + if (version != 0) { + throw new IOException("Version must be 0"); + } + + BigInteger[] result = new BigInteger[8]; // n, e, d, p, q, pe, qe, coeff + /* + * Some implementations do not correctly encode ASN.1 INTEGER values + * in 2's complement format, resulting in a negative integer when + * decoded. Correct the error by converting it to a positive integer. + * + * See CR 6255949 + */ + for (int i = 0; i < result.length; i++) { + result[i] = derValue.data.getPositiveBigInteger(); + } + if (derValue.data.available() != 0) { + throw new IOException("Extra data available"); + } + return result; } /** @@ -258,37 +323,32 @@ public String toString() { */ protected void parseKeyBits() throws InvalidKeyException { try { - DerInputStream in = new DerInputStream(key); - DerValue derValue = in.getDerValue(); - if (derValue.tag != DerValue.tag_Sequence) { - throw new IOException("Not a SEQUENCE"); - } - DerInputStream data = derValue.data; - int version = data.getInteger(); - if (version != 0) { - throw new IOException("Version must be 0"); - } - - /* - * Some implementations do not correctly encode ASN.1 INTEGER values - * in 2's complement format, resulting in a negative integer when - * decoded. Correct the error by converting it to a positive integer. - * - * See CR 6255949 - */ - n = data.getPositiveBigInteger(); - e = data.getPositiveBigInteger(); - d = data.getPositiveBigInteger(); - p = data.getPositiveBigInteger(); - q = data.getPositiveBigInteger(); - pe = data.getPositiveBigInteger(); - qe = data.getPositiveBigInteger(); - coeff = data.getPositiveBigInteger(); - if (derValue.data.available() != 0) { - throw new IOException("Extra data available"); - } + BigInteger[] comps = parseASN1(key); + n = comps[0]; + e = comps[1]; + d = comps[2]; + p = comps[3]; + q = comps[4]; + pe = comps[5]; + qe = comps[6]; + coeff = comps[7]; } catch (IOException e) { throw new InvalidKeyException("Invalid RSA private key", e); } } + + /** + * Restores the state of this object from the stream. + *

+ * Deserialization of this object is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "RSAPrivateCrtKeyImpl keys are not directly deserializable"); + } } diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java b/src/java.base/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java index 792018d4f08..defa58b9fd0 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java +++ b/src/java.base/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ package sun.security.rsa; import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.math.BigInteger; import java.security.*; @@ -33,15 +35,17 @@ import java.security.interfaces.*; import sun.security.util.*; -import sun.security.x509.AlgorithmId; import sun.security.pkcs.PKCS8Key; +import sun.security.rsa.RSAUtil.KeyType; + /** * RSA private key implementation for "RSA", "RSASSA-PSS" algorithms in non-CRT - * form (modulus, private exponent only). For CRT private keys, see - * RSAPrivateCrtKeyImpl. We need separate classes to ensure correct behavior - * in instanceof checks, etc. - * + * form (modulus, private exponent only). + *

+ * For CRT private keys, see RSAPrivateCrtKeyImpl. We need separate classes + * to ensure correct behavior in instanceof checks, etc. + *

* Note: RSA keys must be at least 512 bits long * * @see RSAPrivateCrtKeyImpl @@ -57,26 +61,37 @@ public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey { private final BigInteger n; // modulus private final BigInteger d; // private exponent + private transient final KeyType type; + // optional parameters associated with this RSA key // specified in the encoding of its AlgorithmId. // must be null for "RSA" keys. - private final AlgorithmParameterSpec keyParams; + private transient final AlgorithmParameterSpec keyParams; /** * Construct a key from its components. Used by the * RSAKeyFactory and the RSAKeyPairGenerator. */ - RSAPrivateKeyImpl(AlgorithmId rsaId, BigInteger n, BigInteger d) - throws InvalidKeyException { + RSAPrivateKeyImpl(KeyType type, AlgorithmParameterSpec keyParams, + BigInteger n, BigInteger d) throws InvalidKeyException { + RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), null); this.n = n; this.d = d; - this.keyParams = RSAUtil.getParamSpec(rsaId); - // generate the encoding - algid = rsaId; try { + // validate and generate the algid encoding + algid = RSAUtil.createAlgorithmId(type, keyParams); + } catch (ProviderException pe) { + throw new InvalidKeyException(pe); + } + + this.type = type; + this.keyParams = keyParams; + + try { + // generate the key encoding DerOutputStream out = new DerOutputStream(); out.putInteger(0); // version must be 0 out.putInteger(n); @@ -99,7 +114,7 @@ public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey { // see JCA doc @Override public String getAlgorithm() { - return algid.getName(); + return type.keyAlgo; } // see JCA doc @@ -123,8 +138,23 @@ public AlgorithmParameterSpec getParams() { // return a string representation of this key for debugging @Override public String toString() { - return "Sun " + getAlgorithm() + " private key, " + n.bitLength() + return "Sun " + type.keyAlgo + " private key, " + n.bitLength() + " bits" + "\n params: " + keyParams + "\n modulus: " + n + "\n private exponent: " + d; } + + /** + * Restores the state of this object from the stream. + *

+ * Deserialization of this object is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "RSAPrivateKeyImpl keys are not directly deserializable"); + } } diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPublicKeyImpl.java b/src/java.base/share/classes/sun/security/rsa/RSAPublicKeyImpl.java index 2489107a8c9..96c84333718 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSAPublicKeyImpl.java +++ b/src/java.base/share/classes/sun/security/rsa/RSAPublicKeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ package sun.security.rsa; import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.math.BigInteger; import java.security.*; @@ -34,13 +36,12 @@ import sun.security.util.*; import sun.security.x509.X509Key; -import sun.security.x509.AlgorithmId; -import static sun.security.rsa.RSAUtil.KeyType; +import sun.security.rsa.RSAUtil.KeyType; /** * RSA public key implementation for "RSA", "RSASSA-PSS" algorithms. - * + *

* Note: RSA keys must be at least 512 bits long * * @see RSAPrivateCrtKeyImpl @@ -58,47 +59,76 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey { private BigInteger n; // modulus private BigInteger e; // public exponent + private transient KeyType type; + // optional parameters associated with this RSA key // specified in the encoding of its AlgorithmId // must be null for "RSA" keys. - private AlgorithmParameterSpec keyParams; + private transient AlgorithmParameterSpec keyParams; /** - * Generate a new RSAPublicKey from the specified encoding. - * Used by SunPKCS11 provider. + * Generate a new RSAPublicKey from the specified type, format, and + * encoding. + * Also used by SunPKCS11 provider. */ - public static RSAPublicKey newKey(byte[] encoded) - throws InvalidKeyException { - return new RSAPublicKeyImpl(encoded); + public static RSAPublicKey newKey(KeyType type, String format, + byte[] encoded) throws InvalidKeyException { + RSAPublicKey key; + switch (format) { + case "X.509": + key = new RSAPublicKeyImpl(encoded); + RSAKeyFactory.checkKeyAlgo(key, type.keyAlgo); + break; + case "PKCS#1": + try { + BigInteger[] comps = parseASN1(encoded); + key = new RSAPublicKeyImpl(type, null, comps[0], comps[1]); + } catch (IOException ioe) { + throw new InvalidKeyException("Invalid PKCS#1 encoding", ioe); + } + break; + default: + throw new InvalidKeyException("Unsupported RSA PublicKey format: " + + format); + } + return key; } /** * Generate a new RSAPublicKey from the specified type and components. - * Used by SunPKCS11 provider. + * Also used by SunPKCS11 provider. */ public static RSAPublicKey newKey(KeyType type, AlgorithmParameterSpec params, BigInteger n, BigInteger e) throws InvalidKeyException { - AlgorithmId rsaId = RSAUtil.createAlgorithmId(type, params); - return new RSAPublicKeyImpl(rsaId, n, e); + return new RSAPublicKeyImpl(type, params, n, e); } /** - * Construct a RSA key from AlgorithmId and its components. Used by + * Construct a RSA key from the specified type and components. Used by * RSAKeyFactory and RSAKeyPairGenerator. */ - RSAPublicKeyImpl(AlgorithmId rsaId, BigInteger n, BigInteger e) - throws InvalidKeyException { + RSAPublicKeyImpl(KeyType type, AlgorithmParameterSpec keyParams, + BigInteger n, BigInteger e) throws InvalidKeyException { + RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e); checkExponentRange(n, e); this.n = n; this.e = e; - this.keyParams = RSAUtil.getParamSpec(rsaId); - // generate the encoding - algid = rsaId; try { + // validate and generate algid encoding + algid = RSAUtil.createAlgorithmId(type, keyParams); + } catch (ProviderException pe) { + throw new InvalidKeyException(pe); + } + + this.type = type; + this.keyParams = keyParams; + + try { + // generate the key encoding DerOutputStream out = new DerOutputStream(); out.putInteger(n); out.putInteger(e); @@ -113,9 +143,9 @@ public static RSAPublicKey newKey(KeyType type, } /** - * Construct a key from its encoding. Used by RSAKeyFactory. + * Construct a key from its encoding. */ - RSAPublicKeyImpl(byte[] encoded) throws InvalidKeyException { + private RSAPublicKeyImpl(byte[] encoded) throws InvalidKeyException { if (encoded == null || encoded.length == 0) { throw new InvalidKeyException("Missing key encoding"); } @@ -124,8 +154,10 @@ public static RSAPublicKey newKey(KeyType type, checkExponentRange(n, e); try { - // this will check the validity of params - this.keyParams = RSAUtil.getParamSpec(algid); + // check the validity of oid and params + Object[] o = RSAUtil.getTypeAndParamSpec(algid); + this.type = (KeyType) o[0]; + this.keyParams = (AlgorithmParameterSpec) o[1]; } catch (ProviderException e) { throw new InvalidKeyException(e); } @@ -148,7 +180,7 @@ static void checkExponentRange(BigInteger mod, BigInteger exp) // see JCA doc @Override public String getAlgorithm() { - return algid.getName(); + return type.keyAlgo; } // see JCA doc @@ -169,22 +201,30 @@ public AlgorithmParameterSpec getParams() { return keyParams; } + // utility method for parsing DER encoding of RSA public keys in PKCS#1 + // format as defined in RFC 8017 Appendix A.1.1, i.e. SEQ of n and e. + private static BigInteger[] parseASN1(byte[] raw) throws IOException { + DerValue derValue = new DerValue(raw); + if (derValue.tag != DerValue.tag_Sequence) { + throw new IOException("Not a SEQUENCE"); + } + BigInteger[] result = new BigInteger[2]; // n, e + result[0] = derValue.data.getPositiveBigInteger(); + result[1] = derValue.data.getPositiveBigInteger(); + if (derValue.data.available() != 0) { + throw new IOException("Extra data available"); + } + return result; + } + /** * Parse the key. Called by X509Key. */ protected void parseKeyBits() throws InvalidKeyException { try { - DerInputStream in = new DerInputStream(getKey().toByteArray()); - DerValue derValue = in.getDerValue(); - if (derValue.tag != DerValue.tag_Sequence) { - throw new IOException("Not a SEQUENCE"); - } - DerInputStream data = derValue.data; - n = data.getPositiveBigInteger(); - e = data.getPositiveBigInteger(); - if (derValue.data.available() != 0) { - throw new IOException("Extra data available"); - } + BigInteger[] comps = parseASN1(getKey().toByteArray()); + n = comps[0]; + e = comps[1]; } catch (IOException e) { throw new InvalidKeyException("Invalid RSA public key", e); } @@ -193,15 +233,30 @@ protected void parseKeyBits() throws InvalidKeyException { // return a string representation of this key for debugging @Override public String toString() { - return "Sun " + getAlgorithm() + " public key, " + n.bitLength() + return "Sun " + type.keyAlgo + " public key, " + n.bitLength() + " bits" + "\n params: " + keyParams + "\n modulus: " + n + "\n public exponent: " + e; } - protected Object writeReplace() throws java.io.ObjectStreamException { + private Object writeReplace() throws java.io.ObjectStreamException { return new KeyRep(KeyRep.Type.PUBLIC, getAlgorithm(), getFormat(), getEncoded()); } + + /** + * Restores the state of this object from the stream. + *

+ * Deserialization of this object is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "RSAPublicKeyImpl keys are not directly deserializable"); + } } diff --git a/src/java.base/share/classes/sun/security/rsa/RSAUtil.java b/src/java.base/share/classes/sun/security/rsa/RSAUtil.java index d4a60a04545..1d2e991e1bd 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSAUtil.java +++ b/src/java.base/share/classes/sun/security/rsa/RSAUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -40,52 +40,71 @@ public class RSAUtil { public enum KeyType { - RSA ("RSA"), - PSS ("RSASSA-PSS") + RSA ("RSA", AlgorithmId.RSAEncryption_oid, null), + PSS ("RSASSA-PSS", AlgorithmId.RSASSA_PSS_oid, PSSParameterSpec.class) ; - private final String algo; + final String keyAlgo; + final ObjectIdentifier oid; + final Class paramSpecCls; - KeyType(String keyAlgo) { - this.algo = keyAlgo; + KeyType(String keyAlgo, ObjectIdentifier oid, + Class paramSpecCls) { + this.keyAlgo = keyAlgo; + this.oid = oid; + this.paramSpecCls = paramSpecCls; } - public String keyAlgo() { - return algo; - } - public static KeyType lookup(String name) - throws InvalidKeyException, ProviderException { - if (name == null) { - throw new InvalidKeyException("Null key algorithm"); - } - for (KeyType kt : KeyType.values()) { - if (kt.keyAlgo().equalsIgnoreCase(name)) { - return kt; - } + + public static KeyType lookup(String name) throws ProviderException { + + requireNonNull(name, "Key algorithm should not be null"); + + // match loosely in order to work with 3rd party providers which + // may not follow the standard names + if (name.indexOf("PSS") != -1) { + return PSS; + } else if (name.indexOf("RSA") != -1) { + return RSA; + } else { // no match + throw new ProviderException("Unsupported algorithm " + name); } - // no match - throw new ProviderException("Unsupported algorithm " + name); } } - public static void checkParamsAgainstType(KeyType type, + private static void requireNonNull(Object obj, String msg) { + if (obj == null) throw new ProviderException(msg); + } + + public static AlgorithmParameterSpec checkParamsAgainstType(KeyType type, AlgorithmParameterSpec paramSpec) throws ProviderException { - switch (type) { - case RSA: - if (paramSpec != null) { - throw new ProviderException("null params expected for " + - type.keyAlgo()); - } - break; - case PSS: - if ((paramSpec != null) && - !(paramSpec instanceof PSSParameterSpec)) { - throw new ProviderException - ("PSSParmeterSpec expected for " + type.keyAlgo()); - } - break; - default: - throw new ProviderException - ("Unsupported RSA algorithm " + type); + + // currently no check for null parameter spec + // assumption is parameter spec is optional and can be null + if (paramSpec == null) return null; + + Class expCls = type.paramSpecCls; + if (expCls == null) { + throw new ProviderException("null params expected for " + + type.keyAlgo); + } else if (!expCls.isInstance(paramSpec)) { + throw new ProviderException + (expCls + " expected for " + type.keyAlgo); + } + return paramSpec; + } + + public static AlgorithmParameters getParams(KeyType type, + AlgorithmParameterSpec spec) throws ProviderException { + + if (spec == null) return null; + + try { + AlgorithmParameters params = + AlgorithmParameters.getInstance(type.keyAlgo); + params.init(spec); + return params; + } catch (NoSuchAlgorithmException | InvalidParameterSpecException ex) { + throw new ProviderException(ex); } } @@ -94,69 +113,53 @@ public static AlgorithmId createAlgorithmId(KeyType type, checkParamsAgainstType(type, paramSpec); - ObjectIdentifier oid = null; - AlgorithmParameters params = null; - try { - switch (type) { - case RSA: - oid = AlgorithmId.RSAEncryption_oid; - break; - case PSS: - if (paramSpec != null) { - params = AlgorithmParameters.getInstance(type.keyAlgo()); - params.init(paramSpec); - } - oid = AlgorithmId.RSASSA_PSS_oid; - break; - default: - throw new ProviderException - ("Unsupported RSA algorithm " + type); - } - AlgorithmId result; - if (params == null) { - result = new AlgorithmId(oid); - } else { - result = new AlgorithmId(oid, params); - } - return result; - } catch (NoSuchAlgorithmException | InvalidParameterSpecException e) { - // should not happen - throw new ProviderException(e); - } + ObjectIdentifier oid = type.oid; + AlgorithmParameters params = getParams(type, paramSpec); + return new AlgorithmId(oid, params); } - public static AlgorithmParameterSpec getParamSpec(AlgorithmId algid) - throws ProviderException { - if (algid == null) { - throw new ProviderException("AlgorithmId should not be null"); + public static AlgorithmParameterSpec getParamSpec( + AlgorithmParameters params) throws ProviderException { + + if (params == null) return null; + + String algName = params.getAlgorithm(); + + KeyType type = KeyType.lookup(algName); + Class specCls = type.paramSpecCls; + if (specCls == null) { + throw new ProviderException("No params accepted for " + + type.keyAlgo); + } + try { + return params.getParameterSpec(specCls); + } catch (InvalidParameterSpecException ex) { + throw new ProviderException(ex); } - return getParamSpec(algid.getParameters()); } - public static AlgorithmParameterSpec getParamSpec(AlgorithmParameters params) + public static Object[] getTypeAndParamSpec(AlgorithmId algid) throws ProviderException { - if (params == null) return null; + requireNonNull(algid, "AlgorithmId should not be null"); + + Object[] result = new Object[2]; + + String algName = algid.getName(); try { - String algName = params.getAlgorithm(); - KeyType type = KeyType.lookup(algName); - Class specCls; - switch (type) { - case RSA: - throw new ProviderException("No params accepted for " + - type.keyAlgo()); - case PSS: - specCls = PSSParameterSpec.class; - break; - default: - throw new ProviderException("Unsupported RSA algorithm: " + algName); - } - return params.getParameterSpec(specCls); + result[0] = KeyType.lookup(algName); } catch (ProviderException pe) { - // pass it up - throw pe; - } catch (Exception e) { - throw new ProviderException(e); + // accommodate RSA keys encoded with various RSA signature oids + // for backward compatibility + if (algName.indexOf("RSA") != -1) { + result[0] = KeyType.RSA; + } else { + // pass it up + throw pe; + } } + + result[1] = getParamSpec(algid.getParameters()); + return result; } } diff --git a/src/java.base/share/classes/sun/security/rsa/SunRsaSignEntries.java b/src/java.base/share/classes/sun/security/rsa/SunRsaSignEntries.java index a5cab587d28..f3edf4f25e1 100644 --- a/src/java.base/share/classes/sun/security/rsa/SunRsaSignEntries.java +++ b/src/java.base/share/classes/sun/security/rsa/SunRsaSignEntries.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -27,7 +27,7 @@ import java.util.*; import java.security.Provider; -import static sun.security.provider.SunEntries.createAliasesWithOid; +import static sun.security.util.SecurityProviderConstants.getAliases; /** * Defines the entries of the SunRsaSign provider. @@ -38,7 +38,14 @@ public final class SunRsaSignEntries { private void add(Provider p, String type, String algo, String cn, List aliases, HashMap attrs) { - services.add(new Provider.Service(p, type, algo, cn, aliases, attrs)); + services.add(new Provider.Service(p, type, algo, cn, + aliases, attrs)); + } + + private void addA(Provider p, String type, String algo, String cn, + HashMap attrs) { + services.add(new Provider.Service(p, type, algo, cn, + getAliases(algo), attrs)); } // extend LinkedHashSet for consistency with SunEntries @@ -47,13 +54,6 @@ public SunRsaSignEntries(Provider p) { services = new LinkedHashSet<>(20, 0.9f); // start populating content using the specified provider - - // common oids - String rsaOid = "1.2.840.113549.1.1"; - List rsaAliases = createAliasesWithOid(rsaOid); - List rsapssAliases = createAliasesWithOid(rsaOid + ".10"); - String sha1withRSAOid2 = "1.3.14.3.2.29"; - // common attribute map HashMap attrs = new HashMap<>(3); attrs.put("SupportedKeyClasses", @@ -62,50 +62,37 @@ public SunRsaSignEntries(Provider p) { add(p, "KeyFactory", "RSA", "sun.security.rsa.RSAKeyFactory$Legacy", - rsaAliases, null); + getAliases("PKCS1"), null); add(p, "KeyPairGenerator", "RSA", "sun.security.rsa.RSAKeyPairGenerator$Legacy", - rsaAliases, null); - add(p, "Signature", "MD2withRSA", - "sun.security.rsa.RSASignature$MD2withRSA", - createAliasesWithOid(rsaOid + ".2"), attrs); - add(p, "Signature", "MD5withRSA", - "sun.security.rsa.RSASignature$MD5withRSA", - createAliasesWithOid(rsaOid + ".4"), attrs); - add(p, "Signature", "SHA1withRSA", - "sun.security.rsa.RSASignature$SHA1withRSA", - createAliasesWithOid(rsaOid + ".5", sha1withRSAOid2), attrs); - add(p, "Signature", "SHA224withRSA", - "sun.security.rsa.RSASignature$SHA224withRSA", - createAliasesWithOid(rsaOid + ".14"), attrs); - add(p, "Signature", "SHA256withRSA", - "sun.security.rsa.RSASignature$SHA256withRSA", - createAliasesWithOid(rsaOid + ".11"), attrs); - add(p, "Signature", "SHA384withRSA", - "sun.security.rsa.RSASignature$SHA384withRSA", - createAliasesWithOid(rsaOid + ".12"), attrs); - add(p, "Signature", "SHA512withRSA", - "sun.security.rsa.RSASignature$SHA512withRSA", - createAliasesWithOid(rsaOid + ".13"), attrs); - add(p, "Signature", "SHA512/224withRSA", - "sun.security.rsa.RSASignature$SHA512_224withRSA", - createAliasesWithOid(rsaOid + ".15"), attrs); - add(p, "Signature", "SHA512/256withRSA", - "sun.security.rsa.RSASignature$SHA512_256withRSA", - createAliasesWithOid(rsaOid + ".16"), attrs); + getAliases("PKCS1"), null); + addA(p, "Signature", "MD2withRSA", + "sun.security.rsa.RSASignature$MD2withRSA", attrs); + addA(p, "Signature", "MD5withRSA", + "sun.security.rsa.RSASignature$MD5withRSA", attrs); + addA(p, "Signature", "SHA1withRSA", + "sun.security.rsa.RSASignature$SHA1withRSA", attrs); + addA(p, "Signature", "SHA224withRSA", + "sun.security.rsa.RSASignature$SHA224withRSA", attrs); + addA(p, "Signature", "SHA256withRSA", + "sun.security.rsa.RSASignature$SHA256withRSA", attrs); + addA(p, "Signature", "SHA384withRSA", + "sun.security.rsa.RSASignature$SHA384withRSA", attrs); + addA(p, "Signature", "SHA512withRSA", + "sun.security.rsa.RSASignature$SHA512withRSA", attrs); + addA(p, "Signature", "SHA512/224withRSA", + "sun.security.rsa.RSASignature$SHA512_224withRSA", attrs); + addA(p, "Signature", "SHA512/256withRSA", + "sun.security.rsa.RSASignature$SHA512_256withRSA", attrs); - add(p, "KeyFactory", "RSASSA-PSS", - "sun.security.rsa.RSAKeyFactory$PSS", - rsapssAliases, null); - add(p, "KeyPairGenerator", "RSASSA-PSS", - "sun.security.rsa.RSAKeyPairGenerator$PSS", - rsapssAliases, null); - add(p, "Signature", "RSASSA-PSS", - "sun.security.rsa.RSAPSSSignature", - rsapssAliases, attrs); - add(p, "AlgorithmParameters", "RSASSA-PSS", - "sun.security.rsa.PSSParameters", - rsapssAliases, null); + addA(p, "KeyFactory", "RSASSA-PSS", + "sun.security.rsa.RSAKeyFactory$PSS", attrs); + addA(p, "KeyPairGenerator", "RSASSA-PSS", + "sun.security.rsa.RSAKeyPairGenerator$PSS", attrs); + addA(p, "Signature", "RSASSA-PSS", + "sun.security.rsa.RSAPSSSignature", attrs); + addA(p, "AlgorithmParameters", "RSASSA-PSS", + "sun.security.rsa.PSSParameters", attrs); } public Iterator iterator() { diff --git a/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java b/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java index 6accc74c6ba..d6662235029 100644 --- a/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java +++ b/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java @@ -327,45 +327,36 @@ public SSLPossession createPossession(HandshakeContext context) { } /* - * 768 bits ephemeral DH private keys were used to be used in + * 768 bit ephemeral DH private keys used to be used in * ServerKeyExchange except that exportable ciphers max out at 512 - * bits modulus values. We still adhere to this behavior in legacy + * bit modulus values. We still adhere to this behavior in legacy * mode (system property "jdk.tls.ephemeralDHKeySize" is defined * as "legacy"). * - * Old JDK (JDK 7 and previous) releases don't support DH keys - * bigger than 1024 bits. We have to consider the compatibility - * requirement. 1024 bits DH key is always used for non-exportable - * cipher suites in default mode (system property + * Only very old JDK releases don't support DH keys bigger than + * 1024 bits (JDK 1.5 and 6u/7u releases prior to adding support + * for DH keys > 1024 bits - see JDK-8062834). A 2048 bit + * DH key is always used for non-exportable cipher suites in + * default mode (when the system property * "jdk.tls.ephemeralDHKeySize" is not defined). * - * However, if applications want more stronger strength, setting - * system property "jdk.tls.ephemeralDHKeySize" to "matched" - * is a workaround to use ephemeral DH key which size matches the - * corresponding authentication key. For example, if the public key - * size of an authentication certificate is 2048 bits, then the - * ephemeral DH key size should be 2048 bits accordingly unless - * the cipher suite is exportable. This key sizing scheme keeps - * the cryptographic strength consistent between authentication - * keys and key-exchange keys. - * * Applications may also want to customize the ephemeral DH key * size to a fixed length for non-exportable cipher suites. This - * can be approached by setting system property + * can be done by setting the system property * "jdk.tls.ephemeralDHKeySize" to a valid positive integer between * 1024 and 8192 bits, inclusive. * - * Note that the minimum acceptable key size is 1024 bits except - * exportable cipher suites or legacy mode. + * Note that the minimum acceptable key size is 2048 bits except + * for exportable cipher suites or legacy mode. * * Note that per RFC 2246, the key size limit of DH is 512 bits for * exportable cipher suites. Because of the weakness, exportable * cipher suites are deprecated since TLS v1.1 and they are not * enabled by default in Oracle provider. The legacy behavior is - * reserved and 512 bits DH key is always used for exportable + * preserved and a 512 bit DH key is always used for exportable * cipher suites. */ - int keySize = exportable ? 512 : 1024; // default mode + int keySize = exportable ? 512 : 2048; // default mode if (!exportable) { if (useLegacyEphemeralDHKeys) { // legacy mode keySize = 768; @@ -391,7 +382,7 @@ public SSLPossession createPossession(HandshakeContext context) { // limit in the future when the compatibility and // interoperability impact is limited. keySize = ks <= 1024 ? 1024 : 2048; - } // Otherwise, anonymous cipher suites, 1024-bit is used. + } // Otherwise, anonymous cipher suites, 2048-bit is used. } else if (customizedDHKeySize > 0) { // customized mode keySize = customizedDHKeySize; } diff --git a/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java b/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java index c77c628158a..9daa0f7b07b 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java @@ -143,7 +143,7 @@ final class SSLConfiguration implements Cloneable { this.identificationProtocol = null; this.serverNames = Collections.emptyList(); this.sniMatchers = Collections.emptyList(); - this.preferLocalCipherSuites = false; + this.preferLocalCipherSuites = true; this.applicationProtocols = new String[0]; this.enableRetransmissions = sslContext.isDTLS(); diff --git a/src/java.base/share/classes/sun/security/ssl/SunJSSE.java b/src/java.base/share/classes/sun/security/ssl/SunJSSE.java index c50ba93ecfc..2a2b5d75687 100644 --- a/src/java.base/share/classes/sun/security/ssl/SunJSSE.java +++ b/src/java.base/share/classes/sun/security/ssl/SunJSSE.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -29,7 +29,7 @@ import java.util.*; import sun.security.rsa.SunRsaSignEntries; import static sun.security.util.SecurityConstants.PROVIDER_VER; -import static sun.security.provider.SunEntries.createAliases; +import static sun.security.util.SecurityProviderConstants.*; /** * The JSSE provider. @@ -161,8 +161,8 @@ public Object run() { } private void ps(String type, String algo, String cn, - List aliases, HashMap attrs) { - putService(new Provider.Service(this, type, algo, cn, aliases, attrs)); + List a, HashMap attrs) { + putService(new Provider.Service(this, type, algo, cn, a, attrs)); } private void doRegister(boolean isfips) { @@ -180,17 +180,17 @@ private void doRegister(boolean isfips) { "sun.security.ssl.KeyManagerFactoryImpl$SunX509", null, null); ps("KeyManagerFactory", "NewSunX509", "sun.security.ssl.KeyManagerFactoryImpl$X509", - createAliases("PKIX"), null); + List.of("PKIX"), null); ps("TrustManagerFactory", "SunX509", "sun.security.ssl.TrustManagerFactoryImpl$SimpleFactory", null, null); ps("TrustManagerFactory", "PKIX", "sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", - createAliases("SunPKIX", "X509", "X.509"), null); + List.of("SunPKIX", "X509", "X.509"), null); ps("SSLContext", "TLSv1", "sun.security.ssl.SSLContextImpl$TLS10Context", - (isfips? null : createAliases("SSLv3")), null); + (isfips? null : List.of("SSLv3")), null); ps("SSLContext", "TLSv1.1", "sun.security.ssl.SSLContextImpl$TLS11Context", null, null); ps("SSLContext", "TLSv1.2", @@ -199,7 +199,7 @@ private void doRegister(boolean isfips) { "sun.security.ssl.SSLContextImpl$TLS13Context", null, null); ps("SSLContext", "TLS", "sun.security.ssl.SSLContextImpl$TLSContext", - (isfips? null : createAliases("SSL")), null); + (isfips? null : List.of("SSL")), null); ps("SSLContext", "DTLSv1.0", "sun.security.ssl.SSLContextImpl$DTLS10Context", null, null); diff --git a/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java b/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java index bf7ac162c1f..f5050c279fb 100644 --- a/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java @@ -43,6 +43,7 @@ import javax.net.ssl.*; import sun.security.provider.certpath.AlgorithmChecker; import sun.security.validator.Validator; +import sun.security.util.KnownOIDs; /** * The new X509 key manager implementation. The main differences to the @@ -521,14 +522,19 @@ private static enum CheckType { // enum constant for "tls client" check // valid EKU for TLS client: any, tls_client - CLIENT(new HashSet(Arrays.asList(new String[] { - "2.5.29.37.0", "1.3.6.1.5.5.7.3.2" }))), + CLIENT(new HashSet(List.of( + KnownOIDs.anyExtendedKeyUsage.value(), + KnownOIDs.clientAuth.value() + ))), // enum constant for "tls server" check // valid EKU for TLS server: any, tls_server, ns_sgc, ms_sgc - SERVER(new HashSet(Arrays.asList(new String[] { - "2.5.29.37.0", "1.3.6.1.5.5.7.3.1", "2.16.840.1.113730.4.1", - "1.3.6.1.4.1.311.10.3.3" }))); + SERVER(new HashSet(List.of( + KnownOIDs.anyExtendedKeyUsage.value(), + KnownOIDs.serverAuth.value(), + KnownOIDs.NETSCAPE_ExportApproved.value(), + KnownOIDs.MICROSOFT_ExportApproved.value() + ))); // set of valid EKU values for this type final Set validEku; diff --git a/src/java.base/share/classes/sun/security/timestamp/TSRequest.java b/src/java.base/share/classes/sun/security/timestamp/TSRequest.java index 290981dc7e8..619f2be65ed 100644 --- a/src/java.base/share/classes/sun/security/timestamp/TSRequest.java +++ b/src/java.base/share/classes/sun/security/timestamp/TSRequest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -163,7 +163,7 @@ public byte[] encode() throws IOException { // encode optional elements if (policyId != null) { - request.putOID(new ObjectIdentifier(policyId)); + request.putOID(ObjectIdentifier.of(policyId)); } if (nonce != null) { request.putInteger(nonce); 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 8bf24cdb9bb..c626e76edf5 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 @@ -4277,6 +4277,23 @@ private static Date getStartDate(String s) throws IOException { return c.getTime(); } + /** + * Match a command with a command set. The match can be exact, or + * partial, or case-insensitive. + * + * @param s the command provided by user + * @param list the legal command set represented by KnownOIDs enums. + * @return the position of a single match, or -1 if none matched + * @throws Exception if s is ambiguous + */ + private static int oneOf(String s, KnownOIDs... list) throws Exception { + String[] convertedList = new String[list.length]; + for (int i = 0; i < list.length; i++) { + convertedList[i] = list[i].stdName(); + } + return oneOf(s, convertedList); + } + /** * Match a command (may be abbreviated) with a command set. * @param s the command provided @@ -4395,7 +4412,7 @@ private ObjectIdentifier findOidForExtName(String type) case 5: return PKIXExtensions.SubjectInfoAccess_Id; case 6: return PKIXExtensions.AuthInfoAccess_Id; case 8: return PKIXExtensions.CRLDistributionPoints_Id; - default: return new ObjectIdentifier(type); + default: return ObjectIdentifier.of(type); } } @@ -4616,30 +4633,26 @@ private CertificateExtensions createV3Extensions( case 2: // EKU if(value != null) { Vector v = new Vector<>(); + KnownOIDs[] choices = { + KnownOIDs.anyExtendedKeyUsage, + KnownOIDs.serverAuth, + KnownOIDs.clientAuth, + KnownOIDs.codeSigning, + KnownOIDs.emailProtection, + KnownOIDs.KP_TimeStamping, + KnownOIDs.OCSPSigning + }; for (String s: value.split(",")) { - int p = oneOf(s, - "anyExtendedKeyUsage", - "serverAuth", //1 - "clientAuth", //2 - "codeSigning", //3 - "emailProtection", //4 - "", //5 - "", //6 - "", //7 - "timeStamping", //8 - "OCSPSigning" //9 - ); - if (p < 0) { - try { - v.add(new ObjectIdentifier(s)); - } catch (Exception e) { - throw new Exception(rb.getString( - "Unknown.extendedkeyUsage.type.") + s); - } - } else if (p == 0) { - v.add(new ObjectIdentifier("2.5.29.37.0")); - } else { - v.add(new ObjectIdentifier("1.3.6.1.5.5.7.3." + p)); + int p = oneOf(s, choices); + String o = s; + if (p >= 0) { + o = choices[p].value(); + } + try { + v.add(ObjectIdentifier.of(o)); + } catch (Exception e) { + throw new Exception(rb.getString( + "Unknown.extendedkeyUsage.type.") + s); } } setExt(result, new ExtendedKeyUsageExtension(isCritical, v)); @@ -4694,24 +4707,23 @@ private CertificateExtensions createV3Extensions( String m = item.substring(0, colonpos); String t = item.substring(colonpos+1, colonpos2); String v = item.substring(colonpos2+1); - int p = oneOf(m, - "", - "ocsp", //1 - "caIssuers", //2 - "timeStamping", //3 - "", - "caRepository" //5 - ); + KnownOIDs[] choices = { + KnownOIDs.OCSP, + KnownOIDs.caIssuers, + KnownOIDs.AD_TimeStamping, + KnownOIDs.caRepository + }; + int p = oneOf(m, choices); ObjectIdentifier oid; - if (p < 0) { + if (p >= 0) { + oid = ObjectIdentifier.of(choices[p]); + } else { try { - oid = new ObjectIdentifier(m); + oid = ObjectIdentifier.of(m); } catch (Exception e) { throw new Exception(rb.getString( "Unknown.AccessDescription.type.") + m); } - } else { - oid = new ObjectIdentifier("1.3.6.1.5.5.7.48." + p); } accessDescriptions.add(new AccessDescription( oid, createGeneralName(t, v, exttype))); @@ -4748,7 +4760,7 @@ private CertificateExtensions createV3Extensions( } break; case -1: - ObjectIdentifier oid = new ObjectIdentifier(name); + ObjectIdentifier oid = ObjectIdentifier.of(name); byte[] data = null; if (value != null) { data = new byte[value.length() / 2 + 1]; diff --git a/src/java.base/share/classes/sun/security/util/ConstraintsParameters.java b/src/java.base/share/classes/sun/security/util/ConstraintsParameters.java index f7fc4bf3512..82ce9c97af2 100644 --- a/src/java.base/share/classes/sun/security/util/ConstraintsParameters.java +++ b/src/java.base/share/classes/sun/security/util/ConstraintsParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 diff --git a/src/java.base/share/classes/sun/security/util/CurveDB.java b/src/java.base/share/classes/sun/security/util/CurveDB.java index 7e6f62fe5a3..45dfb106a7a 100644 --- a/src/java.base/share/classes/sun/security/util/CurveDB.java +++ b/src/java.base/share/classes/sun/security/util/CurveDB.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -30,7 +30,6 @@ import java.security.spec.*; import java.util.*; -import java.util.regex.Pattern; /** * Repository for well-known Elliptic Curve parameters. It is used by both @@ -54,8 +53,6 @@ public class CurveDB { private static Collection specCollection; - public static final String SPLIT_PATTERN = ",|\\[|\\]"; - // Used by SunECEntries public static CollectiongetSupportedCurves() { return specCollection; @@ -117,9 +114,8 @@ private static BigInteger bi(String s) { return new BigInteger(s, 16); } - private static void add(String name, String soid, int type, String sfield, - String a, String b, String x, String y, String n, int h, - Pattern nameSplitPattern) { + private static void add(KnownOIDs o, int type, String sfield, + String a, String b, String x, String y, String n, int h) { BigInteger p = bi(sfield); ECField field; if ((type == P) || (type == PD)) { @@ -133,15 +129,16 @@ private static void add(String name, String soid, int type, String sfield, EllipticCurve curve = new EllipticCurve(field, bi(a), bi(b)); ECPoint g = new ECPoint(bi(x), bi(y)); - NamedCurve params = new NamedCurve(name, soid, curve, g, bi(n), h); - if (oidMap.put(soid, params) != null) { - throw new RuntimeException("Duplication oid: " + soid); + String oid = o.value(); + NamedCurve params = new NamedCurve(o, curve, g, bi(n), h); + if (oidMap.put(oid, params) != null) { + throw new RuntimeException("Duplication oid: " + oid); } - String[] commonNames = nameSplitPattern.split(name); - for (String commonName : commonNames) { - if (nameMap.put(commonName.trim(), params) != null) { - throw new RuntimeException("Duplication name: " + commonName); + for (String cn : params.getNameAndAliases()) { + if (nameMap.put(cn, + params) != null) { + throw new RuntimeException("Duplication name: " + cn); } } @@ -153,445 +150,424 @@ private static void add(String name, String soid, int type, String sfield, } } - private static class Holder { - private static final Pattern nameSplitPattern = Pattern.compile( - SPLIT_PATTERN); - } - - // Return all the names the EC curve could be using. - static String[] getNamesByOID(String oid) { - NamedCurve nc = oidMap.get(oid); - if (nc == null) { - return new String[0]; - } - String[] list = Holder.nameSplitPattern.split(nc.getName()); - int i = 0; - do { - list[i] = list[i].trim(); - } while (++i < list.length); - return list; - } - static { - Pattern nameSplitPattern = Holder.nameSplitPattern; - /* SEC2 prime curves */ - add("secp112r1", "1.3.132.0.6", P, + add(KnownOIDs.secp112r1, P, "DB7C2ABF62E35E668076BEAD208B", "DB7C2ABF62E35E668076BEAD2088", "659EF8BA043916EEDE8911702B22", "09487239995A5EE76B55F9C2F098", "A89CE5AF8724C0A23E0E0FF77500", "DB7C2ABF62E35E7628DFAC6561C5", - 1, nameSplitPattern); + 1); - add("secp112r2", "1.3.132.0.7", P, + add(KnownOIDs.secp112r2, P, "DB7C2ABF62E35E668076BEAD208B", "6127C24C05F38A0AAAF65C0EF02C", "51DEF1815DB5ED74FCC34C85D709", "4BA30AB5E892B4E1649DD0928643", "adcd46f5882e3747def36e956e97", "36DF0AAFD8B8D7597CA10520D04B", - 4, nameSplitPattern); + 4); - add("secp128r1", "1.3.132.0.28", P, + add(KnownOIDs.secp128r1, P, "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", "E87579C11079F43DD824993C2CEE5ED3", "161FF7528B899B2D0C28607CA52C5B86", "CF5AC8395BAFEB13C02DA292DDED7A83", "FFFFFFFE0000000075A30D1B9038A115", - 1, nameSplitPattern); + 1); - add("secp128r2", "1.3.132.0.29", P, + add(KnownOIDs.secp128r2, P, "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", "D6031998D1B3BBFEBF59CC9BBFF9AEE1", "5EEEFCA380D02919DC2C6558BB6D8A5D", "7B6AA5D85E572983E6FB32A7CDEBC140", "27B6916A894D3AEE7106FE805FC34B44", "3FFFFFFF7FFFFFFFBE0024720613B5A3", - 4, nameSplitPattern); + 4); - add("secp160k1", "1.3.132.0.9", P, + add(KnownOIDs.secp160k1, P, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", "0000000000000000000000000000000000000000", "0000000000000000000000000000000000000007", "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", "938CF935318FDCED6BC28286531733C3F03C4FEE", "0100000000000000000001B8FA16DFAB9ACA16B6B3", - 1, nameSplitPattern); + 1); - add("secp160r1", "1.3.132.0.8", P, + add(KnownOIDs.secp160r1, P, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", "4A96B5688EF573284664698968C38BB913CBFC82", "23A628553168947D59DCC912042351377AC5FB32", "0100000000000000000001F4C8F927AED3CA752257", - 1, nameSplitPattern); + 1); - add("secp160r2", "1.3.132.0.30", P, + add(KnownOIDs.secp160r2, P, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", "B4E134D3FB59EB8BAB57274904664D5AF50388BA", "52DCB034293A117E1F4FF11B30F7199D3144CE6D", "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", "0100000000000000000000351EE786A818F3A1A16B", - 1, nameSplitPattern); + 1); - add("secp192k1", "1.3.132.0.31", P, + add(KnownOIDs.secp192k1, P, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", "000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000003", "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", - 1, nameSplitPattern); + 1); - add("secp192r1 [NIST P-192, X9.62 prime192v1]", "1.2.840.10045.3.1.1", PD, + add(KnownOIDs.secp192r1, PD, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", - 1, nameSplitPattern); + 1); - add("secp224k1", "1.3.132.0.32", P, + add(KnownOIDs.secp224k1, P, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", "00000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000005", "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", - 1, nameSplitPattern); + 1); - add("secp224r1 [NIST P-224]", "1.3.132.0.33", PD, + add(KnownOIDs.secp224r1, PD, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", - 1, nameSplitPattern); + 1); - add("secp256k1", "1.3.132.0.10", P, + add(KnownOIDs.secp256k1, P, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000007", "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", - 1, nameSplitPattern); + 1); - add("secp256r1 [NIST P-256, X9.62 prime256v1]", "1.2.840.10045.3.1.7", PD, + add(KnownOIDs.secp256r1, PD, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", - 1, nameSplitPattern); + 1); - add("secp384r1 [NIST P-384]", "1.3.132.0.34", PD, + add(KnownOIDs.secp384r1, PD, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", - 1, nameSplitPattern); + 1); - add("secp521r1 [NIST P-521]", "1.3.132.0.35", PD, + add(KnownOIDs.secp521r1, PD, "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", - 1, nameSplitPattern); + 1); /* ANSI X9.62 prime curves */ - add("X9.62 prime192v2", "1.2.840.10045.3.1.2", P, + add(KnownOIDs.prime192v2, P, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953", "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A", "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", - 1, nameSplitPattern); + 1); - add("X9.62 prime192v3", "1.2.840.10045.3.1.3", P, + add(KnownOIDs.prime192v3, P, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916", "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896", "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", - 1, nameSplitPattern); + 1); - add("X9.62 prime239v1", "1.2.840.10045.3.1.4", P, + add(KnownOIDs.prime239v1, P, "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A", "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF", "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", - 1, nameSplitPattern); + 1); - add("X9.62 prime239v2", "1.2.840.10045.3.1.5", P, + add(KnownOIDs.prime239v2, P, "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C", "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7", "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", - 1, nameSplitPattern); + 1); - add("X9.62 prime239v3", "1.2.840.10045.3.1.6", P, + add(KnownOIDs.prime239v3, P, "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E", "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A", "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", - 1, nameSplitPattern); + 1); /* SEC2 binary curves */ - add("sect113r1", "1.3.132.0.4", B, + add(KnownOIDs.sect113r1, B, "020000000000000000000000000201", "003088250CA6E7C7FE649CE85820F7", "00E8BEE4D3E2260744188BE0E9C723", "009D73616F35F4AB1407D73562C10F", "00A52830277958EE84D1315ED31886", "0100000000000000D9CCEC8A39E56F", - 2, nameSplitPattern); + 2); - add("sect113r2", "1.3.132.0.5", B, + add(KnownOIDs.sect113r2, B, "020000000000000000000000000201", "00689918DBEC7E5A0DD6DFC0AA55C7", "0095E9A9EC9B297BD4BF36E059184F", "01A57A6A7B26CA5EF52FCDB8164797", "00B3ADC94ED1FE674C06E695BABA1D", "010000000000000108789B2496AF93", - 2, nameSplitPattern); + 2); - add("sect131r1", "1.3.132.0.22", B, + add(KnownOIDs.sect131r1, B, "080000000000000000000000000000010D", "07A11B09A76B562144418FF3FF8C2570B8", "0217C05610884B63B9C6C7291678F9D341", "0081BAF91FDF9833C40F9C181343638399", "078C6E7EA38C001F73C8134B1B4EF9E150", "0400000000000000023123953A9464B54D", - 2, nameSplitPattern); + 2); - add("sect131r2", "1.3.132.0.23", B, + add(KnownOIDs.sect131r2, B, "080000000000000000000000000000010D", "03E5A88919D7CAFCBF415F07C2176573B2", "04B8266A46C55657AC734CE38F018F2192", "0356DCD8F2F95031AD652D23951BB366A8", "0648F06D867940A5366D9E265DE9EB240F", "0400000000000000016954A233049BA98F", - 2, nameSplitPattern); + 2); - add("sect163k1 [NIST K-163]", "1.3.132.0.1", BD, + add(KnownOIDs.sect163k1, BD, "0800000000000000000000000000000000000000C9", "000000000000000000000000000000000000000001", "000000000000000000000000000000000000000001", "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8", "0289070FB05D38FF58321F2E800536D538CCDAA3D9", "04000000000000000000020108A2E0CC0D99F8A5EF", - 2, nameSplitPattern); + 2); - add("sect163r1", "1.3.132.0.2", B, + add(KnownOIDs.sect163r1, B, "0800000000000000000000000000000000000000C9", "07B6882CAAEFA84F9554FF8428BD88E246D2782AE2", "0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9", "0369979697AB43897789566789567F787A7876A654", "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883", "03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B", - 2, nameSplitPattern); + 2); - add("sect163r2 [NIST B-163]", "1.3.132.0.15", BD, + add(KnownOIDs.sect163r2, BD, "0800000000000000000000000000000000000000C9", "000000000000000000000000000000000000000001", "020A601907B8C953CA1481EB10512F78744A3205FD", "03F0EBA16286A2D57EA0991168D4994637E8343E36", "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", "040000000000000000000292FE77E70C12A4234C33", - 2, nameSplitPattern); + 2); - add("sect193r1", "1.3.132.0.24", B, + add(KnownOIDs.sect193r1, B, "02000000000000000000000000000000000000000000008001", "0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01", "00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814", "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1", "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05", "01000000000000000000000000C7F34A778F443ACC920EBA49", - 2, nameSplitPattern); + 2); - add("sect193r2", "1.3.132.0.25", B, + add(KnownOIDs.sect193r2, B, "02000000000000000000000000000000000000000000008001", "0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B", "00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE", "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F", "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C", "010000000000000000000000015AAB561B005413CCD4EE99D5", - 2, nameSplitPattern); + 2); - add("sect233k1 [NIST K-233]", "1.3.132.0.26", BD, + add(KnownOIDs.sect233k1, BD, "020000000000000000000000000000000000000004000000000000000001", "000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000001", "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126", "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", "008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", - 4, nameSplitPattern); + 4); - add("sect233r1 [NIST B-233]", "1.3.132.0.27", B, + add(KnownOIDs.sect233r1, B, "020000000000000000000000000000000000000004000000000000000001", "000000000000000000000000000000000000000000000000000000000001", "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD", "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B", "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052", "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", - 2, nameSplitPattern); + 2); - add("sect239k1", "1.3.132.0.3", B, + add(KnownOIDs.sect239k1, B, "800000000000000000004000000000000000000000000000000000000001", "000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000001", "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC", "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA", "2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5", - 4, nameSplitPattern); + 4); - add("sect283k1 [NIST K-283]", "1.3.132.0.16", BD, + add(KnownOIDs.sect283k1, BD, "0800000000000000000000000000000000000000000000000000000000000000000010A1", "000000000000000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000000000000001", "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836", "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259", "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", - 4, nameSplitPattern); + 4); - add("sect283r1 [NIST B-283]", "1.3.132.0.17", B, + add(KnownOIDs.sect283r1, B, "0800000000000000000000000000000000000000000000000000000000000000000010A1", "000000000000000000000000000000000000000000000000000000000000000000000001", "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053", "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4", "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", - 2, nameSplitPattern); + 2); - add("sect409k1 [NIST K-409]", "1.3.132.0.36", BD, + add(KnownOIDs.sect409k1, BD, "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746", "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", - 4, nameSplitPattern); + 4); - add("sect409r1 [NIST B-409]", "1.3.132.0.37", B, + add(KnownOIDs.sect409r1, B, "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F", "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7", "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706", "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", - 2, nameSplitPattern); + 2); - add("sect571k1 [NIST K-571]", "1.3.132.0.38", BD, + add(KnownOIDs.sect571k1, BD, "080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972", "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3", "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", - 4, nameSplitPattern); + 4); - add("sect571r1 [NIST B-571]", "1.3.132.0.39", B, + add(KnownOIDs.sect571r1, B, "080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A", "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19", "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B", "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", - 2, nameSplitPattern); + 2); /* ANSI X9.62 binary curves */ - add("X9.62 c2tnb191v1", "1.2.840.10045.3.0.5", B, + add(KnownOIDs.c2tnb191v1, B, "800000000000000000000000000000000000000000000201", "2866537B676752636A68F56554E12640276B649EF7526267", "2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", "36B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D", "765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB", "40000000000000000000000004A20E90C39067C893BBB9A5", - 2, nameSplitPattern); + 2); - add("X9.62 c2tnb191v2", "1.2.840.10045.3.0.6", B, + add(KnownOIDs.c2tnb191v2, B, "800000000000000000000000000000000000000000000201", "401028774D7777C7B7666D1366EA432071274F89FF01E718", "0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01", "3809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10", "17434386626D14F3DBF01760D9213A3E1CF37AEC437D668A", "20000000000000000000000050508CB89F652824E06B8173", - 4, nameSplitPattern); + 4); - add("X9.62 c2tnb191v3", "1.2.840.10045.3.0.7", B, + add(KnownOIDs.c2tnb191v3, B, "800000000000000000000000000000000000000000000201", "6C01074756099122221056911C77D77E77A777E7E7E77FCB", "71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8", "375D4CE24FDE434489DE8746E71786015009E66E38A926DD", "545A39176196575D985999366E6AD34CE0A77CD7127B06BE", "155555555555555555555555610C0B196812BFB6288A3EA3", - 6, nameSplitPattern); + 6); - add("X9.62 c2tnb239v1", "1.2.840.10045.3.0.11", B, + add(KnownOIDs.c2tnb239v1, B, "800000000000000000000000000000000000000000000000001000000001", "32010857077C5431123A46B808906756F543423E8D27877578125778AC76", "790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", "57927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D", "61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305", "2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", - 4, nameSplitPattern); + 4); - add("X9.62 c2tnb239v2", "1.2.840.10045.3.0.12", B, + add(KnownOIDs.c2tnb239v2, B, "800000000000000000000000000000000000000000000000001000000001", "4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F", "5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B", "28F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205", "5667334C45AFF3B5A03BAD9DD75E2C71A99362567D5453F7FA6E227EC833", "1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", - 6, nameSplitPattern); + 6); - add("X9.62 c2tnb239v3", "1.2.840.10045.3.0.13", B, + add(KnownOIDs.c2tnb239v3, B, "800000000000000000000000000000000000000000000000001000000001", "01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F", "6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40", "70F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92", "2E5A0EAF6E5E1305B9004DCE5C0ED7FE59A35608F33837C816D80B79F461", "0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", - 0xA, nameSplitPattern); + 0xA); - add("X9.62 c2tnb359v1", "1.2.840.10045.3.0.18", B, + add(KnownOIDs.c2tnb359v1, B, "800000000000000000000000000000000000000000000000000000000000000000000000100000000000000001", "5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557", "2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988", "3C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097", "53D7E08529547048121E9C95F3791DD804963948F34FAE7BF44EA82365DC7868FE57E4AE2DE211305A407104BD", "01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B", - 0x4C, nameSplitPattern); + 0x4C); - add("X9.62 c2tnb431r1", "1.2.840.10045.3.0.20", B, + add(KnownOIDs.c2tnb431r1, B, "800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001", "1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F", "10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618", "120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7", "20D0AF8903A96F8D5FA2C255745D3C451B302C9346D9B7E485E7BCE41F6B591F3E8F6ADDCBB0BC4C2F947A7DE1A89B625D6A598B3760", "0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91", - 0x2760, nameSplitPattern); + 0x2760); /* ANSI X9.62 binary curves from the 1998 standard but forbidden * in the 2005 version of the standard. @@ -599,77 +575,77 @@ static String[] getNamesByOID(String oid) { * case we need to support them after all. */ /* - add("X9.62 c2pnb163v1", "1.2.840.10045.3.0.1", B, + add(KnownOIDs.c2pnb163v1, B, "080000000000000000000000000000000000000107", "072546B5435234A422E0789675F432C89435DE5242", "00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9", "07AF69989546103D79329FCC3D74880F33BBE803CB", "01EC23211B5966ADEA1D3F87F7EA5848AEF0B7CA9F", "0400000000000000000001E60FC8821CC74DAEAFC1", - 2, nameSplitPattern); + 2); - add("X9.62 c2pnb163v2", "1.2.840.10045.3.0.2", B, + add(KnownOIDs.c2pnb163v2, B, "080000000000000000000000000000000000000107", "0108B39E77C4B108BED981ED0E890E117C511CF072", "0667ACEB38AF4E488C407433FFAE4F1C811638DF20", "0024266E4EB5106D0A964D92C4860E2671DB9B6CC5", "079F684DDF6684C5CD258B3890021B2386DFD19FC5", "03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", - 2, nameSplitPattern); + 2); - add("X9.62 c2pnb163v3", "1.2.840.10045.3.0.3", B, + add(KnownOIDs.c2pnb163v3, B, "080000000000000000000000000000000000000107", "07A526C63D3E25A256A007699F5447E32AE456B50E", "03F7061798EB99E238FD6F1BF95B48FEEB4854252B", "02F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB", "05B935590C155E17EA48EB3FF3718B893DF59A05D0", "03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", - 2, nameSplitPattern); + 2); - add("X9.62 c2pnb176w1", "1.2.840.10045.3.0.4", B, + add(KnownOIDs.c2pnb176w1, B, "0100000000000000000000000000000000080000000007", "E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B", "5DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2", "8D16C2866798B600F9F08BB4A8E860F3298CE04A5798", "6FA4539C2DADDDD6BAB5167D61B436E1D92BB16A562C", "00010092537397ECA4F6145799D62B0A19CE06FE26AD", - 0xFF6E, nameSplitPattern); + 0xFF6E); - add("X9.62 c2pnb208w1", "1.2.840.10045.3.0.10", B, + add(KnownOIDs.c2pnb208w1, B, "010000000000000000000000000000000800000000000000000007", "0000000000000000000000000000000000000000000000000000", "C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E", "89FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A", "0F55B51A06E78E9AC38A035FF520D8B01781BEB1A6BB08617DE3", "000101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", - 0xFE48, nameSplitPattern); + 0xFE48); - add("X9.62 c2pnb272w1", "1.2.840.10045.3.0.16", B, + add(KnownOIDs.c2pnb272w1, B, "010000000000000000000000000000000000000000000000000000010000000000000B", "91A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20", "7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7", "6108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D", "10C7695716851EEF6BA7F6872E6142FBD241B830FF5EFCACECCAB05E02005DDE9D23", "000100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521", - 0xFF06, nameSplitPattern); + 0xFF06); - add("X9.62 c2pnb304w1", "1.2.840.10045.3.0.17", B, + add(KnownOIDs.c2pnb304w1, B, "010000000000000000000000000000000000000000000000000000000000000000000000000807", "FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681", "BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE", "197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614", "E19FBEB76E0DA171517ECF401B50289BF014103288527A9B416A105E80260B549FDC1B92C03B", "000101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D", - 0xFE2E, nameSplitPattern); + 0xFE2E); - add("X9.62 c2pnb368w1", "1.2.840.10045.3.0.19", B, + add(KnownOIDs.c2pnb368w1, B, "0100000000000000000000000000000000000000000000000000000000000000000000002000000000000000000007", "E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D", "FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A", "1085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F", "7B3EB1BDDCBA62D5D8B2059B525797FC73822C59059C623A45FF3843CEE8F87CD1855ADAA81E2A0750B80FDA2310", "00010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967", - 0xFF70, nameSplitPattern); + 0xFF70); */ /* @@ -677,68 +653,68 @@ static String[] getNamesByOID(String oid) { * (Twisted curves are not included) */ - add("brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1", P, + add(KnownOIDs.brainpoolP160r1, P, "E95E4A5F737059DC60DFC7AD95B3D8139515620F", "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", "1E589A8595423412134FAA2DBDEC95C8D8675E58", "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3", "1667CB477A1A8EC338F94741669C976316DA6321", "E95E4A5F737059DC60DF5991D45029409E60FC09", - 1, nameSplitPattern); + 1); - add("brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3", P, + add(KnownOIDs.brainpoolP192r1, P, "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6", "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", - 1, nameSplitPattern); + 1); - add("brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5", P, + add(KnownOIDs.brainpoolP224r1, P, "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D", "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", - 1, nameSplitPattern); + 1); - add("brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", P, + add(KnownOIDs.brainpoolP256r1, P, "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", - 1, nameSplitPattern); + 1); - add("brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9", P, + add(KnownOIDs.brainpoolP320r1, P, "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", - 1, nameSplitPattern); + 1); - add("brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11", P, + add(KnownOIDs.brainpoolP384r1, P, "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", - 1, nameSplitPattern); + 1); - add("brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13", P, + add(KnownOIDs.brainpoolP512r1, P, "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", - 1, nameSplitPattern); + 1); specCollection = Collections.unmodifiableCollection(oidMap.values()); } diff --git a/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java index 0d2346e19f8..dc320b85d7e 100644 --- a/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java +++ b/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java @@ -261,7 +261,7 @@ private static List getNamedCurveFromKey(Key key) { if (key instanceof ECKey) { NamedCurve nc = CurveDB.lookup(((ECKey)key).getParams()); return (nc == null ? List.of() - : Arrays.asList(CurveDB.getNamesByOID(nc.getObjectId()))); + : Arrays.asList(nc.getNameAndAliases())); } else if (key instanceof XECKey) { return List.of( ((NamedParameterSpec)((XECKey)key).getParams()).getName()); diff --git a/src/java.base/share/classes/sun/security/util/KnownOIDs.java b/src/java.base/share/classes/sun/security/util/KnownOIDs.java index 92ecb9adc0c..b5cc3b05f14 100644 --- a/src/java.base/share/classes/sun/security/util/KnownOIDs.java +++ b/src/java.base/share/classes/sun/security/util/KnownOIDs.java @@ -356,6 +356,11 @@ public enum KnownOIDs { boolean registerNames() { return false; } }, + OIW_SHA1withRSA_Odd("1.3.14.3.2.15", "SHA1withRSA") { + @Override + boolean registerNames() { return false; } + }, + SHA_1("1.3.14.3.2.26", "SHA-1", "SHA", "SHA1"), OIW_SHA1withDSA("1.3.14.3.2.27", "SHA1withDSA") { diff --git a/src/java.base/share/classes/sun/security/util/NamedCurve.java b/src/java.base/share/classes/sun/security/util/NamedCurve.java index 0a677aad414..f12aba4f9c7 100644 --- a/src/java.base/share/classes/sun/security/util/NamedCurve.java +++ b/src/java.base/share/classes/sun/security/util/NamedCurve.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -29,7 +29,7 @@ import java.math.BigInteger; import java.security.spec.*; - +import java.util.Arrays; /** * Contains Elliptic Curve parameters. @@ -39,8 +39,8 @@ */ public final class NamedCurve extends ECParameterSpec { - // friendly name for toString() output - private final String name; + // friendly names with stdName followed by aliases + private final String[] nameAndAliases; // well known OID private final String oid; @@ -48,25 +48,28 @@ public final class NamedCurve extends ECParameterSpec { // encoded form (as NamedCurve identified via OID) private final byte[] encoded; - NamedCurve(String name, String oid, EllipticCurve curve, + NamedCurve(KnownOIDs ko, EllipticCurve curve, ECPoint g, BigInteger n, int h) { super(curve, g, n, h); - this.name = name; - this.oid = oid; + String[] aliases = ko.aliases(); + this.nameAndAliases = new String[aliases.length + 1]; + nameAndAliases[0] = ko.stdName(); + System.arraycopy(aliases, 0, nameAndAliases, 1, aliases.length); - DerOutputStream out = new DerOutputStream(); + this.oid = ko.value(); + DerOutputStream out = new DerOutputStream(); try { - out.putOID(new ObjectIdentifier(oid)); + out.putOID(ObjectIdentifier.of(ko)); } catch (IOException e) { throw new RuntimeException("Internal error", e); } - encoded = out.toByteArray(); } - public String getName() { - return name; + // returns the curve's standard name followed by its aliases + public String[] getNameAndAliases() { + return nameAndAliases; } public byte[] getEncoded() { @@ -78,6 +81,17 @@ public String getObjectId() { } public String toString() { - return name + " (" + oid + ")"; + StringBuilder sb = new StringBuilder(nameAndAliases[0]); + if (nameAndAliases.length > 1) { + sb.append(" ["); + int j = 1; + while (j < nameAndAliases.length - 1) { + sb.append(nameAndAliases[j++]); + sb.append(','); + } + sb.append(nameAndAliases[j] + "]"); + } + sb.append(" (" + oid + ")"); + return sb.toString(); } } 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 b74d84e1df0..2d554057712 100644 --- a/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java +++ b/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java @@ -51,9 +51,7 @@ * @author Hemma Prafullchandra */ -public final -class ObjectIdentifier implements Serializable -{ +public final class ObjectIdentifier implements Serializable { /* * The maximum encoded OID length, excluding the ASN.1 encoding tag and * length. @@ -73,7 +71,6 @@ class ObjectIdentifier implements Serializable */ private static final int MAXIMUM_OID_SIZE = 4096; // 2^12 - /** * We use the DER value (no tag, no length) as the internal format * @serial @@ -119,6 +116,7 @@ class ObjectIdentifier implements Serializable * @serial */ private Object components = null; // path from root + /** * @serial */ @@ -163,15 +161,15 @@ private void writeObject(ObjectOutputStream os) static class HugeOidNotSupportedByOldJDK implements Serializable { private static final long serialVersionUID = 1L; - static HugeOidNotSupportedByOldJDK theOne = new HugeOidNotSupportedByOldJDK(); + static HugeOidNotSupportedByOldJDK theOne = + new HugeOidNotSupportedByOldJDK(); } /** * Constructs, from a string. This string should be of the form 1.23.56. * Validity check included. */ - public ObjectIdentifier (String oid) throws IOException - { + private ObjectIdentifier(String oid) throws IOException { int ch = '.'; int start = 0; int end = 0; @@ -267,8 +265,7 @@ public ObjectIdentifier(int[] values) throws IOException * @param in DER-encoded data holding an object ID * @exception IOException indicates a decoding error */ - public ObjectIdentifier (DerInputStream in) throws IOException - { + public ObjectIdentifier(DerInputStream in) throws IOException { byte type_id; int bufferEnd; @@ -281,7 +278,7 @@ public ObjectIdentifier (DerInputStream in) throws IOException * up so that we can use in.available() to check for the end of * this value in the data stream. */ - type_id = (byte) in.getByte (); + type_id = (byte)in.getByte(); if (type_id != DerValue.tag_ObjectId) throw new IOException ( "ObjectIdentifier() -- data isn't an object ID" @@ -306,8 +303,7 @@ public ObjectIdentifier (DerInputStream in) throws IOException * the tag and length have been removed/verified * Validity check NOT included. */ - ObjectIdentifier (DerInputBuffer buf) throws IOException - { + ObjectIdentifier(DerInputBuffer buf) throws IOException { DerInputStream in = new DerInputStream(buf); int len = in.available(); checkOidSize(len); @@ -361,6 +357,11 @@ public static ObjectIdentifier newInternal(int[] values) { private static ConcurrentHashMap oidTable = new ConcurrentHashMap<>(); + /** + * Returns an ObjectIdentifier instance for the specific String. + * + * If the String is not a valid OID string, an IOException is thrown. + */ public static ObjectIdentifier of(String oidStr) throws IOException { // check cache first ObjectIdentifier oid = oidTable.get(oidStr); @@ -393,8 +394,7 @@ public static ObjectIdentifier of(KnownOIDs o) { /* * n.b. the only public interface is DerOutputStream.putOID() */ - void encode (DerOutputStream out) throws IOException - { + void encode(DerOutputStream out) throws IOException { out.write (DerValue.tag_ObjectId, encoding); } @@ -435,17 +435,21 @@ private int[] toIntArray() { if ((encoding[i] & 0x80) == 0) { // one section [fromPos..i] if (i - fromPos + 1 > 4) { - BigInteger big = new BigInteger(1, pack(encoding, fromPos, i-fromPos+1, 7, 8)); + BigInteger big = new BigInteger(1, pack(encoding, + fromPos, i-fromPos+1, 7, 8)); if (fromPos == 0) { result[which++] = 2; - BigInteger second = big.subtract(BigInteger.valueOf(80)); - if (second.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 1) { + BigInteger second = + big.subtract(BigInteger.valueOf(80)); + if (second.compareTo( + BigInteger.valueOf(Integer.MAX_VALUE)) == 1) { return null; } else { result[which++] = second.intValue(); } } else { - if (big.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 1) { + if (big.compareTo( + BigInteger.valueOf(Integer.MAX_VALUE)) == 1) { return null; } else { result[which++] = big.intValue(); @@ -500,7 +504,8 @@ public String toString() { sb.append('.'); } if (i - fromPos + 1 > 4) { // maybe big integer - BigInteger big = new BigInteger(1, pack(encoding, fromPos, i-fromPos+1, 7, 8)); + BigInteger big = new BigInteger( + 1, pack(encoding, fromPos, i-fromPos+1, 7, 8)); if (fromPos == 0) { // first section encoded with more than 4 bytes, // must be 2.something @@ -541,7 +546,7 @@ public String toString() { /** * Repack all bits from input to output. On the both sides, only a portion * (from the least significant bit) of the 8 bits in a byte is used. This - * number is defined as the number of useful bits (NUB) for the array. All the + * number is defined as the number of useful bits (NUB) for the array. All * used bits from the input byte array and repacked into the output in the * exactly same order. The output bits are aligned so that the final bit of * the input (the least significant bit in the last byte), when repacked as @@ -563,7 +568,8 @@ public String toString() { * @param ow NUB for output * @return the repacked bytes */ - private static byte[] pack(byte[] in, int ioffset, int ilength, int iw, int ow) { + private static byte[] pack(byte[] in, + int ioffset, int ilength, int iw, int ow) { assert (iw > 0 && iw <= 8): "input NUB must be between 1 and 8"; assert (ow > 0 && ow <= 8): "output NUB must be between 1 and 8"; @@ -585,12 +591,13 @@ private static byte[] pack(byte[] in, int ioffset, int ilength, int iw, int ow) if (count > ow - opos%ow) { // free space available in output byte count = ow - opos%ow; // choose the smaller number } + // and move them! - out[opos/ow] |= // paste! - (((in[ioffset+ipos/iw]+256) // locate the byte (+256 so that it's never negative) - >> (iw-ipos%iw-count)) // move to the end of a byte - & ((1 << (count))-1)) // zero out all other bits - << (ow-opos%ow-count); // move to the output position + out[opos/ow] |= // paste! + (((in[ioffset+ipos/iw]+256) // locate the byte (+256 so that it's never negative) + >> (iw-ipos%iw-count)) & // move to the end of a byte + ((1 << (count))-1)) // zero out all other bits + << (ow-opos%ow-count); // move to the output position ipos += count; // advance opos += count; // advance } @@ -606,7 +613,8 @@ private static byte[] pack(byte[] in, int ioffset, int ilength, int iw, int ow) * @param ooffset the starting position to paste * @return the number of bytes pasted */ - private static int pack7Oid(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) { + private static int pack7Oid(byte[] in, + int ioffset, int ilength, byte[] out, int ooffset) { byte[] pack = pack(in, ioffset, ilength, 8, 7); int firstNonZero = pack.length-1; // paste at least one byte for (int i=pack.length-2; i>=0; i--) { @@ -615,7 +623,8 @@ private static int pack7Oid(byte[] in, int ioffset, int ilength, byte[] out, int } pack[i] |= 0x80; } - System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero); + System.arraycopy(pack, firstNonZero, + out, ooffset, pack.length-firstNonZero); return pack.length-firstNonZero; } @@ -626,7 +635,8 @@ private static int pack7Oid(byte[] in, int ioffset, int ilength, byte[] out, int * @param ooffset the starting position to paste * @return the number of bytes pasted */ - private static int pack8(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) { + private static int pack8(byte[] in, + int ioffset, int ilength, byte[] out, int ooffset) { byte[] pack = pack(in, ioffset, ilength, 7, 8); int firstNonZero = pack.length-1; // paste at least one byte for (int i=pack.length-2; i>=0; i--) { @@ -634,7 +644,8 @@ private static int pack8(byte[] in, int ioffset, int ilength, byte[] out, int oo firstNonZero = i; } } - System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero); + System.arraycopy(pack, firstNonZero, + out, ooffset, pack.length-firstNonZero); return pack.length-firstNonZero; } @@ -686,31 +697,39 @@ private static void check(byte[] encoding) throws IOException { } } } + private static void checkCount(int count) throws IOException { if (count < 2) { throw new IOException("ObjectIdentifier() -- " + "Must be at least two oid components "); } } + private static void checkFirstComponent(int first) throws IOException { if (first < 0 || first > 2) { throw new IOException("ObjectIdentifier() -- " + "First oid component is invalid "); } } - private static void checkFirstComponent(BigInteger first) throws IOException { + + private static void checkFirstComponent( + BigInteger first) throws IOException { if (first.signum() == -1 || first.compareTo(BigInteger.TWO) > 0) { throw new IOException("ObjectIdentifier() -- " + "First oid component is invalid "); } } - private static void checkSecondComponent(int first, int second) throws IOException { + + private static void checkSecondComponent( + int first, int second) throws IOException { if (second < 0 || first != 2 && second > 39) { throw new IOException("ObjectIdentifier() -- " + "Second oid component is invalid "); } } - private static void checkSecondComponent(int first, BigInteger second) throws IOException { + + private static void checkSecondComponent( + int first, BigInteger second) throws IOException { if (second.signum() == -1 || first != 2 && second.compareTo(BigInteger.valueOf(39)) == 1) { @@ -718,13 +737,16 @@ private static void checkSecondComponent(int first, BigInteger second) throws IO "Second oid component is invalid "); } } + private static void checkOtherComponent(int i, int num) throws IOException { if (num < 0) { throw new IOException("ObjectIdentifier() -- " + "oid component #" + (i+1) + " must be non-negative "); } } - private static void checkOtherComponent(int i, BigInteger num) throws IOException { + + private static void checkOtherComponent( + int i, BigInteger num) throws IOException { if (num.signum() == -1) { throw new IOException("ObjectIdentifier() -- " + "oid component #" + (i+1) + " must be non-negative "); diff --git a/src/java.base/share/classes/sun/security/util/SecurityProviderConstants.java b/src/java.base/share/classes/sun/security/util/SecurityProviderConstants.java index 37e6df348d4..26aad9ada0a 100644 --- a/src/java.base/share/classes/sun/security/util/SecurityProviderConstants.java +++ b/src/java.base/share/classes/sun/security/util/SecurityProviderConstants.java @@ -25,8 +25,11 @@ package sun.security.util; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.regex.PatternSyntaxException; import java.security.InvalidParameterException; +import java.security.ProviderException; import javax.crypto.spec.DHParameterSpec; import sun.security.action.GetPropertyAction; @@ -35,11 +38,59 @@ * the JDK security/crypto providers. */ public final class SecurityProviderConstants { + // Cannot create one of these + private SecurityProviderConstants () {} + private static final Debug debug = Debug.getInstance("jca", "ProviderConfig"); - // Cannot create one of these - private SecurityProviderConstants () { + // cache for provider aliases; key is the standard algorithm name + // value is the associated aliases List + private static final ConcurrentHashMap> aliasesMap; + + // utility method for generating aliases list using the supplied + // 'oid' and 'extraAliases', then store into "aliasesMap" cache under the + // key 'stdName' + private static List store(String stdName, KnownOIDs oid, + String ... extraAliases) { + List value; + if (oid == null && extraAliases.length != 0) { + value = List.of(extraAliases); + } else { + value = new ArrayList<>(); + if (oid != null) { + value.add("OID." + oid.value()); + value.add(oid.value()); + String[] knownAliases = oid.aliases(); + if (knownAliases != null) { + for (String ka : knownAliases) { + value.add(ka); + } + } + } + for (String ea : extraAliases) { + value.add(ea); + } + } + aliasesMap.put(stdName, value); + return value; + } + + // returns an aliases List for the specified algorithm name o + // NOTE: exception is thrown if no aliases nor oid found, so + // only call this method if aliases are expected + public static List getAliases(String o) { + List res = aliasesMap.get(o); + if (res == null) { + KnownOIDs e = KnownOIDs.findMatch(o); + if (e != null) { + return store(o, e); + } + ProviderException pe = + new ProviderException("Cannot find aliases for " + o); + throw pe; + } + return res; } public static final int getDefDSASubprimeSize(int primeSize) { @@ -99,6 +150,7 @@ public static final int getDefDHPrivateExpSize(DHParameterSpec spec) { private static final String KEY_LENGTH_PROP = "jdk.security.defaultKeySize"; + static { String keyLengthStr = GetPropertyAction.privilegedGetProperty (KEY_LENGTH_PROP); @@ -169,5 +221,39 @@ public static final int getDefDHPrivateExpSize(DHParameterSpec spec) { DEF_RSASSA_PSS_KEY_SIZE = rsaSsaPssKeySize; DEF_DH_KEY_SIZE = dhKeySize; DEF_EC_KEY_SIZE = ecKeySize; + + // Set up aliases with default mappings + // This is needed when the mapping contains non-oid + // aliases + aliasesMap = new ConcurrentHashMap<>(); + + store("SHA1withDSA", KnownOIDs.SHA1withDSA, + KnownOIDs.OIW_JDK_SHA1withDSA.value(), + KnownOIDs.OIW_SHA1withDSA.value(), + "DSA", "SHA/DSA", "SHA-1/DSA", + "SHA1/DSA", "SHAwithDSA", "DSAWithSHA1"); + + store("DSA", KnownOIDs.DSA, KnownOIDs.OIW_DSA.value()); + + store("SHA1withRSA", KnownOIDs.SHA1withRSA, + KnownOIDs.OIW_SHA1withRSA.value()); + + store("SHA-1", KnownOIDs.SHA_1); + + store("PBEWithMD5AndDES", KnownOIDs.PBEWithMD5AndDES, "PBE"); + + store("DiffieHellman", KnownOIDs.DiffieHellman); + + store("AES", KnownOIDs.AES, "Rijndael"); + + store("EC", KnownOIDs.EC, "EllipticCurve"); + + store("X.509", null, "X509"); + store("NONEwithDSA", null, "RawDSA"); + store("DESede", null, "TripleDES"); + store("ARCFOUR", KnownOIDs.ARCFOUR); + // For backward compatility, refer to PKCS1 mapping for RSA + // KeyPairGenerator and KeyFactory + store("PKCS1", KnownOIDs.PKCS1, KnownOIDs.RSA.value()); } } diff --git a/src/java.base/share/classes/sun/security/validator/EndEntityChecker.java b/src/java.base/share/classes/sun/security/validator/EndEntityChecker.java index d3398cb2e90..03675d0b257 100644 --- a/src/java.base/share/classes/sun/security/validator/EndEntityChecker.java +++ b/src/java.base/share/classes/sun/security/validator/EndEntityChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -28,7 +28,7 @@ import java.util.*; import java.security.cert.*; - +import sun.security.util.KnownOIDs; import sun.security.x509.NetscapeCertTypeExtension; /** @@ -71,24 +71,32 @@ class EndEntityChecker { private static final String OID_EXTENDED_KEY_USAGE = SimpleValidator.OID_EXTENDED_KEY_USAGE; - private static final String OID_EKU_TLS_SERVER = "1.3.6.1.5.5.7.3.1"; + private static final String OID_EKU_TLS_SERVER = + KnownOIDs.serverAuth.value(); - private static final String OID_EKU_TLS_CLIENT = "1.3.6.1.5.5.7.3.2"; + private static final String OID_EKU_TLS_CLIENT = + KnownOIDs.clientAuth.value(); - private static final String OID_EKU_CODE_SIGNING = "1.3.6.1.5.5.7.3.3"; + private static final String OID_EKU_CODE_SIGNING = + KnownOIDs.codeSigning.value(); - private static final String OID_EKU_TIME_STAMPING = "1.3.6.1.5.5.7.3.8"; + private static final String OID_EKU_TIME_STAMPING = + KnownOIDs.KP_TimeStamping.value(); - private static final String OID_EKU_ANY_USAGE = "2.5.29.37.0"; + private static final String OID_EKU_ANY_USAGE = + KnownOIDs.anyExtendedKeyUsage.value(); // the Netscape Server-Gated-Cryptography EKU extension OID - private static final String OID_EKU_NS_SGC = "2.16.840.1.113730.4.1"; + private static final String OID_EKU_NS_SGC = + KnownOIDs.NETSCAPE_ExportApproved.value(); // the Microsoft Server-Gated-Cryptography EKU extension OID - private static final String OID_EKU_MS_SGC = "1.3.6.1.4.1.311.10.3.3"; + private static final String OID_EKU_MS_SGC = + KnownOIDs.MICROSOFT_ExportApproved.value(); // the recognized extension OIDs - private static final String OID_SUBJECT_ALT_NAME = "2.5.29.17"; + private static final String OID_SUBJECT_ALT_NAME = + KnownOIDs.SubjectAlternativeName.value(); private static final String NSCT_SSL_CLIENT = NetscapeCertTypeExtension.SSL_CLIENT; diff --git a/src/java.base/share/classes/sun/security/validator/SimpleValidator.java b/src/java.base/share/classes/sun/security/validator/SimpleValidator.java index 7b7068fa9e6..b7f72f8bdeb 100644 --- a/src/java.base/share/classes/sun/security/validator/SimpleValidator.java +++ b/src/java.base/share/classes/sun/security/validator/SimpleValidator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -39,6 +39,7 @@ import sun.security.util.DerValue; import sun.security.util.DerInputStream; import sun.security.util.ObjectIdentifier; +import sun.security.util.KnownOIDs; import sun.security.provider.certpath.AlgorithmChecker; import sun.security.provider.certpath.UntrustedChecker; @@ -60,24 +61,28 @@ public final class SimpleValidator extends Validator { // Constants for the OIDs we need - static final String OID_BASIC_CONSTRAINTS = "2.5.29.19"; + static final String OID_BASIC_CONSTRAINTS = + KnownOIDs.BasicConstraints.value(); - static final String OID_NETSCAPE_CERT_TYPE = "2.16.840.1.113730.1.1"; + static final String OID_NETSCAPE_CERT_TYPE = + KnownOIDs.NETSCAPE_CertType.value(); - static final String OID_KEY_USAGE = "2.5.29.15"; + static final String OID_KEY_USAGE = KnownOIDs.KeyUsage.value(); - static final String OID_EXTENDED_KEY_USAGE = "2.5.29.37"; + static final String OID_EXTENDED_KEY_USAGE = + KnownOIDs.extendedKeyUsage.value(); - static final String OID_EKU_ANY_USAGE = "2.5.29.37.0"; + static final String OID_EKU_ANY_USAGE = + KnownOIDs.anyExtendedKeyUsage.value(); static final ObjectIdentifier OBJID_NETSCAPE_CERT_TYPE = - NetscapeCertTypeExtension.NetscapeCertType_Id; + NetscapeCertTypeExtension.NetscapeCertType_Id; private static final String NSCT_SSL_CA = - NetscapeCertTypeExtension.SSL_CA; + NetscapeCertTypeExtension.SSL_CA; private static final String NSCT_CODE_SIGNING_CA = - NetscapeCertTypeExtension.OBJECT_SIGNING_CA; + NetscapeCertTypeExtension.OBJECT_SIGNING_CA; /** * The trusted certificates as: diff --git a/src/java.base/share/classes/sun/security/x509/AVA.java b/src/java.base/share/classes/sun/security/x509/AVA.java index b3a673756a0..77bc088af6d 100644 --- a/src/java.base/share/classes/sun/security/x509/AVA.java +++ b/src/java.base/share/classes/sun/security/x509/AVA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -1237,7 +1237,7 @@ private boolean isCompliant(int standard) { return ak.oid; } } else { - return new ObjectIdentifier(oidString); + return ObjectIdentifier.of(oidString); } // no keyword found, check if OID string @@ -1255,7 +1255,7 @@ private boolean isCompliant(int standard) { if (number == false) { throw new IOException("Invalid keyword \"" + keyword + "\""); } - return new ObjectIdentifier(keyword); + return ObjectIdentifier.of(keyword); } /** diff --git a/src/java.base/share/classes/sun/security/x509/AccessDescription.java b/src/java.base/share/classes/sun/security/x509/AccessDescription.java index 45fa695e88c..c2843a971e7 100644 --- a/src/java.base/share/classes/sun/security/x509/AccessDescription.java +++ b/src/java.base/share/classes/sun/security/x509/AccessDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -42,16 +42,16 @@ public final class AccessDescription { private GeneralName accessLocation; public static final ObjectIdentifier Ad_OCSP_Id = - ObjectIdentifier.newInternal(new int[] {1, 3, 6, 1, 5, 5, 7, 48, 1}); + ObjectIdentifier.of(KnownOIDs.OCSP); public static final ObjectIdentifier Ad_CAISSUERS_Id = - ObjectIdentifier.newInternal(new int[] {1, 3, 6, 1, 5, 5, 7, 48, 2}); + ObjectIdentifier.of(KnownOIDs.caIssuers); public static final ObjectIdentifier Ad_TIMESTAMPING_Id = - ObjectIdentifier.newInternal(new int[] {1, 3, 6, 1, 5, 5, 7, 48, 3}); + ObjectIdentifier.of(KnownOIDs.AD_TimeStamping); public static final ObjectIdentifier Ad_CAREPOSITORY_Id = - ObjectIdentifier.newInternal(new int[] {1, 3, 6, 1, 5, 5, 7, 48, 5}); + ObjectIdentifier.of(KnownOIDs.caRepository); public AccessDescription(ObjectIdentifier accessMethod, GeneralName accessLocation) { this.accessMethod = accessMethod; diff --git a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java index 9f86115013c..ff8c3ea3299 100644 --- a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java +++ b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java @@ -31,6 +31,7 @@ import java.security.spec.MGF1ParameterSpec; import java.security.spec.PSSParameterSpec; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.security.*; import sun.security.rsa.PSSParameters; @@ -256,21 +257,31 @@ public final ObjectIdentifier getOID () { * returns the "full" signature algorithm (Ex: SHA256withECDSA) directly. */ public String getName() { - String algName = nameTable.get(algid); - if (algName != null) { - return algName; - } - if ((params != null) && algid.equals((Object)specifiedWithECDSA_oid)) { - try { - AlgorithmId paramsId = + String oidStr = algid.toString(); + // first check the list of support oids + KnownOIDs o = KnownOIDs.findMatch(oidStr); + if (o == KnownOIDs.SpecifiedSHA2withECDSA) { + if (params != null) { + try { + AlgorithmId paramsId = AlgorithmId.parse(new DerValue(encodedParams)); - String paramsName = paramsId.getName(); - algName = makeSigAlg(paramsName, "EC"); - } catch (IOException e) { - // ignore + String paramsName = paramsId.getName(); + return makeSigAlg(paramsName, "EC"); + } catch (IOException e) { + // ignore + } + } + } + if (o != null) { + return o.stdName(); + } else { + String n = aliasOidsTable().get(oidStr); + if (n != null) { + return n; + } else { + return algid.toString(); } } - return (algName == null) ? algid.toString() : algName; } public AlgorithmParameters getParameters() { @@ -292,7 +303,8 @@ public AlgorithmParameters getParameters() { * @return DER encoded parameters, or null not present. */ public byte[] getEncodedParams() throws IOException { - return (encodedParams == null || algid.equals(specifiedWithECDSA_oid)) + return (encodedParams == null || + algid.toString().equals(KnownOIDs.SpecifiedSHA2withECDSA.value())) ? null : encodedParams.clone(); } @@ -488,541 +500,142 @@ public static AlgorithmId get(AlgorithmParameters algparams) * used as a "KeyPairGenerator" algorithm. */ private static ObjectIdentifier algOID(String name) throws IOException { - // See if algname is in printable OID ("dot-dot") notation - if (name.indexOf('.') != -1) { - if (name.startsWith("OID.")) { - return new ObjectIdentifier(name.substring("OID.".length())); - } else { - return new ObjectIdentifier(name); - } + if (name.startsWith("OID.")) { + name = name.substring("OID.".length()); } - // Digesting algorithms - if (name.equalsIgnoreCase("MD5")) { - return AlgorithmId.MD5_oid; - } - if (name.equalsIgnoreCase("MD2")) { - return AlgorithmId.MD2_oid; - } - if (name.equalsIgnoreCase("SHA") || name.equalsIgnoreCase("SHA1") - || name.equalsIgnoreCase("SHA-1")) { - return AlgorithmId.SHA_oid; - } - if (name.equalsIgnoreCase("SHA-256") || - name.equalsIgnoreCase("SHA256")) { - return AlgorithmId.SHA256_oid; - } - if (name.equalsIgnoreCase("SHA-384") || - name.equalsIgnoreCase("SHA384")) { - return AlgorithmId.SHA384_oid; - } - if (name.equalsIgnoreCase("SHA-512") || - name.equalsIgnoreCase("SHA512")) { - return AlgorithmId.SHA512_oid; - } - if (name.equalsIgnoreCase("SHA-224") || - name.equalsIgnoreCase("SHA224")) { - return AlgorithmId.SHA224_oid; - } - if (name.equalsIgnoreCase("SHA-512/224") || - name.equalsIgnoreCase("SHA512/224")) { - return AlgorithmId.SHA512_224_oid; - } - if (name.equalsIgnoreCase("SHA-512/256") || - name.equalsIgnoreCase("SHA512/256")) { - return AlgorithmId.SHA512_256_oid; - } - // Various public key algorithms - if (name.equalsIgnoreCase("RSA")) { - return AlgorithmId.RSAEncryption_oid; - } - if (name.equalsIgnoreCase("RSASSA-PSS")) { - return AlgorithmId.RSASSA_PSS_oid; - } - if (name.equalsIgnoreCase("RSAES-OAEP")) { - return AlgorithmId.RSAES_OAEP_oid; - } - if (name.equalsIgnoreCase("Diffie-Hellman") - || name.equalsIgnoreCase("DH")) { - return AlgorithmId.DH_oid; - } - if (name.equalsIgnoreCase("DSA")) { - return AlgorithmId.DSA_oid; - } - if (name.equalsIgnoreCase("EC")) { - return EC_oid; - } - if (name.equalsIgnoreCase("ECDH")) { - return AlgorithmId.ECDH_oid; - } - - // Secret key algorithms - if (name.equalsIgnoreCase("AES")) { - return AlgorithmId.AES_oid; + KnownOIDs k = KnownOIDs.findMatch(name); + if (k != null) { + return ObjectIdentifier.of(k); } - // Common signature types - if (name.equalsIgnoreCase("MD5withRSA") - || name.equalsIgnoreCase("MD5/RSA")) { - return AlgorithmId.md5WithRSAEncryption_oid; - } - if (name.equalsIgnoreCase("MD2withRSA") - || name.equalsIgnoreCase("MD2/RSA")) { - return AlgorithmId.md2WithRSAEncryption_oid; - } - if (name.equalsIgnoreCase("SHAwithDSA") - || name.equalsIgnoreCase("SHA1withDSA") - || name.equalsIgnoreCase("SHA/DSA") - || name.equalsIgnoreCase("SHA1/DSA") - || name.equalsIgnoreCase("DSAWithSHA1") - || name.equalsIgnoreCase("DSS") - || name.equalsIgnoreCase("SHA-1/DSA")) { - return AlgorithmId.sha1WithDSA_oid; - } - if (name.equalsIgnoreCase("SHA224WithDSA")) { - return AlgorithmId.sha224WithDSA_oid; - } - if (name.equalsIgnoreCase("SHA256WithDSA")) { - return AlgorithmId.sha256WithDSA_oid; - } - if (name.equalsIgnoreCase("SHA1WithRSA") - || name.equalsIgnoreCase("SHA1/RSA")) { - return AlgorithmId.sha1WithRSAEncryption_oid; - } - if (name.equalsIgnoreCase("SHA256WithRSA")) { - return AlgorithmId.sha256WithRSAEncryption_oid; - } - if (name.equalsIgnoreCase("SHA384WithRSA")) { - return AlgorithmId.sha384WithRSAEncryption_oid; - } - if (name.equalsIgnoreCase("SHA512WithRSA")) { - return AlgorithmId.sha512WithRSAEncryption_oid; - } - if (name.equalsIgnoreCase("SHA1withECDSA") - || name.equalsIgnoreCase("ECDSA")) { - return AlgorithmId.sha1WithECDSA_oid; - } - if (name.equalsIgnoreCase("SHA224withECDSA")) { - return AlgorithmId.sha224WithECDSA_oid; - } - if (name.equalsIgnoreCase("SHA256withECDSA")) { - return AlgorithmId.sha256WithECDSA_oid; - } - if (name.equalsIgnoreCase("SHA384withECDSA")) { - return AlgorithmId.sha384WithECDSA_oid; - } - if (name.equalsIgnoreCase("SHA512withECDSA")) { - return AlgorithmId.sha512WithECDSA_oid; + // unknown algorithm oids + if (name.indexOf(".") == -1) { + // see if there is a matching oid string alias mapping from + // 3rd party providers + name = name.toUpperCase(Locale.ENGLISH); + String oidStr = aliasOidsTable().get(name); + if (oidStr != null) { + return ObjectIdentifier.of(oidStr); + } return null; + } else { + return ObjectIdentifier.of(name); } - - return oidTable().get(name.toUpperCase(Locale.ENGLISH)); - } - - private static ObjectIdentifier oid(int ... values) { - return ObjectIdentifier.newInternal(values); } - private static volatile Map oidTable; - private static final Map nameTable; + // oid string cache index'ed by algorithm name and oid strings + private static volatile Map aliasOidsTable; - /** Returns the oidTable, lazily initializing it on first access. */ - private static Map oidTable() - throws IOException { - // Double checked locking; safe because oidTable is volatile - Map tab; - if ((tab = oidTable) == null) { + // returns the aliasOidsTable, lazily initializing it on first access. + private static Map aliasOidsTable() { + // Double checked locking; safe because aliasOidsTable is volatile + Map tab = aliasOidsTable; + if (tab == null) { synchronized (AlgorithmId.class) { - if ((tab = oidTable) == null) - oidTable = tab = computeOidTable(); + if ((tab = aliasOidsTable) == null) { + aliasOidsTable = tab = collectOIDAliases(); + } } } return tab; } - /** Collects the algorithm names from the installed providers. */ - private static HashMap computeOidTable() - throws IOException { - HashMap tab = new HashMap<>(); + private static boolean isKnownProvider(Provider p) { + String pn = p.getName(); + String mn = p.getClass().getModule().getName(); + if (pn != null && mn != null) { + return ((mn.equals("java.base") && + (pn.equals("SUN") || pn.equals("SunRsaSign") || + pn.equals("SunJCE") || pn.equals("SunJSSE"))) || + (mn.equals("jdk.crypto.ec") && pn.equals("SunEC")) || + (mn.equals("jdk.crypto.mscapi") && pn.equals("SunMSCAPI")) || + (mn.equals("jdk.crypto.cryptoki") && + pn.startsWith("SunPKCS11"))); + } else { + return false; + } + } + + private static ConcurrentHashMap collectOIDAliases() { + ConcurrentHashMap t = new ConcurrentHashMap<>(); for (Provider provider : Security.getProviders()) { + // skip providers which are already using SecurityProviderConstants + // and KnownOIDs + if (isKnownProvider(provider)) { + continue; + } for (Object key : provider.keySet()) { String alias = (String)key; String upperCaseAlias = alias.toUpperCase(Locale.ENGLISH); int index; if (upperCaseAlias.startsWith("ALG.ALIAS") && - (index=upperCaseAlias.indexOf("OID.", 0)) != -1) { + (index = upperCaseAlias.indexOf("OID.", 0)) != -1) { index += "OID.".length(); if (index == alias.length()) { // invalid alias entry break; } - String oidString = alias.substring(index); + String ostr = alias.substring(index); String stdAlgName = provider.getProperty(alias); if (stdAlgName != null) { stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH); } - if (stdAlgName != null && - tab.get(stdAlgName) == null) { - tab.put(stdAlgName, new ObjectIdentifier(oidString)); + // add the name->oid and oid->name mappings if none exists + if (KnownOIDs.findMatch(stdAlgName) == null) { + // not override earlier entries if it exists + t.putIfAbsent(stdAlgName, ostr); + } + if (KnownOIDs.findMatch(ostr) == null) { + // not override earlier entries if it exists + t.putIfAbsent(ostr, stdAlgName); } } } } - return tab; + return t; } - /*****************************************************************/ - - /* - * HASHING ALGORITHMS - */ - - /** - * Algorithm ID for the MD2 Message Digest Algorthm, from RFC 1319. - * OID = 1.2.840.113549.2.2 - */ public static final ObjectIdentifier MD2_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 2, 2}); + ObjectIdentifier.of(KnownOIDs.MD2); - /** - * Algorithm ID for the MD5 Message Digest Algorthm, from RFC 1321. - * OID = 1.2.840.113549.2.5 - */ public static final ObjectIdentifier MD5_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 2, 5}); + ObjectIdentifier.of(KnownOIDs.MD5); - /** - * Algorithm ID for the SHA1 Message Digest Algorithm, from FIPS 180-1. - * This is sometimes called "SHA", though that is often confusing since - * many people refer to FIPS 180 (which has an error) as defining SHA. - * OID = 1.3.14.3.2.26. Old SHA-0 OID: 1.3.14.3.2.18. - */ public static final ObjectIdentifier SHA_oid = - ObjectIdentifier.newInternal(new int[] {1, 3, 14, 3, 2, 26}); + ObjectIdentifier.of(KnownOIDs.SHA_1); public static final ObjectIdentifier SHA224_oid = - ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 4}); + ObjectIdentifier.of(KnownOIDs.SHA_224); public static final ObjectIdentifier SHA256_oid = - ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 1}); + ObjectIdentifier.of(KnownOIDs.SHA_256); public static final ObjectIdentifier SHA384_oid = - ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 2}); + ObjectIdentifier.of(KnownOIDs.SHA_384); public static final ObjectIdentifier SHA512_oid = - ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 3}); + ObjectIdentifier.of(KnownOIDs.SHA_512); public static final ObjectIdentifier SHA512_224_oid = - ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 5}); + ObjectIdentifier.of(KnownOIDs.SHA_512$224); public static final ObjectIdentifier SHA512_256_oid = - ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 6}); - - /* - * COMMON PUBLIC KEY TYPES - */ - private static final int[] DH_data = { 1, 2, 840, 113549, 1, 3, 1 }; - private static final int[] DH_PKIX_data = { 1, 2, 840, 10046, 2, 1 }; - private static final int[] DSA_OIW_data = { 1, 3, 14, 3, 2, 12 }; - private static final int[] DSA_PKIX_data = { 1, 2, 840, 10040, 4, 1 }; - private static final int[] RSA_data = { 2, 5, 8, 1, 1 }; - - public static final ObjectIdentifier DH_oid; - public static final ObjectIdentifier DH_PKIX_oid; - public static final ObjectIdentifier DSA_oid; - public static final ObjectIdentifier DSA_OIW_oid; - public static final ObjectIdentifier EC_oid = oid(1, 2, 840, 10045, 2, 1); - public static final ObjectIdentifier ECDH_oid = oid(1, 3, 132, 1, 12); - public static final ObjectIdentifier RSA_oid; - public static final ObjectIdentifier RSAEncryption_oid = - oid(1, 2, 840, 113549, 1, 1, 1); - public static final ObjectIdentifier RSAES_OAEP_oid = - oid(1, 2, 840, 113549, 1, 1, 7); - public static final ObjectIdentifier mgf1_oid = - oid(1, 2, 840, 113549, 1, 1, 8); - public static final ObjectIdentifier RSASSA_PSS_oid = - oid(1, 2, 840, 113549, 1, 1, 10); - - /* - * COMMON SECRET KEY TYPES - */ - public static final ObjectIdentifier AES_oid = - oid(2, 16, 840, 1, 101, 3, 4, 1); - - /* - * COMMON SIGNATURE ALGORITHMS - */ - private static final int[] md2WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 2 }; - private static final int[] md5WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 4 }; - private static final int[] sha1WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 5 }; - private static final int[] sha1WithRSAEncryption_OIW_data = - { 1, 3, 14, 3, 2, 29 }; - private static final int[] sha224WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 14 }; - private static final int[] sha256WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 11 }; - private static final int[] sha384WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 12 }; - private static final int[] sha512WithRSAEncryption_data = - { 1, 2, 840, 113549, 1, 1, 13 }; - - private static final int[] shaWithDSA_OIW_data = - { 1, 3, 14, 3, 2, 13 }; - private static final int[] sha1WithDSA_OIW_data = - { 1, 3, 14, 3, 2, 27 }; - private static final int[] dsaWithSHA1_PKIX_data = - { 1, 2, 840, 10040, 4, 3 }; - - public static final ObjectIdentifier md2WithRSAEncryption_oid; - public static final ObjectIdentifier md5WithRSAEncryption_oid; - public static final ObjectIdentifier sha1WithRSAEncryption_oid; - public static final ObjectIdentifier sha1WithRSAEncryption_OIW_oid; - public static final ObjectIdentifier sha224WithRSAEncryption_oid; - public static final ObjectIdentifier sha256WithRSAEncryption_oid; - public static final ObjectIdentifier sha384WithRSAEncryption_oid; - public static final ObjectIdentifier sha512WithRSAEncryption_oid; - public static final ObjectIdentifier sha512_224WithRSAEncryption_oid = - oid(1, 2, 840, 113549, 1, 1, 15); - public static final ObjectIdentifier sha512_256WithRSAEncryption_oid = - oid(1, 2, 840, 113549, 1, 1, 16);; - - public static final ObjectIdentifier shaWithDSA_OIW_oid; - public static final ObjectIdentifier sha1WithDSA_OIW_oid; - public static final ObjectIdentifier sha1WithDSA_oid; - public static final ObjectIdentifier sha224WithDSA_oid = - oid(2, 16, 840, 1, 101, 3, 4, 3, 1); - public static final ObjectIdentifier sha256WithDSA_oid = - oid(2, 16, 840, 1, 101, 3, 4, 3, 2); - - public static final ObjectIdentifier sha1WithECDSA_oid = - oid(1, 2, 840, 10045, 4, 1); - public static final ObjectIdentifier sha224WithECDSA_oid = - oid(1, 2, 840, 10045, 4, 3, 1); - public static final ObjectIdentifier sha256WithECDSA_oid = - oid(1, 2, 840, 10045, 4, 3, 2); - public static final ObjectIdentifier sha384WithECDSA_oid = - oid(1, 2, 840, 10045, 4, 3, 3); - public static final ObjectIdentifier sha512WithECDSA_oid = - oid(1, 2, 840, 10045, 4, 3, 4); - public static final ObjectIdentifier specifiedWithECDSA_oid = - oid(1, 2, 840, 10045, 4, 3); - - /** - * Algorithm ID for the PBE encryption algorithms from PKCS#5 and - * PKCS#12. - */ - public static final ObjectIdentifier pbeWithMD5AndDES_oid = - ObjectIdentifier.newInternal(new int[]{1, 2, 840, 113549, 1, 5, 3}); - public static final ObjectIdentifier pbeWithMD5AndRC2_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 5, 6}); - public static final ObjectIdentifier pbeWithSHA1AndDES_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 5, 10}); - public static final ObjectIdentifier pbeWithSHA1AndRC2_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 5, 11}); - public static ObjectIdentifier pbeWithSHA1AndRC4_128_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 12, 1, 1}); - public static ObjectIdentifier pbeWithSHA1AndRC4_40_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 12, 1, 2}); - public static ObjectIdentifier pbeWithSHA1AndDESede_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 12, 1, 3}); - public static ObjectIdentifier pbeWithSHA1AndRC2_128_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 12, 1, 5}); - public static ObjectIdentifier pbeWithSHA1AndRC2_40_oid = - ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 12, 1, 6}); - - static { - /* - * Note the preferred OIDs are named simply with no "OIW" or - * "PKIX" in them, even though they may point to data from these - * specs; e.g. SHA_oid, DH_oid, DSA_oid, SHA1WithDSA_oid... - */ - /** - * Algorithm ID for Diffie Hellman Key agreement, from PKCS #3. - * Parameters include public values P and G, and may optionally specify - * the length of the private key X. Alternatively, algorithm parameters - * may be derived from another source such as a Certificate Authority's - * certificate. - * OID = 1.2.840.113549.1.3.1 - */ - DH_oid = ObjectIdentifier.newInternal(DH_data); - - /** - * Algorithm ID for the Diffie Hellman Key Agreement (DH), from RFC 3279. - * Parameters may include public values P and G. - * OID = 1.2.840.10046.2.1 - */ - DH_PKIX_oid = ObjectIdentifier.newInternal(DH_PKIX_data); - - /** - * Algorithm ID for the Digital Signing Algorithm (DSA), from the - * NIST OIW Stable Agreements part 12. - * Parameters may include public values P, Q, and G; or these may be - * derived from - * another source such as a Certificate Authority's certificate. - * OID = 1.3.14.3.2.12 - */ - DSA_OIW_oid = ObjectIdentifier.newInternal(DSA_OIW_data); - - /** - * Algorithm ID for the Digital Signing Algorithm (DSA), from RFC 3279. - * Parameters may include public values P, Q, and G; or these may be - * derived from another source such as a Certificate Authority's - * certificate. - * OID = 1.2.840.10040.4.1 - */ - DSA_oid = ObjectIdentifier.newInternal(DSA_PKIX_data); - - /** - * Algorithm ID for RSA keys used for any purpose, as defined in X.509. - * The algorithm parameter is a single value, the number of bits in the - * public modulus. - * OID = 2.5.8.1.1 - */ - RSA_oid = ObjectIdentifier.newInternal(RSA_data); + ObjectIdentifier.of(KnownOIDs.SHA_512$256); - /** - * Identifies a signing algorithm where an MD2 digest is encrypted - * using an RSA private key; defined in PKCS #1. Use of this - * signing algorithm is discouraged due to MD2 vulnerabilities. - * OID = 1.2.840.113549.1.1.2 - */ - md2WithRSAEncryption_oid = - ObjectIdentifier.newInternal(md2WithRSAEncryption_data); - - /** - * Identifies a signing algorithm where an MD5 digest is - * encrypted using an RSA private key; defined in PKCS #1. - * OID = 1.2.840.113549.1.1.4 - */ - md5WithRSAEncryption_oid = - ObjectIdentifier.newInternal(md5WithRSAEncryption_data); - - /** - * Identifies a signing algorithm where a SHA1 digest is - * encrypted using an RSA private key; defined by RSA DSI. - * OID = 1.2.840.113549.1.1.5 - */ - sha1WithRSAEncryption_oid = - ObjectIdentifier.newInternal(sha1WithRSAEncryption_data); + public static final ObjectIdentifier DSA_oid = + ObjectIdentifier.of(KnownOIDs.DSA); - /** - * Identifies a signing algorithm where a SHA1 digest is - * encrypted using an RSA private key; defined in NIST OIW. - * OID = 1.3.14.3.2.29 - */ - sha1WithRSAEncryption_OIW_oid = - ObjectIdentifier.newInternal(sha1WithRSAEncryption_OIW_data); - - /** - * Identifies a signing algorithm where a SHA224 digest is - * encrypted using an RSA private key; defined by PKCS #1. - * OID = 1.2.840.113549.1.1.14 - */ - sha224WithRSAEncryption_oid = - ObjectIdentifier.newInternal(sha224WithRSAEncryption_data); - - /** - * Identifies a signing algorithm where a SHA256 digest is - * encrypted using an RSA private key; defined by PKCS #1. - * OID = 1.2.840.113549.1.1.11 - */ - sha256WithRSAEncryption_oid = - ObjectIdentifier.newInternal(sha256WithRSAEncryption_data); + public static final ObjectIdentifier EC_oid = + ObjectIdentifier.of(KnownOIDs.EC); - /** - * Identifies a signing algorithm where a SHA384 digest is - * encrypted using an RSA private key; defined by PKCS #1. - * OID = 1.2.840.113549.1.1.12 - */ - sha384WithRSAEncryption_oid = - ObjectIdentifier.newInternal(sha384WithRSAEncryption_data); - - /** - * Identifies a signing algorithm where a SHA512 digest is - * encrypted using an RSA private key; defined by PKCS #1. - * OID = 1.2.840.113549.1.1.13 - */ - sha512WithRSAEncryption_oid = - ObjectIdentifier.newInternal(sha512WithRSAEncryption_data); - - /** - * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a - * SHA digest is signed using the Digital Signing Algorithm (DSA). - * This should not be used. - * OID = 1.3.14.3.2.13 - */ - shaWithDSA_OIW_oid = ObjectIdentifier.newInternal(shaWithDSA_OIW_data); + public static final ObjectIdentifier RSAEncryption_oid = + ObjectIdentifier.of(KnownOIDs.RSA); - /** - * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a - * SHA1 digest is signed using the Digital Signing Algorithm (DSA). - * OID = 1.3.14.3.2.27 - */ - sha1WithDSA_OIW_oid = ObjectIdentifier.newInternal(sha1WithDSA_OIW_data); + public static final ObjectIdentifier RSASSA_PSS_oid = + ObjectIdentifier.of(KnownOIDs.RSASSA_PSS); - /** - * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a - * SHA1 digest is signed using the Digital Signing Algorithm (DSA). - * OID = 1.2.840.10040.4.3 - */ - sha1WithDSA_oid = ObjectIdentifier.newInternal(dsaWithSHA1_PKIX_data); - - nameTable = new HashMap<>(); - nameTable.put(MD5_oid, "MD5"); - nameTable.put(MD2_oid, "MD2"); - nameTable.put(SHA_oid, "SHA-1"); - nameTable.put(SHA224_oid, "SHA-224"); - nameTable.put(SHA256_oid, "SHA-256"); - nameTable.put(SHA384_oid, "SHA-384"); - nameTable.put(SHA512_oid, "SHA-512"); - nameTable.put(SHA512_224_oid, "SHA-512/224"); - nameTable.put(SHA512_256_oid, "SHA-512/256"); - nameTable.put(RSAEncryption_oid, "RSA"); - nameTable.put(RSA_oid, "RSA"); - nameTable.put(DH_oid, "Diffie-Hellman"); - nameTable.put(DH_PKIX_oid, "Diffie-Hellman"); - nameTable.put(DSA_oid, "DSA"); - nameTable.put(DSA_OIW_oid, "DSA"); - nameTable.put(EC_oid, "EC"); - nameTable.put(ECDH_oid, "ECDH"); - - nameTable.put(AES_oid, "AES"); - - nameTable.put(sha1WithECDSA_oid, "SHA1withECDSA"); - nameTable.put(sha224WithECDSA_oid, "SHA224withECDSA"); - nameTable.put(sha256WithECDSA_oid, "SHA256withECDSA"); - nameTable.put(sha384WithECDSA_oid, "SHA384withECDSA"); - nameTable.put(sha512WithECDSA_oid, "SHA512withECDSA"); - nameTable.put(md5WithRSAEncryption_oid, "MD5withRSA"); - nameTable.put(md2WithRSAEncryption_oid, "MD2withRSA"); - nameTable.put(sha1WithDSA_oid, "SHA1withDSA"); - nameTable.put(sha1WithDSA_OIW_oid, "SHA1withDSA"); - nameTable.put(shaWithDSA_OIW_oid, "SHA1withDSA"); - nameTable.put(sha224WithDSA_oid, "SHA224withDSA"); - nameTable.put(sha256WithDSA_oid, "SHA256withDSA"); - nameTable.put(sha1WithRSAEncryption_oid, "SHA1withRSA"); - nameTable.put(sha1WithRSAEncryption_OIW_oid, "SHA1withRSA"); - nameTable.put(sha224WithRSAEncryption_oid, "SHA224withRSA"); - nameTable.put(sha256WithRSAEncryption_oid, "SHA256withRSA"); - nameTable.put(sha384WithRSAEncryption_oid, "SHA384withRSA"); - nameTable.put(sha512WithRSAEncryption_oid, "SHA512withRSA"); - nameTable.put(sha512_224WithRSAEncryption_oid, "SHA512/224withRSA"); - nameTable.put(sha512_256WithRSAEncryption_oid, "SHA512/256withRSA"); - nameTable.put(RSASSA_PSS_oid, "RSASSA-PSS"); - nameTable.put(RSAES_OAEP_oid, "RSAES-OAEP"); - - nameTable.put(pbeWithMD5AndDES_oid, "PBEWithMD5AndDES"); - nameTable.put(pbeWithMD5AndRC2_oid, "PBEWithMD5AndRC2"); - nameTable.put(pbeWithSHA1AndDES_oid, "PBEWithSHA1AndDES"); - nameTable.put(pbeWithSHA1AndRC2_oid, "PBEWithSHA1AndRC2"); - nameTable.put(pbeWithSHA1AndRC4_128_oid, "PBEWithSHA1AndRC4_128"); - nameTable.put(pbeWithSHA1AndRC4_40_oid, "PBEWithSHA1AndRC4_40"); - nameTable.put(pbeWithSHA1AndDESede_oid, "PBEWithSHA1AndDESede"); - nameTable.put(pbeWithSHA1AndRC2_128_oid, "PBEWithSHA1AndRC2_128"); - nameTable.put(pbeWithSHA1AndRC2_40_oid, "PBEWithSHA1AndRC2_40"); - } + public static final ObjectIdentifier MGF1_oid = + ObjectIdentifier.of(KnownOIDs.MGF1); /** * Creates a signature algorithm name from a digest algorithm diff --git a/src/java.base/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java b/src/java.base/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java index c8968448c7f..6f73a3af6d0 100644 --- a/src/java.base/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java +++ b/src/java.base/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -34,9 +34,7 @@ import java.util.Map; import java.util.Vector; -import sun.security.util.DerValue; -import sun.security.util.DerOutputStream; -import sun.security.util.ObjectIdentifier; +import sun.security.util.*; /** * This class defines the Extended Key Usage Extension, which @@ -94,35 +92,6 @@ public class ExtendedKeyUsageExtension extends Extension public static final String NAME = "ExtendedKeyUsage"; public static final String USAGES = "usages"; - // OID defined in RFC 5280 Sections 4.2.1.12 - // more from http://www.alvestrand.no/objectid/1.3.6.1.5.5.7.3.html - private static final Map map = - new HashMap (); - - private static final int[] anyExtendedKeyUsageOidData = {2, 5, 29, 37, 0}; - private static final int[] serverAuthOidData = {1, 3, 6, 1, 5, 5, 7, 3, 1}; - private static final int[] clientAuthOidData = {1, 3, 6, 1, 5, 5, 7, 3, 2}; - private static final int[] codeSigningOidData = {1, 3, 6, 1, 5, 5, 7, 3, 3}; - private static final int[] emailProtectionOidData = {1, 3, 6, 1, 5, 5, 7, 3, 4}; - private static final int[] ipsecEndSystemOidData = {1, 3, 6, 1, 5, 5, 7, 3, 5}; - private static final int[] ipsecTunnelOidData = {1, 3, 6, 1, 5, 5, 7, 3, 6}; - private static final int[] ipsecUserOidData = {1, 3, 6, 1, 5, 5, 7, 3, 7}; - private static final int[] timeStampingOidData = {1, 3, 6, 1, 5, 5, 7, 3, 8}; - private static final int[] OCSPSigningOidData = {1, 3, 6, 1, 5, 5, 7, 3, 9}; - - static { - map.put(ObjectIdentifier.newInternal(anyExtendedKeyUsageOidData), "anyExtendedKeyUsage"); - map.put(ObjectIdentifier.newInternal(serverAuthOidData), "serverAuth"); - map.put(ObjectIdentifier.newInternal(clientAuthOidData), "clientAuth"); - map.put(ObjectIdentifier.newInternal(codeSigningOidData), "codeSigning"); - map.put(ObjectIdentifier.newInternal(emailProtectionOidData), "emailProtection"); - map.put(ObjectIdentifier.newInternal(ipsecEndSystemOidData), "ipsecEndSystem"); - map.put(ObjectIdentifier.newInternal(ipsecTunnelOidData), "ipsecTunnel"); - map.put(ObjectIdentifier.newInternal(ipsecUserOidData), "ipsecUser"); - map.put(ObjectIdentifier.newInternal(timeStampingOidData), "timeStamping"); - map.put(ObjectIdentifier.newInternal(OCSPSigningOidData), "OCSPSigning"); - }; - /** * Vector of KeyUsages for this object. */ @@ -209,11 +178,12 @@ public String toString() { usage += "\n "; } - String result = map.get(oid); - if (result != null) { - usage += result; + String res = oid.toString(); + KnownOIDs os = KnownOIDs.findMatch(res); + if (os != null) { + usage += os.stdName(); } else { - usage += oid.toString(); + usage += res; } first = false; } diff --git a/src/java.base/share/classes/sun/security/x509/GeneralSubtrees.java b/src/java.base/share/classes/sun/security/x509/GeneralSubtrees.java index 847f56aba86..8adafe20344 100644 --- a/src/java.base/share/classes/sun/security/x509/GeneralSubtrees.java +++ b/src/java.base/share/classes/sun/security/x509/GeneralSubtrees.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -270,8 +270,7 @@ private GeneralSubtree createWidestSubtree(GeneralNameInterface name) { newName = new GeneralName(new IPAddressName((byte[])null)); break; case GeneralNameInterface.NAME_OID: - newName = new GeneralName - (new OIDName(new ObjectIdentifier((int[])null))); + newName = new GeneralName(new OIDName("")); break; default: throw new IOException diff --git a/src/java.base/share/classes/sun/security/x509/InhibitAnyPolicyExtension.java b/src/java.base/share/classes/sun/security/x509/InhibitAnyPolicyExtension.java index a20a1f55803..6fa2ae16729 100644 --- a/src/java.base/share/classes/sun/security/x509/InhibitAnyPolicyExtension.java +++ b/src/java.base/share/classes/sun/security/x509/InhibitAnyPolicyExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -29,10 +29,7 @@ import java.io.OutputStream; import java.util.Enumeration; -import sun.security.util.Debug; -import sun.security.util.DerOutputStream; -import sun.security.util.DerValue; -import sun.security.util.ObjectIdentifier; +import sun.security.util.*; /** * This class represents the Inhibit Any-Policy Extension. @@ -75,14 +72,8 @@ public class InhibitAnyPolicyExtension extends Extension /** * Object identifier for "any-policy" */ - public static ObjectIdentifier AnyPolicy_Id; - static { - try { - AnyPolicy_Id = new ObjectIdentifier("2.5.29.32.0"); - } catch (IOException ioe) { - // Should not happen - } - } + public static ObjectIdentifier AnyPolicy_Id = + ObjectIdentifier.of(KnownOIDs.CE_CERT_POLICIES_ANY); /** * Attribute names. diff --git a/src/java.base/share/classes/sun/security/x509/NetscapeCertTypeExtension.java b/src/java.base/share/classes/sun/security/x509/NetscapeCertTypeExtension.java index ca4dc3c53c3..d455f00f8a8 100644 --- a/src/java.base/share/classes/sun/security/x509/NetscapeCertTypeExtension.java +++ b/src/java.base/share/classes/sun/security/x509/NetscapeCertTypeExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -69,20 +69,11 @@ public class NetscapeCertTypeExtension extends Extension public static final String S_MIME_CA = "s_mime_ca"; public static final String OBJECT_SIGNING_CA = "object_signing_ca"; - private static final int[] CertType_data = { 2, 16, 840, 1, 113730, 1, 1 }; - /** * Object identifier for the Netscape-Cert-Type extension. */ - public static ObjectIdentifier NetscapeCertType_Id; - - static { - try { - NetscapeCertType_Id = new ObjectIdentifier(CertType_data); - } catch (IOException ioe) { - // should not happen - } - } + public static ObjectIdentifier NetscapeCertType_Id = + ObjectIdentifier.of(KnownOIDs.NETSCAPE_CertType); private boolean[] bitString; diff --git a/src/java.base/share/classes/sun/security/x509/OIDMap.java b/src/java.base/share/classes/sun/security/x509/OIDMap.java index a39493e279a..54a8d9146c8 100644 --- a/src/java.base/share/classes/sun/security/x509/OIDMap.java +++ b/src/java.base/share/classes/sun/security/x509/OIDMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -102,9 +102,6 @@ private OIDMap() { private static final String OCSPNOCHECK = ROOT + "." + OCSPNoCheckExtension.NAME; - private static final int[] NetscapeCertType_data = - { 2, 16, 840, 1, 113730, 1, 1 }; - /** Map ObjectIdentifier(oid) -> OIDInfo(info) */ private static final Map oidMap; @@ -138,8 +135,8 @@ private OIDMap() { "sun.security.x509.AuthorityKeyIdentifierExtension"); addInternal(POLICY_CONSTRAINTS, PKIXExtensions.PolicyConstraints_Id, "sun.security.x509.PolicyConstraintsExtension"); - addInternal(NETSCAPE_CERT, ObjectIdentifier.newInternal - (new int[] {2,16,840,1,113730,1,1}), + addInternal(NETSCAPE_CERT, + ObjectIdentifier.of(KnownOIDs.NETSCAPE_CertType), "sun.security.x509.NetscapeCertTypeExtension"); addInternal(CERT_POLICIES, PKIXExtensions.CertificatePolicies_Id, "sun.security.x509.CertificatePoliciesExtension"); @@ -230,7 +227,7 @@ public static void addAttribute(String name, String oid, Class clazz) throws CertificateException { ObjectIdentifier objId; try { - objId = new ObjectIdentifier(oid); + objId = ObjectIdentifier.of(oid); } catch (IOException ioe) { throw new CertificateException ("Invalid Object identifier: " + oid); diff --git a/src/java.base/share/classes/sun/security/x509/OIDName.java b/src/java.base/share/classes/sun/security/x509/OIDName.java index 6db9d11e2d3..4377fc3ee71 100644 --- a/src/java.base/share/classes/sun/security/x509/OIDName.java +++ b/src/java.base/share/classes/sun/security/x509/OIDName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -69,7 +69,7 @@ public OIDName(ObjectIdentifier oid) { */ public OIDName(String name) throws IOException { try { - oid = new ObjectIdentifier(name); + oid = ObjectIdentifier.of(name); } catch (Exception e) { throw new IOException("Unable to create OIDName: " + e); } diff --git a/src/java.base/share/classes/sun/security/x509/PKIXExtensions.java b/src/java.base/share/classes/sun/security/x509/PKIXExtensions.java index bf4f8fdf80c..754d3d0e726 100644 --- a/src/java.base/share/classes/sun/security/x509/PKIXExtensions.java +++ b/src/java.base/share/classes/sun/security/x509/PKIXExtensions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -25,7 +25,6 @@ package sun.security.x509; -import java.io.*; import sun.security.util.*; @@ -48,163 +47,151 @@ * @author Hemma Prafullchandra */ public class PKIXExtensions { - // The object identifiers - private static final int[] AuthorityKey_data = { 2, 5, 29, 35 }; - private static final int[] SubjectKey_data = { 2, 5, 29, 14 }; - private static final int[] KeyUsage_data = { 2, 5, 29, 15 }; - private static final int[] PrivateKeyUsage_data = { 2, 5, 29, 16 }; - private static final int[] CertificatePolicies_data = { 2, 5, 29, 32 }; - private static final int[] PolicyMappings_data = { 2, 5, 29, 33 }; - private static final int[] SubjectAlternativeName_data = { 2, 5, 29, 17 }; - private static final int[] IssuerAlternativeName_data = { 2, 5, 29, 18 }; - private static final int[] SubjectDirectoryAttributes_data = { 2, 5, 29, 9 }; - private static final int[] BasicConstraints_data = { 2, 5, 29, 19 }; - private static final int[] NameConstraints_data = { 2, 5, 29, 30 }; - private static final int[] PolicyConstraints_data = { 2, 5, 29, 36 }; - private static final int[] CRLDistributionPoints_data = { 2, 5, 29, 31 }; - private static final int[] CRLNumber_data = { 2, 5, 29, 20 }; - private static final int[] IssuingDistributionPoint_data = { 2, 5, 29, 28 }; - private static final int[] DeltaCRLIndicator_data = { 2, 5, 29, 27 }; - private static final int[] ReasonCode_data = { 2, 5, 29, 21 }; - private static final int[] HoldInstructionCode_data = { 2, 5, 29, 23 }; - private static final int[] InvalidityDate_data = { 2, 5, 29, 24 }; - private static final int[] ExtendedKeyUsage_data = { 2, 5, 29, 37 }; - private static final int[] InhibitAnyPolicy_data = { 2, 5, 29, 54 }; - private static final int[] CertificateIssuer_data = { 2, 5, 29, 29 }; - private static final int[] AuthInfoAccess_data = { 1, 3, 6, 1, 5, 5, 7, 1, 1}; - private static final int[] SubjectInfoAccess_data = { 1, 3, 6, 1, 5, 5, 7, 1, 11}; - private static final int[] FreshestCRL_data = { 2, 5, 29, 46 }; - private static final int[] OCSPNoCheck_data = { 1, 3, 6, 1, 5, 5, 7, - 48, 1, 5}; - - // Additional extensions under the PKIX arc that are not necessarily - // used in X.509 Certificates or CRLs. - private static final int OCSPNonce_data [] = { 1, 3, 6, 1, 5, 5, 7, - 48, 1, 2}; - /** * Identifies the particular public key used to sign the certificate. */ - public static final ObjectIdentifier AuthorityKey_Id; + public static final ObjectIdentifier AuthorityKey_Id = + ObjectIdentifier.of(KnownOIDs.AuthorityKeyID); /** * Identifies the particular public key used in an application. */ - public static final ObjectIdentifier SubjectKey_Id; + public static final ObjectIdentifier SubjectKey_Id = + ObjectIdentifier.of(KnownOIDs.SubjectKeyID); /** * Defines the purpose of the key contained in the certificate. */ - public static final ObjectIdentifier KeyUsage_Id; + public static final ObjectIdentifier KeyUsage_Id = + ObjectIdentifier.of(KnownOIDs.KeyUsage); /** * Allows the certificate issuer to specify a different validity period * for the private key than the certificate. */ - public static final ObjectIdentifier PrivateKeyUsage_Id; + public static final ObjectIdentifier PrivateKeyUsage_Id = + ObjectIdentifier.of(KnownOIDs.PrivateKeyUsage); /** * Contains the sequence of policy information terms. */ - public static final ObjectIdentifier CertificatePolicies_Id; + public static final ObjectIdentifier CertificatePolicies_Id = + ObjectIdentifier.of(KnownOIDs.CertificatePolicies); /** * Lists pairs of object identifiers of policies considered equivalent by * the issuing CA to the subject CA. */ - public static final ObjectIdentifier PolicyMappings_Id; + public static final ObjectIdentifier PolicyMappings_Id = + ObjectIdentifier.of(KnownOIDs.PolicyMappings); /** * Allows additional identities to be bound to the subject of the * certificate. */ - public static final ObjectIdentifier SubjectAlternativeName_Id; + public static final ObjectIdentifier SubjectAlternativeName_Id = + ObjectIdentifier.of(KnownOIDs.SubjectAlternativeName); /** * Allows additional identities to be associated with the certificate * issuer. */ - public static final ObjectIdentifier IssuerAlternativeName_Id; + public static final ObjectIdentifier IssuerAlternativeName_Id = + ObjectIdentifier.of(KnownOIDs.IssuerAlternativeName); /** * Identifies additional directory attributes. * This extension is always non-critical. */ - public static final ObjectIdentifier SubjectDirectoryAttributes_Id; + public static final ObjectIdentifier SubjectDirectoryAttributes_Id = + ObjectIdentifier.of(KnownOIDs.SubjectDirectoryAttributes); /** * Identifies whether the subject of the certificate is a CA and how deep * a certification path may exist through that CA. */ - public static final ObjectIdentifier BasicConstraints_Id; + public static final ObjectIdentifier BasicConstraints_Id = + ObjectIdentifier.of(KnownOIDs.BasicConstraints); /** * Provides for permitted and excluded subtrees that place restrictions * on names that may be included within a certificate issued by a given CA. */ - public static final ObjectIdentifier NameConstraints_Id; + public static final ObjectIdentifier NameConstraints_Id = + ObjectIdentifier.of(KnownOIDs.NameConstraints); /** * Used to either prohibit policy mapping or limit the set of policies * that can be in subsequent certificates. */ - public static final ObjectIdentifier PolicyConstraints_Id; + public static final ObjectIdentifier PolicyConstraints_Id = + ObjectIdentifier.of(KnownOIDs.PolicyConstraints); /** * Identifies how CRL information is obtained. */ - public static final ObjectIdentifier CRLDistributionPoints_Id; + public static final ObjectIdentifier CRLDistributionPoints_Id = + ObjectIdentifier.of(KnownOIDs.CRLDistributionPoints); /** * Conveys a monotonically increasing sequence number for each CRL * issued by a given CA. */ - public static final ObjectIdentifier CRLNumber_Id; + public static final ObjectIdentifier CRLNumber_Id = + ObjectIdentifier.of(KnownOIDs.CRLNumber); /** * Identifies the CRL distribution point for a particular CRL. */ - public static final ObjectIdentifier IssuingDistributionPoint_Id; + public static final ObjectIdentifier IssuingDistributionPoint_Id = + ObjectIdentifier.of(KnownOIDs.IssuingDistributionPoint); /** * Identifies the delta CRL. */ - public static final ObjectIdentifier DeltaCRLIndicator_Id; + public static final ObjectIdentifier DeltaCRLIndicator_Id = + ObjectIdentifier.of(KnownOIDs.DeltaCRLIndicator); /** * Identifies the reason for the certificate revocation. */ - public static final ObjectIdentifier ReasonCode_Id; + public static final ObjectIdentifier ReasonCode_Id = + ObjectIdentifier.of(KnownOIDs.ReasonCode); /** * This extension provides a registered instruction identifier indicating * the action to be taken, after encountering a certificate that has been * placed on hold. */ - public static final ObjectIdentifier HoldInstructionCode_Id; + public static final ObjectIdentifier HoldInstructionCode_Id = + ObjectIdentifier.of(KnownOIDs.HoldInstructionCode); /** * Identifies the date on which it is known or suspected that the private * key was compromised or that the certificate otherwise became invalid. */ - public static final ObjectIdentifier InvalidityDate_Id; + public static final ObjectIdentifier InvalidityDate_Id = + ObjectIdentifier.of(KnownOIDs.InvalidityDate); /** * Identifies one or more purposes for which the certified public key * may be used, in addition to or in place of the basic purposes * indicated in the key usage extension field. */ - public static final ObjectIdentifier ExtendedKeyUsage_Id; + public static final ObjectIdentifier ExtendedKeyUsage_Id = + ObjectIdentifier.of(KnownOIDs.extendedKeyUsage); /** * Specifies whether any-policy policy OID is permitted */ - public static final ObjectIdentifier InhibitAnyPolicy_Id; + public static final ObjectIdentifier InhibitAnyPolicy_Id = + ObjectIdentifier.of(KnownOIDs.InhibitAnyPolicy); /** * Identifies the certificate issuer associated with an entry in an * indirect CRL. */ - public static final ObjectIdentifier CertificateIssuer_Id; + public static final ObjectIdentifier CertificateIssuer_Id = + ObjectIdentifier.of(KnownOIDs.CertificateIssuer); /** * This extension indicates how to access CA information and services for @@ -212,73 +199,33 @@ public class PKIXExtensions { * This information may be used for on-line certification validation * services. */ - public static final ObjectIdentifier AuthInfoAccess_Id; + public static final ObjectIdentifier AuthInfoAccess_Id = + ObjectIdentifier.of(KnownOIDs.AuthInfoAccess); /** * This extension indicates how to access CA information and services for * the subject of the certificate in which the extension appears. */ - public static final ObjectIdentifier SubjectInfoAccess_Id; + public static final ObjectIdentifier SubjectInfoAccess_Id = + ObjectIdentifier.of(KnownOIDs.SubjectInfoAccess); /** * Identifies how delta CRL information is obtained. */ - public static final ObjectIdentifier FreshestCRL_Id; + public static final ObjectIdentifier FreshestCRL_Id = + ObjectIdentifier.of(KnownOIDs.FreshestCRL); /** * Identifies the OCSP client can trust the responder for the * lifetime of the responder's certificate. */ - public static final ObjectIdentifier OCSPNoCheck_Id; + public static final ObjectIdentifier OCSPNoCheck_Id = + ObjectIdentifier.of(KnownOIDs.OCSPNoCheck); /** * This extension is used to provide nonce data for OCSP requests * or responses. */ - public static final ObjectIdentifier OCSPNonce_Id; - - static { - AuthorityKey_Id = ObjectIdentifier.newInternal(AuthorityKey_data); - SubjectKey_Id = ObjectIdentifier.newInternal(SubjectKey_data); - KeyUsage_Id = ObjectIdentifier.newInternal(KeyUsage_data); - PrivateKeyUsage_Id = ObjectIdentifier.newInternal(PrivateKeyUsage_data); - CertificatePolicies_Id = - ObjectIdentifier.newInternal(CertificatePolicies_data); - PolicyMappings_Id = ObjectIdentifier.newInternal(PolicyMappings_data); - SubjectAlternativeName_Id = - ObjectIdentifier.newInternal(SubjectAlternativeName_data); - IssuerAlternativeName_Id = - ObjectIdentifier.newInternal(IssuerAlternativeName_data); - ExtendedKeyUsage_Id = ObjectIdentifier.newInternal(ExtendedKeyUsage_data); - InhibitAnyPolicy_Id = ObjectIdentifier.newInternal(InhibitAnyPolicy_data); - SubjectDirectoryAttributes_Id = - ObjectIdentifier.newInternal(SubjectDirectoryAttributes_data); - BasicConstraints_Id = - ObjectIdentifier.newInternal(BasicConstraints_data); - ReasonCode_Id = ObjectIdentifier.newInternal(ReasonCode_data); - HoldInstructionCode_Id = - ObjectIdentifier.newInternal(HoldInstructionCode_data); - InvalidityDate_Id = ObjectIdentifier.newInternal(InvalidityDate_data); - - NameConstraints_Id = ObjectIdentifier.newInternal(NameConstraints_data); - PolicyConstraints_Id = - ObjectIdentifier.newInternal(PolicyConstraints_data); - CRLDistributionPoints_Id = - ObjectIdentifier.newInternal(CRLDistributionPoints_data); - CRLNumber_Id = - ObjectIdentifier.newInternal(CRLNumber_data); - IssuingDistributionPoint_Id = - ObjectIdentifier.newInternal(IssuingDistributionPoint_data); - DeltaCRLIndicator_Id = - ObjectIdentifier.newInternal(DeltaCRLIndicator_data); - CertificateIssuer_Id = - ObjectIdentifier.newInternal(CertificateIssuer_data); - AuthInfoAccess_Id = - ObjectIdentifier.newInternal(AuthInfoAccess_data); - SubjectInfoAccess_Id = - ObjectIdentifier.newInternal(SubjectInfoAccess_data); - FreshestCRL_Id = ObjectIdentifier.newInternal(FreshestCRL_data); - OCSPNoCheck_Id = ObjectIdentifier.newInternal(OCSPNoCheck_data); - OCSPNonce_Id = ObjectIdentifier.newInternal(OCSPNonce_data); - } + public static final ObjectIdentifier OCSPNonce_Id = + ObjectIdentifier.of(KnownOIDs.OCSPNonceExt); } diff --git a/src/java.base/share/classes/sun/security/x509/X500Name.java b/src/java.base/share/classes/sun/security/x509/X500Name.java index 9bf9c55fb61..701ee40b31a 100644 --- a/src/java.base/share/classes/sun/security/x509/X500Name.java +++ b/src/java.base/share/classes/sun/security/x509/X500Name.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -1102,104 +1102,83 @@ private String generateRFC1779DN(Map oidMap) { * Includes all those specified in RFC 5280 as MUST or SHOULD * be recognized */ - private static final int[] commonName_data = { 2, 5, 4, 3 }; - private static final int[] SURNAME_DATA = { 2, 5, 4, 4 }; - private static final int[] SERIALNUMBER_DATA = { 2, 5, 4, 5 }; - private static final int[] countryName_data = { 2, 5, 4, 6 }; - private static final int[] localityName_data = { 2, 5, 4, 7 }; - private static final int[] stateName_data = { 2, 5, 4, 8 }; - private static final int[] streetAddress_data = { 2, 5, 4, 9 }; - private static final int[] orgName_data = { 2, 5, 4, 10 }; - private static final int[] orgUnitName_data = { 2, 5, 4, 11 }; - private static final int[] title_data = { 2, 5, 4, 12 }; - private static final int[] GIVENNAME_DATA = { 2, 5, 4, 42 }; - private static final int[] INITIALS_DATA = { 2, 5, 4, 43 }; - private static final int[] GENERATIONQUALIFIER_DATA = { 2, 5, 4, 44 }; - private static final int[] DNQUALIFIER_DATA = { 2, 5, 4, 46 }; - - private static final int[] ipAddress_data = { 1, 3, 6, 1, 4, 1, 42, 2, 11, 2, 1 }; - private static final int[] DOMAIN_COMPONENT_DATA = - { 0, 9, 2342, 19200300, 100, 1, 25 }; - private static final int[] userid_data = - { 0, 9, 2342, 19200300, 100, 1, 1 }; - // OID for the "CN=" attribute, denoting a person's common name. public static final ObjectIdentifier commonName_oid = - ObjectIdentifier.newInternal(commonName_data); + ObjectIdentifier.of(KnownOIDs.CommonName); + + // OID for the "SURNAME=" attribute, denoting a person's surname. + public static final ObjectIdentifier SURNAME_OID = + ObjectIdentifier.of(KnownOIDs.Surname); // OID for the "SERIALNUMBER=" attribute, denoting a serial number for. // a name. Do not confuse with PKCS#9 issuerAndSerialNumber or the // certificate serial number. public static final ObjectIdentifier SERIALNUMBER_OID = - ObjectIdentifier.newInternal(SERIALNUMBER_DATA); + ObjectIdentifier.of(KnownOIDs.SerialNumber); // OID for the "C=" attribute, denoting a country. public static final ObjectIdentifier countryName_oid = - ObjectIdentifier.newInternal(countryName_data); + ObjectIdentifier.of(KnownOIDs.CountryName); // OID for the "L=" attribute, denoting a locality (such as a city). public static final ObjectIdentifier localityName_oid = - ObjectIdentifier.newInternal(localityName_data); - - // OID for the "O=" attribute, denoting an organization name. - public static final ObjectIdentifier orgName_oid = - ObjectIdentifier.newInternal(orgName_data); - - // OID for the "OU=" attribute, denoting an organizational unit name. - public static final ObjectIdentifier orgUnitName_oid = - ObjectIdentifier.newInternal(orgUnitName_data); + ObjectIdentifier.of(KnownOIDs.LocalityName); // OID for the "S=" attribute, denoting a state (such as Delaware). public static final ObjectIdentifier stateName_oid = - ObjectIdentifier.newInternal(stateName_data); + ObjectIdentifier.of(KnownOIDs.StateName); // OID for the "STREET=" attribute, denoting a street address. public static final ObjectIdentifier streetAddress_oid = - ObjectIdentifier.newInternal(streetAddress_data); + ObjectIdentifier.of(KnownOIDs.StreetAddress); - // OID for the "T=" attribute, denoting a person's title. - public static final ObjectIdentifier title_oid = - ObjectIdentifier.newInternal(title_data); + // OID for the "O=" attribute, denoting an organization name. + public static final ObjectIdentifier orgName_oid = + ObjectIdentifier.of(KnownOIDs.OrgName); - // OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN - // disambiguating information. - public static final ObjectIdentifier DNQUALIFIER_OID = - ObjectIdentifier.newInternal(DNQUALIFIER_DATA); + // OID for the "OU=" attribute, denoting an organizational unit name. + public static final ObjectIdentifier orgUnitName_oid = + ObjectIdentifier.of(KnownOIDs.OrgUnitName); - // OID for the "SURNAME=" attribute, denoting a person's surname. - public static final ObjectIdentifier SURNAME_OID = - ObjectIdentifier.newInternal(SURNAME_DATA); + // OID for the "T=" attribute, denoting a person's title. + public static final ObjectIdentifier title_oid = + ObjectIdentifier.of(KnownOIDs.Title); // OID for the "GIVENNAME=" attribute, denoting a person's given name. public static final ObjectIdentifier GIVENNAME_OID = - ObjectIdentifier.newInternal(GIVENNAME_DATA); + ObjectIdentifier.of(KnownOIDs.GivenName); // OID for the "INITIALS=" attribute, denoting a person's initials. public static final ObjectIdentifier INITIALS_OID = - ObjectIdentifier.newInternal(INITIALS_DATA); + ObjectIdentifier.of(KnownOIDs.Initials); // OID for the "GENERATION=" attribute, denoting Jr., II, etc. public static final ObjectIdentifier GENERATIONQUALIFIER_OID = - ObjectIdentifier.newInternal(GENERATIONQUALIFIER_DATA); + ObjectIdentifier.of(KnownOIDs.GenerationQualifier); + + // OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN + // disambiguating information. + public static final ObjectIdentifier DNQUALIFIER_OID = + ObjectIdentifier.of(KnownOIDs.DNQualifier); // OIDs from other sources which show up in X.500 names we // expect to deal with often. // // OID for "IP=" IP address attributes, used with SKIP. public static final ObjectIdentifier ipAddress_oid = - ObjectIdentifier.newInternal(ipAddress_data); + ObjectIdentifier.of(KnownOIDs.SkipIPAddress); // Domain component OID from RFC 1274, RFC 2247, RFC 5280. // - // OID for "DC=" domain component attributes, used with DNSNames in DN + // OID for "DC=" domain component attributes.used with DNSNames in DN // format. public static final ObjectIdentifier DOMAIN_COMPONENT_OID = - ObjectIdentifier.newInternal(DOMAIN_COMPONENT_DATA); + ObjectIdentifier.of(KnownOIDs.UCL_DomainComponent); // OID for "UID=" denoting a user id, defined in RFCs 1274 & 2798. public static final ObjectIdentifier userid_oid = - ObjectIdentifier.newInternal(userid_data); + ObjectIdentifier.of(KnownOIDs.UCL_UserID); /** * Return constraint type:

    diff --git a/src/java.base/share/classes/sun/security/x509/X509CRLEntryImpl.java b/src/java.base/share/classes/sun/security/x509/X509CRLEntryImpl.java index 54e6016b740..aa6ef1ff348 100644 --- a/src/java.base/share/classes/sun/security/x509/X509CRLEntryImpl.java +++ b/src/java.base/share/classes/sun/security/x509/X509CRLEntryImpl.java @@ -252,7 +252,8 @@ public CRLReason getRevocationReason() { */ public static CRLReason getRevocationReason(X509CRLEntry crlEntry) { try { - byte[] ext = crlEntry.getExtensionValue("2.5.29.21"); + byte[] ext = crlEntry.getExtensionValue + (KnownOIDs.ReasonCode.value()); if (ext == null) { return null; } @@ -402,11 +403,11 @@ public byte[] getExtensionValue(String oid) { if (extensions == null) return null; try { - String extAlias = OIDMap.getName(new ObjectIdentifier(oid)); + String extAlias = OIDMap.getName(ObjectIdentifier.of(oid)); Extension crlExt = null; if (extAlias == null) { // may be unknown - ObjectIdentifier findOID = new ObjectIdentifier(oid); + ObjectIdentifier findOID = ObjectIdentifier.of(oid); Extension ex = null; ObjectIdentifier inCertOID; for (Enumeration e = extensions.getElements(); diff --git a/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java b/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java index 6e50047f41e..da438f71890 100644 --- a/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java +++ b/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java @@ -1036,11 +1036,11 @@ public byte[] getExtensionValue(String oid) { if (extensions == null) return null; try { - String extAlias = OIDMap.getName(new ObjectIdentifier(oid)); + String extAlias = OIDMap.getName(ObjectIdentifier.of(oid)); Extension crlExt = null; if (extAlias == null) { // may be unknown - ObjectIdentifier findOID = new ObjectIdentifier(oid); + ObjectIdentifier findOID = ObjectIdentifier.of(oid); Extension ex = null; ObjectIdentifier inCertOID; for (Enumeration e = extensions.getElements(); diff --git a/src/java.base/share/classes/sun/security/x509/X509CertImpl.java b/src/java.base/share/classes/sun/security/x509/X509CertImpl.java index 90d9cfaf20b..34de4e2c5a3 100644 --- a/src/java.base/share/classes/sun/security/x509/X509CertImpl.java +++ b/src/java.base/share/classes/sun/security/x509/X509CertImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,7 @@ package sun.security.x509; -import java.io.BufferedReader; -import java.io.BufferedInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; +import java.io.*; import java.math.BigInteger; import java.security.*; import java.security.spec.AlgorithmParameterSpec; @@ -42,6 +36,7 @@ import javax.security.auth.x500.X500Principal; +import sun.security.jca.JCAUtil; import sun.security.util.*; import sun.security.provider.X509Factory; @@ -130,14 +125,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder { protected AlgorithmId algId = null; protected byte[] signature = null; - // recognized extension OIDS - private static final String KEY_USAGE_OID = "2.5.29.15"; - private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37"; - private static final String BASIC_CONSTRAINT_OID = "2.5.29.19"; - private static final String SUBJECT_ALT_NAME_OID = "2.5.29.17"; - private static final String ISSUER_ALT_NAME_OID = "2.5.29.18"; - private static final String AUTH_INFO_ACCESS_OID = "1.3.6.1.5.5.7.1.1"; - // number of standard key usage bits. private static final int NUM_STANDARD_KEY_USAGE = 9; @@ -312,6 +299,13 @@ public X509CertImpl(DerValue derVal) throws CertificateException { } } + // helper method to record certificate, if necessary, after construction + public static X509CertImpl newX509CertImpl(byte[] certData) throws CertificateException { + var cert = new X509CertImpl(certData); + JCAUtil.tryCommitCertEvent(cert); + return cert; + } + /** * Appends the certificate to an output stream. * @@ -677,7 +671,7 @@ public void checkValidity(Date date) /** * Return the requested attribute from the certificate. - * + *

    * Note that the X509CertInfo is not cloned for performance reasons. * Callers must ensure that they do not modify it. All other * attributes are cloned. @@ -1425,7 +1419,7 @@ public Extension getUnparseableExtension(ObjectIdentifier oid) { */ public byte[] getExtensionValue(String oid) { try { - ObjectIdentifier findOID = new ObjectIdentifier(oid); + ObjectIdentifier findOID = ObjectIdentifier.of(oid); String extAlias = OIDMap.getName(findOID); Extension certExt = null; CertificateExtensions exts = (CertificateExtensions)info.get( @@ -1528,7 +1522,8 @@ public synchronized List getExtendedKeyUsage() public static List getExtendedKeyUsage(X509Certificate cert) throws CertificateParsingException { try { - byte[] ext = cert.getExtensionValue(EXTENDED_KEY_USAGE_OID); + byte[] ext = cert.getExtensionValue + (KnownOIDs.extendedKeyUsage.value()); if (ext == null) return null; DerValue val = new DerValue(ext); @@ -1585,7 +1580,7 @@ private static Collection> makeAltNames(GeneralNames names) { for (GeneralName gname : names.names()) { GeneralNameInterface name = gname.getName(); List nameEntry = new ArrayList<>(2); - nameEntry.add(Integer.valueOf(name.getType())); + nameEntry.add(name.getType()); switch (name.getType()) { case GeneralNameInterface.NAME_RFC822: nameEntry.add(((RFC822Name) name).getName()); @@ -1698,7 +1693,8 @@ public synchronized Collection> getSubjectAlternativeNames() public static Collection> getSubjectAlternativeNames(X509Certificate cert) throws CertificateParsingException { try { - byte[] ext = cert.getExtensionValue(SUBJECT_ALT_NAME_OID); + byte[] ext = cert.getExtensionValue + (KnownOIDs.SubjectAlternativeName.value()); if (ext == null) { return null; } @@ -1761,7 +1757,8 @@ public synchronized Collection> getIssuerAlternativeNames() public static Collection> getIssuerAlternativeNames(X509Certificate cert) throws CertificateParsingException { try { - byte[] ext = cert.getExtensionValue(ISSUER_ALT_NAME_OID); + byte[] ext = cert.getExtensionValue + (KnownOIDs.IssuerAlternativeName.value()); if (ext == null) { return null; } @@ -2005,4 +2002,19 @@ private static void byte2hex(byte b, StringBuilder buf) { buf.append(hexChars[high]) .append(hexChars[low]); } + + /** + * Restores the state of this object from the stream. + *

    + * Deserialization of this object is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "X509CertImpls are not directly deserializable"); + } } diff --git a/src/java.base/share/classes/sun/text/bidi/BidiBase.java b/src/java.base/share/classes/sun/text/bidi/BidiBase.java index 5e2fa026e7d..b5ad1d35f37 100644 --- a/src/java.base/share/classes/sun/text/bidi/BidiBase.java +++ b/src/java.base/share/classes/sun/text/bidi/BidiBase.java @@ -4592,7 +4592,7 @@ public static void reorderVisually(byte[] levels, levelStart + " is out of range 0 to " + (objects.length-1)); } - if (0 > count || objects.length < (objectStart+count)) { + if (0 > count || objects.length - count < objectStart) { throw new IllegalArgumentException("Value count " + levelStart + " is out of range 0 to " + (objects.length - objectStart)); diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index ecd95b116b5..c0eed3f8847 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -22,6 +22,9 @@ # the command line, set the key security.overridePropertiesFile # to false in the master security properties file. It is set to true # by default. +# +# If this properties file fails to load, the JDK implementation will throw +# an unspecified error when initializing the java.security.Security class. # In this file, various security properties are set for use by # java.security classes. This is where users can statically register diff --git a/src/java.base/share/legal/public_suffix.md b/src/java.base/share/legal/public_suffix.md index 61d9607177e..d228ac298b9 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/3c213aab32b3c014f171b1673d4ce9b5cd72bf1c/public_suffix_list.dat. +https://raw.githubusercontent.com/publicsuffix/list/88467c960d6cdad2ca1623e892e5e17506bc269f/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/windows/native/libnet/DefaultProxySelector.c b/src/java.base/windows/native/libnet/DefaultProxySelector.c index ca3eac5abfc..2972617569f 100644 --- a/src/java.base/windows/native/libnet/DefaultProxySelector.c +++ b/src/java.base/windows/native/libnet/DefaultProxySelector.c @@ -243,7 +243,7 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxies(JNIEnv *env, if (use_auto_proxy) { WCHAR url[MAX_STR_LEN]; /* Create url for WinHttpGetProxyForUrl */ - _snwprintf(url, sizeof(url) - 1, L"%s://%s", lpProto, lpHost); + swprintf(url, MAX_STR_LEN, L"%s://%s", lpProto, lpHost); /* Get proxy for URL from Windows */ use_auto_proxy = WinHttpGetProxyForUrl(session, &url[0], &auto_proxy_options, &proxy_info); if (use_auto_proxy) { diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java index d6f79d7c025..5d1ce4c2184 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java @@ -45,6 +45,7 @@ import javax.print.attribute.standard.MediaSize; import javax.print.attribute.standard.MediaSizeName; import javax.print.attribute.standard.PageRanges; +import javax.print.attribute.standard.Sides; import javax.print.attribute.Attribute; import sun.java2d.*; @@ -630,7 +631,8 @@ private PageFormat getPageFormat(int pageIndex) { } catch (Exception e) { return null; } - return page; + + return FlipPageFormat.flipPage(page); } private Printable getPrintable(int pageIndex) { @@ -682,6 +684,24 @@ private Rectangle2D getPageFormatArea(PageFormat page) { return pageFormatArea; } + private int getSides() { + return (this.sidesAttr == null) ? -1 : this.sidesAttr.getValue(); + } + + private void setSides(int sides) { + if (attributes == null) { + return; + } + + final Sides[] sidesTable = new Sides[] {Sides.ONE_SIDED, Sides.TWO_SIDED_LONG_EDGE, Sides.TWO_SIDED_SHORT_EDGE}; + + if (sides >= 0 && sides < sidesTable.length) { + Sides s = sidesTable[sides]; + attributes.add(s); + this.sidesAttr = s; + } + } + private boolean cancelCheck() { // This is called from the native side. @@ -730,7 +750,7 @@ private void printToPathGraphics( final PeekGraphics graphics, // Always an a Graphics2D pathGraphics = new CPrinterGraphics(delegate, printerJob); // Just stores delegate into an ivar Rectangle2D pageFormatArea = getPageFormatArea(page); initPrinterGraphics(pathGraphics, pageFormatArea); - painter.print(pathGraphics, page, pageIndex); + painter.print(pathGraphics, FlipPageFormat.getOriginal(page), pageIndex); delegate.dispose(); delegate = null; } catch (PrinterException pe) { throw new java.lang.reflect.UndeclaredThrowableException(pe); } @@ -757,7 +777,7 @@ private Object[] getPageformatPrintablePeekgraphics(final int pageIndex) { Runnable r = new Runnable() { public void run() { synchronized(ret) { try { Pageable pageable = getPageable(); - PageFormat pageFormat = pageable.getPageFormat(pageIndex); + PageFormat pageFormat = getPageFormat(pageIndex); if (pageFormat != null) { Printable printable = pageable.getPrintable(pageIndex); if (printable != null) { @@ -870,4 +890,75 @@ protected MediaPrintableArea getDefaultPrintableArea(PageFormat page, double w, (float) (paper.getImageableHeight() / dpi), MediaPrintableArea.INCH); } + + // MacOS NSPrintInfo class has one to one correspondence + // between a paper size and its orientation. + // NSPrintInfo with paper width less than height + // has portrait orientation. + // NSPrintInfo with paper width greater than height + // has landscape orientation. + // (w < h) <-> portrait + // (w > h) <-> landscape + // + // Java PageFormat class has the following relation with NSPrintInfo: + // 1. PageFormat: + // page size: width < height + // orientation: portrait + // NSPrintInfo: width < height (portrait orientation) + // 2. PageFormat: + // page size: width < height + // orientation: landscape + // NSPrintInfo: width > height (landscape orientation) + // + // FlipPageFormat class establishes correspondence between + // Java PageFormat class which page width is greater than height + // with NSPrintInfo in the following way: + // 3. PageFormat: + // page size: width > height + // orientation: portrait + // FlipPageFormat + // page size: width < height + // orientation: landscape + // NSPrintInfo: width > height (landscape orientation) + // 4. PageFormat: + // page size: width > height + // orientation: landscape + // FlipPageFormat + // page size: width < height + // orientation: portrait + // NSPrintInfo: width < height (portrait orientation) + // + // FlipPageFormat preserves the original PageFormat class + // to pass it to Printable.print(Graphics, PageFormat, int) + // method overridden by a user. + private static class FlipPageFormat extends PageFormat { + + private final PageFormat original; + + private FlipPageFormat(PageFormat original) { + this.original = original; + Paper paper = original.getPaper(); + Paper copyPaper = this.getPaper(); + copyPaper.setSize(paper.getHeight(), paper.getWidth()); + copyPaper.setImageableArea( + paper.getImageableY(), paper.getImageableX(), + paper.getImageableHeight(), paper.getImageableWidth()); + this.setPaper(copyPaper); + this.setOrientation((original.getOrientation() == PageFormat.PORTRAIT) + ? PageFormat.LANDSCAPE + : PageFormat.PORTRAIT); + } + + private static PageFormat getOriginal(PageFormat page) { + return (page instanceof FlipPageFormat) ? ((FlipPageFormat) page).original : page; + } + + private static PageFormat flipPage(PageFormat page) { + if (page == null) { + return null; + } + Paper paper = page.getPaper(); + return (paper.getWidth() > paper.getHeight()) ? new FlipPageFormat(page) : page; + } + } } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m index 896e11cf568..4945420678e 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m @@ -136,15 +136,16 @@ - (BOOL) checkPasteboardWithoutNotification:(id)application { jint nElements = (*env)->GetArrayLength(env, inTypes); NSMutableArray *formatArray = [NSMutableArray arrayWithCapacity:nElements]; jlong *elements = (*env)->GetPrimitiveArrayCritical(env, inTypes, NULL); + if (elements != NULL) { + for (i = 0; i < nElements; i++) { + NSString *pbFormat = formatForIndex(elements[i]); + if (pbFormat) + [formatArray addObject:pbFormat]; + } - for (i = 0; i < nElements; i++) { - NSString *pbFormat = formatForIndex(elements[i]); - if (pbFormat) - [formatArray addObject:pbFormat]; + (*env)->ReleasePrimitiveArrayCritical(env, inTypes, elements, JNI_ABORT); + [[CClipboard sharedClipboard] declareTypes:formatArray withOwner:inJavaClip jniEnv:env]; } - - (*env)->ReleasePrimitiveArrayCritical(env, inTypes, elements, JNI_ABORT); - [[CClipboard sharedClipboard] declareTypes:formatArray withOwner:inJavaClip jniEnv:env]; JNI_COCOA_EXIT(env); } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m index db5c192c6c8..545138de717 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m @@ -37,6 +37,10 @@ #import "GeomUtilities.h" #import "JNIUtilities.h" +#define ONE_SIDED 0 +#define TWO_SIDED_LONG_EDGE 1 +#define TWO_SIDED_SHORT_EDGE 2 + static jclass sjc_Paper = NULL; static jclass sjc_PageFormat = NULL; static jclass sjc_CPrinterJob = NULL; @@ -351,6 +355,24 @@ static void javaPageFormatToNSPrintInfo(JNIEnv* env, jobject srcPrintJob, jobjec [dstPrintInfo setPrinter:printer]; } +static jint duplexModeToSides(PMDuplexMode duplexMode) { + switch(duplexMode) { + case kPMDuplexNone: return ONE_SIDED; + case kPMDuplexTumble: return TWO_SIDED_SHORT_EDGE; + case kPMDuplexNoTumble: return TWO_SIDED_LONG_EDGE; + default: return -1; + } +} + +static PMDuplexMode sidesToDuplexMode(jint sides) { + switch(sides) { + case ONE_SIDED: return kPMDuplexNone; + case TWO_SIDED_SHORT_EDGE: return kPMDuplexTumble; + case TWO_SIDED_LONG_EDGE: return kPMDuplexNoTumble; + default: return kPMDuplexNone; + } +} + static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject dstPrinterJob, jobject dstPageable) { GET_CPRINTERJOB_CLASS(); @@ -360,6 +382,7 @@ static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject d DECLARE_METHOD(jm_setPageRangeAttribute, sjc_CPrinterJob, "setPageRangeAttribute", "(IIZ)V"); DECLARE_METHOD(jm_setPrintToFile, sjc_CPrinterJob, "setPrintToFile", "(Z)V"); DECLARE_METHOD(jm_setDestinationFile, sjc_CPrinterJob, "setDestinationFile", "(Ljava/lang/String;)V"); + DECLARE_METHOD(jm_setSides, sjc_CPrinterJob, "setSides", "(I)V"); // get the selected printer's name, and set the appropriate PrintService on the Java side NSString *name = [[src printer] name]; @@ -420,6 +443,12 @@ static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject d jFirstPage, jLastPage, isRangeSet); // AWT_THREADING Safe (known object) CHECK_EXCEPTION(); + PMDuplexMode duplexSetting; + if (PMGetDuplex(src.PMPrintSettings, &duplexSetting) == noErr) { + jint sides = duplexModeToSides(duplexSetting); + (*env)->CallVoidMethod(env, dstPrinterJob, jm_setSides, sides); // AWT_THREADING Safe (known object) + CHECK_EXCEPTION(); + } } } @@ -438,6 +467,8 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj DECLARE_METHOD(jm_getNumberOfPages, jc_Pageable, "getNumberOfPages", "()I"); DECLARE_METHOD(jm_getPageFormat, sjc_CPrinterJob, "getPageFormatFromAttributes", "()Ljava/awt/print/PageFormat;"); DECLARE_METHOD(jm_getDestinationFile, sjc_CPrinterJob, "getDestinationFile", "()Ljava/lang/String;"); + DECLARE_METHOD(jm_getSides, sjc_CPrinterJob, "getSides", "()I"); + NSMutableDictionary* printingDictionary = [dst dictionary]; @@ -496,6 +527,17 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj } else { [dst setJobDisposition:NSPrintSpoolJob]; } + + jint sides = (*env)->CallIntMethod(env, srcPrinterJob, jm_getSides); + CHECK_EXCEPTION(); + + if (sides >= 0) { + PMDuplexMode duplexMode = sidesToDuplexMode(sides); + PMPrintSettings printSettings = dst.PMPrintSettings; + if (PMSetDuplex(printSettings, duplexMode) == noErr) { + [dst updateFromPMPrintSettings]; + } + } } /* diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/CCharToGlyphMapper.m b/src/java.desktop/macosx/native/libawt_lwawt/font/CCharToGlyphMapper.m index 393d33bdbe6..e0cefbe01dc 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/CCharToGlyphMapper.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/CCharToGlyphMapper.m @@ -58,12 +58,14 @@ { jint *glyphCodeInts = (*env)->GetPrimitiveArrayCritical(env, glyphs, 0); - CTS_GetGlyphsAsIntsForCharacters(awtFont, unicodes, - cgGlyphs, glyphCodeInts, count); + if (glyphCodeInts != NULL) { + CTS_GetGlyphsAsIntsForCharacters(awtFont, unicodes, + cgGlyphs, glyphCodeInts, count); - // Do not use JNI_COMMIT, as that will not free the buffer copy - // when +ProtectJavaHeap is on. - (*env)->ReleasePrimitiveArrayCritical(env, glyphs, glyphCodeInts, 0); + // Do not use JNI_COMMIT, as that will not free the buffer copy + // when +ProtectJavaHeap is on. + (*env)->ReleasePrimitiveArrayCritical(env, glyphs, glyphCodeInts, 0); + } } static inline void diff --git a/src/java.desktop/macosx/native/libosxui/JRSUIController.m b/src/java.desktop/macosx/native/libosxui/JRSUIController.m index b484319b06e..f7bb8e60e3f 100644 --- a/src/java.desktop/macosx/native/libosxui/JRSUIController.m +++ b/src/java.desktop/macosx/native/libosxui/JRSUIController.m @@ -277,11 +277,13 @@ static inline jint doPaintCGContext(CGContextRef cgRef, jlong controlPtr, jlong CGRect partBounds = JRSUIControlGetScrollBarPartBounds(control, frame, part); jdouble *rect = (*env)->GetPrimitiveArrayCritical(env, rectArray, NULL); - rect[0] = partBounds.origin.x; - rect[1] = partBounds.origin.y; - rect[2] = partBounds.size.width; - rect[3] = partBounds.size.height; - (*env)->ReleasePrimitiveArrayCritical(env, rectArray, rect, 0); + if (rect != NULL) { + rect[0] = partBounds.origin.x; + rect[1] = partBounds.origin.y; + rect[2] = partBounds.size.width; + rect[3] = partBounds.size.height; + (*env)->ReleasePrimitiveArrayCritical(env, rectArray, rect, 0); + } } /* diff --git a/src/java.desktop/share/classes/com/sun/media/sound/DirectAudioDevice.java b/src/java.desktop/share/classes/com/sun/media/sound/DirectAudioDevice.java index 74e30751e29..f616455d515 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/DirectAudioDevice.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/DirectAudioDevice.java @@ -1377,8 +1377,9 @@ public void run() { } } while (doIO && thread == curThread) { - if (newFramePosition >= 0) { - clipBytePosition = newFramePosition * frameSize; + int npf = newFramePosition; // copy into local variable + if (npf >= 0) { + clipBytePosition = npf * frameSize; newFramePosition = -1; } int endFrame = getFrameLength() - 1; diff --git a/src/java.desktop/share/classes/sun/awt/FontConfiguration.java b/src/java.desktop/share/classes/sun/awt/FontConfiguration.java index 00169de3bbf..ec12b812b7e 100644 --- a/src/java.desktop/share/classes/sun/awt/FontConfiguration.java +++ b/src/java.desktop/share/classes/sun/awt/FontConfiguration.java @@ -1252,15 +1252,24 @@ public String getFileNameFromPlatformName(String platformName) { return filenamesMap.get(platformName); } + private static final String fontconfigErrorMessage = + "Fontconfig head is null, check your fonts or fonts configuration"; + /** * Returns a configuration specific path to be appended to the font * search path. */ public String getExtraFontPath() { + if (head == null) { + throw new RuntimeException(fontconfigErrorMessage); + } return getString(head[INDEX_appendedfontpath]); } public String getVersion() { + if (head == null) { + throw new RuntimeException(fontconfigErrorMessage); + } return getString(head[INDEX_version]); } diff --git a/src/java.desktop/share/classes/sun/awt/image/ImageRepresentation.java b/src/java.desktop/share/classes/sun/awt/image/ImageRepresentation.java index 3634fac5e3c..68bdc87dff5 100644 --- a/src/java.desktop/share/classes/sun/awt/image/ImageRepresentation.java +++ b/src/java.desktop/share/classes/sun/awt/image/ImageRepresentation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,24 +27,20 @@ import java.awt.Color; import java.awt.Graphics; -import java.awt.Transparency; -import java.awt.AWTException; +import java.awt.Graphics2D; import java.awt.Rectangle; +import java.awt.Transparency; +import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferInt; import java.awt.image.DirectColorModel; -import java.awt.image.IndexColorModel; import java.awt.image.ImageConsumer; import java.awt.image.ImageObserver; -import sun.awt.image.ByteComponentRaster; -import sun.awt.image.IntegerComponentRaster; +import java.awt.image.IndexColorModel; import java.awt.image.Raster; import java.awt.image.WritableRaster; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferInt; -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; -import sun.awt.image.ImageWatched; import java.util.Hashtable; public class ImageRepresentation extends ImageWatched implements ImageConsumer @@ -114,8 +110,8 @@ public synchronized void reconstruct(int flags) { try { startProduction(); missinginfo = flags & ~availinfo; - while ((availinfo & ImageObserver.ERROR) == 0 && - missinginfo != 0) + while ((availinfo & (ImageObserver.ERROR | ImageObserver.FRAMEBITS)) == 0 + && missinginfo != 0) { try { wait(); diff --git a/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java b/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java index 30e4c11f8ec..2e6d7e34131 100644 --- a/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java +++ b/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java @@ -1077,6 +1077,8 @@ public PrintService[] run() { return false; } + this.attributes = attributes; + if (!service.equals(newService)) { try { setPrintService(newService); diff --git a/src/java.desktop/share/legal/freetype.md b/src/java.desktop/share/legal/freetype.md index e74da8869d3..d602abbe5ae 100644 --- a/src/java.desktop/share/legal/freetype.md +++ b/src/java.desktop/share/legal/freetype.md @@ -1,4 +1,4 @@ -## The FreeType Project: Freetype v2.12.1 +## The FreeType Project: Freetype v2.13.0 ### FreeType Notice @@ -21,27 +21,26 @@ which fits your needs best. ### FreeType License ``` -Copyright (C) 1996-2022 by David Turner, Robert Wilhelm, and Werner Lemberg. -Copyright (C) 2007-2022 by Dereg Clegg and Michael Toftdal. -Copyright (C) 1996-2022 by Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. -Copyright (C) 2004-2022 by Masatake YAMATO and Redhat K.K. -Copyright (C) 2007-2022 by Derek Clegg and Michael Toftdal. -Copyright (C) 2007-2022 by David Turner. -Copyright (C) 2022 by David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. -Copyright (C) 2007-2022 by Rahul Bhalerao , . -Copyright (C) 2008-2022 by David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. -Copyright (C) 2019-2022 by Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. -Copyright (C) 2009-2022 by Oran Agra and Mickey Gabel. -Copyright (C) 2004-2022 by David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. -Copyright (C) 2004-2022 by Masatake YAMATO, Red Hat K.K., -Copyright (C) 2003-2022 by Masatake YAMATO, Redhat K.K., -Copyright (C) 2013-2022 by Google, Inc. -Copyright (C) 2018-2022 by David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. -Copyright (C) 2005-2022 by David Turner, Robert Wilhelm, and Werner Lemberg. -Copyright 2013 by Google, Inc. - - - The FreeType Project LICENSE +Copyright (C) 1996-2023 by David Turner, Robert Wilhelm, and Werner Lemberg. +Copyright (C) 2007-2023 by Dereg Clegg and Michael Toftdal. +Copyright (C) 1996-2023 by Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. +Copyright (C) 2022-2023 by David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and +Copyright (C) 2004-2023 by Masatake YAMATO and Redhat K.K. +Copyright (C) 2007-2023 by Derek Clegg and Michael Toftdal. +Copyright (C) 2003-2023 by Masatake YAMATO, Red Hat K.K., +Copyright (C) 1996-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. +Copyright (C) 2007-2023 by David Turner. +Copyright (C) 2022-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. +Copyright (C) 2007-2023 by Rahul Bhalerao , . +Copyright (C) 2008-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. +Copyright (C) 2013-2023 by Google, Inc. +Copyright (C) 2019-2023 by Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. +Copyright (C) 2009-2023 by Oran Agra and Mickey Gabel. +Copyright (C) 2018-2023 by David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. +Copyright (C) 2004-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. + + + The FreeType Project LICENSE ---------------------------- 2006-Jan-27 @@ -206,7 +205,7 @@ Legal Terms Our home page can be found at - http://www.freetype.org + https://www.freetype.org ``` diff --git a/src/java.desktop/share/legal/harfbuzz.md b/src/java.desktop/share/legal/harfbuzz.md index 3426352d51f..e2ed76aa7c6 100644 --- a/src/java.desktop/share/legal/harfbuzz.md +++ b/src/java.desktop/share/legal/harfbuzz.md @@ -1,8 +1,8 @@ -## Harfbuzz v7.0.1 +## Harfbuzz v7.2.0 ### Harfbuzz License -https://github.com/harfbuzz/harfbuzz/blob/7.0.1/COPYING +https://github.com/harfbuzz/harfbuzz/blob/7.2.0/COPYING

     
    @@ -10,7 +10,7 @@ HarfBuzz is licensed under the so-called "Old MIT" license.  Details follow.
     For parts of HarfBuzz that are licensed under different licenses see individual
     files names COPYING in subdirectories where applicable.
     
    -Copyright © 2010-2022  Google, Inc.
    +Copyright © 2010-2023  Google, Inc.
     Copyright © 2018-2020  Ebrahim Byagowi
     Copyright © 2004-2013  Red Hat, Inc.
     Copyright © 2019  Facebook, Inc.
    diff --git a/src/java.desktop/share/legal/libpng.md b/src/java.desktop/share/legal/libpng.md
    index 4f69da5383a..f11cfe580ce 100644
    --- a/src/java.desktop/share/legal/libpng.md
    +++ b/src/java.desktop/share/legal/libpng.md
    @@ -1,4 +1,4 @@
    -## libpng v1.6.38
    +## libpng v1.6.39
     
     ### libpng License
     
    @@ -188,9 +188,10 @@ Authors, for copyright and licensing purposes.
      * Arm Holdings
        - Richard Townsend
      * Google Inc.
    +   - Dan Field
    +   - Leon Scroggins III
        - Matt Sarett
        - Mike Klein
    -   - Dan Field
        - Sami Boukortt
     
     The build projects, the build scripts, the test scripts, and other
    diff --git a/src/java.desktop/share/native/libawt/java2d/loops/FourByteAbgrPre.c b/src/java.desktop/share/native/libawt/java2d/loops/FourByteAbgrPre.c
    index c95d6a985a1..af109a7d880 100644
    --- a/src/java.desktop/share/native/libawt/java2d/loops/FourByteAbgrPre.c
    +++ b/src/java.desktop/share/native/libawt/java2d/loops/FourByteAbgrPre.c
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2000, 2005, 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
    @@ -69,6 +69,8 @@ DECLARE_SRCOVER_MASKBLIT(IntArgb, FourByteAbgrPre);
     DECLARE_ALPHA_MASKBLIT(IntArgb, FourByteAbgrPre);
     DECLARE_SRCOVER_MASKBLIT(IntArgbPre, FourByteAbgrPre);
     DECLARE_ALPHA_MASKBLIT(IntArgbPre, FourByteAbgrPre);
    +DECLARE_SRCOVER_MASKBLIT(FourByteAbgrPre, IntArgbPre);
    +DECLARE_ALPHA_MASKBLIT(FourByteAbgrPre, IntArgbPre);
     DECLARE_ALPHA_MASKBLIT(IntRgb, FourByteAbgrPre);
     DECLARE_SOLID_DRAWGLYPHLISTAA(FourByteAbgrPre);
     DECLARE_SOLID_DRAWGLYPHLISTLCD(FourByteAbgrPre);
    @@ -103,6 +105,8 @@ NativePrimitive FourByteAbgrPrePrimitives[] = {
         REGISTER_ALPHA_MASKBLIT(IntArgb, FourByteAbgrPre),
         REGISTER_SRCOVER_MASKBLIT(IntArgbPre, FourByteAbgrPre),
         REGISTER_ALPHA_MASKBLIT(IntArgbPre, FourByteAbgrPre),
    +    REGISTER_SRCOVER_MASKBLIT(FourByteAbgrPre, IntArgbPre),
    +    REGISTER_ALPHA_MASKBLIT(FourByteAbgrPre, IntArgbPre),
         REGISTER_ALPHA_MASKBLIT(IntRgb, FourByteAbgrPre),
         REGISTER_SOLID_DRAWGLYPHLISTAA(FourByteAbgrPre),
         REGISTER_SOLID_DRAWGLYPHLISTLCD(FourByteAbgrPre),
    @@ -177,6 +181,10 @@ DEFINE_SRCOVER_MASKBLIT(IntArgbPre, FourByteAbgrPre, 4ByteArgb)
     
     DEFINE_ALPHA_MASKBLIT(IntArgbPre, FourByteAbgrPre, 4ByteArgb)
     
    +DEFINE_SRCOVER_MASKBLIT(FourByteAbgrPre, IntArgbPre, 4ByteArgb)
    +
    +DEFINE_ALPHA_MASKBLIT(FourByteAbgrPre, IntArgbPre, 4ByteArgb)
    +
     DEFINE_ALPHA_MASKBLIT(IntRgb, FourByteAbgrPre, 4ByteArgb)
     
     DEFINE_SOLID_DRAWGLYPHLISTAA(FourByteAbgrPre, 4ByteArgb)
    diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c
    index 772f1f96d7b..20ccde96693 100644
    --- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c
    +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -466,7 +466,8 @@ Java_sun_font_FreetypeFontScaler_createScalerContextNative(
         if ((aa != TEXT_AA_ON) && (fm != TEXT_FM_ON) &&
             !context->doBold && !context->doItalize &&
             (context->transform.yx == 0) && (context->transform.xy == 0) &&
    -        (context->transform.xx > 0) && (context->transform.yy > 0))
    +        (context->transform.xx > 0) && (context->transform.yy > 0) &&
    +        (context->transform.xx == context->transform.yy))
         {
             context->useSbits = 1;
         }
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h
    index c696e900a67..a85151699d0 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h
    @@ -4,7 +4,7 @@
      *
      *   ANSI-specific configuration file (specification only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h
    index a8c6833df77..e607bce15c5 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h
    @@ -4,7 +4,7 @@
      *
      *   Build macros of the FreeType 2 library.
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
    index 2b6b310aaf3..c13a3ef4288 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
    @@ -4,7 +4,7 @@
      *
      *   User-selectable configuration macros (specification only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -461,9 +461,9 @@ FT_BEGIN_HEADER
        *   while compiling in 'release' mode):
        *
        *   ```
    -   *     _af_debug_disable_horz_hints
    -   *     _af_debug_disable_vert_hints
    -   *     _af_debug_disable_blue_hints
    +   *     af_debug_disable_horz_hints_
    +   *     af_debug_disable_vert_hints_
    +   *     af_debug_disable_blue_hints_
        *   ```
        *
        *   Additionally, the following functions provide dumps of various
    @@ -480,7 +480,7 @@ FT_BEGIN_HEADER
        *   As an argument, they use another global variable:
        *
        *   ```
    -   *     _af_debug_hints
    +   *     af_debug_hints_
        *   ```
        *
        *   Please have a look at the `ftgrid` demo program to see how those
    @@ -584,12 +584,12 @@ FT_BEGIN_HEADER
       /**************************************************************************
        *
        * Define `TT_CONFIG_OPTION_POSTSCRIPT_NAMES` if you want to be able to
    -   * load and enumerate the glyph Postscript names in a TrueType or OpenType
    +   * load and enumerate Postscript names of glyphs in a TrueType or OpenType
        * file.
        *
    -   * Note that when you do not compile the 'psnames' module by undefining the
    -   * above `FT_CONFIG_OPTION_POSTSCRIPT_NAMES`, the 'sfnt' module will
    -   * contain additional code used to read the PS Names table from a font.
    +   * Note that if you do not compile the 'psnames' module by undefining the
    +   * above `FT_CONFIG_OPTION_POSTSCRIPT_NAMES` macro, the 'sfnt' module will
    +   * contain additional code to read the PostScript name table from a font.
        *
        * (By default, the module uses 'psnames' to extract glyph names.)
        */
    @@ -739,6 +739,24 @@ FT_BEGIN_HEADER
     #define TT_CONFIG_OPTION_GX_VAR_SUPPORT
     
     
    +  /**************************************************************************
    +   *
    +   * Define `TT_CONFIG_OPTION_NO_BORING_EXPANSION` if you want to exclude
    +   * support for 'boring' OpenType specification expansions.
    +   *
    +   *   https://github.com/harfbuzz/boring-expansion-spec
    +   *
    +   * Right now, the following features are covered:
    +   *
    +   *   - 'avar' version 2.0
    +   *
    +   * Most likely, this is a temporary configuration option to be removed in
    +   * the near future, since it is assumed that eventually those features are
    +   * added to the OpenType standard.
    +   */
    +/* #define TT_CONFIG_OPTION_NO_BORING_EXPANSION */
    +
    +
       /**************************************************************************
        *
        * Define `TT_CONFIG_OPTION_BDF` if you want to include support for an
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h
    index 7958c2a5f75..3c9d2ae59a4 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h
    @@ -5,7 +5,7 @@
      *   ANSI-specific library and header configuration file (specification
      *   only).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h
    index d9d2638d1e6..7258b508541 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType integer types definitions.
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h
    index e42c9fe410d..b77b96d5db8 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h
    @@ -4,7 +4,7 @@
      *
      *   Mac/OS X support configuration header.
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h
    index 0074134f1d1..23d0fa6a329 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h
    @@ -4,7 +4,7 @@
      *
      *   Define a set of compiler macros used in public FreeType headers.
      *
    - * Copyright (C) 2020-2022 by
    + * Copyright (C) 2020-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h
    index aa1a4fe3891..efff74fe399 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType high-level API and common types (specification only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -215,7 +215,6 @@ FT_BEGIN_HEADER
        *   FT_Get_Char_Index
        *   FT_Get_First_Char
        *   FT_Get_Next_Char
    -   *   FT_Get_Name_Index
        *   FT_Load_Char
        *
        *   FT_OPEN_MEMORY
    @@ -254,14 +253,15 @@ FT_BEGIN_HEADER
        *   FT_Get_Kerning
        *   FT_Kerning_Mode
        *   FT_Get_Track_Kerning
    -   *   FT_Get_Glyph_Name
    -   *   FT_Get_Postscript_Name
        *
        *   FT_CharMapRec
        *   FT_Select_Charmap
        *   FT_Set_Charmap
        *   FT_Get_Charmap_Index
        *
    +   *   FT_Get_Name_Index
    +   *   FT_Get_Glyph_Name
    +   *   FT_Get_Postscript_Name
        *   FT_Get_FSType_Flags
        *   FT_Get_SubGlyph_Info
        *
    @@ -646,7 +646,7 @@ FT_BEGIN_HEADER
        *
        * @note:
        *   Despite the name, this enumeration lists specific character
    -   *   repertories (i.e., charsets), and not text encoding methods (e.g.,
    +   *   repertoires (i.e., charsets), and not text encoding methods (e.g.,
        *   UTF-8, UTF-16, etc.).
        *
        *   Other encodings might be defined in the future.
    @@ -779,7 +779,7 @@ FT_BEGIN_HEADER
        *   `encoding_id`.  If, for example, `encoding_id` is `TT_MAC_ID_ROMAN`
        *   and the language ID (minus~1) is `TT_MAC_LANGID_GREEK`, it is the
        *   Greek encoding, not Roman.  `TT_MAC_ID_ARABIC` with
    -   *   `TT_MAC_LANGID_FARSI` means the Farsi variant the Arabic encoding.
    +   *   `TT_MAC_LANGID_FARSI` means the Farsi variant of the Arabic encoding.
        */
       typedef enum  FT_Encoding_
       {
    @@ -1167,9 +1167,9 @@ FT_BEGIN_HEADER
        *   FT_FACE_FLAG_KERNING ::
        *     The face contains kerning information.  If set, the kerning distance
        *     can be retrieved using the function @FT_Get_Kerning.  Otherwise the
    -   *     function always return the vector (0,0).  Note that FreeType doesn't
    -   *     handle kerning data from the SFNT 'GPOS' table (as present in many
    -   *     OpenType fonts).
    +   *     function always returns the vector (0,0).  Note that FreeType
    +   *     doesn't handle kerning data from the SFNT 'GPOS' table (as present
    +   *     in many OpenType fonts).
        *
        *   FT_FACE_FLAG_FAST_GLYPHS ::
        *     THIS FLAG IS DEPRECATED.  DO NOT USE OR TEST IT.
    @@ -1892,13 +1892,13 @@ FT_BEGIN_HEADER
        *     The advance width of the unhinted glyph.  Its value is expressed in
        *     16.16 fractional pixels, unless @FT_LOAD_LINEAR_DESIGN is set when
        *     loading the glyph.  This field can be important to perform correct
    -   *     WYSIWYG layout.  Only relevant for outline glyphs.
    +   *     WYSIWYG layout.  Only relevant for scalable glyphs.
        *
        *   linearVertAdvance ::
        *     The advance height of the unhinted glyph.  Its value is expressed in
        *     16.16 fractional pixels, unless @FT_LOAD_LINEAR_DESIGN is set when
        *     loading the glyph.  This field can be important to perform correct
    -   *     WYSIWYG layout.  Only relevant for outline glyphs.
    +   *     WYSIWYG layout.  Only relevant for scalable glyphs.
        *
        *   advance ::
        *     This shorthand is, depending on @FT_LOAD_IGNORE_TRANSFORM, the
    @@ -2593,8 +2593,8 @@ FT_BEGIN_HEADER
        *   stream attachments.
        */
       FT_EXPORT( FT_Error )
    -  FT_Attach_Stream( FT_Face        face,
    -                    FT_Open_Args*  parameters );
    +  FT_Attach_Stream( FT_Face              face,
    +                    const FT_Open_Args*  parameters );
     
     
       /**************************************************************************
    @@ -3077,7 +3077,7 @@ FT_BEGIN_HEADER
        *
        *   FT_LOAD_NO_HINTING ::
        *     Disable hinting.  This generally generates 'blurrier' bitmap glyphs
    -   *     when the glyph are rendered in any of the anti-aliased modes.  See
    +   *     when the glyphs are rendered in any of the anti-aliased modes.  See
        *     also the note below.
        *
        *     This flag is implied by @FT_LOAD_NO_SCALE.
    @@ -3434,7 +3434,7 @@ FT_BEGIN_HEADER
        *     are not interested in the value.
        *
        *   delta ::
    -   *     A pointer a translation vector.  Set this to NULL if you are not
    +   *     A pointer to a translation vector.  Set this to NULL if you are not
        *     interested in the value.
        *
        * @since:
    @@ -3559,9 +3559,10 @@ FT_BEGIN_HEADER
        *
        *   2. The `sdf` rasterizer has limited support for handling intersecting
        *      contours and *cannot* handle self-intersecting contours whatsoever.
    -   *      Self-intersection happens when a single connected contour intersect
    -   *      itself at some point; having these in your font definitely pose a
    -   *      problem to the rasterizer and cause artifacts, too.
    +   *      Self-intersection happens when a single connected contour
    +   *      intersects itself at some point; having these in your font
    +   *      definitely poses a problem to the rasterizer and cause artifacts,
    +   *      too.
        *
        *   3. Generating SDF for really small glyphs may result in undesirable
        *      output; the pixel grid (which stores distance information) becomes
    @@ -3840,89 +3841,6 @@ FT_BEGIN_HEADER
                             FT_Fixed*  akerning );
     
     
    -  /**************************************************************************
    -   *
    -   * @function:
    -   *   FT_Get_Glyph_Name
    -   *
    -   * @description:
    -   *   Retrieve the ASCII name of a given glyph in a face.  This only works
    -   *   for those faces where @FT_HAS_GLYPH_NAMES(face) returns~1.
    -   *
    -   * @input:
    -   *   face ::
    -   *     A handle to a source face object.
    -   *
    -   *   glyph_index ::
    -   *     The glyph index.
    -   *
    -   *   buffer_max ::
    -   *     The maximum number of bytes available in the buffer.
    -   *
    -   * @output:
    -   *   buffer ::
    -   *     A pointer to a target buffer where the name is copied to.
    -   *
    -   * @return:
    -   *   FreeType error code.  0~means success.
    -   *
    -   * @note:
    -   *   An error is returned if the face doesn't provide glyph names or if the
    -   *   glyph index is invalid.  In all cases of failure, the first byte of
    -   *   `buffer` is set to~0 to indicate an empty name.
    -   *
    -   *   The glyph name is truncated to fit within the buffer if it is too
    -   *   long.  The returned string is always zero-terminated.
    -   *
    -   *   Be aware that FreeType reorders glyph indices internally so that glyph
    -   *   index~0 always corresponds to the 'missing glyph' (called '.notdef').
    -   *
    -   *   This function always returns an error if the config macro
    -   *   `FT_CONFIG_OPTION_NO_GLYPH_NAMES` is not defined in `ftoption.h`.
    -   */
    -  FT_EXPORT( FT_Error )
    -  FT_Get_Glyph_Name( FT_Face     face,
    -                     FT_UInt     glyph_index,
    -                     FT_Pointer  buffer,
    -                     FT_UInt     buffer_max );
    -
    -
    -  /**************************************************************************
    -   *
    -   * @function:
    -   *   FT_Get_Postscript_Name
    -   *
    -   * @description:
    -   *   Retrieve the ASCII PostScript name of a given face, if available.
    -   *   This only works with PostScript, TrueType, and OpenType fonts.
    -   *
    -   * @input:
    -   *   face ::
    -   *     A handle to the source face object.
    -   *
    -   * @return:
    -   *   A pointer to the face's PostScript name.  `NULL` if unavailable.
    -   *
    -   * @note:
    -   *   The returned pointer is owned by the face and is destroyed with it.
    -   *
    -   *   For variation fonts, this string changes if you select a different
    -   *   instance, and you have to call `FT_Get_PostScript_Name` again to
    -   *   retrieve it.  FreeType follows Adobe TechNote #5902, 'Generating
    -   *   PostScript Names for Fonts Using OpenType Font Variations'.
    -   *
    -   *     https://download.macromedia.com/pub/developer/opentype/tech-notes/5902.AdobePSNameGeneration.html
    -   *
    -   *   [Since 2.9] Special PostScript names for named instances are only
    -   *   returned if the named instance is set with @FT_Set_Named_Instance (and
    -   *   the font has corresponding entries in its 'fvar' table).  If
    -   *   @FT_IS_VARIATION returns true, the algorithmically derived PostScript
    -   *   name is provided, not looking up special entries for named instances.
    -   */
    -  FT_EXPORT( const char* )
    -  FT_Get_Postscript_Name( FT_Face  face );
    -
    -
       /**************************************************************************
        *
        * @function:
    @@ -4243,7 +4161,8 @@ FT_BEGIN_HEADER
        *   FT_Get_Name_Index
        *
        * @description:
    -   *   Return the glyph index of a given glyph name.
    +   *   Return the glyph index of a given glyph name.  This only works
    +   *   for those faces where @FT_HAS_GLYPH_NAMES returns true.
        *
        * @input:
        *   face ::
    @@ -4254,12 +4173,107 @@ FT_BEGIN_HEADER
        *
        * @return:
        *   The glyph index.  0~means 'undefined character code'.
    +   *
    +   * @note:
    +   *   Acceptable glyph names might come from the [Adobe Glyph
    +   *   List](https://github.com/adobe-type-tools/agl-aglfn).  See
    +   *   @FT_Get_Glyph_Name for the inverse functionality.
    +   *
    +   *   This function has limited capabilities if the config macro
    +   *   `FT_CONFIG_OPTION_POSTSCRIPT_NAMES` is not defined in `ftoption.h`:
    +   *   It then works only for fonts that actually embed glyph names (which
    +   *   many recent OpenType fonts do not).
        */
       FT_EXPORT( FT_UInt )
       FT_Get_Name_Index( FT_Face           face,
                          const FT_String*  glyph_name );
     
     
    +  /**************************************************************************
    +   *
    +   * @function:
    +   *   FT_Get_Glyph_Name
    +   *
    +   * @description:
    +   *   Retrieve the ASCII name of a given glyph in a face.  This only works
    +   *   for those faces where @FT_HAS_GLYPH_NAMES returns true.
    +   *
    +   * @input:
    +   *   face ::
    +   *     A handle to a source face object.
    +   *
    +   *   glyph_index ::
    +   *     The glyph index.
    +   *
    +   *   buffer_max ::
    +   *     The maximum number of bytes available in the buffer.
    +   *
    +   * @output:
    +   *   buffer ::
    +   *     A pointer to a target buffer where the name is copied to.
    +   *
    +   * @return:
    +   *   FreeType error code.  0~means success.
    +   *
    +   * @note:
    +   *   An error is returned if the face doesn't provide glyph names or if the
    +   *   glyph index is invalid.  In all cases of failure, the first byte of
    +   *   `buffer` is set to~0 to indicate an empty name.
    +   *
    +   *   The glyph name is truncated to fit within the buffer if it is too
    +   *   long.  The returned string is always zero-terminated.
    +   *
    +   *   Be aware that FreeType reorders glyph indices internally so that glyph
    +   *   index~0 always corresponds to the 'missing glyph' (called '.notdef').
    +   *
    +   *   This function has limited capabilities if the config macro
    +   *   `FT_CONFIG_OPTION_POSTSCRIPT_NAMES` is not defined in `ftoption.h`:
    +   *   It then works only for fonts that actually embed glyph names (which
    +   *   many recent OpenType fonts do not).
    +   */
    +  FT_EXPORT( FT_Error )
    +  FT_Get_Glyph_Name( FT_Face     face,
    +                     FT_UInt     glyph_index,
    +                     FT_Pointer  buffer,
    +                     FT_UInt     buffer_max );
    +
    +
    +  /**************************************************************************
    +   *
    +   * @function:
    +   *   FT_Get_Postscript_Name
    +   *
    +   * @description:
    +   *   Retrieve the ASCII PostScript name of a given face, if available.
    +   *   This only works with PostScript, TrueType, and OpenType fonts.
    +   *
    +   * @input:
    +   *   face ::
    +   *     A handle to the source face object.
    +   *
    +   * @return:
    +   *   A pointer to the face's PostScript name.  `NULL` if unavailable.
    +   *
    +   * @note:
    +   *   The returned pointer is owned by the face and is destroyed with it.
    +   *
    +   *   For variation fonts, this string changes if you select a different
    +   *   instance, and you have to call `FT_Get_PostScript_Name` again to
    +   *   retrieve it.  FreeType follows Adobe TechNote #5902, 'Generating
    +   *   PostScript Names for Fonts Using OpenType Font Variations'.
    +   *
    +   *     https://download.macromedia.com/pub/developer/opentype/tech-notes/5902.AdobePSNameGeneration.html
    +   *
    +   *   [Since 2.9] Special PostScript names for named instances are only
    +   *   returned if the named instance is set with @FT_Set_Named_Instance (and
    +   *   the font has corresponding entries in its 'fvar' table).  If
    +   *   @FT_IS_VARIATION returns true, the algorithmically derived PostScript
    +   *   name is provided, not looking up special entries for named instances.
    +   */
    +  FT_EXPORT( const char* )
    +  FT_Get_Postscript_Name( FT_Face  face );
    +
    +
       /**************************************************************************
        *
        * @enum:
    @@ -4346,13 +4360,6 @@ FT_BEGIN_HEADER
                             FT_Matrix    *p_transform );
     
     
    -  /**************************************************************************
    -   *
    -   * @section:
    -   *   base_interface
    -   *
    -   */
    -
       /**************************************************************************
        *
        * @enum:
    @@ -4688,7 +4695,8 @@ FT_BEGIN_HEADER
        *
        * @description:
        *   This section contains various functions used to perform computations
    -   *   on 16.16 fixed-float numbers or 2d vectors.
    +   *   on 16.16 fixed-point numbers or 2D vectors.  FreeType does not use
    +   *   floating-point data types.
        *
        *   **Attention**: Most arithmetic functions take `FT_Long` as arguments.
        *   For historical reasons, FreeType was designed under the assumption
    @@ -4941,8 +4949,8 @@ FT_BEGIN_HEADER
        *
        */
     #define FREETYPE_MAJOR  2
    -#define FREETYPE_MINOR  12
    -#define FREETYPE_PATCH  1
    +#define FREETYPE_MINOR  13
    +#define FREETYPE_PATCH  0
     
     
       /**************************************************************************
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h
    index 8ce4846668c..4560ded6dcb 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h
    @@ -4,7 +4,7 @@
      *
      *   Quick computation of advance widths (specification only).
      *
    - * Copyright (C) 2008-2022 by
    + * Copyright (C) 2008-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h
    index 768478f399b..fc21740fc2b 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType exact bbox computation (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h
    index 04d6094f753..e8ce6431285 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType API for accessing BDF-specific strings (specification).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h
    index c3462dadc51..eb6b4b1eebe 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType utility functions for bitmaps (specification).
      *
    - * Copyright (C) 2004-2022 by
    + * Copyright (C) 2004-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h
    index d80108387ac..ef229390224 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType API for accessing CID font information (specification).
      *
    - * Copyright (C) 2007-2022 by
    + * Copyright (C) 2007-2023 by
      * Dereg Clegg and Michael Toftdal.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h
    index 3edaee4ec19..eae200fdf14 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType's glyph color management (specification).
      *
    - * Copyright (C) 2018-2022 by
    + * Copyright (C) 2018-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -456,6 +456,9 @@ FT_BEGIN_HEADER
        *                                           &iterator ) );
        *     }
        *   ```
    +   *
    +   * @since:
    +   *   2.10
        */
       FT_EXPORT( FT_Bool )
       FT_Get_Color_Glyph_Layer( FT_Face            face,
    @@ -475,7 +478,7 @@ FT_BEGIN_HEADER
        *   extensions to the 'COLR' table, see
        *   'https://github.com/googlefonts/colr-gradients-spec'.
        *
    -   *   The enumeration values losely correspond with the format numbers of
    +   *   The enumeration values loosely correspond with the format numbers of
        *   the specification: FreeType always returns a fully specified 'Paint'
        *   structure for the 'Transform', 'Translate', 'Scale', 'Rotate', and
        *   'Skew' table types even though the specification has different formats
    @@ -489,9 +492,7 @@ FT_BEGIN_HEADER
        *   structures.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef enum  FT_PaintFormat_
       {
    @@ -521,9 +522,10 @@ FT_BEGIN_HEADER
        *
        * @description:
        *   This iterator object is needed for @FT_Get_Colorline_Stops.  It keeps
    -   *   state while iterating over the stops of an @FT_ColorLine,
    -   *   representing the `ColorLine` struct of the v1 extensions to 'COLR',
    -   *   see 'https://github.com/googlefonts/colr-gradients-spec'.
    +   *   state while iterating over the stops of an @FT_ColorLine, representing
    +   *   the `ColorLine` struct of the v1 extensions to 'COLR', see
    +   *   'https://github.com/googlefonts/colr-gradients-spec'.  Do not manually
    +   *   modify fields of this iterator.
        *
        * @fields:
        *   num_color_stops ::
    @@ -537,10 +539,12 @@ FT_BEGIN_HEADER
        *     An opaque pointer into 'COLR' table data.  Set by @FT_Get_Paint.
        *     Updated by @FT_Get_Colorline_Stops.
        *
    -   * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    +   *   read_variable ::
    +   *     A boolean keeping track of whether variable color lines are to be
    +   *     read.  Set by @FT_Get_Paint.
        *
    +   * @since:
    +   *   2.13
        */
       typedef struct  FT_ColorStopIterator_
       {
    @@ -549,6 +553,8 @@ FT_BEGIN_HEADER
     
         FT_Byte*  p;
     
    +    FT_Bool  read_variable;
    +
       } FT_ColorStopIterator;
     
     
    @@ -569,9 +575,7 @@ FT_BEGIN_HEADER
        *     Alpha transparency value multiplied with the value from 'CPAL'.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_ColorIndex_
       {
    @@ -592,19 +596,18 @@ FT_BEGIN_HEADER
        *
        * @fields:
        *   stop_offset ::
    -   *     The stop offset between 0 and 1 along the gradient.
    +   *     The stop offset along the gradient, expressed as a 16.16 fixed-point
    +   *     coordinate.
        *
        *   color ::
        *     The color information for this stop, see @FT_ColorIndex.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_ColorStop_
       {
    -    FT_F2Dot14     stop_offset;
    +    FT_Fixed       stop_offset;
         FT_ColorIndex  color;
     
       } FT_ColorStop;
    @@ -621,9 +624,7 @@ FT_BEGIN_HEADER
        *   It describes how the gradient fill continues at the other boundaries.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef enum  FT_PaintExtend_
       {
    @@ -653,9 +654,7 @@ FT_BEGIN_HEADER
        *     actual @FT_ColorStop's.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_ColorLine_
       {
    @@ -699,9 +698,7 @@ FT_BEGIN_HEADER
        *     y translation.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_Affine_23_
       {
    @@ -722,9 +719,7 @@ FT_BEGIN_HEADER
        *   'https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators'.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef enum  FT_Composite_Mode_
       {
    @@ -786,9 +781,7 @@ FT_BEGIN_HEADER
        *     to be provided.  Do not set this value.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_Opaque_Paint_
       {
    @@ -815,9 +808,7 @@ FT_BEGIN_HEADER
        *     The layer iterator that describes the layers of this paint.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_PaintColrLayers_
       {
    @@ -842,9 +833,7 @@ FT_BEGIN_HEADER
        *     The color information for this solid paint, see @FT_ColorIndex.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_PaintSolid_
       {
    @@ -883,9 +872,7 @@ FT_BEGIN_HEADER
        *     Otherwise equal to~p0.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_PaintLinearGradient_
       {
    @@ -908,8 +895,7 @@ FT_BEGIN_HEADER
        *   A structure representing a `PaintRadialGradient` value of the 'COLR'
        *   v1 extensions, see
        *   'https://github.com/googlefonts/colr-gradients-spec'.  The glyph
    -   *   layer filled with this paint is drawn filled filled with a radial
    -   *   gradient.
    +   *   layer filled with this paint is drawn filled with a radial gradient.
        *
        * @fields:
        *   colorline ::
    @@ -933,9 +919,7 @@ FT_BEGIN_HEADER
        *     units represented as a 16.16 fixed-point value.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_PaintRadialGradient_
       {
    @@ -983,9 +967,7 @@ FT_BEGIN_HEADER
        *     given counter-clockwise, starting from the (positive) y~axis.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_PaintSweepGradient_
       {
    @@ -1016,9 +998,7 @@ FT_BEGIN_HEADER
        *     information that is filled with paint.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_PaintGlyph_
       {
    @@ -1042,9 +1022,7 @@ FT_BEGIN_HEADER
        *     this paint.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_PaintColrGlyph_
       {
    @@ -1070,9 +1048,7 @@ FT_BEGIN_HEADER
        *     16.16 fixed-point values.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_PaintTransform_
       {
    @@ -1105,9 +1081,7 @@ FT_BEGIN_HEADER
        *     16.16 fixed-point value.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_PaintTranslate_
       {
    @@ -1156,9 +1130,7 @@ FT_BEGIN_HEADER
        *     16.16 fixed-point value.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward-compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_PaintScale_
       {
    @@ -1194,16 +1166,14 @@ FT_BEGIN_HEADER
        *
        *   center_x ::
        *     The x~coordinate of the pivot point of the rotation in font
    -   *     units) represented as a 16.16 fixed-point value.
    +   *     units represented as a 16.16 fixed-point value.
        *
        *   center_y ::
        *     The y~coordinate of the pivot point of the rotation in font
        *     units represented as a 16.16 fixed-point value.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
     
       typedef struct  FT_PaintRotate_
    @@ -1252,9 +1222,7 @@ FT_BEGIN_HEADER
        *     represented as a 16.16 fixed-point value.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_PaintSkew_
       {
    @@ -1275,9 +1243,8 @@ FT_BEGIN_HEADER
        *   FT_PaintComposite
        *
        * @description:
    -   *   A structure representing a 'COLR'v1 `PaintComposite` paint table.
    -   *   Used for compositing two paints in a 'COLR' v1 directed acycling
    -   *   graph.
    +   *   A structure representing a 'COLR' v1 `PaintComposite` paint table.
    +   *   Used for compositing two paints in a 'COLR' v1 directed acyclic graph.
        *
        * @fields:
        *   source_paint ::
    @@ -1293,9 +1260,7 @@ FT_BEGIN_HEADER
        *     `source_paint` is composited onto.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_PaintComposite_
       {
    @@ -1339,9 +1304,7 @@ FT_BEGIN_HEADER
        *       * @FT_PaintColrGlyph
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_COLR_Paint_
       {
    @@ -1386,9 +1349,7 @@ FT_BEGIN_HEADER
        *     Do not output an initial root transform.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef enum  FT_Color_Root_Transform_
       {
    @@ -1429,9 +1390,7 @@ FT_BEGIN_HEADER
        *     fixed-point coordinates in 26.6 format.
        *
        * @since:
    -   *   2.12 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       typedef struct  FT_ClipBox_
       {
    @@ -1524,9 +1483,7 @@ FT_BEGIN_HEADER
        *   error, value~0 is returned also.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       FT_EXPORT( FT_Bool )
       FT_Get_Color_Glyph_Paint( FT_Face                  face,
    @@ -1568,9 +1525,7 @@ FT_BEGIN_HEADER
        *   and remove transforms configured using @FT_Set_Transform.
        *
        * @since:
    -   *   2.12 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       FT_EXPORT( FT_Bool )
       FT_Get_Color_Glyph_ClipBox( FT_Face      face,
    @@ -1617,9 +1572,7 @@ FT_BEGIN_HEADER
        *   object can not be retrieved or any other error occurs.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       FT_EXPORT( FT_Bool )
       FT_Get_Paint_Layers( FT_Face            face,
    @@ -1660,9 +1613,7 @@ FT_BEGIN_HEADER
        *   also.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       FT_EXPORT( FT_Bool )
       FT_Get_Colorline_Stops( FT_Face                face,
    @@ -1698,9 +1649,7 @@ FT_BEGIN_HEADER
        *   this paint or any other error occured.
        *
        * @since:
    -   *   2.11 -- **currently experimental only!**  There might be changes
    -   *   without retaining backward compatibility of both the API and ABI.
    -   *
    +   *   2.13
        */
       FT_EXPORT( FT_Bool )
       FT_Get_Paint( FT_Face         face,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h
    index 0dc91e8b404..f90946fd17d 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType API for controlling driver modules (specification only).
      *
    - * Copyright (C) 2017-2022 by
    + * Copyright (C) 2017-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -820,7 +820,6 @@ FT_BEGIN_HEADER
        *   2.5
        */
     
    -
       /**************************************************************************
        *
        * @property:
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h b/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h
    index a3acfce4304..d59b3cc2da2 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType error codes (specification).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h b/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h
    index ff1b375d7d5..15ef3f76b59 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType error code handling (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -29,7 +29,7 @@
        *
        * @description:
        *   The header file `fterrors.h` (which is automatically included by
    -   *   `freetype.h` defines the handling of FreeType's enumeration
    +   *   `freetype.h`) defines the handling of FreeType's enumeration
        *   constants.  It can also be used to generate error message strings
        *   with a small macro trick explained below.
        *
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h
    index 77d553578ba..c0018fc830c 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h
    @@ -4,7 +4,7 @@
      *
      *   Support functions for font formats.
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h
    index d4ab9b32dbd..d5f19add8f2 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h
    @@ -4,7 +4,7 @@
      *
      *   Access of TrueType's 'gasp' table (specification).
      *
    - * Copyright (C) 2007-2022 by
    + * Copyright (C) 2007-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h
    index 6b77bd3d2a9..4658895f7a9 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType convenience functions to handle glyphs (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -355,7 +355,7 @@ FT_BEGIN_HEADER
        *
        * @output:
        *   aglyph ::
    -   *     A handle to the glyph object.
    +   *     A handle to the glyph object.  `NULL` in case of error.
        *
        * @return:
        *   FreeType error code.  0~means success.
    @@ -385,7 +385,7 @@ FT_BEGIN_HEADER
        *
        * @output:
        *   target ::
    -   *     A handle to the target glyph object.  0~in case of error.
    +   *     A handle to the target glyph object.  `NULL` in case of error.
        *
        * @return:
        *   FreeType error code.  0~means success.
    @@ -413,7 +413,7 @@ FT_BEGIN_HEADER
        *
        *   delta ::
        *     A pointer to a 2d vector to apply.  Coordinates are expressed in
    -   *     1/64th of a pixel.
    +   *     1/64 of a pixel.
        *
        * @return:
        *   FreeType error code (if not 0, the glyph format is not scalable).
    @@ -500,7 +500,7 @@ FT_BEGIN_HEADER
        * @output:
        *   acbox ::
        *     The glyph coordinate bounding box.  Coordinates are expressed in
    -   *     1/64th of pixels if it is grid-fitted.
    +   *     1/64 of pixels if it is grid-fitted.
        *
        * @note:
        *   Coordinates are relative to the glyph origin, using the y~upwards
    @@ -671,7 +671,7 @@ FT_BEGIN_HEADER
        *
        * @input:
        *   glyph ::
    -   *     A handle to the target glyph object.
    +   *     A handle to the target glyph object.  Can be `NULL`.
        */
       FT_EXPORT( void )
       FT_Done_Glyph( FT_Glyph  glyph );
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h
    index 0880290f9e2..443ec29db1b 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h
    @@ -4,7 +4,7 @@
      *
      *   Gzip-compressed stream support.
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h
    index 7f2d721cdc2..2e8e6734cc0 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h
    @@ -5,7 +5,7 @@
      *   FreeType glyph image formats and default raster interface
      *   (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h
    index 3b3d93c2d31..2d4f5def241 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType incremental loading (specification).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h
    index c767c6cb483..d3723e16f67 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h
    @@ -5,7 +5,7 @@
      *   FreeType API for color filtering of subpixel bitmap glyphs
      *   (specification).
      *
    - * Copyright (C) 2006-2022 by
    + * Copyright (C) 2006-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -137,11 +137,11 @@ FT_BEGIN_HEADER
        *
        *   FT_LCD_FILTER_DEFAULT ::
        *     This is a beveled, normalized, and color-balanced five-tap filter
    -   *     with weights of [0x08 0x4D 0x56 0x4D 0x08] in 1/256th units.
    +   *     with weights of [0x08 0x4D 0x56 0x4D 0x08] in 1/256 units.
        *
        *   FT_LCD_FILTER_LIGHT ::
        *     this is a boxy, normalized, and color-balanced three-tap filter with
    -   *     weights of [0x00 0x55 0x56 0x55 0x00] in 1/256th units.
    +   *     weights of [0x00 0x55 0x56 0x55 0x00] in 1/256 units.
        *
        *   FT_LCD_FILTER_LEGACY ::
        *   FT_LCD_FILTER_LEGACY1 ::
    @@ -226,7 +226,7 @@ FT_BEGIN_HEADER
        *
        *   weights ::
        *     A pointer to an array; the function copies the first five bytes and
    -   *     uses them to specify the filter weights in 1/256th units.
    +   *     uses them to specify the filter weights in 1/256 units.
        *
        * @return:
        *   FreeType error code.  0~means success.
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h
    index 4dca2bf163d..b5531313359 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h
    @@ -4,7 +4,7 @@
      *
      *   Generic list support for FreeType (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h
    index 7213dc30a8a..2246dc83651 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h
    @@ -4,7 +4,7 @@
      *
      *   Additional debugging APIs.
      *
    - * Copyright (C) 2020-2022 by
    + * Copyright (C) 2020-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h
    index 3dd61d0fe12..a91e38f9ea7 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h
    @@ -4,7 +4,7 @@
      *
      *   Additional Mac-specific API.
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h
    index c74ce618cb4..e381ef3d30a 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType Multiple Master font interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -398,6 +398,10 @@ FT_BEGIN_HEADER
        *   FreeType error code.  0~means success.
        *
        * @note:
    +   *   The design coordinates are 16.16 fractional values for TrueType GX and
    +   *   OpenType variation fonts.  For Adobe MM fonts, the values are
    +   *   integers.
    +   *
        *   [Since 2.8.1] To reset all axes to the default values, call the
        *   function with `num_coords` set to zero and `coords` set to `NULL`.
        *   [Since 2.9] 'Default values' means the currently selected named
    @@ -440,6 +444,11 @@ FT_BEGIN_HEADER
        * @return:
        *   FreeType error code.  0~means success.
        *
    +   * @note:
    +   *   The design coordinates are 16.16 fractional values for TrueType GX and
    +   *   OpenType variation fonts.  For Adobe MM fonts, the values are
    +   *   integers.
    +   *
        * @since:
        *   2.7.1
        */
    @@ -471,9 +480,9 @@ FT_BEGIN_HEADER
        *     the number of axes, use default values for the remaining axes.
        *
        *   coords ::
    -   *     The design coordinates array (each element must be between 0 and 1.0
    -   *     for Adobe MM fonts, and between -1.0 and 1.0 for TrueType GX and
    -   *     OpenType variation fonts).
    +   *     The design coordinates array.  Each element is a 16.16 fractional
    +   *     value and must be between 0 and 1.0 for Adobe MM fonts, and between
    +   *     -1.0 and 1.0 for TrueType GX and OpenType variation fonts.
        *
        * @return:
        *   FreeType error code.  0~means success.
    @@ -518,7 +527,7 @@ FT_BEGIN_HEADER
        *
        * @output:
        *   coords ::
    -   *     The normalized blend coordinates array.
    +   *     The normalized blend coordinates array (as 16.16 fractional values).
        *
        * @return:
        *   FreeType error code.  0~means success.
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h
    index b78db724c73..c8f0c2c2a45 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType modules public interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h
    index 88d29177717..c8c892dcce8 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType module error offsets (specification).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h
    index 46ebf9371bb..54434b25f6f 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h
    @@ -5,7 +5,7 @@
      *   Support for the FT_Outline type used to store glyph shapes of
      *   most scalable font formats (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h
    index 72080f396a3..6a9f243bc90 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType API for possible FT_Parameter tags (specification only).
      *
    - * Copyright (C) 2017-2022 by
    + * Copyright (C) 2017-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h
    index 0fab3f8c2a2..a8576dab002 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType renderer modules public interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h
    index e30938d8624..7bfb1aed4c2 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType size objects management (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h
    index 384096a5857..9d5d22bb255 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h
    @@ -7,7 +7,7 @@
      *
      *   This is _not_ used to retrieve glyph names!
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h
    index 12c006d3fb8..b3d90802a56 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType path stroker (specification).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -293,7 +293,7 @@ FT_BEGIN_HEADER
        *
        *   miter_limit ::
        *     The maximum reciprocal sine of half-angle at the miter join,
    -   *     expressed as 16.16 fixed point value.
    +   *     expressed as 16.16 fixed-point value.
        *
        * @note:
        *   The `radius` is expressed in the same units as the outline
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h
    index afc40b1d84a..5d196976572 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h
    @@ -5,7 +5,7 @@
      *   FreeType synthesizing code for emboldening and slanting
      *   (specification).
      *
    - * Copyright (C) 2000-2022 by
    + * Copyright (C) 2000-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -68,10 +68,19 @@ FT_BEGIN_HEADER
       FT_EXPORT( void )
       FT_GlyphSlot_Embolden( FT_GlyphSlot  slot );
     
    -  /* Slant an outline glyph to the right by about 12 degrees. */
    +  /* Slant an outline glyph to the right by about 12 degrees.              */
       FT_EXPORT( void )
       FT_GlyphSlot_Oblique( FT_GlyphSlot  slot );
     
    +  /* Slant an outline glyph by a given sine of an angle.  You can apply    */
    +  /* slant along either x- or y-axis by choosing a corresponding non-zero  */
    +  /* argument.  If both slants are non-zero, some affine transformation    */
    +  /* will result.                                                          */
    +  FT_EXPORT( void )
    +  FT_GlyphSlot_Slant( FT_GlyphSlot  slot,
    +                      FT_Fixed      xslant,
    +                      FT_Fixed      yslant );
    +
       /* */
     
     
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h
    index 5f8aec7b7ce..a995b078de5 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType low-level system interface definition (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -229,7 +229,8 @@ FT_BEGIN_HEADER
        *     A handle to the source stream.
        *
        *   offset ::
    -   *     The offset of read in stream (always from start).
    +   *     The offset from the start of the stream to seek to if this is a seek
    +   *     operation (see note).
        *
        *   buffer ::
        *     The address of the read buffer.
    @@ -241,8 +242,13 @@ FT_BEGIN_HEADER
        *   The number of bytes effectively read by the stream.
        *
        * @note:
    -   *   This function might be called to perform a seek or skip operation with
    -   *   a `count` of~0.  A non-zero return value then indicates an error.
    +   *   This function performs a seek *or* a read operation depending on the
    +   *   argument values.  If `count` is zero, the operation is a seek to
    +   *   `offset` bytes.  If `count` is >~0, the operation is a read of `count`
    +   *   bytes from the current position in the stream, and the `offset` value
    +   *   should be ignored.
    +   *
    +   *   For seek operations, a non-zero return value indicates an error.
        *
        */
       typedef unsigned long
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h b/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h
    index 4e8d871decc..294981a6f31 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType trigonometric functions (specification).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h
    index 29f32fbb261..5b109f0c73c 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType simple types definitions (specification only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -45,7 +45,10 @@ FT_BEGIN_HEADER
        * @description:
        *   This section contains the basic data types defined by FreeType~2,
        *   ranging from simple scalar types to bitmap descriptors.  More
    -   *   font-specific structures are defined in a different section.
    +   *   font-specific structures are defined in a different section.  Note
    +   *   that FreeType does not use floating-point data types.  Fractional
    +   *   values are represented by fixed-point integers, with lower bits
    +   *   storing the fractional part.
        *
        * @order:
        *   FT_Byte
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h
    index aedf48984d4..bf9c8b7cf2a 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h
    @@ -4,7 +4,7 @@
      *
      *   High-level 'autohint' module-specific interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h
    index 700f586c41e..50d53538498 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h
    @@ -4,7 +4,7 @@
      *
      *   Basic OpenType/CFF object type definitions (specification).
      *
    - * Copyright (C) 2017-2022 by
    + * Copyright (C) 2017-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h
    index 23d26c1b346..c2521764caa 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h
    @@ -5,7 +5,7 @@
      *   Basic OpenType/CFF type definitions and interface (specification
      *   only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -315,7 +315,7 @@ FT_BEGIN_HEADER
         /* The normal stack then points to these values instead of the DICT   */
         /* because all other operators in Private DICT clear the stack.       */
         /* `blend_stack' could be cleared at each operator other than blend.  */
    -    /* Blended values are stored as 5-byte fixed point values.            */
    +    /* Blended values are stored as 5-byte fixed-point values.            */
     
         FT_Byte*  blend_stack;    /* base of stack allocation     */
         FT_Byte*  blend_top;      /* first empty slot             */
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h
    index 66fa13c3c50..7883317fed9 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h
    @@ -4,7 +4,7 @@
      *
      *   Compiler-specific macro definitions used internally by FreeType.
      *
    - * Copyright (C) 2020-2022 by
    + * Copyright (C) 2020-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -34,6 +34,19 @@ FT_BEGIN_HEADER
     #  if defined( _COMPILER_VERSION ) && ( _COMPILER_VERSION >= 730 )
     #    pragma set woff 3505
     #  endif
    +#endif
    +
    +  /* Newer compilers warn for fall-through case statements. */
    +#ifndef FALL_THROUGH
    +#  if ( defined( __STDC_VERSION__ ) && __STDC_VERSION__ > 201710L ) || \
    +      ( defined( __cplusplus ) && __cplusplus > 201402L )
    +#    define FALL_THROUGH  [[__fallthrough__]]
    +#  elif ( defined( __GNUC__ ) && __GNUC__ >= 7 )          || \
    +        ( defined( __clang__ ) && __clang_major__ >= 10 )
    +#    define FALL_THROUGH  __attribute__(( __fallthrough__ ))
    +#  else
    +#    define FALL_THROUGH  ( (void)0 )
    +#  endif
     #endif
     
       /*
    @@ -258,7 +271,7 @@ FT_BEGIN_HEADER
        * To export a variable, use `FT_EXPORT_VAR`.
        */
     
    -  /* See `freetype/config/compiler_macros.h` for the `FT_EXPORT` definition */
    +  /* See `freetype/config/public-macros.h` for the `FT_EXPORT` definition */
     #define FT_EXPORT_DEF( x )  FT_FUNCTION_DEFINITION( x )
     
       /*
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h
    index e6a87db94ee..d1baa392bd6 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h
    @@ -4,7 +4,7 @@
      *
      *   Arithmetic computations (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -278,6 +278,40 @@ FT_BEGIN_HEADER
                           FT_Long  c );
     
     
    +  /**************************************************************************
    +   *
    +   * @function:
    +   *   FT_MulAddFix
    +   *
    +   * @description:
    +   *   Compute `(s[0] * f[0] + s[1] * f[1] + ...) / 0x10000`, where `s[n]` is
    +   *   usually a 16.16 scalar.
    +   *
    +   * @input:
    +   *   s ::
    +   *     The array of scalars.
    +   *   f ::
    +   *     The array of factors.
    +   *   count ::
    +   *     The number of entries in the array.
    +   *
    +   * @return:
    +   *   The result of `(s[0] * f[0] + s[1] * f[1] + ...) / 0x10000`.
    +   *
    +   * @note:
    +   *   This function is currently used for the scaled delta computation of
    +   *   variation stores.  It internally uses 64-bit data types when
    +   *   available, otherwise it emulates 64-bit math by using 32-bit
    +   *   operations, which produce a correct result but most likely at a slower
    +   *   performance in comparison to the implementation base on `int64_t`.
    +   *
    +   */
    +  FT_BASE( FT_Int32 )
    +  FT_MulAddFix( FT_Fixed*  s,
    +                FT_Int32*  f,
    +                FT_UInt    count );
    +
    +
       /*
        * A variant of FT_Matrix_Multiply which scales its result afterwards.  The
        * idea is that both `a' and `b' are scaled by factors of 10 so that the
    @@ -413,11 +447,11 @@ FT_BEGIN_HEADER
       extern __inline FT_Int32
       FT_MSB_i386( FT_UInt32  x );
     
    -#pragma aux FT_MSB_i386 =     \
    -  "bsr eax, eax"              \
    -  parm [eax] nomemory         \
    -  value [eax]                 \
    -  modify exact [eax] nomemory;
    +#pragma aux FT_MSB_i386 =             \
    +  "bsr eax, eax"                      \
    +  __parm [__eax] __nomemory           \
    +  __value [__eax]                     \
    +  __modify __exact [__eax] __nomemory;
     
     #define FT_MSB( x )  FT_MSB_i386( x )
     
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h
    index f05b1395cb2..4e013ba1e26 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h
    @@ -4,7 +4,7 @@
      *
      *   Debugging and logging component (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h
    index 9459a9a1901..f78912ca0c7 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType internal font driver interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h
    index f73b6631c8a..36e5509f9ea 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType glyph loader (specification).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h
    index 10d753aa5e9..5eb1d21ff67 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType memory management macros (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -96,15 +96,15 @@ extern "C++"
     
     #ifdef FT_DEBUG_MEMORY
     
    -  FT_BASE( const char* )  _ft_debug_file;
    -  FT_BASE( long )         _ft_debug_lineno;
    +  FT_BASE( const char* )  ft_debug_file_;
    +  FT_BASE( long )         ft_debug_lineno_;
     
    -#define FT_DEBUG_INNER( exp )  ( _ft_debug_file   = __FILE__, \
    -                                 _ft_debug_lineno = __LINE__, \
    +#define FT_DEBUG_INNER( exp )  ( ft_debug_file_   = __FILE__, \
    +                                 ft_debug_lineno_ = __LINE__, \
                                      (exp) )
     
    -#define FT_ASSIGNP_INNER( p, exp )  ( _ft_debug_file   = __FILE__, \
    -                                      _ft_debug_lineno = __LINE__, \
    +#define FT_ASSIGNP_INNER( p, exp )  ( ft_debug_file_   = __FILE__, \
    +                                      ft_debug_lineno_ = __LINE__, \
                                           FT_ASSIGNP( p, exp ) )
     
     #else /* !FT_DEBUG_MEMORY */
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h
    new file mode 100644
    index 00000000000..b7c66c35def
    --- /dev/null
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h
    @@ -0,0 +1,85 @@
    +/****************************************************************************
    + *
    + * ftmmtypes.h
    + *
    + *   OpenType Variations type definitions for internal use
    + *   with the multi-masters service (specification).
    + *
    + * Copyright (C) 2022-2023 by
    + * David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and
    + * Dominik Röttsches.
    + *
    + * This file is part of the FreeType project, and may only be used,
    + * modified, and distributed under the terms of the FreeType project
    + * license, LICENSE.TXT.  By continuing to use, modify, or distribute
    + * this file you indicate that you have read the license and
    + * understand and accept it fully.
    + *
    + */
    +
    +
    +#ifndef FTMMTYPES_H_
    +#define FTMMTYPES_H_
    +
    +FT_BEGIN_HEADER
    +
    +
    +  typedef FT_Int32  FT_ItemVarDelta;
    +
    +  typedef struct  GX_ItemVarDataRec_
    +  {
    +    FT_UInt            itemCount;       /* number of delta sets per item    */
    +    FT_UInt            regionIdxCount;  /* number of region indices         */
    +    FT_UInt*           regionIndices;   /* array of `regionCount' indices;  */
    +                                        /* these index `varRegionList'      */
    +    FT_ItemVarDelta*   deltaSet;        /* array of `itemCount' deltas      */
    +                                        /* use `innerIndex' for this array  */
    +
    +  } GX_ItemVarDataRec, *GX_ItemVarData;
    +
    +
    +  /* contribution of one axis to a region */
    +  typedef struct  GX_AxisCoordsRec_
    +  {
    +    FT_Fixed  startCoord;
    +    FT_Fixed  peakCoord;      /* zero means no effect (factor = 1) */
    +    FT_Fixed  endCoord;
    +
    +  } GX_AxisCoordsRec, *GX_AxisCoords;
    +
    +
    +  typedef struct  GX_VarRegionRec_
    +  {
    +    GX_AxisCoords  axisList;               /* array of axisCount records */
    +
    +  } GX_VarRegionRec, *GX_VarRegion;
    +
    +
    +  /* item variation store */
    +  typedef struct  GX_ItemVarStoreRec_
    +  {
    +    FT_UInt         dataCount;
    +    GX_ItemVarData  varData;            /* array of dataCount records;     */
    +                                        /* use `outerIndex' for this array */
    +    FT_UShort     axisCount;
    +    FT_UInt       regionCount;          /* total number of regions defined */
    +    GX_VarRegion  varRegionList;
    +
    +  } GX_ItemVarStoreRec, *GX_ItemVarStore;
    +
    +
    +  typedef struct  GX_DeltaSetIdxMapRec_
    +  {
    +    FT_ULong  mapCount;
    +    FT_UInt*  outerIndex;               /* indices to item var data */
    +    FT_UInt*  innerIndex;               /* indices to delta set     */
    +
    +  } GX_DeltaSetIdxMapRec, *GX_DeltaSetIdxMap;
    +
    +
    +FT_END_HEADER
    +
    +#endif /* FTMMTYPES_H_ */
    +
    +
    +/* END */
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h
    index 1c779ceaeb2..28bc9b65f05 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType private base classes (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h
    index 47373211cb0..1d5b287ad20 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h
    @@ -4,7 +4,7 @@
      *
      *   Get and set properties of PostScript drivers (specification).
      *
    - * Copyright (C) 2017-2022 by
    + * Copyright (C) 2017-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h
    index 165e67f245b..e96459921ef 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h
    @@ -4,7 +4,7 @@
      *
      *   Embedded resource forks accessor (specification).
      *
    - * Copyright (C) 2004-2022 by
    + * Copyright (C) 2004-2023 by
      * Masatake YAMATO and Redhat K.K.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h
    index 78996d9c852..1e85d6d3856 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType services (specification only).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h
    index aa51fe5a873..88e19287c80 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h
    @@ -4,7 +4,7 @@
      *
      *   Stream handling (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -238,42 +238,42 @@ FT_BEGIN_HEADER
     #define FT_NEXT_BYTE( buffer )         \
               ( (unsigned char)*buffer++ )
     
    -#define FT_NEXT_SHORT( buffer )                                   \
    -          ( (short)( buffer += 2, FT_PEEK_SHORT( buffer - 2 ) ) )
    +#define FT_NEXT_SHORT( buffer )                        \
    +          ( buffer += 2, FT_PEEK_SHORT( buffer - 2 ) )
     
    -#define FT_NEXT_USHORT( buffer )                                            \
    -          ( (unsigned short)( buffer += 2, FT_PEEK_USHORT( buffer - 2 ) ) )
    +#define FT_NEXT_USHORT( buffer )                        \
    +          ( buffer += 2, FT_PEEK_USHORT( buffer - 2 ) )
     
    -#define FT_NEXT_OFF3( buffer )                                  \
    -          ( (long)( buffer += 3, FT_PEEK_OFF3( buffer - 3 ) ) )
    +#define FT_NEXT_OFF3( buffer )                        \
    +          ( buffer += 3, FT_PEEK_OFF3( buffer - 3 ) )
     
    -#define FT_NEXT_UOFF3( buffer )                                           \
    -          ( (unsigned long)( buffer += 3, FT_PEEK_UOFF3( buffer - 3 ) ) )
    +#define FT_NEXT_UOFF3( buffer )                        \
    +          ( buffer += 3, FT_PEEK_UOFF3( buffer - 3 ) )
     
    -#define FT_NEXT_LONG( buffer )                                  \
    -          ( (long)( buffer += 4, FT_PEEK_LONG( buffer - 4 ) ) )
    +#define FT_NEXT_LONG( buffer )                        \
    +          ( buffer += 4, FT_PEEK_LONG( buffer - 4 ) )
     
    -#define FT_NEXT_ULONG( buffer )                                           \
    -          ( (unsigned long)( buffer += 4, FT_PEEK_ULONG( buffer - 4 ) ) )
    +#define FT_NEXT_ULONG( buffer )                        \
    +          ( buffer += 4, FT_PEEK_ULONG( buffer - 4 ) )
     
     
    -#define FT_NEXT_SHORT_LE( buffer )                                   \
    -          ( (short)( buffer += 2, FT_PEEK_SHORT_LE( buffer - 2 ) ) )
    +#define FT_NEXT_SHORT_LE( buffer )                        \
    +          ( buffer += 2, FT_PEEK_SHORT_LE( buffer - 2 ) )
     
    -#define FT_NEXT_USHORT_LE( buffer )                                            \
    -          ( (unsigned short)( buffer += 2, FT_PEEK_USHORT_LE( buffer - 2 ) ) )
    +#define FT_NEXT_USHORT_LE( buffer )                        \
    +          ( buffer += 2, FT_PEEK_USHORT_LE( buffer - 2 ) )
     
    -#define FT_NEXT_OFF3_LE( buffer )                                  \
    -          ( (long)( buffer += 3, FT_PEEK_OFF3_LE( buffer - 3 ) ) )
    +#define FT_NEXT_OFF3_LE( buffer )                        \
    +          ( buffer += 3, FT_PEEK_OFF3_LE( buffer - 3 ) )
     
    -#define FT_NEXT_UOFF3_LE( buffer )                                           \
    -          ( (unsigned long)( buffer += 3, FT_PEEK_UOFF3_LE( buffer - 3 ) ) )
    +#define FT_NEXT_UOFF3_LE( buffer )                        \
    +          ( buffer += 3, FT_PEEK_UOFF3_LE( buffer - 3 ) )
     
    -#define FT_NEXT_LONG_LE( buffer )                                  \
    -          ( (long)( buffer += 4, FT_PEEK_LONG_LE( buffer - 4 ) ) )
    +#define FT_NEXT_LONG_LE( buffer )                        \
    +          ( buffer += 4, FT_PEEK_LONG_LE( buffer - 4 ) )
     
    -#define FT_NEXT_ULONG_LE( buffer )                                           \
    -          ( (unsigned long)( buffer += 4, FT_PEEK_ULONG_LE( buffer - 4 ) ) )
    +#define FT_NEXT_ULONG_LE( buffer )                        \
    +          ( buffer += 4, FT_PEEK_ULONG_LE( buffer - 4 ) )
     
     
       /**************************************************************************
    @@ -307,17 +307,17 @@ FT_BEGIN_HEADER
     
     #define FT_GET_CHAR()       FT_GET_MACRO( FT_Stream_GetByte, FT_Char )
     #define FT_GET_BYTE()       FT_GET_MACRO( FT_Stream_GetByte, FT_Byte )
    -#define FT_GET_SHORT()      FT_GET_MACRO( FT_Stream_GetUShort, FT_Short )
    -#define FT_GET_USHORT()     FT_GET_MACRO( FT_Stream_GetUShort, FT_UShort )
    -#define FT_GET_UOFF3()      FT_GET_MACRO( FT_Stream_GetUOffset, FT_ULong )
    -#define FT_GET_LONG()       FT_GET_MACRO( FT_Stream_GetULong, FT_Long )
    -#define FT_GET_ULONG()      FT_GET_MACRO( FT_Stream_GetULong, FT_ULong )
    -#define FT_GET_TAG4()       FT_GET_MACRO( FT_Stream_GetULong, FT_ULong )
    -
    -#define FT_GET_SHORT_LE()   FT_GET_MACRO( FT_Stream_GetUShortLE, FT_Short )
    -#define FT_GET_USHORT_LE()  FT_GET_MACRO( FT_Stream_GetUShortLE, FT_UShort )
    -#define FT_GET_LONG_LE()    FT_GET_MACRO( FT_Stream_GetULongLE, FT_Long )
    -#define FT_GET_ULONG_LE()   FT_GET_MACRO( FT_Stream_GetULongLE, FT_ULong )
    +#define FT_GET_SHORT()      FT_GET_MACRO( FT_Stream_GetUShort, FT_Int16 )
    +#define FT_GET_USHORT()     FT_GET_MACRO( FT_Stream_GetUShort, FT_UInt16 )
    +#define FT_GET_UOFF3()      FT_GET_MACRO( FT_Stream_GetUOffset, FT_UInt32 )
    +#define FT_GET_LONG()       FT_GET_MACRO( FT_Stream_GetULong, FT_Int32 )
    +#define FT_GET_ULONG()      FT_GET_MACRO( FT_Stream_GetULong, FT_UInt32 )
    +#define FT_GET_TAG4()       FT_GET_MACRO( FT_Stream_GetULong, FT_UInt32 )
    +
    +#define FT_GET_SHORT_LE()   FT_GET_MACRO( FT_Stream_GetUShortLE, FT_Int16 )
    +#define FT_GET_USHORT_LE()  FT_GET_MACRO( FT_Stream_GetUShortLE, FT_UInt16 )
    +#define FT_GET_LONG_LE()    FT_GET_MACRO( FT_Stream_GetULongLE, FT_Int32 )
    +#define FT_GET_ULONG_LE()   FT_GET_MACRO( FT_Stream_GetULongLE, FT_UInt32 )
     #endif
     
     
    @@ -334,16 +334,16 @@ FT_BEGIN_HEADER
        */
     #define FT_READ_BYTE( var )       FT_READ_MACRO( FT_Stream_ReadByte, FT_Byte, var )
     #define FT_READ_CHAR( var )       FT_READ_MACRO( FT_Stream_ReadByte, FT_Char, var )
    -#define FT_READ_SHORT( var )      FT_READ_MACRO( FT_Stream_ReadUShort, FT_Short, var )
    -#define FT_READ_USHORT( var )     FT_READ_MACRO( FT_Stream_ReadUShort, FT_UShort, var )
    -#define FT_READ_UOFF3( var )      FT_READ_MACRO( FT_Stream_ReadUOffset, FT_ULong, var )
    -#define FT_READ_LONG( var )       FT_READ_MACRO( FT_Stream_ReadULong, FT_Long, var )
    -#define FT_READ_ULONG( var )      FT_READ_MACRO( FT_Stream_ReadULong, FT_ULong, var )
    +#define FT_READ_SHORT( var )      FT_READ_MACRO( FT_Stream_ReadUShort, FT_Int16, var )
    +#define FT_READ_USHORT( var )     FT_READ_MACRO( FT_Stream_ReadUShort, FT_UInt16, var )
    +#define FT_READ_UOFF3( var )      FT_READ_MACRO( FT_Stream_ReadUOffset, FT_UInt32, var )
    +#define FT_READ_LONG( var )       FT_READ_MACRO( FT_Stream_ReadULong, FT_Int32, var )
    +#define FT_READ_ULONG( var )      FT_READ_MACRO( FT_Stream_ReadULong, FT_UInt32, var )
     
    -#define FT_READ_SHORT_LE( var )   FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_Short, var )
    -#define FT_READ_USHORT_LE( var )  FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_UShort, var )
    -#define FT_READ_LONG_LE( var )    FT_READ_MACRO( FT_Stream_ReadULongLE, FT_Long, var )
    -#define FT_READ_ULONG_LE( var )   FT_READ_MACRO( FT_Stream_ReadULongLE, FT_ULong, var )
    +#define FT_READ_SHORT_LE( var )   FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_Int16, var )
    +#define FT_READ_USHORT_LE( var )  FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_UInt16, var )
    +#define FT_READ_LONG_LE( var )    FT_READ_MACRO( FT_Stream_ReadULongLE, FT_Int32, var )
    +#define FT_READ_ULONG_LE( var )   FT_READ_MACRO( FT_Stream_ReadULongLE, FT_UInt32, var )
     
     
     #ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM
    @@ -459,23 +459,23 @@ FT_BEGIN_HEADER
       FT_Stream_GetByte( FT_Stream  stream );
     
       /* read a 16-bit big-endian unsigned integer from an entered frame */
    -  FT_BASE( FT_UShort )
    +  FT_BASE( FT_UInt16 )
       FT_Stream_GetUShort( FT_Stream  stream );
     
       /* read a 24-bit big-endian unsigned integer from an entered frame */
    -  FT_BASE( FT_ULong )
    +  FT_BASE( FT_UInt32 )
       FT_Stream_GetUOffset( FT_Stream  stream );
     
       /* read a 32-bit big-endian unsigned integer from an entered frame */
    -  FT_BASE( FT_ULong )
    +  FT_BASE( FT_UInt32 )
       FT_Stream_GetULong( FT_Stream  stream );
     
       /* read a 16-bit little-endian unsigned integer from an entered frame */
    -  FT_BASE( FT_UShort )
    +  FT_BASE( FT_UInt16 )
       FT_Stream_GetUShortLE( FT_Stream  stream );
     
       /* read a 32-bit little-endian unsigned integer from an entered frame */
    -  FT_BASE( FT_ULong )
    +  FT_BASE( FT_UInt32 )
       FT_Stream_GetULongLE( FT_Stream  stream );
     
     
    @@ -485,7 +485,7 @@ FT_BEGIN_HEADER
                           FT_Error*  error );
     
       /* read a 16-bit big-endian unsigned integer from a stream */
    -  FT_BASE( FT_UShort )
    +  FT_BASE( FT_UInt16 )
       FT_Stream_ReadUShort( FT_Stream  stream,
                             FT_Error*  error );
     
    @@ -495,17 +495,17 @@ FT_BEGIN_HEADER
                              FT_Error*  error );
     
       /* read a 32-bit big-endian integer from a stream */
    -  FT_BASE( FT_ULong )
    +  FT_BASE( FT_UInt32 )
       FT_Stream_ReadULong( FT_Stream  stream,
                            FT_Error*  error );
     
       /* read a 16-bit little-endian unsigned integer from a stream */
    -  FT_BASE( FT_UShort )
    +  FT_BASE( FT_UInt16 )
       FT_Stream_ReadUShortLE( FT_Stream  stream,
                               FT_Error*  error );
     
       /* read a 32-bit little-endian unsigned integer from a stream */
    -  FT_BASE( FT_ULong )
    +  FT_BASE( FT_UInt32 )
       FT_Stream_ReadULongLE( FT_Stream  stream,
                              FT_Error*  error );
     
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h
    index 43c6a8713b9..319fe56fd2d 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h
    @@ -4,7 +4,7 @@
      *
      *   Tracing handling (specification only).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h
    index 171c2cb6f57..e98ee4e4737 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType validation support (specification).
      *
    - * Copyright (C) 2004-2022 by
    + * Copyright (C) 2004-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h
    index 48ec1df963d..dfb1987f868 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h
    @@ -5,7 +5,7 @@
      *   Auxiliary functions and data structures related to PostScript fonts
      *   (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -132,9 +132,6 @@ FT_BEGIN_HEADER
        *   max_elems ::
        *     The maximum number of elements in table.
        *
    -   *   num_elems ::
    -   *     The current number of elements in table.
    -   *
        *   elements ::
        *     A table of element addresses within the block.
        *
    @@ -155,7 +152,6 @@ FT_BEGIN_HEADER
         FT_ULong           init;
     
         FT_Int             max_elems;
    -    FT_Int             num_elems;
         FT_Byte**          elements;       /* addresses of table elements */
         FT_UInt*           lengths;        /* lengths of table elements   */
     
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h
    index 5de83e45657..ededc4c72e7 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h
    @@ -6,7 +6,7 @@
      *   recorders (specification only).  These are used to support native
      *   T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers.
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -294,7 +294,7 @@ FT_BEGIN_HEADER
        *
        * @note:
        *   On input, all points within the outline are in font coordinates. On
    -   *   output, they are in 1/64th of pixels.
    +   *   output, they are in 1/64 of pixels.
        *
        *   The scaling transformation is taken from the 'globals' object which
        *   must correspond to the same font as the glyph.
    @@ -607,7 +607,7 @@ FT_BEGIN_HEADER
        *
        * @note:
        *   On input, all points within the outline are in font coordinates. On
    -   *   output, they are in 1/64th of pixels.
    +   *   output, they are in 1/64 of pixels.
        *
        *   The scaling transformation is taken from the 'globals' object which
        *   must correspond to the same font than the glyph.
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h
    index 06e3b531c87..bf0c1dcc714 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType BDF services (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h
    index 1dea6bcda97..4a20498ee0c 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType CFF tables loader service (specification).
      *
    - * Copyright (C) 2017-2022 by
    + * Copyright (C) 2017-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h
    index acf9178d0a8..06d0cb8fd62 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType CID font services (specification).
      *
    - * Copyright (C) 2007-2022 by
    + * Copyright (C) 2007-2023 by
      * Derek Clegg and Michael Toftdal.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h
    index a7280319c5d..bc45e80568f 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType font format service (specification only).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h
    index 489021d8971..6437abfbf2e 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType glyph dictionary services (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h
    index 59ae411b55d..31016afe0d0 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType API for validating TrueTypeGX/AAT tables (specification).
      *
    - * Copyright (C) 2004-2022 by
    + * Copyright (C) 2004-2023 by
      * Masatake YAMATO, Red Hat K.K.,
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h
    index c567acad46d..bcabbc3e68f 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType Kerning service (specification).
      *
    - * Copyright (C) 2006-2022 by
    + * Copyright (C) 2006-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h
    index 7accdc46ff7..e588ea4872a 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType services for metrics variations (specification).
      *
    - * Copyright (C) 2016-2022 by
    + * Copyright (C) 2016-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h
    index c6394890ac6..d94204232e1 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h
    @@ -4,8 +4,8 @@
      *
      *   The FreeType Multiple Masters and GX var services (specification).
      *
    - * Copyright (C) 2003-2022 by
    - * David Turner, Robert Wilhelm, and Werner Lemberg.
    + * Copyright (C) 2003-2023 by
    + * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
      *
      * This file is part of the FreeType project, and may only be used,
      * modified, and distributed under the terms of the FreeType project
    @@ -19,7 +19,9 @@
     #ifndef SVMM_H_
     #define SVMM_H_
     
    +#include 
     #include 
    +#include 
     
     
     FT_BEGIN_HEADER
    @@ -96,53 +98,94 @@ FT_BEGIN_HEADER
                                       FT_UInt*   len,
                                       FT_Fixed*  weight_vector );
     
    +  typedef FT_Error
    +  (*FT_Var_Load_Delta_Set_Idx_Map_Func)( FT_Face            face,
    +                                         FT_ULong           offset,
    +                                         GX_DeltaSetIdxMap  map,
    +                                         GX_ItemVarStore    itemStore,
    +                                         FT_ULong           table_len );
    +
    +  typedef FT_Error
    +  (*FT_Var_Load_Item_Var_Store_Func)( FT_Face          face,
    +                                      FT_ULong         offset,
    +                                      GX_ItemVarStore  itemStore );
    +
    +  typedef FT_ItemVarDelta
    +  (*FT_Var_Get_Item_Delta_Func)( FT_Face          face,
    +                                 GX_ItemVarStore  itemStore,
    +                                 FT_UInt          outerIndex,
    +                                 FT_UInt          innerIndex );
    +
    +  typedef void
    +  (*FT_Var_Done_Item_Var_Store_Func)( FT_Face          face,
    +                                      GX_ItemVarStore  itemStore );
    +
    +  typedef void
    +  (*FT_Var_Done_Delta_Set_Idx_Map_Func)( FT_Face            face,
    +                                         GX_DeltaSetIdxMap  deltaSetIdxMap );
    +
     
       FT_DEFINE_SERVICE( MultiMasters )
       {
    -    FT_Get_MM_Func               get_mm;
    -    FT_Set_MM_Design_Func        set_mm_design;
    -    FT_Set_MM_Blend_Func         set_mm_blend;
    -    FT_Get_MM_Blend_Func         get_mm_blend;
    -    FT_Get_MM_Var_Func           get_mm_var;
    -    FT_Set_Var_Design_Func       set_var_design;
    -    FT_Get_Var_Design_Func       get_var_design;
    -    FT_Set_Instance_Func         set_instance;
    -    FT_Set_MM_WeightVector_Func  set_mm_weightvector;
    -    FT_Get_MM_WeightVector_Func  get_mm_weightvector;
    +    FT_Get_MM_Func                        get_mm;
    +    FT_Set_MM_Design_Func                 set_mm_design;
    +    FT_Set_MM_Blend_Func                  set_mm_blend;
    +    FT_Get_MM_Blend_Func                  get_mm_blend;
    +    FT_Get_MM_Var_Func                    get_mm_var;
    +    FT_Set_Var_Design_Func                set_var_design;
    +    FT_Get_Var_Design_Func                get_var_design;
    +    FT_Set_Instance_Func                  set_instance;
    +    FT_Set_MM_WeightVector_Func           set_mm_weightvector;
    +    FT_Get_MM_WeightVector_Func           get_mm_weightvector;
     
         /* for internal use; only needed for code sharing between modules */
    -    FT_Get_Var_Blend_Func  get_var_blend;
    -    FT_Done_Blend_Func     done_blend;
    +    FT_Var_Load_Delta_Set_Idx_Map_Func    load_delta_set_idx_map;
    +    FT_Var_Load_Item_Var_Store_Func       load_item_var_store;
    +    FT_Var_Get_Item_Delta_Func            get_item_delta;
    +    FT_Var_Done_Item_Var_Store_Func       done_item_var_store;
    +    FT_Var_Done_Delta_Set_Idx_Map_Func    done_delta_set_idx_map;
    +    FT_Get_Var_Blend_Func                 get_var_blend;
    +    FT_Done_Blend_Func                    done_blend;
       };
     
     
    -#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_,            \
    -                                           get_mm_,           \
    -                                           set_mm_design_,    \
    -                                           set_mm_blend_,     \
    -                                           get_mm_blend_,     \
    -                                           get_mm_var_,       \
    -                                           set_var_design_,   \
    -                                           get_var_design_,   \
    -                                           set_instance_,     \
    -                                           set_weightvector_, \
    -                                           get_weightvector_, \
    -                                           get_var_blend_,    \
    -                                           done_blend_ )      \
    -  static const FT_Service_MultiMastersRec  class_ =           \
    -  {                                                           \
    -    get_mm_,                                                  \
    -    set_mm_design_,                                           \
    -    set_mm_blend_,                                            \
    -    get_mm_blend_,                                            \
    -    get_mm_var_,                                              \
    -    set_var_design_,                                          \
    -    get_var_design_,                                          \
    -    set_instance_,                                            \
    -    set_weightvector_,                                        \
    -    get_weightvector_,                                        \
    -    get_var_blend_,                                           \
    -    done_blend_                                               \
    +#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_,                  \
    +                                           get_mm_,                 \
    +                                           set_mm_design_,          \
    +                                           set_mm_blend_,           \
    +                                           get_mm_blend_,           \
    +                                           get_mm_var_,             \
    +                                           set_var_design_,         \
    +                                           get_var_design_,         \
    +                                           set_instance_,           \
    +                                           set_weightvector_,       \
    +                                           get_weightvector_,       \
    +                                           load_delta_set_idx_map_, \
    +                                           load_item_var_store_,    \
    +                                           get_item_delta_,         \
    +                                           done_item_var_store_,    \
    +                                           done_delta_set_idx_map_, \
    +                                           get_var_blend_,          \
    +                                           done_blend_ )            \
    +  static const FT_Service_MultiMastersRec  class_ =                 \
    +  {                                                                 \
    +    get_mm_,                                                        \
    +    set_mm_design_,                                                 \
    +    set_mm_blend_,                                                  \
    +    get_mm_blend_,                                                  \
    +    get_mm_var_,                                                    \
    +    set_var_design_,                                                \
    +    get_var_design_,                                                \
    +    set_instance_,                                                  \
    +    set_weightvector_,                                              \
    +    get_weightvector_,                                              \
    +    load_delta_set_idx_map_,                                        \
    +    load_item_var_store_,                                           \
    +    get_item_delta_,                                                \
    +    done_item_var_store_,                                           \
    +    done_delta_set_idx_map_,                                        \
    +    get_var_blend_,                                                 \
    +    done_blend_                                                     \
       };
     
       /* */
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h
    index 3c72d1f8557..a4683cd5fb6 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType OpenType validation service (specification).
      *
    - * Copyright (C) 2004-2022 by
    + * Copyright (C) 2004-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h
    index bde0ed3545b..fd189c7de77 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h
    @@ -4,7 +4,7 @@
      *
      *   Internal PFR service functions (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h
    index 05f6291e138..2b8f6dfecfb 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType PostScript name services (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h
    index 29c568640bc..932ce32e03d 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType property service (specification).
      *
    - * Copyright (C) 2012-2022 by
    + * Copyright (C) 2012-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h
    index 7d586587a59..fd99d857e47 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType PostScript charmap service (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h
    index 6e45f3272d3..09c4cdccc53 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType PostScript info service (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h
    index 03938a562b6..f98df2ef5fe 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType SFNT table loading service (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h
    index a0b1bbd2f3d..5f9eb02d665 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType TrueType/sfnt cmap extra information service.
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * Masatake YAMATO, Redhat K.K.,
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h
    index f8396eb08cf..ad577cb2904 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType TrueType engine query service (specification).
      *
    - * Copyright (C) 2006-2022 by
    + * Copyright (C) 2006-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h
    index 982630c0aab..ca6fff74444 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType TrueType glyph service.
      *
    - * Copyright (C) 2007-2022 by
    + * Copyright (C) 2007-2023 by
      * David Turner.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h
    index 950f4a8824c..002923f8c91 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType Windows FNT/FONT service (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h
    index c67b47e8606..a2d4e15baaf 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h
    @@ -4,7 +4,7 @@
      *
      *   High-level 'sfnt' driver interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h
    index 1b325e5e9d1..f464b2c0583 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h
    @@ -4,7 +4,7 @@
      *
      *   Interface of ot-svg module (specification only).
      *
    - * Copyright (C) 2022 by
    + * Copyright (C) 2022-2023 by
      * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h
    index b6a3de14d0d..5a105c58795 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h
    @@ -5,7 +5,7 @@
      *   Basic Type1/Type2 type definitions and interface (specification
      *   only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -172,8 +172,8 @@ FT_BEGIN_HEADER
       {
         FT_Bool        IsCIDFont;
         FT_BBox        FontBBox;
    -    FT_Fixed       Ascender;
    -    FT_Fixed       Descender;
    +    FT_Fixed       Ascender;     /* optional, mind the zero */
    +    FT_Fixed       Descender;    /* optional, mind the zero */
         AFM_TrackKern  TrackKerns;   /* free if non-NULL */
         FT_UInt        NumTrackKern;
         AFM_KernPair   KernPairs;    /* free if non-NULL */
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h
    index df719387b58..3b521924ca5 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h
    @@ -5,7 +5,7 @@
      *   Basic SFNT/TrueType type definitions and interface (specification
      *   only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h
    index 94804fa72ff..0c1d8eeaf8c 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h
    @@ -5,7 +5,7 @@
      *   Basic WOFF/WOFF2 type definitions and interface (specification
      *   only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h b/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h
    index 2caadfdeeb6..bfe9a6ab74e 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h
    @@ -4,7 +4,7 @@
      *
      *   Interface for OT-SVG support related things (specification).
      *
    - * Copyright (C) 2022 by
    + * Copyright (C) 2022-2023 by
      * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h
    index 4068b204a93..1aecfbbd902 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h
    @@ -5,7 +5,7 @@
      *   Basic Type 1/Type 2 tables definitions and interface (specification
      *   only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h b/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h
    index 37b505a05bd..e31c68b9baf 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h
    @@ -4,7 +4,7 @@
      *
      *   TrueType name ID definitions (specification only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h b/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h
    index 21664df7b34..a9f60e76201 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h
    @@ -5,7 +5,7 @@
      *   Basic SFNT/TrueType tables definitions and interface
      *   (specification only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -424,8 +424,8 @@ FT_BEGIN_HEADER
     
         /* only version 5 and higher: */
     
    -    FT_UShort  usLowerOpticalPointSize;       /* in twips (1/20th points) */
    -    FT_UShort  usUpperOpticalPointSize;       /* in twips (1/20th points) */
    +    FT_UShort  usLowerOpticalPointSize;       /* in twips (1/20 points) */
    +    FT_UShort  usUpperOpticalPointSize;       /* in twips (1/20 points) */
     
       } TT_OS2;
     
    diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h b/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h
    index 8b807641b8b..9bf4fca23fb 100644
    --- a/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h
    +++ b/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h
    @@ -4,7 +4,7 @@
      *
      *   Tags for TrueType and OpenType tables (specification only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/include/ft2build.h b/src/java.desktop/share/native/libfreetype/include/ft2build.h
    index 2543ac435a6..58491ceea1f 100644
    --- a/src/java.desktop/share/native/libfreetype/include/ft2build.h
    +++ b/src/java.desktop/share/native/libfreetype/include/ft2build.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType 2 build and setup macros.
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c
    index b986eb4a132..d7655b9b99e 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c
    @@ -7,7 +7,7 @@
      *
      *   Auto-fitter data for blue strings (body).
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin
    index f7e27ad8e5a..d561c5093b7 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter data for blue strings (body).
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat
    index 201acc4f6fb..b7efe8be6ce 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat
    @@ -2,7 +2,7 @@
     //
     //   Auto-fitter data for blue strings.
     //
    -// Copyright (C) 2013-2022 by
    +// Copyright (C) 2013-2023 by
     // David Turner, Robert Wilhelm, and Werner Lemberg.
     //
     // This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h
    index 0e56abb94d7..76f2f47cb00 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h
    @@ -7,7 +7,7 @@
      *
      *   Auto-fitter data for blue strings (specification).
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin
    index f9fd5aa3b44..6a31298e65f 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter data for blue strings (specification).
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c
    index 1853a17f5c3..5daefff359c 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter hinting routines for CJK writing system (body).
      *
    - * Copyright (C) 2006-2022 by
    + * Copyright (C) 2006-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -650,7 +650,7 @@
           af_cjk_metrics_check_digits( metrics, face );
         }
     
    -    FT_Set_Charmap( face, oldmap );
    +    face->charmap = oldmap;
         return FT_Err_Ok;
       }
     
    @@ -741,9 +741,11 @@
                         ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V',
                         nn, blue->ref.org, blue->shoot.org ));
             FT_TRACE5(( "     ref:   cur=%.2f fit=%.2f\n",
    -                    blue->ref.cur / 64.0, blue->ref.fit / 64.0 ));
    +                    (double)blue->ref.cur / 64,
    +                    (double)blue->ref.fit / 64 ));
             FT_TRACE5(( "     shoot: cur=%.2f fit=%.2f\n",
    -                    blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
    +                    (double)blue->shoot.cur / 64,
    +                    (double)blue->shoot.fit / 64 ));
     
             blue->flags |= AF_CJK_BLUE_ACTIVE;
           }
    @@ -1044,7 +1046,7 @@
         {
           AF_Edge  found = NULL;
           FT_Pos   best  = 0xFFFFU;
    -      FT_Int   ee;
    +      FT_UInt  ee;
     
     
           /* look for an edge corresponding to the segment */
    @@ -1629,8 +1631,10 @@
         FT_TRACE5(( "  CJKLINK: edge %ld @%d (opos=%.2f) linked to %.2f,"
                     " dist was %.2f, now %.2f\n",
                     stem_edge - hints->axis[dim].edges, stem_edge->fpos,
    -                stem_edge->opos / 64.0, stem_edge->pos / 64.0,
    -                dist / 64.0, fitted_width / 64.0 ));
    +                (double)stem_edge->opos / 64,
    +                (double)stem_edge->pos / 64,
    +                (double)dist / 64,
    +                (double)fitted_width / 64 ));
       }
     
     
    @@ -1850,8 +1854,8 @@
     #ifdef FT_DEBUG_LEVEL_TRACE
             FT_TRACE5(( "  CJKBLUE: edge %ld @%d (opos=%.2f) snapped to %.2f,"
                         " was %.2f\n",
    -                    edge1 - edges, edge1->fpos, edge1->opos / 64.0,
    -                    blue->fit / 64.0, edge1->pos / 64.0 ));
    +                    edge1 - edges, edge1->fpos, (double)edge1->opos / 64,
    +                    (double)blue->fit / 64, (double)edge1->pos / 64 ));
     
             num_actions++;
     #endif
    @@ -2024,8 +2028,8 @@
     #if 0
           printf( "stem (%d,%d) adjusted (%.1f,%.1f)\n",
                    edge - edges, edge2 - edges,
    -               ( edge->pos - edge->opos ) / 64.0,
    -               ( edge2->pos - edge2->opos ) / 64.0 );
    +               (double)( edge->pos - edge->opos ) / 64,
    +               (double)( edge2->pos - edge2->opos ) / 64 );
     #endif
     
           anchor = edge;
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h
    index bf948bcec0c..bd7b81b3e24 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter hinting routines for CJK writing system (specification).
      *
    - * Copyright (C) 2006-2022 by
    + * Copyright (C) 2006-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h b/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h
    index be71fe39deb..102ed427828 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter coverages (specification only).
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c
    index 5fdbfcfd429..a4629b528dc 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c
    @@ -5,7 +5,7 @@
      *   Auto-fitter dummy routines to be used if no hinting should be
      *   performed (body).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h
    index 4dddbd5215d..a7af3f62c9e 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h
    @@ -5,7 +5,7 @@
      *   Auto-fitter dummy routines to be used if no hinting should be
      *   performed (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h b/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h
    index d31b1a9c882..88faf05c950 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h
    @@ -4,7 +4,7 @@
      *
      *   Autofitter error codes (specification only).
      *
    - * Copyright (C) 2005-2022 by
    + * Copyright (C) 2005-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c
    index 87a3fbfb0fe..ede27eb1660 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter routines to compute global hinting values (body).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -129,13 +129,13 @@
         FT_Face     face        = globals->face;
         FT_CharMap  old_charmap = face->charmap;
         FT_UShort*  gstyles     = globals->glyph_styles;
    -    FT_UInt     ss;
    +    FT_UShort   ss;
    +    FT_UShort   dflt        = 0xFFFFU; /* a non-valid value */
         FT_UInt     i;
    -    FT_UInt     dflt        = ~0U; /* a non-valid value */
     
     
         /* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */
    -    for ( i = 0; i < (FT_UInt)globals->glyph_count; i++ )
    +    for ( i = 0; i < globals->glyph_count; i++ )
           gstyles[i] = AF_STYLE_UNASSIGNED;
     
         error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
    @@ -168,8 +168,7 @@
            */
           if ( style_class->coverage == AF_COVERAGE_DEFAULT )
           {
    -        if ( (FT_UInt)style_class->script ==
    -             globals->module->default_script )
    +        if ( style_class->script == globals->module->default_script )
               dflt = ss;
     
             for ( range = script_class->script_uni_ranges;
    @@ -183,9 +182,9 @@
               gindex = FT_Get_Char_Index( face, charcode );
     
               if ( gindex != 0                                                &&
    -               gindex < (FT_ULong)globals->glyph_count                    &&
    +               gindex < globals->glyph_count                              &&
                    ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
    -            gstyles[gindex] = (FT_UShort)ss;
    +            gstyles[gindex] = ss;
     
               for (;;)
               {
    @@ -194,9 +193,9 @@
                 if ( gindex == 0 || charcode > range->last )
                   break;
     
    -            if ( gindex < (FT_ULong)globals->glyph_count                    &&
    +            if ( gindex < globals->glyph_count                              &&
                      ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
    -              gstyles[gindex] = (FT_UShort)ss;
    +              gstyles[gindex] = ss;
               }
             }
     
    @@ -211,9 +210,9 @@
     
               gindex = FT_Get_Char_Index( face, charcode );
     
    -          if ( gindex != 0                                          &&
    -               gindex < (FT_ULong)globals->glyph_count              &&
    -               ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss )
    +          if ( gindex != 0                               &&
    +               gindex < globals->glyph_count             &&
    +               ( gstyles[gindex] & AF_STYLE_MASK ) == ss )
                 gstyles[gindex] |= AF_NONBASE;
     
               for (;;)
    @@ -223,8 +222,8 @@
                 if ( gindex == 0 || charcode > range->last )
                   break;
     
    -            if ( gindex < (FT_ULong)globals->glyph_count              &&
    -                 ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss )
    +            if ( gindex < globals->glyph_count             &&
    +                 ( gstyles[gindex] & AF_STYLE_MASK ) == ss )
                   gstyles[gindex] |= AF_NONBASE;
               }
             }
    @@ -255,7 +254,7 @@
           FT_UInt  gindex = FT_Get_Char_Index( face, i );
     
     
    -      if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count )
    +      if ( gindex != 0 && gindex < globals->glyph_count )
             gstyles[gindex] |= AF_DIGIT;
         }
     
    @@ -266,7 +265,7 @@
          */
         if ( globals->module->fallback_style != AF_STYLE_UNASSIGNED )
         {
    -      FT_Long  nn;
    +      FT_UInt  nn;
     
     
           for ( nn = 0; nn < globals->glyph_count; nn++ )
    @@ -290,7 +289,7 @@
         {
           AF_StyleClass  style_class = af_style_classes[ss];
           FT_UInt        count       = 0;
    -      FT_Long        idx;
    +      FT_UInt        idx;
     
     
           FT_TRACE4(( "%s:\n", af_style_names[style_class->style] ));
    @@ -302,7 +301,7 @@
               if ( !( count % 10 ) )
                 FT_TRACE4(( " " ));
     
    -          FT_TRACE4(( " %ld", idx ));
    +          FT_TRACE4(( " %d", idx ));
               count++;
     
               if ( !( count % 10 ) )
    @@ -318,7 +317,7 @@
     
     #endif /* FT_DEBUG_LEVEL_TRACE */
     
    -    FT_Set_Charmap( face, old_charmap );
    +    face->charmap = old_charmap;
         return error;
       }
     
    @@ -345,7 +344,7 @@
         FT_ZERO( &globals->metrics );
     
         globals->face                      = face;
    -    globals->glyph_count               = face->num_glyphs;
    +    globals->glyph_count               = (FT_UInt)face->num_glyphs;
         /* right after the globals structure come the glyph styles */
         globals->glyph_styles              = (FT_UShort*)( globals + 1 );
         globals->module                    = module;
    @@ -357,7 +356,7 @@
         globals->scale_down_factor         = 0;
     
     #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
    -    globals->hb_font = hb_ft_font_create( face, NULL );
    +    globals->hb_font = hb_ft_font_create_( face, NULL );
         globals->hb_buf  = hb_buffer_create();
     #endif
     
    @@ -429,7 +428,7 @@
         FT_Error  error = FT_Err_Ok;
     
     
    -    if ( gindex >= (FT_ULong)globals->glyph_count )
    +    if ( gindex >= globals->glyph_count )
         {
           error = FT_THROW( Invalid_Argument );
           goto Exit;
    @@ -501,7 +500,7 @@
       af_face_globals_is_digit( AF_FaceGlobals  globals,
                                 FT_UInt         gindex )
       {
    -    if ( gindex < (FT_ULong)globals->glyph_count )
    +    if ( gindex < globals->glyph_count )
           return FT_BOOL( globals->glyph_styles[gindex] & AF_DIGIT );
     
         return FT_BOOL( 0 );
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h
    index f7ebf8d57a2..83a7c2ff15b 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h
    @@ -5,7 +5,7 @@
      *   Auto-fitter routines to compute global hinting values
      *   (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -105,7 +105,7 @@ FT_BEGIN_HEADER
       typedef struct  AF_FaceGlobalsRec_
       {
         FT_Face          face;
    -    FT_Long          glyph_count;    /* same as face->num_glyphs */
    +    FT_UInt          glyph_count;    /* unsigned face->num_glyphs */
         FT_UShort*       glyph_styles;
     
     #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
    @@ -158,7 +158,7 @@ FT_BEGIN_HEADER
       FT_LOCAL( void )
       af_face_globals_free( AF_FaceGlobals  globals );
     
    -  FT_LOCAL_DEF( FT_Bool )
    +  FT_LOCAL( FT_Bool )
       af_face_globals_is_digit( AF_FaceGlobals  globals,
                                 FT_UInt         gindex );
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c
    index ae7d10528da..6515af9f04e 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter hinting routines (body).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -151,9 +151,9 @@
         }
         else if ( axis->num_segments >= axis->max_segments )
         {
    -      FT_Int  old_max = axis->max_segments;
    -      FT_Int  new_max = old_max;
    -      FT_Int  big_max = (FT_Int)( FT_INT_MAX / sizeof ( *segment ) );
    +      FT_UInt  old_max = axis->max_segments;
    +      FT_UInt  new_max = old_max;
    +      FT_UInt  big_max = FT_INT_MAX / sizeof ( *segment );
     
     
           if ( old_max >= big_max )
    @@ -193,7 +193,7 @@
       /* Get new edge for given axis, direction, and position, */
       /* without initializing the edge itself.                 */
     
    -  FT_LOCAL( FT_Error )
    +  FT_LOCAL_DEF( FT_Error )
       af_axis_hints_new_edge( AF_AxisHints  axis,
                               FT_Int        fpos,
                               AF_Direction  dir,
    @@ -216,9 +216,9 @@
         }
         else if ( axis->num_edges >= axis->max_edges )
         {
    -      FT_Int  old_max = axis->max_edges;
    -      FT_Int  new_max = old_max;
    -      FT_Int  big_max = (FT_Int)( FT_INT_MAX / sizeof ( *edge ) );
    +      FT_UInt  old_max = axis->max_edges;
    +      FT_UInt  new_max = old_max;
    +      FT_UInt  big_max = FT_INT_MAX / sizeof ( *edge );
     
     
           if ( old_max >= big_max )
    @@ -471,10 +471,10 @@
     
                     point->fx,
                     point->fy,
    -                point->ox / 64.0,
    -                point->oy / 64.0,
    -                point->x / 64.0,
    -                point->y / 64.0,
    +                (double)point->ox / 64,
    +                (double)point->oy / 64,
    +                (double)point->x / 64,
    +                (double)point->y / 64,
     
                     af_print_idx( buf5, af_get_strong_edge_index( hints,
                                                                   point->before,
    @@ -597,7 +597,7 @@
       FT_Error
       af_glyph_hints_get_num_segments( AF_GlyphHints  hints,
                                        FT_Int         dimension,
    -                                   FT_Int*        num_segments )
    +                                   FT_UInt*       num_segments )
       {
         AF_Dimension  dim;
         AF_AxisHints  axis;
    @@ -623,7 +623,7 @@
       FT_Error
       af_glyph_hints_get_segment_offset( AF_GlyphHints  hints,
                                          FT_Int         dimension,
    -                                     FT_Int         idx,
    +                                     FT_UInt        idx,
                                          FT_Pos        *offset,
                                          FT_Bool       *is_blue,
                                          FT_Pos        *blue_offset )
    @@ -640,7 +640,7 @@
     
         axis = &hints->axis[dim];
     
    -    if ( idx < 0 || idx >= axis->num_segments )
    +    if ( idx >= axis->num_segments )
           return FT_THROW( Invalid_Argument );
     
         seg      = &axis->segments[idx];
    @@ -692,13 +692,13 @@
           if ( dimension == AF_DIMENSION_HORZ )
             AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n",
                       "vertical",
    -                  65536.0 * 64.0 / hints->x_scale,
    -                  10.0 * hints->x_scale / 65536.0 / 64.0 ));
    +                  65536 * 64 / (double)hints->x_scale,
    +                  10 * (double)hints->x_scale / 65536 / 64 ));
           else
             AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n",
                       "horizontal",
    -                  65536.0 * 64.0 / hints->y_scale,
    -                  10.0 * hints->y_scale / 65536.0 / 64.0 ));
    +                  65536 * 64 / (double)hints->y_scale,
    +                  10 * (double)hints->y_scale / 65536 / 64 ));
     
           if ( axis->num_edges )
           {
    @@ -714,14 +714,14 @@
             AF_DUMP(( "  %5d  %7.2f  %5s  %4s  %5s"
                       "    %c   %7.2f  %7.2f  %11s\n",
                       AF_INDEX_NUM( edge, edges ),
    -                  (int)edge->opos / 64.0,
    +                  (double)(int)edge->opos / 64,
                       af_dir_str( (AF_Direction)edge->dir ),
                       af_print_idx( buf1, AF_INDEX_NUM( edge->link, edges ) ),
                       af_print_idx( buf2, AF_INDEX_NUM( edge->serif, edges ) ),
     
                       edge->blue_edge ? 'y' : 'n',
    -                  edge->opos / 64.0,
    -                  edge->pos / 64.0,
    +                  (double)edge->opos / 64,
    +                  (double)edge->pos / 64,
                       af_edge_flags_to_string( edge->flags ) ));
           AF_DUMP(( "\n" ));
         }
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h
    index 96001cd80da..d1cf9529bf1 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter hinting routines (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -21,8 +21,6 @@
     
     #include "aftypes.h"
     
    -#define xxAF_SORT_SEGMENTS
    -
     FT_BEGIN_HEADER
     
       /*
    @@ -310,15 +308,12 @@ FT_BEGIN_HEADER
     
       typedef struct  AF_AxisHintsRec_
       {
    -    FT_Int        num_segments; /* number of used segments      */
    -    FT_Int        max_segments; /* number of allocated segments */
    +    FT_UInt       num_segments; /* number of used segments      */
    +    FT_UInt       max_segments; /* number of allocated segments */
         AF_Segment    segments;     /* segments array               */
    -#ifdef AF_SORT_SEGMENTS
    -    FT_Int        mid_segments;
    -#endif
     
    -    FT_Int        num_edges;    /* number of used edges      */
    -    FT_Int        max_edges;    /* number of allocated edges */
    +    FT_UInt       num_edges;    /* number of used edges      */
    +    FT_UInt       max_edges;    /* number of allocated edges */
         AF_Edge       edges;        /* edges array               */
     
         AF_Direction  major_dir;    /* either vertical or horizontal */
    @@ -380,14 +375,14 @@ FT_BEGIN_HEADER
     #ifdef FT_DEBUG_AUTOFIT
     
     #define AF_HINTS_DO_HORIZONTAL( h )                                     \
    -          ( !_af_debug_disable_horz_hints                            && \
    +          ( !af_debug_disable_horz_hints_                            && \
                 !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL ) )
     
     #define AF_HINTS_DO_VERTICAL( h )                                     \
    -          ( !_af_debug_disable_vert_hints                          && \
    +          ( !af_debug_disable_vert_hints_                          && \
                 !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL ) )
     
    -#define AF_HINTS_DO_BLUES( h )  ( !_af_debug_disable_blue_hints )
    +#define AF_HINTS_DO_BLUES( h )  ( !af_debug_disable_blue_hints_ )
     
     #else /* !FT_DEBUG_AUTOFIT */
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c
    index 5bf0b5f9451..289a09d71d8 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter hinting routines for Indic writing system (body).
      *
    - * Copyright (C) 2007-2022 by
    + * Copyright (C) 2007-2023 by
      * Rahul Bhalerao , .
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -49,8 +49,7 @@
           af_cjk_metrics_check_digits( metrics, face );
         }
     
    -    FT_Set_Charmap( face, oldmap );
    -
    +    face->charmap = oldmap;
         return FT_Err_Ok;
       }
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h
    index 59ae11a6773..3eb67f63b00 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h
    @@ -5,7 +5,7 @@
      *   Auto-fitter hinting routines for Indic writing system
      *   (specification).
      *
    - * Copyright (C) 2007-2022 by
    + * Copyright (C) 2007-2023 by
      * Rahul Bhalerao , .
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c
    index bed0ccee080..4b3c59b3c31 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter hinting routines for latin writing system (body).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -1043,7 +1043,7 @@
           AF_FaceGlobals  globals = metrics->root.globals;
           FT_UShort*      gstyles = globals->glyph_styles;
     
    -      FT_Long  i;
    +      FT_UInt  i;
     
     
           FT_TRACE5(( "no blue zones found:"
    @@ -1157,7 +1157,7 @@
         }
     
       Exit:
    -    FT_Set_Charmap( face, oldmap );
    +    face->charmap = oldmap;
         return error;
       }
     
    @@ -1275,8 +1275,8 @@
                   FT_TRACE5(( "                           "
                               " vertical scaling changed"
                               " from %.5f to %.5f (by %ld%%)\n",
    -                          scale / 65536.0,
    -                          new_scale / 65536.0,
    +                          (double)scale / 65536,
    +                          (double)new_scale / 65536,
                               ( fitted - scaled ) * 100 / scaled ));
                   FT_TRACE5(( "\n" ));
     
    @@ -1327,7 +1327,7 @@
     
           FT_TRACE5(( "  %ld scaled to %.2f\n",
                       width->org,
    -                  width->cur / 64.0 ));
    +                  (double)width->cur / 64 ));
         }
     
         FT_TRACE5(( "\n" ));
    @@ -1471,13 +1471,13 @@
             FT_TRACE5(( "  reference %d: %ld scaled to %.2f%s\n",
                         nn,
                         blue->ref.org,
    -                    blue->ref.fit / 64.0,
    +                    (double)blue->ref.fit / 64,
                         ( blue->flags & AF_LATIN_BLUE_ACTIVE ) ? ""
                                                                : " (inactive)" ));
             FT_TRACE5(( "  overshoot %d: %ld scaled to %.2f%s\n",
                         nn,
                         blue->shoot.org,
    -                    blue->shoot.fit / 64.0,
    +                    (double)blue->shoot.fit / 64,
                         ( blue->flags & AF_LATIN_BLUE_ACTIVE ) ? ""
                                                                : " (inactive)" ));
           }
    @@ -2203,7 +2203,7 @@
         for ( seg = segments; seg < segment_limit; seg++ )
         {
           AF_Edge  found = NULL;
    -      FT_Int   ee;
    +      FT_UInt  ee;
     
     
           /* ignore too short segments, too wide ones, and, in this loop, */
    @@ -2277,7 +2277,7 @@
         for ( seg = segments; seg < segment_limit; seg++ )
         {
           AF_Edge  found = NULL;
    -      FT_Int   ee;
    +      FT_UInt  ee;
     
     
           if ( seg->dir != AF_DIR_NONE )
    @@ -2955,8 +2955,9 @@
     
         FT_TRACE5(( "  LINK: edge %ld (opos=%.2f) linked to %.2f,"
                     " dist was %.2f, now %.2f\n",
    -                stem_edge - hints->axis[dim].edges, stem_edge->opos / 64.0,
    -                stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
    +                stem_edge - hints->axis[dim].edges,
    +                (double)stem_edge->opos / 64, (double)stem_edge->pos / 64,
    +                (double)dist / 64, (double)fitted_width / 64 ));
       }
     
     
    @@ -3079,13 +3080,15 @@
             if ( !anchor )
               FT_TRACE5(( "  BLUE_ANCHOR: edge %ld (opos=%.2f) snapped to %.2f,"
                           " was %.2f (anchor=edge %ld)\n",
    -                      edge1 - edges, edge1->opos / 64.0, blue->fit / 64.0,
    -                      edge1->pos / 64.0, edge - edges ));
    +                      edge1 - edges,
    +                      (double)edge1->opos / 64, (double)blue->fit / 64,
    +                      (double)edge1->pos / 64, edge - edges ));
             else
               FT_TRACE5(( "  BLUE: edge %ld (opos=%.2f) snapped to %.2f,"
                           " was %.2f\n",
    -                      edge1 - edges, edge1->opos / 64.0, blue->fit / 64.0,
    -                      edge1->pos / 64.0 ));
    +                      edge1 - edges,
    +                      (double)edge1->opos / 64, (double)blue->fit / 64,
    +                      (double)edge1->pos / 64 ));
     
             num_actions++;
     #endif
    @@ -3201,9 +3204,9 @@
     
             FT_TRACE5(( "  ANCHOR: edge %ld (opos=%.2f) and %ld (opos=%.2f)"
                         " snapped to %.2f and %.2f\n",
    -                    edge - edges, edge->opos / 64.0,
    -                    edge2 - edges, edge2->opos / 64.0,
    -                    edge->pos / 64.0, edge2->pos / 64.0 ));
    +                    edge - edges, (double)edge->opos / 64,
    +                    edge2 - edges, (double)edge2->opos / 64,
    +                    (double)edge->pos / 64, (double)edge2->pos / 64 ));
     
             af_latin_align_linked_edge( hints, dim, edge, edge2 );
     
    @@ -3229,8 +3232,8 @@
             if ( edge2->flags & AF_EDGE_DONE )
             {
               FT_TRACE5(( "  ADJUST: edge %ld (pos=%.2f) moved to %.2f\n",
    -                      edge - edges, edge->pos / 64.0,
    -                      ( edge2->pos - cur_len ) / 64.0 ));
    +                      edge - edges, (double)edge->pos / 64,
    +                      (double)( edge2->pos - cur_len ) / 64 ));
     
               edge->pos = edge2->pos - cur_len;
             }
    @@ -3271,9 +3274,9 @@
     
               FT_TRACE5(( "  STEM: edge %ld (opos=%.2f) linked to %ld (opos=%.2f)"
                           " snapped to %.2f and %.2f\n",
    -                      edge - edges, edge->opos / 64.0,
    -                      edge2 - edges, edge2->opos / 64.0,
    -                      edge->pos / 64.0, edge2->pos / 64.0 ));
    +                      edge - edges, (double)edge->opos / 64,
    +                      edge2 - edges, (double)edge2->opos / 64,
    +                      (double)edge->pos / 64, (double)edge2->pos / 64 ));
             }
     
             else
    @@ -3302,9 +3305,9 @@
     
               FT_TRACE5(( "  STEM: edge %ld (opos=%.2f) linked to %ld (opos=%.2f)"
                           " snapped to %.2f and %.2f\n",
    -                      edge - edges, edge->opos / 64.0,
    -                      edge2 - edges, edge2->opos / 64.0,
    -                      edge->pos / 64.0, edge2->pos / 64.0 ));
    +                      edge - edges, (double)edge->opos / 64,
    +                      edge2 - edges, (double)edge2->opos / 64,
    +                      (double)edge->pos / 64, (double)edge2->pos / 64 ));
             }
     
     #ifdef FT_DEBUG_LEVEL_TRACE
    @@ -3325,8 +3328,8 @@
     #ifdef FT_DEBUG_LEVEL_TRACE
                 FT_TRACE5(( "  BOUND: edge %ld (pos=%.2f) moved to %.2f\n",
                             edge - edges,
    -                        edge->pos / 64.0,
    -                        edge[-1].pos / 64.0 ));
    +                        (double)edge->pos / 64,
    +                        (double)edge[-1].pos / 64 ));
     
                 num_actions++;
     #endif
    @@ -3427,9 +3430,9 @@
               af_latin_align_serif_edge( hints, edge->serif, edge );
               FT_TRACE5(( "  SERIF: edge %ld (opos=%.2f) serif to %ld (opos=%.2f)"
                           " aligned to %.2f\n",
    -                      edge - edges, edge->opos / 64.0,
    -                      edge->serif - edges, edge->serif->opos / 64.0,
    -                      edge->pos / 64.0 ));
    +                      edge - edges, (double)edge->opos / 64,
    +                      edge->serif - edges, (double)edge->serif->opos / 64,
    +                      (double)edge->pos / 64 ));
             }
             else if ( !anchor )
             {
    @@ -3437,7 +3440,8 @@
               anchor    = edge;
               FT_TRACE5(( "  SERIF_ANCHOR: edge %ld (opos=%.2f)"
                           " snapped to %.2f\n",
    -                      edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
    +                      edge-edges,
    +                      (double)edge->opos / 64, (double)edge->pos / 64 ));
             }
             else
             {
    @@ -3465,9 +3469,9 @@
     
                 FT_TRACE5(( "  SERIF_LINK1: edge %ld (opos=%.2f) snapped to %.2f"
                             " from %ld (opos=%.2f)\n",
    -                        edge - edges, edge->opos / 64.0,
    -                        edge->pos / 64.0,
    -                        before - edges, before->opos / 64.0 ));
    +                        edge - edges, (double)edge->opos / 64,
    +                        (double)edge->pos / 64,
    +                        before - edges, (double)before->opos / 64 ));
               }
               else
               {
    @@ -3475,7 +3479,8 @@
                             ( ( edge->opos - anchor->opos + 16 ) & ~31 );
                 FT_TRACE5(( "  SERIF_LINK2: edge %ld (opos=%.2f)"
                             " snapped to %.2f\n",
    -                        edge - edges, edge->opos / 64.0, edge->pos / 64.0 ));
    +                        edge - edges,
    +                        (double)edge->opos / 64, (double)edge->pos / 64 ));
               }
             }
     
    @@ -3495,8 +3500,8 @@
     #ifdef FT_DEBUG_LEVEL_TRACE
                 FT_TRACE5(( "  BOUND: edge %ld (pos=%.2f) moved to %.2f\n",
                             edge - edges,
    -                        edge->pos / 64.0,
    -                        edge[-1].pos / 64.0 ));
    +                        (double)edge->pos / 64,
    +                        (double)edge[-1].pos / 64 ));
     
                 num_actions++;
     #endif
    @@ -3516,8 +3521,8 @@
     #ifdef FT_DEBUG_LEVEL_TRACE
                 FT_TRACE5(( "  BOUND: edge %ld (pos=%.2f) moved to %.2f\n",
                             edge - edges,
    -                        edge->pos / 64.0,
    -                        edge[1].pos / 64.0 ));
    +                        (double)edge->pos / 64,
    +                        (double)edge[1].pos / 64 ));
     
                 num_actions++;
     #endif
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h
    index facc663450d..3c6a7ee4f62 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h
    @@ -5,7 +5,7 @@
      *   Auto-fitter hinting routines for latin writing system
      *   (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
    index e55183a509f..c8082796fe8 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter glyph loading routines (body).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -229,9 +229,6 @@
         AF_WritingSystemClass  writing_system_class;
     
     
    -    if ( !size )
    -      return FT_THROW( Invalid_Size_Handle );
    -
         FT_ZERO( &scaler );
     
         if ( !size_internal->autohint_metrics.x_scale                          ||
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h
    index b345e463953..e4e197e374f 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter glyph loading routines (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -75,7 +75,7 @@ FT_BEGIN_HEADER
                             FT_UInt    gindex,
                             FT_Int32   load_flags );
     
    -  FT_LOCAL_DEF( FT_Fixed )
    +  FT_LOCAL( FT_Fixed )
       af_loader_compute_darkening( AF_Loader  loader,
                                    FT_Face    face,
                                    FT_Pos     standard_width );
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c
    index 1b14ae682eb..92e5156ab2d 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter module implementation (body).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -43,14 +43,14 @@
     
     #endif
     
    -  int  _af_debug_disable_horz_hints;
    -  int  _af_debug_disable_vert_hints;
    -  int  _af_debug_disable_blue_hints;
    +  int  af_debug_disable_horz_hints_;
    +  int  af_debug_disable_vert_hints_;
    +  int  af_debug_disable_blue_hints_;
     
       /* we use a global object instead of a local one for debugging */
    -  static AF_GlyphHintsRec  _af_debug_hints_rec[1];
    +  static AF_GlyphHintsRec  af_debug_hints_rec_[1];
     
    -  void*  _af_debug_hints = _af_debug_hints_rec;
    +  void*  af_debug_hints_ = af_debug_hints_rec_;
     #endif
     
     #include 
    @@ -119,8 +119,8 @@
     
         if ( !ft_strcmp( property_name, "fallback-script" ) )
         {
    -      FT_UInt*  fallback_script;
    -      FT_UInt   ss;
    +      AF_Script*  fallback_script;
    +      FT_UInt     ss;
     
     
     #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
    @@ -128,7 +128,7 @@
             return FT_THROW( Invalid_Argument );
     #endif
     
    -      fallback_script = (FT_UInt*)value;
    +      fallback_script = (AF_Script*)value;
     
           /* We translate the fallback script to a fallback style that uses */
           /* `fallback-script' as its script and `AF_COVERAGE_NONE' as its  */
    @@ -138,8 +138,8 @@
             AF_StyleClass  style_class = af_style_classes[ss];
     
     
    -        if ( (FT_UInt)style_class->script == *fallback_script &&
    -             style_class->coverage == AF_COVERAGE_DEFAULT     )
    +        if ( style_class->script   == *fallback_script    &&
    +             style_class->coverage == AF_COVERAGE_DEFAULT )
             {
               module->fallback_style = ss;
               break;
    @@ -157,7 +157,7 @@
         }
         else if ( !ft_strcmp( property_name, "default-script" ) )
         {
    -      FT_UInt*  default_script;
    +      AF_Script*  default_script;
     
     
     #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
    @@ -165,7 +165,7 @@
             return FT_THROW( Invalid_Argument );
     #endif
     
    -      default_script = (FT_UInt*)value;
    +      default_script = (AF_Script*)value;
     
           module->default_script = *default_script;
     
    @@ -291,8 +291,6 @@
       {
         FT_Error   error          = FT_Err_Ok;
         AF_Module  module         = (AF_Module)ft_module;
    -    FT_UInt    fallback_style = module->fallback_style;
    -    FT_UInt    default_script = module->default_script;
     
     
         if ( !ft_strcmp( property_name, "glyph-to-script-map" ) )
    @@ -309,9 +307,9 @@
         }
         else if ( !ft_strcmp( property_name, "fallback-script" ) )
         {
    -      FT_UInt*  val = (FT_UInt*)value;
    +      AF_Script*  val = (AF_Script*)value;
     
    -      AF_StyleClass  style_class = af_style_classes[fallback_style];
    +      AF_StyleClass  style_class = af_style_classes[module->fallback_style];
     
     
           *val = style_class->script;
    @@ -320,10 +318,10 @@
         }
         else if ( !ft_strcmp( property_name, "default-script" ) )
         {
    -      FT_UInt*  val = (FT_UInt*)value;
    +      AF_Script*  val = (AF_Script*)value;
     
     
    -      *val = default_script;
    +      *val = module->default_script;
     
           return error;
         }
    @@ -425,8 +423,8 @@
         FT_UNUSED( ft_module );
     
     #ifdef FT_DEBUG_AUTOFIT
    -    if ( _af_debug_hints_rec->memory )
    -      af_glyph_hints_done( _af_debug_hints_rec );
    +    if ( af_debug_hints_rec_->memory )
    +      af_glyph_hints_done( af_debug_hints_rec_ );
     #endif
       }
     
    @@ -445,7 +443,7 @@
     
         /* in debug mode, we use a global object that survives this routine */
     
    -    AF_GlyphHints  hints = _af_debug_hints_rec;
    +    AF_GlyphHints  hints = af_debug_hints_rec_;
         AF_LoaderRec   loader[1];
     
         FT_UNUSED( size );
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h
    index 1d1bfaf5447..4b8b4562c67 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter module implementation (specification).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -36,7 +36,7 @@ FT_BEGIN_HEADER
         FT_ModuleRec  root;
     
         FT_UInt       fallback_style;
    -    FT_UInt       default_script;
    +    AF_Script     default_script;
         FT_Bool       no_stem_darkening;
         FT_Int        darken_params[8];
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c
    index 2de1991a57a..cfcaf340a79 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter Unicode script ranges (body).
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h
    index acd01faf687..5775738bc0b 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter Unicode script ranges (specification).
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h b/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h
    index 172b5980696..3a101937d70 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter scripts (specification only).
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c
    index 298480d864f..1b8b870e89d 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c
    @@ -4,7 +4,7 @@
      *
      *   HarfBuzz interface for accessing OpenType features (body).
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h
    index 558f03bdef0..054a18ffbc2 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h
    @@ -4,7 +4,7 @@
      *
      *   HarfBuzz interface for accessing OpenType features (specification).
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -27,7 +27,7 @@
     
     #include 
     #include 
    -#include 
    +#include "ft-hb.h"
     
     #endif
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h b/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h
    index 9080b9fb657..73ebef01716 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter styles (specification only).
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h b/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h
    index 754aad7ba4b..66151944965 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter types (specification only).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -57,10 +57,10 @@ FT_BEGIN_HEADER
     
     #ifdef FT_DEBUG_AUTOFIT
     
    -extern int    _af_debug_disable_horz_hints;
    -extern int    _af_debug_disable_vert_hints;
    -extern int    _af_debug_disable_blue_hints;
    -extern void*  _af_debug_hints;
    +extern int    af_debug_disable_horz_hints_;
    +extern int    af_debug_disable_vert_hints_;
    +extern int    af_debug_disable_blue_hints_;
    +extern void*  af_debug_hints_;
     
     #endif /* FT_DEBUG_AUTOFIT */
     
    @@ -119,13 +119,13 @@ extern void*  _af_debug_hints;
     
       typedef struct  AF_ScalerRec_
       {
    -    FT_Face         face;        /* source font face                        */
    -    FT_Fixed        x_scale;     /* from font units to 1/64th device pixels */
    -    FT_Fixed        y_scale;     /* from font units to 1/64th device pixels */
    -    FT_Pos          x_delta;     /* in 1/64th device pixels                 */
    -    FT_Pos          y_delta;     /* in 1/64th device pixels                 */
    -    FT_Render_Mode  render_mode; /* monochrome, anti-aliased, LCD, etc.     */
    -    FT_UInt32       flags;       /* additional control flags, see above     */
    +    FT_Face         face;        /* source font face                      */
    +    FT_Fixed        x_scale;     /* from font units to 1/64 device pixels */
    +    FT_Fixed        y_scale;     /* from font units to 1/64 device pixels */
    +    FT_Pos          x_delta;     /* in 1/64 device pixels                 */
    +    FT_Pos          y_delta;     /* in 1/64 device pixels                 */
    +    FT_Render_Mode  render_mode; /* monochrome, anti-aliased, LCD, etc.   */
    +    FT_UInt32       flags;       /* additional control flags, see above   */
     
       } AF_ScalerRec, *AF_Scaler;
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h b/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h
    index c93845ef953..48c888afed8 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter writing system declarations (specification only).
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h b/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h
    index 9cda3509bc1..a0a686f8cee 100644
    --- a/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h
    +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h
    @@ -4,7 +4,7 @@
      *
      *   Auto-fitter writing systems iterator (specification only).
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c
    index fc6b4288174..de25476fe92 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c
    @@ -4,7 +4,7 @@
      *
      *   Quick computation of advance widths (body).
      *
    - * Copyright (C) 2008-2022 by
    + * Copyright (C) 2008-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -23,7 +23,7 @@
     
     
       static FT_Error
    -  _ft_face_scale_advances( FT_Face    face,
    +  ft_face_scale_advances_( FT_Face    face,
                                FT_Fixed*  advances,
                                FT_UInt    count,
                                FT_Int32   flags )
    @@ -96,7 +96,7 @@
     
           error = func( face, gindex, 1, flags, padvance );
           if ( !error )
    -        return _ft_face_scale_advances( face, padvance, 1, flags );
    +        return ft_face_scale_advances_( face, padvance, 1, flags );
     
           if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
             return error;
    @@ -142,7 +142,7 @@
         {
           error = func( face, start, count, flags, padvances );
           if ( !error )
    -        return _ft_face_scale_advances( face, padvances, count, flags );
    +        return ft_face_scale_advances_( face, padvances, count, flags );
     
           if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
             return error;
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbase.h b/src/java.desktop/share/native/libfreetype/src/base/ftbase.h
    index f873566f222..00790d3b226 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftbase.h
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftbase.h
    @@ -4,7 +4,7 @@
      *
      *   Private functions used in the `base' module (specification).
      *
    - * Copyright (C) 2008-2022 by
    + * Copyright (C) 2008-2023 by
      * David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c b/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c
    index 30aedf780cd..7dd71882ea5 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType bbox computation (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c
    index 7825895ad6a..1c93648dcbc 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType utility functions for bitmaps (body).
      *
    - * Copyright (C) 2004-2022 by
    + * Copyright (C) 2004-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -66,11 +66,8 @@
       {
         FT_Memory  memory;
         FT_Error   error  = FT_Err_Ok;
    -
    -    FT_Int    pitch;
    -    FT_ULong  size;
    -
    -    FT_Int  source_pitch_sign, target_pitch_sign;
    +    FT_Int     pitch;
    +    FT_Int     flip;
     
     
         if ( !library )
    @@ -82,53 +79,29 @@
         if ( source == target )
           return FT_Err_Ok;
     
    -    source_pitch_sign = source->pitch < 0 ? -1 : 1;
    -    target_pitch_sign = target->pitch < 0 ? -1 : 1;
    +    flip = ( source->pitch < 0 && target->pitch > 0 ) ||
    +           ( source->pitch > 0 && target->pitch < 0 );
     
    -    if ( !source->buffer )
    -    {
    -      *target = *source;
    -      if ( source_pitch_sign != target_pitch_sign )
    -        target->pitch = -target->pitch;
    +    memory = library->memory;
    +    FT_FREE( target->buffer );
    +
    +    *target = *source;
    +
    +    if ( flip )
    +      target->pitch = -target->pitch;
     
    +    if ( !source->buffer )
           return FT_Err_Ok;
    -    }
     
    -    memory = library->memory;
         pitch  = source->pitch;
    -
         if ( pitch < 0 )
           pitch = -pitch;
    -    size = (FT_ULong)pitch * source->rows;
    -
    -    if ( target->buffer )
    -    {
    -      FT_Int    target_pitch = target->pitch;
    -      FT_ULong  target_size;
     
    -
    -      if ( target_pitch < 0 )
    -        target_pitch = -target_pitch;
    -      target_size = (FT_ULong)target_pitch * target->rows;
    -
    -      if ( target_size != size )
    -        FT_MEM_QREALLOC( target->buffer, target_size, size );
    -    }
    -    else
    -      FT_MEM_QALLOC( target->buffer, size );
    +    FT_MEM_QALLOC_MULT( target->buffer, target->rows, pitch );
     
         if ( !error )
         {
    -      unsigned char *p;
    -
    -
    -      p = target->buffer;
    -      *target = *source;
    -      target->buffer = p;
    -
    -      if ( source_pitch_sign == target_pitch_sign )
    -        FT_MEM_COPY( target->buffer, source->buffer, size );
    -      else
    +      if ( flip )
           {
             /* take care of bitmap flow */
             FT_UInt   i;
    @@ -146,6 +119,9 @@
               t -= pitch;
             }
           }
    +      else
    +        FT_MEM_COPY( target->buffer, source->buffer,
    +                     (FT_Long)source->rows * pitch );
         }
     
         return error;
    @@ -542,39 +518,31 @@
         case FT_PIXEL_MODE_LCD_V:
         case FT_PIXEL_MODE_BGRA:
           {
    -        FT_Int    pad, old_target_pitch, target_pitch;
    -        FT_ULong  old_size;
    +        FT_Int  width = (FT_Int)source->width;
    +        FT_Int  neg   = ( target->pitch == 0 && source->pitch < 0 ) ||
    +                          target->pitch  < 0;
     
     
    -        old_target_pitch = target->pitch;
    -        if ( old_target_pitch < 0 )
    -          old_target_pitch = -old_target_pitch;
    -
    -        old_size = target->rows * (FT_UInt)old_target_pitch;
    +        FT_Bitmap_Done( library, target );
     
             target->pixel_mode = FT_PIXEL_MODE_GRAY;
             target->rows       = source->rows;
             target->width      = source->width;
     
    -        pad = 0;
    -        if ( alignment > 0 )
    +        if ( alignment )
             {
    -          pad = (FT_Int)source->width % alignment;
    -          if ( pad != 0 )
    -            pad = alignment - pad;
    -        }
    +          FT_Int  rem = width % alignment;
     
    -        target_pitch = (FT_Int)source->width + pad;
     
    -        if ( target_pitch > 0                                               &&
    -             (FT_ULong)target->rows > FT_ULONG_MAX / (FT_ULong)target_pitch )
    -          return FT_THROW( Invalid_Argument );
    +          if ( rem )
    +            width = alignment > 0 ? width - rem + alignment
    +                                  : width - rem - alignment;
    +        }
     
    -        if ( FT_QREALLOC( target->buffer,
    -                          old_size, target->rows * (FT_UInt)target_pitch ) )
    +        if ( FT_QALLOC_MULT( target->buffer, target->rows, width ) )
               return error;
     
    -        target->pitch = target->pitch < 0 ? -target_pitch : target_pitch;
    +        target->pitch = neg ? -width : width;
           }
           break;
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c b/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c
    index 6c1e7fbd45a..13e74f3353b 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c
    @@ -4,7 +4,7 @@
      *
      *   Arithmetic computations (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -1085,4 +1085,71 @@
       }
     
     
    +  FT_BASE_DEF( FT_Int32 )
    +  FT_MulAddFix( FT_Fixed*  s,
    +                FT_Int32*  f,
    +                FT_UInt    count )
    +  {
    +    FT_UInt   i;
    +    FT_Int64  temp;
    +#ifndef FT_INT64
    +    FT_Int64  halfUnit;
    +#endif
    +
    +
    +#ifdef FT_INT64
    +    temp = 0;
    +
    +    for ( i = 0; i < count; ++i )
    +      temp += (FT_Int64)s[i] * f[i];
    +
    +    return ( temp + 0x8000 ) >> 16;
    +#else
    +    temp.hi = 0;
    +    temp.lo = 0;
    +
    +    for ( i = 0; i < count; ++i )
    +    {
    +      FT_Int64  multResult;
    +
    +      FT_Int     sign  = 1;
    +      FT_UInt32  carry = 0;
    +
    +      FT_UInt32  scalar;
    +      FT_UInt32  factor;
    +
    +
    +      scalar = (FT_UInt32)s[i];
    +      factor = (FT_UInt32)f[i];
    +
    +      FT_MOVE_SIGN( s[i], scalar, sign );
    +      FT_MOVE_SIGN( f[i], factor, sign );
    +
    +      ft_multo64( scalar, factor, &multResult );
    +
    +      if ( sign < 0 )
    +      {
    +        /* Emulated `FT_Int64` negation. */
    +        carry = ( multResult.lo == 0 );
    +
    +        multResult.lo = ~multResult.lo + 1;
    +        multResult.hi = ~multResult.hi + carry;
    +      }
    +
    +      FT_Add64( &temp, &multResult, &temp );
    +    }
    +
    +    /* Round value. */
    +    halfUnit.hi = 0;
    +    halfUnit.lo = 0x8000;
    +    FT_Add64( &temp, &halfUnit, &temp );
    +
    +    return (FT_Int32)( ( (FT_Int32)( temp.hi & 0xFFFF ) << 16 ) |
    +                                   ( temp.lo >> 16 )            );
    +
    +#endif /* !FT_INT64 */
    +
    +  }
    +
    +
     /* END */
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcid.c b/src/java.desktop/share/native/libfreetype/src/base/ftcid.c
    index b882ca3de0a..866cd23e91b 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftcid.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftcid.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType API for accessing CID font information.
      *
    - * Copyright (C) 2007-2022 by
    + * Copyright (C) 2007-2023 by
      * Derek Clegg and Michael Toftdal.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c b/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c
    new file mode 100644
    index 00000000000..bcd6e893d4a
    --- /dev/null
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c
    @@ -0,0 +1,156 @@
    +/****************************************************************************
    + *
    + * ftcolor.c
    + *
    + *   FreeType's glyph color management (body).
    + *
    + * Copyright (C) 2018-2023 by
    + * David Turner, Robert Wilhelm, and Werner Lemberg.
    + *
    + * This file is part of the FreeType project, and may only be used,
    + * modified, and distributed under the terms of the FreeType project
    + * license, LICENSE.TXT.  By continuing to use, modify, or distribute
    + * this file you indicate that you have read the license and
    + * understand and accept it fully.
    + *
    + */
    +
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +
    +#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
    +
    +  static
    +  const FT_Palette_Data  null_palette_data = { 0, NULL, NULL, 0, NULL };
    +
    +
    +  /* documentation is in ftcolor.h */
    +
    +  FT_EXPORT_DEF( FT_Error )
    +  FT_Palette_Data_Get( FT_Face           face,
    +                       FT_Palette_Data  *apalette_data )
    +  {
    +    if ( !face )
    +      return FT_THROW( Invalid_Face_Handle );
    +    if ( !apalette_data)
    +      return FT_THROW( Invalid_Argument );
    +
    +    if ( FT_IS_SFNT( face ) )
    +      *apalette_data = ( (TT_Face)face )->palette_data;
    +    else
    +      *apalette_data = null_palette_data;
    +
    +    return FT_Err_Ok;
    +  }
    +
    +
    +  /* documentation is in ftcolor.h */
    +
    +  FT_EXPORT_DEF( FT_Error )
    +  FT_Palette_Select( FT_Face     face,
    +                     FT_UShort   palette_index,
    +                     FT_Color*  *apalette )
    +  {
    +    FT_Error  error;
    +
    +    TT_Face       ttface;
    +    SFNT_Service  sfnt;
    +
    +
    +    if ( !face )
    +      return FT_THROW( Invalid_Face_Handle );
    +
    +    if ( !FT_IS_SFNT( face ) )
    +    {
    +      if ( apalette )
    +        *apalette = NULL;
    +
    +      return FT_Err_Ok;
    +    }
    +
    +    ttface = (TT_Face)face;
    +    sfnt   = (SFNT_Service)ttface->sfnt;
    +
    +    error = sfnt->set_palette( ttface, palette_index );
    +    if ( error )
    +      return error;
    +
    +    ttface->palette_index = palette_index;
    +
    +    if ( apalette )
    +      *apalette = ttface->palette;
    +
    +    return FT_Err_Ok;
    +  }
    +
    +
    +  /* documentation is in ftcolor.h */
    +
    +  FT_EXPORT_DEF( FT_Error )
    +  FT_Palette_Set_Foreground_Color( FT_Face   face,
    +                                   FT_Color  foreground_color )
    +  {
    +    TT_Face  ttface;
    +
    +
    +    if ( !face )
    +      return FT_THROW( Invalid_Face_Handle );
    +
    +    if ( !FT_IS_SFNT( face ) )
    +      return FT_Err_Ok;
    +
    +    ttface = (TT_Face)face;
    +
    +    ttface->foreground_color      = foreground_color;
    +    ttface->have_foreground_color = 1;
    +
    +    return FT_Err_Ok;
    +  }
    +
    +#else /* !TT_CONFIG_OPTION_COLOR_LAYERS */
    +
    +  FT_EXPORT_DEF( FT_Error )
    +  FT_Palette_Data_Get( FT_Face           face,
    +                       FT_Palette_Data  *apalette_data )
    +  {
    +    FT_UNUSED( face );
    +    FT_UNUSED( apalette_data );
    +
    +
    +    return FT_THROW( Unimplemented_Feature );
    +  }
    +
    +
    +  FT_EXPORT_DEF( FT_Error )
    +  FT_Palette_Select( FT_Face     face,
    +                     FT_UShort   palette_index,
    +                     FT_Color*  *apalette )
    +  {
    +    FT_UNUSED( face );
    +    FT_UNUSED( palette_index );
    +    FT_UNUSED( apalette );
    +
    +
    +    return FT_THROW( Unimplemented_Feature );
    +  }
    +
    +
    +  FT_EXPORT_DEF( FT_Error )
    +  FT_Palette_Set_Foreground_Color( FT_Face   face,
    +                                   FT_Color  foreground_color )
    +  {
    +    FT_UNUSED( face );
    +    FT_UNUSED( foreground_color );
    +
    +
    +    return FT_THROW( Unimplemented_Feature );
    +  }
    +
    +#endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */
    +
    +
    +/* END */
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c b/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c
    index 1df83c404db..6730c4c8d38 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c
    @@ -4,7 +4,7 @@
      *
      *   Memory debugger (body).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -35,8 +35,8 @@
     
     #include FT_CONFIG_STANDARD_LIBRARY_H
     
    -  FT_BASE_DEF( const char* )  _ft_debug_file   = NULL;
    -  FT_BASE_DEF( long )         _ft_debug_lineno = 0;
    +  FT_BASE_DEF( const char* )  ft_debug_file_   = NULL;
    +  FT_BASE_DEF( long )         ft_debug_lineno_ = 0;
     
       extern void
       FT_DumpMemory( FT_Memory  memory );
    @@ -415,8 +415,8 @@
     
         /* cast to FT_PtrDist first since void* can be larger */
         /* than FT_UInt32 and GCC 4.1.1 emits a warning       */
    -    hash  = (FT_UInt32)(FT_PtrDist)(void*)_ft_debug_file +
    -              (FT_UInt32)( 5 * _ft_debug_lineno );
    +    hash  = (FT_UInt32)(FT_PtrDist)(void*)ft_debug_file_ +
    +              (FT_UInt32)( 5 * ft_debug_lineno_ );
         pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS];
     
         for (;;)
    @@ -425,8 +425,8 @@
           if ( !node )
             break;
     
    -      if ( node->file_name == _ft_debug_file   &&
    -           node->line_no   == _ft_debug_lineno )
    +      if ( node->file_name == ft_debug_file_   &&
    +           node->line_no   == ft_debug_lineno_ )
             goto Exit;
     
           pnode = &node->link;
    @@ -437,8 +437,8 @@
           ft_mem_debug_panic(
             "not enough memory to perform memory debugging\n" );
     
    -    node->file_name = _ft_debug_file;
    -    node->line_no   = _ft_debug_lineno;
    +    node->file_name = ft_debug_file_;
    +    node->line_no   = ft_debug_lineno_;
     
         node->cur_blocks = 0;
         node->max_blocks = 0;
    @@ -495,7 +495,7 @@
                 "org=%s:%d new=%s:%d\n",
                 node->address, node->size,
                 FT_FILENAME( node->source->file_name ), node->source->line_no,
    -            FT_FILENAME( _ft_debug_file ), _ft_debug_lineno );
    +            FT_FILENAME( ft_debug_file_ ), ft_debug_lineno_ );
             }
           }
     
    @@ -582,7 +582,7 @@
                 "  Block was allocated at (%s:%ld)\n"
                 "  and released at (%s:%ld).",
                 address,
    -            FT_FILENAME( _ft_debug_file ), _ft_debug_lineno,
    +            FT_FILENAME( ft_debug_file_ ), ft_debug_lineno_,
                 FT_FILENAME( node->source->file_name ), node->source->line_no,
                 FT_FILENAME( node->free_file_name ), node->free_line_no );
     
    @@ -604,8 +604,8 @@
               /* we simply invert the node's size to indicate that the node */
               /* was freed.                                                 */
               node->size           = -node->size;
    -          node->free_file_name = _ft_debug_file;
    -          node->free_line_no   = _ft_debug_lineno;
    +          node->free_file_name = ft_debug_file_;
    +          node->free_line_no   = ft_debug_lineno_;
             }
             else
             {
    @@ -627,7 +627,7 @@
             ft_mem_debug_panic(
               "trying to free unknown block at %p in (%s:%ld)\n",
               address,
    -          FT_FILENAME( _ft_debug_file ), _ft_debug_lineno );
    +          FT_FILENAME( ft_debug_file_ ), ft_debug_lineno_ );
         }
       }
     
    @@ -661,8 +661,8 @@
           table->alloc_count++;
         }
     
    -    _ft_debug_file   = "";
    -    _ft_debug_lineno = 0;
    +    ft_debug_file_   = "";
    +    ft_debug_lineno_ = 0;
     
         return (FT_Pointer)block;
       }
    @@ -677,8 +677,8 @@
     
         if ( !block )
           ft_mem_debug_panic( "trying to free NULL in (%s:%ld)",
    -                          FT_FILENAME( _ft_debug_file ),
    -                          _ft_debug_lineno );
    +                          FT_FILENAME( ft_debug_file_ ),
    +                          ft_debug_lineno_ );
     
         ft_mem_table_remove( table, (FT_Byte*)block, 0 );
     
    @@ -687,8 +687,8 @@
     
         table->alloc_count--;
     
    -    _ft_debug_file   = "";
    -    _ft_debug_lineno = 0;
    +    ft_debug_file_   = "";
    +    ft_debug_lineno_ = 0;
       }
     
     
    @@ -703,8 +703,8 @@
         FT_Pointer   new_block;
         FT_Long      delta;
     
    -    const char*  file_name = FT_FILENAME( _ft_debug_file );
    -    FT_Long      line_no   = _ft_debug_lineno;
    +    const char*  file_name = FT_FILENAME( ft_debug_file_ );
    +    FT_Long      line_no   = ft_debug_lineno_;
     
     
         /* unlikely, but possible */
    @@ -767,8 +767,8 @@
     
         ft_mem_table_remove( table, (FT_Byte*)block, delta );
     
    -    _ft_debug_file   = "";
    -    _ft_debug_lineno = 0;
    +    ft_debug_file_   = "";
    +    ft_debug_lineno_ = 0;
     
         if ( !table->keep_alive )
           ft_mem_table_free( table, block );
    @@ -874,7 +874,7 @@
       }
     
     
    -  static int
    +  FT_COMPARE_DEF( int )
       ft_mem_source_compare( const void*  p1,
                              const void*  p2 )
       {
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c b/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c
    index 648fff44edb..61c4563b0c4 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c
    @@ -4,7 +4,7 @@
      *
      *   Debugging and logging component (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c b/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c
    index e69c1e06842..0b41f7cc83d 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType utility file for font formats (body).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c b/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c
    index 009d58c57d5..ea24e64c6ea 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType utility file to access FSType data (body).
      *
    - * Copyright (C) 2008-2022 by
    + * Copyright (C) 2008-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c b/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c
    index 7567e3077ae..29b7b08b787 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c
    @@ -4,7 +4,7 @@
      *
      *   Access of TrueType's `gasp' table (body).
      *
    - * Copyright (C) 2007-2022 by
    + * Copyright (C) 2007-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c b/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c
    index f05abdee818..9823d09e41a 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c
    @@ -4,7 +4,7 @@
      *
      *   The FreeType glyph loader (body).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -212,12 +212,12 @@
         FT_Outline*  current = &loader->current.outline;
         FT_Bool      adjust  = 0;
     
    -    FT_UInt      new_max, old_max;
    +    FT_UInt  new_max, old_max, min_new_max;
     
     
         error = FT_GlyphLoader_CreateExtra( loader );
         if ( error )
    -      return error;
    +      goto Exit;
     
         /* check points & tags */
         new_max = (FT_UInt)base->n_points + (FT_UInt)current->n_points +
    @@ -226,10 +226,18 @@
     
         if ( new_max > old_max )
         {
    -      new_max = FT_PAD_CEIL( new_max, 8 );
    +      if ( new_max > FT_OUTLINE_POINTS_MAX )
    +      {
    +        error = FT_THROW( Array_Too_Large );
    +        goto Exit;
    +      }
     
    +      min_new_max = old_max + ( old_max >> 1 );
    +      if ( new_max < min_new_max )
    +        new_max = min_new_max;
    +      new_max = FT_PAD_CEIL( new_max, 8 );
           if ( new_max > FT_OUTLINE_POINTS_MAX )
    -        return FT_THROW( Array_Too_Large );
    +        new_max = FT_OUTLINE_POINTS_MAX;
     
           if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) ||
                FT_RENEW_ARRAY( base->tags,   old_max, new_max ) )
    @@ -254,7 +262,7 @@
     
         error = FT_GlyphLoader_CreateExtra( loader );
         if ( error )
    -      return error;
    +      goto Exit;
     
         /* check contours */
         old_max = loader->max_contours;
    @@ -262,10 +270,18 @@
                   n_contours;
         if ( new_max > old_max )
         {
    -      new_max = FT_PAD_CEIL( new_max, 4 );
    +      if ( new_max > FT_OUTLINE_CONTOURS_MAX )
    +      {
    +        error = FT_THROW( Array_Too_Large );
    +        goto Exit;
    +      }
     
    +      min_new_max = old_max + ( old_max >> 1 );
    +      if ( new_max < min_new_max )
    +        new_max = min_new_max;
    +      new_max = FT_PAD_CEIL( new_max, 4 );
           if ( new_max > FT_OUTLINE_CONTOURS_MAX )
    -        return FT_THROW( Array_Too_Large );
    +        new_max = FT_OUTLINE_CONTOURS_MAX;
     
           if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) )
             goto Exit;
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c
    index 571dca1a965..393d4949f84 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType convenience functions to handle glyphs (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -682,7 +682,10 @@
       Exit2:
         /* if an error occurred, destroy the glyph */
         if ( error )
    +    {
           FT_Done_Glyph( glyph );
    +      *aglyph = NULL;
    +    }
         else
           *aglyph = glyph;
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftinit.c b/src/java.desktop/share/native/libfreetype/src/base/ftinit.c
    index 0f29a6017e5..c9c71d24bf9 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftinit.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftinit.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType initialization layer (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c
    index e72f6d668d7..6c3fd66e0bb 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType API for color filtering of subpixel bitmap glyphs (body).
      *
    - * Copyright (C) 2006-2022 by
    + * Copyright (C) 2006-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftmac.c b/src/java.desktop/share/native/libfreetype/src/base/ftmac.c
    index 21f1894ad38..de34e834f25 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftmac.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftmac.c
    @@ -8,7 +8,7 @@
      * This file is for Mac OS X only; see builds/mac/ftoldmac.c for
      * classic platforms built by MPW.
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -67,6 +67,7 @@
     
     #include 
     #include 
    +#include 
     #include 
     #include "ftbase.h"
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftmm.c b/src/java.desktop/share/native/libfreetype/src/base/ftmm.c
    index dbbd87c9b9c..a2b4bd03d78 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftmm.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftmm.c
    @@ -4,7 +4,7 @@
      *
      *   Multiple Master font support (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c
    index eeda69c3ed8..ad6ef0ae168 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c
    @@ -4,7 +4,7 @@
      *
      *   The FreeType private base classes (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -508,7 +508,7 @@
     
         case FT_PIXEL_MODE_LCD_V:
           height *= 3;
    -      /* fall through */
    +      FALL_THROUGH;
     
         case FT_PIXEL_MODE_GRAY:
         default:
    @@ -605,7 +605,7 @@
     
     
             FT_FREE( doc->svg_document );
    -        slot->internal->load_flags &= ~FT_GLYPH_OWN_GZIP_SVG;
    +        slot->internal->flags &= ~FT_GLYPH_OWN_GZIP_SVG;
           }
         }
     #endif
    @@ -631,8 +631,9 @@
     #ifdef FT_CONFIG_OPTION_SVG
         if ( slot->face->face_flags & FT_FACE_FLAG_SVG )
         {
    -      /* free memory in case SVG was there */
    -      if ( slot->internal->flags & FT_GLYPH_OWN_GZIP_SVG )
    +      /* Free memory in case SVG was there.                          */
    +      /* `slot->internal` might be NULL in out-of-memory situations. */
    +      if ( slot->internal && slot->internal->flags & FT_GLYPH_OWN_GZIP_SVG )
           {
             FT_SVG_Document  doc = (FT_SVG_Document)slot->other;
     
    @@ -1184,28 +1185,34 @@
                     pixel_modes[slot->bitmap.pixel_mode],
                     slot->bitmap.pixel_mode ));
         FT_TRACE5(( "\n" ));
    -    FT_TRACE5(( "  x advance: %f\n", slot->advance.x / 64.0 ));
    -    FT_TRACE5(( "  y advance: %f\n", slot->advance.y / 64.0 ));
    +    FT_TRACE5(( "  x advance: %f\n", (double)slot->advance.x / 64 ));
    +    FT_TRACE5(( "  y advance: %f\n", (double)slot->advance.y / 64 ));
         FT_TRACE5(( "  linear x advance: %f\n",
    -                slot->linearHoriAdvance / 65536.0 ));
    +                (double)slot->linearHoriAdvance / 65536 ));
         FT_TRACE5(( "  linear y advance: %f\n",
    -                slot->linearVertAdvance / 65536.0 ));
    +                (double)slot->linearVertAdvance / 65536 ));
     
         {
           FT_Glyph_Metrics*  metrics = &slot->metrics;
     
     
           FT_TRACE5(( "  metrics:\n" ));
    -      FT_TRACE5(( "    width:  %f\n", metrics->width  / 64.0 ));
    -      FT_TRACE5(( "    height: %f\n", metrics->height / 64.0 ));
    +      FT_TRACE5(( "    width:  %f\n", (double)metrics->width / 64 ));
    +      FT_TRACE5(( "    height: %f\n", (double)metrics->height / 64 ));
           FT_TRACE5(( "\n" ));
    -      FT_TRACE5(( "    horiBearingX: %f\n", metrics->horiBearingX / 64.0 ));
    -      FT_TRACE5(( "    horiBearingY: %f\n", metrics->horiBearingY / 64.0 ));
    -      FT_TRACE5(( "    horiAdvance:  %f\n", metrics->horiAdvance  / 64.0 ));
    +      FT_TRACE5(( "    horiBearingX: %f\n",
    +                  (double)metrics->horiBearingX / 64 ));
    +      FT_TRACE5(( "    horiBearingY: %f\n",
    +                  (double)metrics->horiBearingY / 64 ));
    +      FT_TRACE5(( "    horiAdvance:  %f\n",
    +                  (double)metrics->horiAdvance / 64 ));
           FT_TRACE5(( "\n" ));
    -      FT_TRACE5(( "    vertBearingX: %f\n", metrics->vertBearingX / 64.0 ));
    -      FT_TRACE5(( "    vertBearingY: %f\n", metrics->vertBearingY / 64.0 ));
    -      FT_TRACE5(( "    vertAdvance:  %f\n", metrics->vertAdvance  / 64.0 ));
    +      FT_TRACE5(( "    vertBearingX: %f\n",
    +                  (double)metrics->vertBearingX / 64 ));
    +      FT_TRACE5(( "    vertBearingY: %f\n",
    +                  (double)metrics->vertBearingY / 64 ));
    +      FT_TRACE5(( "    vertAdvance:  %f\n",
    +                  (double)metrics->vertAdvance / 64 ));
         }
     #endif
     
    @@ -1488,7 +1495,7 @@
       static FT_Error
       open_face( FT_Driver      driver,
                  FT_Stream      *astream,
    -             FT_Bool        external_stream,
    +             FT_Bool        *anexternal_stream,
                  FT_Long        face_index,
                  FT_Int         num_params,
                  FT_Parameter*  params,
    @@ -1514,7 +1521,7 @@
         face->stream = *astream;
     
         /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
    -    if ( external_stream )
    +    if ( *anexternal_stream )
           face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
     
         if ( FT_NEW( internal ) )
    @@ -1544,7 +1551,10 @@
                                     (FT_Int)face_index,
                                     num_params,
                                     params );
    -    *astream = face->stream; /* Stream may have been changed. */
    +    /* Stream may have been changed. */
    +    *astream = face->stream;
    +    *anexternal_stream =
    +      ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0;
         if ( error )
           goto Fail;
     
    @@ -1668,13 +1678,13 @@
       static void
       memory_stream_close( FT_Stream  stream )
       {
    -    FT_Memory  memory = stream->memory;
    +    FT_Memory  memory = (FT_Memory)stream->descriptor.pointer;
     
     
         FT_FREE( stream->base );
    -
         stream->size  = 0;
         stream->close = NULL;
    +    FT_FREE( stream );
       }
     
     
    @@ -1705,7 +1715,8 @@
     
         FT_Stream_OpenMemory( stream, base, size );
     
    -    stream->close = close;
    +    stream->descriptor.pointer = memory;
    +    stream->close              = close;
     
         *astream = stream;
     
    @@ -1726,28 +1737,36 @@
       {
         FT_Open_Args  args;
         FT_Error      error;
    -    FT_Stream     stream = NULL;
         FT_Memory     memory = library->memory;
     
     
    +    args.flags = 0;
    +
    +    if ( driver_name )
    +    {
    +      args.driver = FT_Get_Module( library, driver_name );
    +      if ( !args.driver )
    +      {
    +        FT_FREE( base );
    +        return FT_THROW( Missing_Module );
    +      }
    +
    +      args.flags = args.flags | FT_OPEN_DRIVER;
    +    }
    +
    +    /* `memory_stream_close` also frees the stream object. */
         error = new_memory_stream( library,
                                    base,
                                    size,
                                    memory_stream_close,
    -                               &stream );
    +                               &args.stream );
         if ( error )
         {
           FT_FREE( base );
           return error;
         }
     
    -    args.flags  = FT_OPEN_STREAM;
    -    args.stream = stream;
    -    if ( driver_name )
    -    {
    -      args.flags  = args.flags | FT_OPEN_DRIVER;
    -      args.driver = FT_Get_Module( library, driver_name );
    -    }
    +    args.flags |= FT_OPEN_STREAM;
     
     #ifdef FT_MACINTOSH
         /* At this point, the face index has served its purpose;  */
    @@ -1759,21 +1778,7 @@
           face_index &= 0x7FFF0000L; /* retain GX data */
     #endif
     
    -    error = ft_open_face_internal( library, &args, face_index, aface, 0 );
    -
    -    if ( !error )
    -      (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
    -    else
    -#ifdef FT_MACINTOSH
    -      FT_Stream_Free( stream, 0 );
    -#else
    -    {
    -      FT_Stream_Close( stream );
    -      FT_FREE( stream );
    -    }
    -#endif
    -
    -    return error;
    +    return ft_open_face_internal( library, &args, face_index, aface, 0 );
       }
     
     
    @@ -1916,7 +1921,7 @@
                                        sfnt_ps,
                                        length,
                                        FT_MIN( face_index, 0 ),
    -                                   is_sfnt_cid ? "cid" : "type1",
    +                                   is_sfnt_cid ? "t1cid" : "type1",
                                        aface );
       Exit:
         {
    @@ -2177,7 +2182,7 @@
         FT_Byte*   sfnt_data = NULL;
         FT_Error   error;
         FT_ULong   flag_offset;
    -    FT_Long    rlen;
    +    FT_ULong   rlen;
         int        is_cff;
         FT_Long    face_index_in_resource = 0;
     
    @@ -2192,11 +2197,11 @@
         if ( error )
           goto Exit;
     
    -    if ( FT_READ_LONG( rlen ) )
    +    if ( FT_READ_ULONG( rlen ) )
           goto Exit;
    -    if ( rlen < 1 )
    +    if ( !rlen )
           return FT_THROW( Cannot_Open_Resource );
    -    if ( (FT_ULong)rlen > FT_MAC_RFORK_MAX_LEN )
    +    if ( rlen > FT_MAC_RFORK_MAX_LEN )
           return FT_THROW( Invalid_Offset );
     
         error = open_face_PS_from_sfnt_stream( library,
    @@ -2214,8 +2219,9 @@
     
         if ( FT_QALLOC( sfnt_data, rlen ) )
           return error;
    -    error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, (FT_ULong)rlen );
    -    if ( error ) {
    +    error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
    +    if ( error )
    +    {
           FT_FREE( sfnt_data );
           goto Exit;
         }
    @@ -2223,7 +2229,7 @@
         is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
         error = open_face_from_buffer( library,
                                        sfnt_data,
    -                                   (FT_ULong)rlen,
    +                                   rlen,
                                        face_index_in_resource,
                                        is_cff ? "cff" : "truetype",
                                        aface );
    @@ -2552,7 +2558,7 @@
     
         /* test for valid `library' delayed to `FT_Stream_New' */
     
    -    if ( ( !aface && face_index >= 0 ) || !args )
    +    if ( !args )
           return FT_THROW( Invalid_Argument );
     
         external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
    @@ -2563,6 +2569,14 @@
         if ( error )
           goto Fail3;
     
    +    /* Do this error check after `FT_Stream_New` to ensure that the */
    +    /* 'close' callback is called.                                  */
    +    if ( !aface && face_index >= 0 )
    +    {
    +      error = FT_THROW( Invalid_Argument );
    +      goto Fail3;
    +    }
    +
         memory = library->memory;
     
         /* If the font driver is specified in the `args' structure, use */
    @@ -2584,7 +2598,7 @@
               params     = args->params;
             }
     
    -        error = open_face( driver, &stream, external_stream, face_index,
    +        error = open_face( driver, &stream, &external_stream, face_index,
                                num_params, params, &face );
             if ( !error )
               goto Success;
    @@ -2620,7 +2634,7 @@
                 params     = args->params;
               }
     
    -          error = open_face( driver, &stream, external_stream, face_index,
    +          error = open_face( driver, &stream, &external_stream, face_index,
                                  num_params, params, &face );
               if ( !error )
                 goto Success;
    @@ -2852,8 +2866,8 @@
       /* documentation is in freetype.h */
     
       FT_EXPORT_DEF( FT_Error )
    -  FT_Attach_Stream( FT_Face        face,
    -                    FT_Open_Args*  parameters )
    +  FT_Attach_Stream( FT_Face              face,
    +                    const FT_Open_Args*  parameters )
       {
         FT_Stream  stream;
         FT_Error   error;
    @@ -3278,34 +3292,49 @@
           scaled_h = FT_REQUEST_HEIGHT( req );
     
           /* determine scales */
    -      if ( req->width )
    +      if ( req->height || !req->width )
           {
    -        metrics->x_scale = FT_DivFix( scaled_w, w );
    -
    -        if ( req->height )
    +        if ( h == 0 )
             {
    -          metrics->y_scale = FT_DivFix( scaled_h, h );
    -
    -          if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
    -          {
    -            if ( metrics->y_scale > metrics->x_scale )
    -              metrics->y_scale = metrics->x_scale;
    -            else
    -              metrics->x_scale = metrics->y_scale;
    -          }
    +          FT_ERROR(( "FT_Request_Metrics: Divide by zero\n" ));
    +          error = FT_ERR( Divide_By_Zero );
    +          goto Exit;
             }
    -        else
    +
    +        metrics->y_scale = FT_DivFix( scaled_h, h );
    +      }
    +
    +      if ( req->width )
    +      {
    +        if ( w == 0 )
             {
    -          metrics->y_scale = metrics->x_scale;
    -          scaled_h = FT_MulDiv( scaled_w, h, w );
    +          FT_ERROR(( "FT_Request_Metrics: Divide by zero\n" ));
    +          error = FT_ERR( Divide_By_Zero );
    +          goto Exit;
             }
    +
    +        metrics->x_scale = FT_DivFix( scaled_w, w );
           }
           else
           {
    -        metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );
    +        metrics->x_scale = metrics->y_scale;
             scaled_w = FT_MulDiv( scaled_h, w, h );
           }
     
    +      if ( !req->height )
    +      {
    +        metrics->y_scale = metrics->x_scale;
    +        scaled_h = FT_MulDiv( scaled_w, h, w );
    +      }
    +
    +      if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
    +      {
    +        if ( metrics->y_scale > metrics->x_scale )
    +          metrics->y_scale = metrics->x_scale;
    +        else
    +          metrics->x_scale = metrics->y_scale;
    +      }
    +
       Calculate_Ppem:
           /* calculate the ppems */
           if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
    @@ -3379,15 +3408,19 @@
     
     
           FT_TRACE5(( "  x scale: %ld (%f)\n",
    -                  metrics->x_scale, metrics->x_scale / 65536.0 ));
    +                  metrics->x_scale, (double)metrics->x_scale / 65536 ));
           FT_TRACE5(( "  y scale: %ld (%f)\n",
    -                  metrics->y_scale, metrics->y_scale / 65536.0 ));
    -      FT_TRACE5(( "  ascender: %f\n",    metrics->ascender / 64.0 ));
    -      FT_TRACE5(( "  descender: %f\n",   metrics->descender / 64.0 ));
    -      FT_TRACE5(( "  height: %f\n",      metrics->height / 64.0 ));
    -      FT_TRACE5(( "  max advance: %f\n", metrics->max_advance / 64.0 ));
    -      FT_TRACE5(( "  x ppem: %d\n",      metrics->x_ppem ));
    -      FT_TRACE5(( "  y ppem: %d\n",      metrics->y_ppem ));
    +                  metrics->y_scale, (double)metrics->y_scale / 65536 ));
    +      FT_TRACE5(( "  ascender: %f\n",
    +                  (double)metrics->ascender / 64 ));
    +      FT_TRACE5(( "  descender: %f\n",
    +                  (double)metrics->descender / 64 ));
    +      FT_TRACE5(( "  height: %f\n",
    +                  (double)metrics->height / 64 ));
    +      FT_TRACE5(( "  max advance: %f\n",
    +                  (double)metrics->max_advance / 64 ));
    +      FT_TRACE5(( "  x ppem: %d\n", metrics->x_ppem ));
    +      FT_TRACE5(( "  y ppem: %d\n", metrics->y_ppem ));
         }
     #endif
     
    @@ -3459,15 +3492,19 @@
     
     
           FT_TRACE5(( "  x scale: %ld (%f)\n",
    -                  metrics->x_scale, metrics->x_scale / 65536.0 ));
    +                  metrics->x_scale, (double)metrics->x_scale / 65536 ));
           FT_TRACE5(( "  y scale: %ld (%f)\n",
    -                  metrics->y_scale, metrics->y_scale / 65536.0 ));
    -      FT_TRACE5(( "  ascender: %f\n",    metrics->ascender / 64.0 ));
    -      FT_TRACE5(( "  descender: %f\n",   metrics->descender / 64.0 ));
    -      FT_TRACE5(( "  height: %f\n",      metrics->height / 64.0 ));
    -      FT_TRACE5(( "  max advance: %f\n", metrics->max_advance / 64.0 ));
    -      FT_TRACE5(( "  x ppem: %d\n",      metrics->x_ppem ));
    -      FT_TRACE5(( "  y ppem: %d\n",      metrics->y_ppem ));
    +                  metrics->y_scale, (double)metrics->y_scale / 65536 ));
    +      FT_TRACE5(( "  ascender: %f\n",
    +                  (double)metrics->ascender / 64 ));
    +      FT_TRACE5(( "  descender: %f\n",
    +                  (double)metrics->descender / 64 ));
    +      FT_TRACE5(( "  height: %f\n",
    +                  (double)metrics->height / 64 ));
    +      FT_TRACE5(( "  max advance: %f\n",
    +                  (double)metrics->max_advance / 64 ));
    +      FT_TRACE5(( "  x ppem: %d\n", metrics->x_ppem ));
    +      FT_TRACE5(( "  y ppem: %d\n", metrics->y_ppem ));
         }
     #endif
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c b/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c
    index 624df03ad8d..30ff21ff39e 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType outline management (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -130,7 +130,7 @@
           }
     
           FT_TRACE5(( "  move to (%.2f, %.2f)\n",
    -                  v_start.x / 64.0, v_start.y / 64.0 ));
    +                  (double)v_start.x / 64, (double)v_start.y / 64 ));
           error = func_interface->move_to( &v_start, user );
           if ( error )
             goto Exit;
    @@ -152,7 +152,7 @@
                 vec.y = SCALED( point->y );
     
                 FT_TRACE5(( "  line to (%.2f, %.2f)\n",
    -                        vec.x / 64.0, vec.y / 64.0 ));
    +                        (double)vec.x / 64, (double)vec.y / 64 ));
                 error = func_interface->line_to( &vec, user );
                 if ( error )
                   goto Exit;
    @@ -181,8 +181,10 @@
                 {
                   FT_TRACE5(( "  conic to (%.2f, %.2f)"
                               " with control (%.2f, %.2f)\n",
    -                          vec.x / 64.0, vec.y / 64.0,
    -                          v_control.x / 64.0, v_control.y / 64.0 ));
    +                          (double)vec.x / 64,
    +                          (double)vec.y / 64,
    +                          (double)v_control.x / 64,
    +                          (double)v_control.y / 64 ));
                   error = func_interface->conic_to( &v_control, &vec, user );
                   if ( error )
                     goto Exit;
    @@ -197,8 +199,10 @@
     
                 FT_TRACE5(( "  conic to (%.2f, %.2f)"
                             " with control (%.2f, %.2f)\n",
    -                        v_middle.x / 64.0, v_middle.y / 64.0,
    -                        v_control.x / 64.0, v_control.y / 64.0 ));
    +                        (double)v_middle.x / 64,
    +                        (double)v_middle.y / 64,
    +                        (double)v_control.x / 64,
    +                        (double)v_control.y / 64 ));
                 error = func_interface->conic_to( &v_control, &v_middle, user );
                 if ( error )
                   goto Exit;
    @@ -209,8 +213,10 @@
     
               FT_TRACE5(( "  conic to (%.2f, %.2f)"
                           " with control (%.2f, %.2f)\n",
    -                      v_start.x / 64.0, v_start.y / 64.0,
    -                      v_control.x / 64.0, v_control.y / 64.0 ));
    +                      (double)v_start.x / 64,
    +                      (double)v_start.y / 64,
    +                      (double)v_control.x / 64,
    +                      (double)v_control.y / 64 ));
               error = func_interface->conic_to( &v_control, &v_start, user );
               goto Close;
     
    @@ -242,9 +248,12 @@
     
                   FT_TRACE5(( "  cubic to (%.2f, %.2f)"
                               " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
    -                          vec.x / 64.0, vec.y / 64.0,
    -                          vec1.x / 64.0, vec1.y / 64.0,
    -                          vec2.x / 64.0, vec2.y / 64.0 ));
    +                          (double)vec.x / 64,
    +                          (double)vec.y / 64,
    +                          (double)vec1.x / 64,
    +                          (double)vec1.y / 64,
    +                          (double)vec2.x / 64,
    +                          (double)vec2.y / 64 ));
                   error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
                   if ( error )
                     goto Exit;
    @@ -253,9 +262,12 @@
     
                 FT_TRACE5(( "  cubic to (%.2f, %.2f)"
                             " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
    -                        v_start.x / 64.0, v_start.y / 64.0,
    -                        vec1.x / 64.0, vec1.y / 64.0,
    -                        vec2.x / 64.0, vec2.y / 64.0 ));
    +                        (double)v_start.x / 64,
    +                        (double)v_start.y / 64,
    +                        (double)vec1.x / 64,
    +                        (double)vec1.y / 64,
    +                        (double)vec2.x / 64,
    +                        (double)vec2.y / 64 ));
                 error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
                 goto Close;
               }
    @@ -264,7 +276,7 @@
     
           /* close the contour with a line segment */
           FT_TRACE5(( "  line to (%.2f, %.2f)\n",
    -                  v_start.x / 64.0, v_start.y / 64.0 ));
    +                  (double)v_start.x / 64, (double)v_start.y / 64 ));
           error = func_interface->line_to( &v_start, user );
     
         Close:
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c b/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c
    index 353ed2b5317..cb5efadffb1 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c
    @@ -5,7 +5,7 @@
      *   FreeType API for checking patented TrueType bytecode instructions
      *   (body).  Obsolete, retained for backward compatibility.
      *
    - * Copyright (C) 2007-2022 by
    + * Copyright (C) 2007-2023 by
      * David Turner.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c b/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c
    index 81fcee08f6f..cefdf489d7f 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c
    @@ -5,7 +5,7 @@
      *   Get and set properties of PostScript drivers (body).
      *   See `ftdriver.h' for available properties.
      *
    - * Copyright (C) 2017-2022 by
    + * Copyright (C) 2017-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c b/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c
    index 356998d3fa1..2ab430195f2 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c
    @@ -4,7 +4,7 @@
      *
      *   Embedded resource forks accessor (body).
      *
    - * Copyright (C) 2004-2022 by
    + * Copyright (C) 2004-2023 by
      * Masatake YAMATO and Redhat K.K.
      *
      * FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c b/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c
    index 3bf20c389b3..1917a3f1dff 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c
    @@ -7,7 +7,7 @@
      *
      *   This is _not_ used to retrieve glyph names!
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftstream.c b/src/java.desktop/share/native/libfreetype/src/base/ftstream.c
    index cc926565c32..05c5637578b 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftstream.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftstream.c
    @@ -4,7 +4,7 @@
      *
      *   I/O stream support (body).
      *
    - * Copyright (C) 2000-2022 by
    + * Copyright (C) 2000-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -261,7 +261,7 @@
           }
     
     #ifdef FT_DEBUG_MEMORY
    -      /* assume _ft_debug_file and _ft_debug_lineno are already set */
    +      /* assume `ft_debug_file_` and `ft_debug_lineno_` are already set */
           stream->base = (unsigned char*)ft_mem_qalloc( memory,
                                                         (FT_Long)count,
                                                         &error );
    @@ -363,11 +363,11 @@
       }
     
     
    -  FT_BASE_DEF( FT_UShort )
    +  FT_BASE_DEF( FT_UInt16 )
       FT_Stream_GetUShort( FT_Stream  stream )
       {
         FT_Byte*   p;
    -    FT_UShort  result;
    +    FT_UInt16  result;
     
     
         FT_ASSERT( stream && stream->cursor );
    @@ -382,11 +382,11 @@
       }
     
     
    -  FT_BASE_DEF( FT_UShort )
    +  FT_BASE_DEF( FT_UInt16 )
       FT_Stream_GetUShortLE( FT_Stream  stream )
       {
         FT_Byte*   p;
    -    FT_UShort  result;
    +    FT_UInt16  result;
     
     
         FT_ASSERT( stream && stream->cursor );
    @@ -401,11 +401,11 @@
       }
     
     
    -  FT_BASE_DEF( FT_ULong )
    +  FT_BASE_DEF( FT_UInt32 )
       FT_Stream_GetUOffset( FT_Stream  stream )
       {
         FT_Byte*  p;
    -    FT_ULong  result;
    +    FT_UInt32 result;
     
     
         FT_ASSERT( stream && stream->cursor );
    @@ -419,11 +419,11 @@
       }
     
     
    -  FT_BASE_DEF( FT_ULong )
    +  FT_BASE_DEF( FT_UInt32 )
       FT_Stream_GetULong( FT_Stream  stream )
       {
         FT_Byte*  p;
    -    FT_ULong  result;
    +    FT_UInt32 result;
     
     
         FT_ASSERT( stream && stream->cursor );
    @@ -437,11 +437,11 @@
       }
     
     
    -  FT_BASE_DEF( FT_ULong )
    +  FT_BASE_DEF( FT_UInt32 )
       FT_Stream_GetULongLE( FT_Stream  stream )
       {
         FT_Byte*  p;
    -    FT_ULong  result;
    +    FT_UInt32 result;
     
     
         FT_ASSERT( stream && stream->cursor );
    @@ -493,13 +493,13 @@
       }
     
     
    -  FT_BASE_DEF( FT_UShort )
    +  FT_BASE_DEF( FT_UInt16 )
       FT_Stream_ReadUShort( FT_Stream  stream,
                             FT_Error*  error )
       {
         FT_Byte    reads[2];
         FT_Byte*   p;
    -    FT_UShort  result = 0;
    +    FT_UInt16  result = 0;
     
     
         FT_ASSERT( stream );
    @@ -538,13 +538,13 @@
       }
     
     
    -  FT_BASE_DEF( FT_UShort )
    +  FT_BASE_DEF( FT_UInt16 )
       FT_Stream_ReadUShortLE( FT_Stream  stream,
                               FT_Error*  error )
       {
         FT_Byte    reads[2];
         FT_Byte*   p;
    -    FT_UShort  result = 0;
    +    FT_UInt16  result = 0;
     
     
         FT_ASSERT( stream );
    @@ -628,13 +628,13 @@
       }
     
     
    -  FT_BASE_DEF( FT_ULong )
    +  FT_BASE_DEF( FT_UInt32 )
       FT_Stream_ReadULong( FT_Stream  stream,
                            FT_Error*  error )
       {
         FT_Byte   reads[4];
         FT_Byte*  p;
    -    FT_ULong  result = 0;
    +    FT_UInt32 result = 0;
     
     
         FT_ASSERT( stream );
    @@ -673,13 +673,13 @@
       }
     
     
    -  FT_BASE_DEF( FT_ULong )
    +  FT_BASE_DEF( FT_UInt32 )
       FT_Stream_ReadULongLE( FT_Stream  stream,
                              FT_Error*  error )
       {
         FT_Byte   reads[4];
         FT_Byte*  p;
    -    FT_ULong  result = 0;
    +    FT_UInt32 result = 0;
     
     
         FT_ASSERT( stream );
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c b/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c
    index aa983f940f2..db358e772ed 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType path stroker (body).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c b/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c
    index 10bbe0dfdaf..6ec25e13e47 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType synthesizing code for emboldening and slanting (body).
      *
    - * Copyright (C) 2000-2022 by
    + * Copyright (C) 2000-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -45,6 +45,18 @@
     
       FT_EXPORT_DEF( void )
       FT_GlyphSlot_Oblique( FT_GlyphSlot  slot )
    +  {
    +    /* Value '0x0366A' corresponds to a shear angle of about 12 degrees. */
    +    FT_GlyphSlot_Slant( slot, 0x0366A, 0 );
    +  }
    +
    +
    +  /* documentation is in ftsynth.h */
    +
    +  FT_EXPORT_DEF( void )
    +  FT_GlyphSlot_Slant( FT_GlyphSlot  slot,
    +                      FT_Fixed      xslant,
    +                      FT_Fixed      yslant )
       {
         FT_Matrix    transform;
         FT_Outline*  outline;
    @@ -61,13 +73,11 @@
     
         /* we don't touch the advance width */
     
    -    /* For italic, simply apply a shear transform, with an angle */
    -    /* of about 12 degrees.                                      */
    -
    +    /* For italic, simply apply a shear transform */
         transform.xx = 0x10000L;
    -    transform.yx = 0x00000L;
    +    transform.yx = -yslant;
     
    -    transform.xy = 0x0366AL;
    +    transform.xy = xslant;
         transform.yy = 0x10000L;
     
         FT_Outline_Transform( outline, &transform );
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c b/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c
    index d8826b23671..fcd289d19f4 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c
    @@ -4,7 +4,7 @@
      *
      *   ANSI-specific FreeType low-level system interface (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c b/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c
    index 6964edb0f59..2dd2c3459e5 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType trigonometric functions (body).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/fttype1.c b/src/java.desktop/share/native/libfreetype/src/base/fttype1.c
    index de3d5a48bdc..637c5cf775e 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/fttype1.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/fttype1.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType utility file for PS names support (body).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c
    index 5a913825802..6120846d2ca 100644
    --- a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c
    +++ b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType utility file for memory and list management (body).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c
    index 2d667a7248f..6ed31432227 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c
    @@ -4,7 +4,7 @@
      *
      *   CFF character mapping table (cmap) support (body).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h
    index 2818d3c6fed..b2afc2fab62 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h
    @@ -4,7 +4,7 @@
      *
      *   CFF character mapping table (cmap) support (specification).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c
    index d945afdfe82..4e2e0e00deb 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c
    @@ -4,8 +4,8 @@
      *
      *   OpenType font driver implementation (body).
      *
    - * Copyright (C) 1996-2022 by
    - * David Turner, Robert Wilhelm, and Werner Lemberg.
    + * Copyright (C) 1996-2023 by
    + * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
      *
      * This file is part of the FreeType project, and may only be used,
      * modified, and distributed under the terms of the FreeType project
    @@ -936,22 +936,103 @@
       }
     
     
    +  static FT_Error
    +  cff_load_item_variation_store( CFF_Face         face,
    +                                 FT_ULong         offset,
    +                                 GX_ItemVarStore  itemStore )
    +  {
    +    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
    +
    +
    +    return mm->load_item_var_store( FT_FACE(face), offset, itemStore );
    +  }
    +
    +
    +  static FT_Error
    +  cff_load_delta_set_index_mapping( CFF_Face           face,
    +                                    FT_ULong           offset,
    +                                    GX_DeltaSetIdxMap  map,
    +                                    GX_ItemVarStore    itemStore,
    +                                    FT_ULong           table_len )
    +  {
    +    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
    +
    +
    +    return mm->load_delta_set_idx_map( FT_FACE( face ), offset, map,
    +                                       itemStore, table_len );
    +  }
    +
    +
    +  static FT_Int
    +  cff_get_item_delta( CFF_Face         face,
    +                      GX_ItemVarStore  itemStore,
    +                      FT_UInt          outerIndex,
    +                      FT_UInt          innerIndex )
    +  {
    +    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
    +
    +
    +    return mm->get_item_delta( FT_FACE( face ), itemStore,
    +                               outerIndex, innerIndex );
    +  }
    +
    +
    +  static void
    +  cff_done_item_variation_store( CFF_Face          face,
    +                                 GX_ItemVarStore  itemStore )
    +  {
    +    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
    +
    +
    +    mm->done_item_var_store( FT_FACE( face ), itemStore );
    +  }
    +
    +
    +  static void
    +  cff_done_delta_set_index_map( CFF_Face           face,
    +                                GX_DeltaSetIdxMap  deltaSetIdxMap )
    +  {
    +    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
    +
    +
    +    mm->done_delta_set_idx_map( FT_FACE ( face ), deltaSetIdxMap );
    +  }
    +
    +
    +
       FT_DEFINE_SERVICE_MULTIMASTERSREC(
         cff_service_multi_masters,
     
    -    (FT_Get_MM_Func)             NULL,                    /* get_mm              */
    -    (FT_Set_MM_Design_Func)      NULL,                    /* set_mm_design       */
    -    (FT_Set_MM_Blend_Func)       cff_set_mm_blend,        /* set_mm_blend        */
    -    (FT_Get_MM_Blend_Func)       cff_get_mm_blend,        /* get_mm_blend        */
    -    (FT_Get_MM_Var_Func)         cff_get_mm_var,          /* get_mm_var          */
    -    (FT_Set_Var_Design_Func)     cff_set_var_design,      /* set_var_design      */
    -    (FT_Get_Var_Design_Func)     cff_get_var_design,      /* get_var_design      */
    -    (FT_Set_Instance_Func)       cff_set_instance,        /* set_instance        */
    -    (FT_Set_MM_WeightVector_Func)cff_set_mm_weightvector, /* set_mm_weightvector */
    -    (FT_Get_MM_WeightVector_Func)cff_get_mm_weightvector, /* get_mm_weightvector */
    -
    -    (FT_Get_Var_Blend_Func)      cff_get_var_blend,       /* get_var_blend       */
    -    (FT_Done_Blend_Func)         cff_done_blend           /* done_blend          */
    +    (FT_Get_MM_Func)        NULL,               /* get_mm                    */
    +    (FT_Set_MM_Design_Func) NULL,               /* set_mm_design             */
    +    (FT_Set_MM_Blend_Func)  cff_set_mm_blend,   /* set_mm_blend              */
    +    (FT_Get_MM_Blend_Func)  cff_get_mm_blend,   /* get_mm_blend              */
    +    (FT_Get_MM_Var_Func)    cff_get_mm_var,     /* get_mm_var                */
    +    (FT_Set_Var_Design_Func)cff_set_var_design, /* set_var_design            */
    +    (FT_Get_Var_Design_Func)cff_get_var_design, /* get_var_design            */
    +    (FT_Set_Instance_Func)  cff_set_instance,   /* set_instance              */
    +    (FT_Set_MM_WeightVector_Func)
    +                            cff_set_mm_weightvector,
    +                                                /* set_mm_weightvector       */
    +    (FT_Get_MM_WeightVector_Func)
    +                            cff_get_mm_weightvector,
    +                                                /* get_mm_weightvector       */
    +    (FT_Var_Load_Delta_Set_Idx_Map_Func)
    +                            cff_load_delta_set_index_mapping,
    +                                                /* load_delta_set_idx_map    */
    +    (FT_Var_Load_Item_Var_Store_Func)
    +                            cff_load_item_variation_store,
    +                                                /* load_item_variation_store */
    +    (FT_Var_Get_Item_Delta_Func)
    +                            cff_get_item_delta, /* get_item_delta            */
    +    (FT_Var_Done_Item_Var_Store_Func)
    +                            cff_done_item_variation_store,
    +                                                /* done_item_variation_store */
    +    (FT_Var_Done_Delta_Set_Idx_Map_Func)
    +                            cff_done_delta_set_index_map,
    +                                                /* done_delta_set_index_map  */
    +    (FT_Get_Var_Blend_Func) cff_get_var_blend,  /* get_var_blend             */
    +    (FT_Done_Blend_Func)    cff_done_blend      /* done_blend                */
       )
     
     
    @@ -1027,8 +1108,7 @@
       /*************************************************************************/
       /*************************************************************************/
     
    -#if !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES && \
    -     defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +#if defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
       FT_DEFINE_SERVICEDESCREC10(
         cff_services,
     
    @@ -1043,7 +1123,7 @@
         FT_SERVICE_ID_PROPERTIES,           &cff_service_properties,
         FT_SERVICE_ID_CFF_LOAD,             &cff_service_cff_load
       )
    -#elif !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES
    +#else
       FT_DEFINE_SERVICEDESCREC8(
         cff_services,
     
    @@ -1056,32 +1136,6 @@
         FT_SERVICE_ID_PROPERTIES,           &cff_service_properties,
         FT_SERVICE_ID_CFF_LOAD,             &cff_service_cff_load
       )
    -#elif defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
    -  FT_DEFINE_SERVICEDESCREC9(
    -    cff_services,
    -
    -    FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
    -    FT_SERVICE_ID_MULTI_MASTERS,        &cff_service_multi_masters,
    -    FT_SERVICE_ID_METRICS_VARIATIONS,   &cff_service_metrics_var,
    -    FT_SERVICE_ID_POSTSCRIPT_INFO,      &cff_service_ps_info,
    -    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name,
    -    FT_SERVICE_ID_TT_CMAP,              &cff_service_get_cmap_info,
    -    FT_SERVICE_ID_CID,                  &cff_service_cid_info,
    -    FT_SERVICE_ID_PROPERTIES,           &cff_service_properties,
    -    FT_SERVICE_ID_CFF_LOAD,             &cff_service_cff_load
    -  )
    -#else
    -  FT_DEFINE_SERVICEDESCREC7(
    -    cff_services,
    -
    -    FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
    -    FT_SERVICE_ID_POSTSCRIPT_INFO,      &cff_service_ps_info,
    -    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name,
    -    FT_SERVICE_ID_TT_CMAP,              &cff_service_get_cmap_info,
    -    FT_SERVICE_ID_CID,                  &cff_service_cid_info,
    -    FT_SERVICE_ID_PROPERTIES,           &cff_service_properties,
    -    FT_SERVICE_ID_CFF_LOAD,             &cff_service_cff_load
    -  )
     #endif
     
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h
    index a312003be73..ab1f147bb2a 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h
    @@ -4,7 +4,7 @@
      *
      *   High-level OpenType driver interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h b/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h
    index 90d32897c78..bc9a3043fcf 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h
    @@ -4,7 +4,7 @@
      *
      *   CFF error codes (specification only).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c
    index 7586b886f10..cfa0aaf2b69 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c
    @@ -4,7 +4,7 @@
      *
      *   OpenType Glyph Loader (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -356,18 +356,14 @@
     
     #ifdef FT_CONFIG_OPTION_SVG
         /* check for OT-SVG */
    -    if ( ( load_flags & FT_LOAD_COLOR )     &&
    -         ( (TT_Face)glyph->root.face )->svg )
    +    if ( ( load_flags & FT_LOAD_COLOR ) && face->svg )
         {
           /*
            * We load the SVG document and try to grab the advances from the
            * table.  For the bearings we rely on the presetting hook to do that.
            */
     
    -      FT_Short      dummy;
    -      FT_UShort     advanceX;
    -      FT_UShort     advanceY;
    -      SFNT_Service  sfnt;
    +      SFNT_Service  sfnt  = (SFNT_Service)face->sfnt;
     
     
           if ( size && (size->root.metrics.x_ppem < 1 ||
    @@ -379,10 +375,17 @@
     
           FT_TRACE3(( "Trying to load SVG glyph\n" ));
     
    -      sfnt  = (SFNT_Service)((TT_Face)glyph->root.face)->sfnt;
           error = sfnt->load_svg_doc( (FT_GlyphSlot)glyph, glyph_index );
           if ( !error )
           {
    +        FT_Fixed  x_scale = size->root.metrics.x_scale;
    +        FT_Fixed  y_scale = size->root.metrics.y_scale;
    +
    +        FT_Short   dummy;
    +        FT_UShort  advanceX;
    +        FT_UShort  advanceY;
    +
    +
             FT_TRACE3(( "Successfully loaded SVG glyph\n" ));
     
             glyph->root.format = FT_GLYPH_FORMAT_SVG;
    @@ -404,17 +407,11 @@
                                &dummy,
                                &advanceY );
     
    -        advanceX =
    -          (FT_UShort)FT_MulDiv( advanceX,
    -                                glyph->root.face->size->metrics.x_ppem,
    -                                glyph->root.face->units_per_EM );
    -        advanceY =
    -          (FT_UShort)FT_MulDiv( advanceY,
    -                                glyph->root.face->size->metrics.y_ppem,
    -                                glyph->root.face->units_per_EM );
    +        glyph->root.linearHoriAdvance = advanceX;
    +        glyph->root.linearVertAdvance = advanceY;
     
    -        glyph->root.metrics.horiAdvance = advanceX << 6;
    -        glyph->root.metrics.vertAdvance = advanceY << 6;
    +        glyph->root.metrics.horiAdvance = FT_MulFix( advanceX, x_scale );
    +        glyph->root.metrics.vertAdvance = FT_MulFix( advanceY, y_scale );
     
             return error;
           }
    @@ -491,13 +488,14 @@
           decoder.builder.no_recurse =
             FT_BOOL( load_flags & FT_LOAD_NO_RECURSE );
     
    -      /* now load the unscaled outline */
    -      error = cff_get_glyph_data( face, glyph_index,
    -                                  &charstring, &charstring_len );
    +      /* this function also checks for a valid subfont index */
    +      error = decoder_funcs->prepare( &decoder, size, glyph_index );
           if ( error )
             goto Glyph_Build_Finished;
     
    -      error = decoder_funcs->prepare( &decoder, size, glyph_index );
    +      /* now load the unscaled outline */
    +      error = cff_get_glyph_data( face, glyph_index,
    +                                  &charstring, &charstring_len );
           if ( error )
             goto Glyph_Build_Finished;
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h
    index 33616b96846..3b8cf236ddc 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h
    @@ -4,7 +4,7 @@
      *
      *   OpenType Glyph Loader (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c
    index d6f8a1013d8..4b8c6e16c58 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c
    @@ -4,7 +4,7 @@
      *
      *   OpenType and CFF data/program tables loader (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -1288,7 +1288,7 @@
       /* Blended values are written to a different buffer,     */
       /* using reserved operator 255.                          */
       /*                                                       */
    -  /* Blend calculation is done in 16.16 fixed point.       */
    +  /* Blend calculation is done in 16.16 fixed-point.       */
       FT_LOCAL_DEF( FT_Error )
       cff_blend_doBlend( CFF_SubFont  subFont,
                          CFF_Parser   parser,
    @@ -1364,7 +1364,7 @@
           FT_UInt32        sum;
     
     
    -      /* convert inputs to 16.16 fixed point */
    +      /* convert inputs to 16.16 fixed-point */
           sum = cff_parse_num( parser, &parser->stack[i + base] ) * 0x10000;
     
           for ( j = 1; j < blend->lenBV; j++ )
    @@ -1373,7 +1373,7 @@
           /* point parser stack to new value on blend_stack */
           parser->stack[i + base] = subFont->blend_top;
     
    -      /* Push blended result as Type 2 5-byte fixed point number.  This */
    +      /* Push blended result as Type 2 5-byte fixed-point number.  This */
           /* will not conflict with actual DICTs because 255 is a reserved  */
           /* opcode in both CFF and CFF2 DICTs.  See `cff_parse_num' for    */
           /* decode of this, which rounds to an integer.                    */
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffload.h b/src/java.desktop/share/native/libfreetype/src/cff/cffload.h
    index a3cc642b777..5a41cdebc8e 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cffload.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffload.h
    @@ -4,7 +4,7 @@
      *
      *   OpenType & CFF data/program tables loader (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c
    index fa42accb656..40cd9bf9173 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c
    @@ -4,7 +4,7 @@
      *
      *   OpenType objects manager (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -1031,12 +1031,10 @@
             cffface->style_flags = flags;
           }
     
    -#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
           /* CID-keyed CFF or CFF2 fonts don't have glyph names -- the SFNT */
           /* loader has unset this flag because of the 3.0 `post' table.    */
           if ( dict->cid_registry == 0xFFFFU && !cff2 )
             cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
    -#endif
     
           if ( dict->cid_registry != 0xFFFFU && pure_cff )
             cffface->face_flags |= FT_FACE_FLAG_CID_KEYED;
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h
    index d48c1cded9f..8f05f6132bc 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h
    @@ -4,7 +4,7 @@
      *
      *   OpenType objects manager (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c
    index 2536a21866b..e16206fd553 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c
    @@ -4,7 +4,7 @@
      *
      *   CFF token stream parser (body)
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -530,7 +530,7 @@
     
         else if ( **d == 255 )
         {
    -      /* 16.16 fixed point is used internally for CFF2 blend results. */
    +      /* 16.16 fixed-point is used internally for CFF2 blend results. */
           /* Since these are trusted values, a limit check is not needed. */
     
           /* After the 255, 4 bytes give the number.                 */
    @@ -758,12 +758,12 @@
           *upm = (FT_ULong)power_tens[-max_scaling];
     
           FT_TRACE4(( " [%f %f %f %f %f %f]\n",
    -                  (double)matrix->xx / *upm / 65536,
    -                  (double)matrix->xy / *upm / 65536,
    -                  (double)matrix->yx / *upm / 65536,
    -                  (double)matrix->yy / *upm / 65536,
    -                  (double)offset->x  / *upm / 65536,
    -                  (double)offset->y  / *upm / 65536 ));
    +                  (double)matrix->xx / (double)*upm / 65536,
    +                  (double)matrix->xy / (double)*upm / 65536,
    +                  (double)matrix->yx / (double)*upm / 65536,
    +                  (double)matrix->yy / (double)*upm / 65536,
    +                  (double)offset->x  / (double)*upm / 65536,
    +                  (double)offset->y  / (double)*upm / 65536 ));
     
           if ( !FT_Matrix_Check( matrix ) )
           {
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h
    index 55b6fe6e7cf..58d59fa4ac5 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h
    @@ -4,7 +4,7 @@
      *
      *   CFF token stream parser (specification)
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h
    index 15237de9e5f..b61cb0e66e8 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h
    @@ -4,7 +4,7 @@
      *
      *   CFF token definitions (specification only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h b/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h
    index d07da5a01d8..40a1097d0ac 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h
    @@ -4,7 +4,7 @@
      *
      *   CID error codes (specification only).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c
    index 24d37d32952..ba4b7565d54 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c
    +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c
    @@ -4,7 +4,7 @@
      *
      *   CID-keyed Type1 Glyph Loader (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h
    index c06bb29d3d3..97954d418ff 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h
    @@ -4,7 +4,7 @@
      *
      *   OpenType Glyph Loader (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidload.c b/src/java.desktop/share/native/libfreetype/src/cid/cidload.c
    index fe8fa1abffe..26daa5da7f6 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cid/cidload.c
    +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidload.c
    @@ -4,7 +4,7 @@
      *
      *   CID-keyed Type1 font loader (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidload.h b/src/java.desktop/share/native/libfreetype/src/cid/cidload.h
    index 90ced9280b1..d12d2962a68 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cid/cidload.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidload.h
    @@ -4,7 +4,7 @@
      *
      *   CID-keyed Type1 font loader (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c
    index c39de6369cd..06b2139a93d 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c
    +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c
    @@ -4,7 +4,7 @@
      *
      *   CID objects manager (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -153,7 +153,7 @@
       }
     
     
    -  FT_LOCAL( FT_Error )
    +  FT_LOCAL_DEF( FT_Error )
       cid_size_request( FT_Size          size,
                         FT_Size_Request  req )
       {
    diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h
    index fd76a1cba5d..83c0c61c3ca 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h
    @@ -4,7 +4,7 @@
      *
      *   CID objects manager (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c
    index cfc820561f3..16889db9b6f 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c
    +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c
    @@ -4,7 +4,7 @@
      *
      *   CID-keyed Type1 parser (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h
    index ba363f7803a..2fd4e7a9310 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h
    @@ -4,7 +4,7 @@
      *
      *   CID-keyed Type1 parser (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c
    index a63c01064ad..f7499237d73 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c
    +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c
    @@ -4,7 +4,7 @@
      *
      *   CID driver interface (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h
    index 5073b7a8eb5..a6249385c81 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h
    @@ -4,7 +4,7 @@
      *
      *   High-level CID driver interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h
    index 7640137eac0..925951acdbd 100644
    --- a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h
    +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h
    @@ -4,7 +4,7 @@
      *
      *   CID token definitions (specification only).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c
    index bd86129f7e2..68f95698e65 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c
    @@ -4,7 +4,7 @@
      *
      *   AFM parser (body).
      *
    - * Copyright (C) 2006-2022 by
    + * Copyright (C) 2006-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -563,7 +563,7 @@
       }
     
     
    -  FT_LOCAL( void )
    +  FT_LOCAL_DEF( void )
       afm_parser_done( AFM_Parser  parser )
       {
         FT_Memory  memory = parser->memory;
    @@ -1061,7 +1061,7 @@
             if ( error )
               goto Fail;
             /* we only support kern data, so ... */
    -        /* fall through                      */
    +        FALL_THROUGH;
     
           case AFM_TOKEN_ENDFONTMETRICS:
             return FT_Err_Ok;
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h
    index eee49e36015..2d3b6e6e169 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h
    @@ -4,7 +4,7 @@
      *
      *   AFM parser (specification).
      *
    - * Copyright (C) 2006-2022 by
    + * Copyright (C) 2006-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c
    index 92139c93ad8..2cd91c96f35 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c
    @@ -4,7 +4,7 @@
      *
      *   PostScript CFF (Type 2) decoding routines (body).
      *
    - * Copyright (C) 2017-2022 by
    + * Copyright (C) 2017-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h
    index a9f6761824b..e8bb4001cba 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h
    @@ -4,7 +4,7 @@
      *
      *   PostScript CFF (Type 2) decoding routines (specification).
      *
    - * Copyright (C) 2017-2022 by
    + * Copyright (C) 2017-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h b/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h
    index 1504b34ee56..895ffa48c2c 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h
    @@ -4,7 +4,7 @@
      *
      *   PS auxiliary module error codes (specification only).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c
    index 113490abcd2..45e35aa53c4 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType auxiliary PostScript module implementation (body).
      *
    - * Copyright (C) 2000-2022 by
    + * Copyright (C) 2000-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h
    index 2d508edc2ac..94dbf48813c 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType auxiliary PostScript module implementation (specification).
      *
    - * Copyright (C) 2000-2022 by
    + * Copyright (C) 2000-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c
    index 9b8c0d90c30..b9c7138d846 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c
    @@ -4,7 +4,7 @@
      *
      *   Some convenience conversions (body).
      *
    - * Copyright (C) 2006-2022 by
    + * Copyright (C) 2006-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h
    index 650d7c93b27..b7c3ee00be8 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h
    @@ -4,7 +4,7 @@
      *
      *   Some convenience conversions (specification).
      *
    - * Copyright (C) 2006-2022 by
    + * Copyright (C) 2006-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psfixed.h b/src/java.desktop/share/native/libfreetype/src/psaux/psfixed.h
    index 7dff9ef1bd5..299d0763705 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/psfixed.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psfixed.h
    @@ -2,7 +2,7 @@
      *
      * psfixed.h
      *
    - *   Adobe's code for Fixed Point Mathematics (specification only).
    + *   Adobe's code for Fixed-Point Mathematics (specification only).
      *
      * Copyright 2007-2013 Adobe Systems Incorporated.
      *
    @@ -43,10 +43,10 @@
     FT_BEGIN_HEADER
     
     
    -  /* rasterizer integer and fixed point arithmetic must be 32-bit */
    +  /* rasterizer integer and fixed-point arithmetic must be 32-bit */
     
     #define   CF2_Fixed  CF2_F16Dot16
    -  typedef FT_Int32   CF2_Frac;   /* 2.30 fixed point */
    +  typedef FT_Int32   CF2_Frac;   /* 2.30 fixed-point */
     
     
     #define CF2_FIXED_MAX      ( (CF2_Fixed)0x7FFFFFFFL )
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psft.c b/src/java.desktop/share/native/libfreetype/src/psaux/psft.c
    index ac72d8259c4..618864e6e07 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/psft.c
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psft.c
    @@ -68,11 +68,10 @@
         CF2_Fixed  maxScale;
     
     
    -    FT_ASSERT( unitsPerEm > 0 );
    -
         if ( transform->a <= 0 || transform->d <= 0 )
           return FT_THROW( Invalid_Size_Handle );
     
    +    FT_ASSERT( unitsPerEm > 0 );
         FT_ASSERT( transform->b == 0 && transform->c == 0 );
         FT_ASSERT( transform->tx == 0 && transform->ty == 0 );
     
    @@ -297,7 +296,6 @@
       cf2_getUnitsPerEm( PS_Decoder*  decoder )
       {
         FT_ASSERT( decoder && decoder->builder.face );
    -    FT_ASSERT( decoder->builder.face->units_per_EM );
     
         return decoder->builder.face->units_per_EM;
       }
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psglue.h b/src/java.desktop/share/native/libfreetype/src/psaux/psglue.h
    index 022aafbfcac..63085d71cf5 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/psglue.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psglue.h
    @@ -72,7 +72,7 @@ FT_BEGIN_HEADER
       } CF2_PathOp;
     
     
    -  /* a matrix of fixed point values */
    +  /* a matrix of fixed-point values */
       typedef struct  CF2_Matrix_
       {
         CF2_F16Dot16  a;
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/pshints.c b/src/java.desktop/share/native/libfreetype/src/psaux/pshints.c
    index ad472c98df5..6f44d0adbb7 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/pshints.c
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/pshints.c
    @@ -693,8 +693,10 @@
             CF2_Fixed  midpoint =
                          cf2_hintmap_map(
                            hintmap->initialHintMap,
    -                       ADD_INT32( secondHintEdge->csCoord,
    -                                  firstHintEdge->csCoord ) / 2 );
    +                       ADD_INT32(
    +                         firstHintEdge->csCoord,
    +                         SUB_INT32 ( secondHintEdge->csCoord,
    +                                     firstHintEdge->csCoord ) / 2 ) );
             CF2_Fixed  halfWidth =
                          FT_MulFix( SUB_INT32( secondHintEdge->csCoord,
                                                firstHintEdge->csCoord ) / 2,
    @@ -1034,10 +1036,10 @@
         {
           FT_TRACE6(( "flags: [p]air [g]host [t]op"
                       " [b]ottom [L]ocked [S]ynthetic\n" ));
    -      FT_TRACE6(( "Initial hintmap" ));
    +      FT_TRACE6(( "Initial hintmap:\n" ));
         }
         else
    -      FT_TRACE6(( "Hints:" ));
    +      FT_TRACE6(( "Hints:\n" ));
     #endif
     
         cf2_hintmap_dump( hintmap );
    @@ -1054,7 +1056,7 @@
         /* adjust positions of hint edges that are not locked to blue zones */
         cf2_hintmap_adjustHints( hintmap );
     
    -    FT_TRACE6(( "(adjusted)\n" ));
    +    FT_TRACE6(( "Hints adjusted:\n" ));
         cf2_hintmap_dump( hintmap );
     
         /* save the position of all hints that were used in this hint map; */
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c
    index 371e5380207..8da755d0e57 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c
    @@ -4,7 +4,7 @@
      *
      *   Auxiliary functions for PostScript fonts (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -84,7 +84,6 @@
     
         table->max_elems = count;
         table->init      = 0xDEADBEEFUL;
    -    table->num_elems = 0;
         table->block     = NULL;
         table->capacity  = 0;
         table->cursor    = 0;
    @@ -235,7 +234,7 @@
         FT_Memory  memory = table->memory;
     
     
    -    if ( (FT_ULong)table->init == 0xDEADBEEFUL )
    +    if ( table->init == 0xDEADBEEFUL )
         {
           FT_FREE( table->block );
           FT_FREE( table->elements );
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h
    index f01d4bd503a..d5bce541082 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h
    @@ -4,7 +4,7 @@
      *
      *   Auxiliary functions for PostScript fonts (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psstack.h b/src/java.desktop/share/native/libfreetype/src/psaux/psstack.h
    index b9ef9edf1b2..907b4240007 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/psstack.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psstack.h
    @@ -49,8 +49,8 @@ FT_BEGIN_HEADER
       {
         union
         {
    -      CF2_Fixed  r;      /* 16.16 fixed point */
    -      CF2_Frac   f;      /* 2.30 fixed point (for font matrix) */
    +      CF2_Fixed  r;      /* 16.16 fixed-point */
    +      CF2_Frac   f;      /* 2.30 fixed-point (for font matrix) */
           CF2_Int    i;
         } u;
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c
    index f297ce75e1f..bf0a393b456 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c
    @@ -4,7 +4,7 @@
      *
      *   Type 1 character map support (body).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h
    index 460d91f5904..b3702498a55 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h
    @@ -4,7 +4,7 @@
      *
      *   Type 1 character map support (specification).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c
    index 1cdf436fa72..bfed45b53a3 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c
    @@ -4,7 +4,7 @@
      *
      *   PostScript Type 1 decoding routines (body).
      *
    - * Copyright (C) 2000-2022 by
    + * Copyright (C) 2000-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h
    index d60d61c9043..0970def960b 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h
    @@ -4,7 +4,7 @@
      *
      *   PostScript Type 1 decoding routines (specification).
      *
    - * Copyright (C) 2000-2022 by
    + * Copyright (C) 2000-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c
    index dca539766f2..a7f321291a9 100644
    --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c
    +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c
    @@ -4,7 +4,7 @@
      *
      *   PostScript hinting algorithm (body).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used
    diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h
    index ab978bf6d0b..3f0ba28a693 100644
    --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h
    +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h
    @@ -4,7 +4,7 @@
      *
      *   PostScript hinting algorithm (specification).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c
    index 887ea8d9c18..d4c5eb32b1c 100644
    --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c
    +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c
    @@ -5,7 +5,7 @@
      *   PostScript hinter global hinting management (body).
      *   Inspired by the new auto-hinter module.
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used
    diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h
    index 47247f969eb..579eb2148a5 100644
    --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h
    +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h
    @@ -4,7 +4,7 @@
      *
      *   PostScript hinter global hinting management.
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c
    index a74a4fe99f2..a12e4856601 100644
    --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c
    +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType PostScript hinter module implementation (body).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h
    index cdf95b7c203..4bd781a35d7 100644
    --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h
    +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h
    @@ -4,7 +4,7 @@
      *
      *   PostScript hinter module interface (specification).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h
    index 789afb59901..97624952d8c 100644
    --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h
    +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h
    @@ -4,7 +4,7 @@
      *
      *   PS Hinter error codes (specification only).
      *
    - * Copyright (C) 2003-2022 by
    + * Copyright (C) 2003-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c
    index 2a5cffbadae..58c8cf1b486 100644
    --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c
    +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c
    @@ -4,7 +4,7 @@
      *
      *   FreeType PostScript hints recorder (body).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -765,7 +765,7 @@
     
     
       /* destroy hints */
    -  FT_LOCAL( void )
    +  FT_LOCAL_DEF( void )
       ps_hints_done( PS_Hints  hints )
       {
         FT_Memory  memory = hints->memory;
    @@ -779,7 +779,7 @@
       }
     
     
    -  FT_LOCAL( void )
    +  FT_LOCAL_DEF( void )
       ps_hints_init( PS_Hints   hints,
                      FT_Memory  memory )
       {
    diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h
    index a0d37979cc0..0b2484af121 100644
    --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h
    +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h
    @@ -4,7 +4,7 @@
      *
      *   Postscript (Type1/Type2) hints recorder (specification).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c
    index e7d51e950eb..db454e558eb 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c
    +++ b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c
    @@ -4,7 +4,7 @@
      *
      *   psnames module implementation (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -412,21 +412,18 @@
       ps_unicodes_char_index( PS_Unicodes  table,
                               FT_UInt32    unicode )
       {
    -    PS_UniMap  *min, *max, *mid, *result = NULL;
    +    PS_UniMap  *result = NULL;
    +    PS_UniMap  *min = table->maps;
    +    PS_UniMap  *max = min + table->num_maps;
    +    PS_UniMap  *mid = min + ( ( max - min ) >> 1 );
     
     
         /* Perform a binary search on the table. */
    -
    -    min = table->maps;
    -    max = min + table->num_maps - 1;
    -
    -    while ( min <= max )
    +    while ( min < max )
         {
           FT_UInt32  base_glyph;
     
     
    -      mid = min + ( ( max - min ) >> 1 );
    -
           if ( mid->unicode == unicode )
           {
             result = mid;
    @@ -438,13 +435,15 @@
           if ( base_glyph == unicode )
             result = mid; /* remember match but continue search for base glyph */
     
    -      if ( min == max )
    -        break;
    -
           if ( base_glyph < unicode )
             min = mid + 1;
           else
    -        max = mid - 1;
    +        max = mid;
    +
    +      /* reasonable prediction in a continuous block */
    +      mid += unicode - base_glyph;
    +      if ( mid >= max || mid < min )
    +        mid = min + ( ( max - min ) >> 1 );
         }
     
         if ( result )
    @@ -465,14 +464,13 @@
         {
           FT_UInt     min = 0;
           FT_UInt     max = table->num_maps;
    -      FT_UInt     mid;
    +      FT_UInt     mid = min + ( ( max - min ) >> 1 );
           PS_UniMap*  map;
           FT_UInt32   base_glyph;
     
     
           while ( min < max )
           {
    -        mid = min + ( ( max - min ) >> 1 );
             map = table->maps + mid;
     
             if ( map->unicode == char_code )
    @@ -490,6 +488,11 @@
               min = mid + 1;
             else
               max = mid;
    +
    +        /* reasonable prediction in a continuous block */
    +        mid += char_code - base_glyph;
    +        if ( mid >= max || mid < min )
    +          mid = min + ( max - min ) / 2;
           }
     
           if ( result )
    diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h
    index ff3eda564c7..0904700bfb8 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h
    @@ -4,7 +4,7 @@
      *
      *   High-level psnames module interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h b/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h
    index ae56620275f..0073f822848 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h
    @@ -4,7 +4,7 @@
      *
      *   PS names module error codes (specification only).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h b/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h
    index d28d580b9ca..7f92cce6039 100644
    --- a/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h
    +++ b/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h
    @@ -4,7 +4,7 @@
      *
      *   PostScript glyph names.
      *
    - * Copyright (C) 2005-2022 by
    + * Copyright (C) 2005-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h b/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h
    index 75fb5f8437d..33dbfd631e9 100644
    --- a/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h
    +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h
    @@ -5,7 +5,7 @@
      *   Miscellaneous macros for stand-alone rasterizer (specification
      *   only).
      *
    - * Copyright (C) 2005-2022 by
    + * Copyright (C) 2005-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used
    diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c
    index 68b0e1fdd95..67cbfd5d9b7 100644
    --- a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c
    +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c
    @@ -4,7 +4,7 @@
      *
      *   The FreeType glyph rasterizer (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -2219,8 +2219,8 @@
         /* represent multiples of 1/(1<<12) = 1/4096                    */
         FT_TRACE7(( "  y=%d x=[% .12f;% .12f]",
                     y,
    -                x1 / (double)ras.precision,
    -                x2 / (double)ras.precision ));
    +                (double)x1 / (double)ras.precision,
    +                (double)x2 / (double)ras.precision ));
     
         /* Drop-out control */
     
    @@ -2294,8 +2294,8 @@
     
         FT_TRACE7(( "  y=%d x=[% .12f;% .12f]",
                     y,
    -                x1 / (double)ras.precision,
    -                x2 / (double)ras.precision ));
    +                (double)x1 / (double)ras.precision,
    +                (double)x2 / (double)ras.precision ));
     
         /* Drop-out control */
     
    @@ -2477,8 +2477,8 @@
     
         FT_TRACE7(( "  x=%d y=[% .12f;% .12f]",
                     y,
    -                x1 / (double)ras.precision,
    -                x2 / (double)ras.precision ));
    +                (double)x1 / (double)ras.precision,
    +                (double)x2 / (double)ras.precision ));
     
         /* We should not need this procedure but the vertical sweep   */
         /* mishandles horizontal lines through pixel centers.  So we  */
    @@ -2548,8 +2548,8 @@
     
         FT_TRACE7(( "  x=%d y=[% .12f;% .12f]",
                     y,
    -                x1 / (double)ras.precision,
    -                x2 / (double)ras.precision ));
    +                (double)x1 / (double)ras.precision,
    +                (double)x2 / (double)ras.precision ));
     
         /* During the horizontal sweep, we only take care of drop-outs */
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h
    index e9ece8cf0bf..b511b3a99e9 100644
    --- a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h
    +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType glyph rasterizer (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used
    diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c
    index f319f03d9c6..0b5d8671478 100644
    --- a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c
    +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c
    @@ -4,7 +4,7 @@
      *
      *   The FreeType glyph rasterizer interface (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h
    index 14ec336b111..cec35c8528a 100644
    --- a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h
    +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h
    @@ -4,7 +4,7 @@
      *
      *   The FreeType glyph rasterizer interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h b/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h
    index 8b1ebf07a3c..989d8b44be1 100644
    --- a/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h
    +++ b/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h
    @@ -4,7 +4,7 @@
      *
      *   monochrome renderer error codes (specification only).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c
    index 0ce4bdb6b5c..423b07b02a5 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c
    @@ -4,7 +4,7 @@
      *
      *   PNG Bitmap glyph support.
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * Google, Inc.
      * Written by Stuart Gill and Behdad Esfahbod.
      *
    @@ -239,7 +239,7 @@
           *e = FT_THROW( Invalid_Stream_Read );
           png_error( png, NULL );
     
    -      return;
    +      /* return; (never reached) */
         }
     
         ft_memcpy( data, stream->cursor, length );
    @@ -407,7 +407,8 @@
         switch ( color_type )
         {
         default:
    -      /* Shouldn't happen, but fall through. */
    +      /* Shouldn't happen, but ... */
    +      FALL_THROUGH;
     
         case PNG_COLOR_TYPE_RGB_ALPHA:
           png_set_read_user_transform_fn( png, premultiply_data );
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h
    index 36d749c3c35..903bd2bc348 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h
    @@ -4,7 +4,7 @@
      *
      *   PNG Bitmap glyph support.
      *
    - * Copyright (C) 2013-2022 by
    + * Copyright (C) 2013-2023 by
      * Google, Inc.
      * Written by Stuart Gill and Behdad Esfahbod.
      *
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c
    index cc121e57907..762883db542 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c
    @@ -4,7 +4,7 @@
      *
      *   High-level SFNT driver interface (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -378,61 +378,61 @@
           {
           case 15:
             k4 ^= (FT_UInt32)tail[14] << 16;
    -        /* fall through */
    +        FALL_THROUGH;
           case 14:
             k4 ^= (FT_UInt32)tail[13] << 8;
    -        /* fall through */
    +        FALL_THROUGH;
           case 13:
             k4 ^= (FT_UInt32)tail[12];
             k4 *= c4;
             k4  = ROTL32( k4, 18 );
             k4 *= c1;
             h4 ^= k4;
    -        /* fall through */
    +        FALL_THROUGH;
     
           case 12:
             k3 ^= (FT_UInt32)tail[11] << 24;
    -        /* fall through */
    +        FALL_THROUGH;
           case 11:
             k3 ^= (FT_UInt32)tail[10] << 16;
    -        /* fall through */
    +        FALL_THROUGH;
           case 10:
             k3 ^= (FT_UInt32)tail[9] << 8;
    -        /* fall through */
    +        FALL_THROUGH;
           case 9:
             k3 ^= (FT_UInt32)tail[8];
             k3 *= c3;
             k3  = ROTL32( k3, 17 );
             k3 *= c4;
             h3 ^= k3;
    -        /* fall through */
    +        FALL_THROUGH;
     
           case 8:
             k2 ^= (FT_UInt32)tail[7] << 24;
    -        /* fall through */
    +        FALL_THROUGH;
           case 7:
             k2 ^= (FT_UInt32)tail[6] << 16;
    -        /* fall through */
    +        FALL_THROUGH;
           case 6:
             k2 ^= (FT_UInt32)tail[5] << 8;
    -        /* fall through */
    +        FALL_THROUGH;
           case 5:
             k2 ^= (FT_UInt32)tail[4];
             k2 *= c2;
             k2  = ROTL32( k2, 16 );
             k2 *= c3;
             h2 ^= k2;
    -        /* fall through */
    +        FALL_THROUGH;
     
           case 4:
             k1 ^= (FT_UInt32)tail[3] << 24;
    -        /* fall through */
    +        FALL_THROUGH;
           case 3:
             k1 ^= (FT_UInt32)tail[2] << 16;
    -        /* fall through */
    +        FALL_THROUGH;
           case 2:
             k1 ^= (FT_UInt32)tail[1] << 8;
    -        /* fall through */
    +        FALL_THROUGH;
           case 1:
             k1 ^= (FT_UInt32)tail[0];
             k1 *= c1;
    @@ -657,7 +657,7 @@
     
     
       /*
    -   * Find the shortest decimal representation of a 16.16 fixed point
    +   * Find the shortest decimal representation of a 16.16 fixed-point
        * number.  The function fills `buf' with the result, returning a pointer
        * to the position after the representation's last byte.
        */
    @@ -733,7 +733,7 @@
             an equivalent representation of `fixed'.
     
             The above FOR loop always finds the larger of the two values; I
    -        verified this by iterating over all possible fixed point numbers.
    +        verified this by iterating over all possible fixed-point numbers.
     
             If the remainder is 17232*10, both values are equally good, and we
             take the next even number (following IEEE 754's `round to nearest,
    @@ -741,7 +741,7 @@
     
             If the remainder is smaller than 17232*10, the lower of the two
             numbers is nearer to the exact result (values 17232 and 34480 were
    -        also found by testing all possible fixed point values).
    +        also found by testing all possible fixed-point values).
     
             We use this to find a shorter decimal representation.  If not ending
             with digit zero, we take the representation with less error.
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h
    index 6a2e3e9c7b0..2445958b69f 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h
    @@ -4,7 +4,7 @@
      *
      *   High-level SFNT driver interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h
    index 99ef3f9fce9..e7a8eb04bb8 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h
    @@ -4,7 +4,7 @@
      *
      *   SFNT error codes (specification only).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c
    index a0da984e7ac..e018934ccaa 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c
    @@ -4,7 +4,7 @@
      *
      *   SFNT object management (base).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -1107,13 +1107,7 @@
           /* Don't bother to load the tables unless somebody asks for them. */
           /* No need to do work which will (probably) not be used.          */
           if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR )
    -      {
    -        if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
    -             tt_face_lookup_table( face, TTAG_gvar ) != 0 )
    -          flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
    -        if ( tt_face_lookup_table( face, TTAG_CFF2 ) != 0 )
    -          flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
    -      }
    +        flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
     #endif
     
           root->face_flags = flags;
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h
    index 1d99bfede47..906aebbf904 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h
    @@ -4,7 +4,7 @@
      *
      *   SFNT object management (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c
    index 0e8ec3fa932..9559bf34214 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c
    @@ -4,7 +4,7 @@
      *
      *   WOFF format management (base).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -162,8 +162,7 @@
         }
     
         /* Don't trust `totalSfntSize' before thorough checks. */
    -    if ( FT_QALLOC( sfnt, 12 + woff.num_tables * 16UL ) ||
    -         FT_NEW( sfnt_stream )                          )
    +    if ( FT_QALLOC( sfnt, 12 ) || FT_NEW( sfnt_stream ) )
           goto Exit;
     
         sfnt_header = sfnt;
    @@ -196,8 +195,8 @@
         /* tag value, the tables themselves are not.  We thus have to */
         /* sort them by offset and check that they don't overlap.     */
     
    -    if ( FT_NEW_ARRAY( tables, woff.num_tables )  ||
    -         FT_NEW_ARRAY( indices, woff.num_tables ) )
    +    if ( FT_QNEW_ARRAY( tables, woff.num_tables )  ||
    +         FT_QNEW_ARRAY( indices, woff.num_tables ) )
           goto Exit;
     
         FT_TRACE2(( "\n" ));
    @@ -328,9 +327,7 @@
         }
     
         /* Now use `totalSfntSize'. */
    -    if ( FT_REALLOC( sfnt,
    -                     12 + woff.num_tables * 16UL,
    -                     woff.totalSfntSize ) )
    +    if ( FT_QREALLOC( sfnt, 12, woff.totalSfntSize ) )
           goto Exit;
     
         sfnt_header = sfnt + 12;
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h
    index 5866a16194e..d4384227376 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h
    @@ -4,7 +4,7 @@
      *
      *   WOFFF format management (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c
    index b2855b8e72b..7a01977f866 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c
    @@ -4,7 +4,7 @@
      *
      *   WOFF2 format management (base).
      *
    - * Copyright (C) 2019-2022 by
    + * Copyright (C) 2019-2023 by
      * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -229,9 +229,9 @@
         {
           FT_TRACE6(( "Reallocating %lu to %lu.\n",
                       *dst_size, (*offset + size) ));
    -      if ( FT_REALLOC( dst,
    -                       (FT_ULong)( *dst_size ),
    -                       (FT_ULong)( *offset + size ) ) )
    +      if ( FT_QREALLOC( dst,
    +                        (FT_ULong)( *dst_size ),
    +                        (FT_ULong)( *offset + size ) ) )
             goto Exit;
     
           *dst_size = *offset + size;
    @@ -784,7 +784,7 @@
           goto Fail;
     
         loca_buf_size = loca_values_size * offset_size;
    -    if ( FT_QNEW_ARRAY( loca_buf, loca_buf_size ) )
    +    if ( FT_QALLOC( loca_buf, loca_buf_size ) )
           goto Fail;
     
         dst = loca_buf;
    @@ -863,7 +863,7 @@
         WOFF2_Point  points       = NULL;
     
     
    -    if ( FT_NEW_ARRAY( substreams, num_substreams ) )
    +    if ( FT_QNEW_ARRAY( substreams, num_substreams ) )
           goto Fail;
     
         if ( FT_STREAM_SKIP( 2 ) )
    @@ -926,7 +926,7 @@
           offset += overlap_bitmap_length;
         }
     
    -    if ( FT_NEW_ARRAY( loca_values, num_glyphs + 1 ) )
    +    if ( FT_QNEW_ARRAY( loca_values, num_glyphs + 1 ) )
           goto Fail;
     
         points_size        = 0;
    @@ -938,10 +938,10 @@
         substreams[BBOX_STREAM].offset += bbox_bitmap_length;
     
         glyph_buf_size = WOFF2_DEFAULT_GLYPH_BUF;
    -    if ( FT_NEW_ARRAY( glyph_buf, glyph_buf_size ) )
    +    if ( FT_QALLOC( glyph_buf, glyph_buf_size ) )
           goto Fail;
     
    -    if ( FT_NEW_ARRAY( info->x_mins, num_glyphs ) )
    +    if ( FT_QNEW_ARRAY( info->x_mins, num_glyphs ) )
           goto Fail;
     
         for ( i = 0; i < num_glyphs; ++i )
    @@ -999,7 +999,7 @@
             size_needed = 12 + composite_size + instruction_size;
             if ( glyph_buf_size < size_needed )
             {
    -          if ( FT_RENEW_ARRAY( glyph_buf, glyph_buf_size, size_needed ) )
    +          if ( FT_QREALLOC( glyph_buf, glyph_buf_size, size_needed ) )
                 goto Fail;
               glyph_buf_size = size_needed;
             }
    @@ -1075,7 +1075,7 @@
                 have_overlap = TRUE;
             }
     
    -        if ( FT_NEW_ARRAY( n_points_arr, n_contours ) )
    +        if ( FT_QNEW_ARRAY( n_points_arr, n_contours ) )
               goto Fail;
     
             if ( FT_STREAM_SEEK( substreams[N_POINTS_STREAM].offset ) )
    @@ -1112,7 +1112,7 @@
     
             /* Create array to store point information. */
             points_size = total_n_points;
    -        if ( FT_NEW_ARRAY( points, points_size ) )
    +        if ( FT_QNEW_ARRAY( points, points_size ) )
               goto Fail;
     
             if ( triplet_decode( flags_buf,
    @@ -1141,7 +1141,7 @@
                           instruction_size;
             if ( glyph_buf_size < size_needed )
             {
    -          if ( FT_RENEW_ARRAY( glyph_buf, glyph_buf_size, size_needed ) )
    +          if ( FT_QREALLOC( glyph_buf, glyph_buf_size, size_needed ) )
                 goto Fail;
               glyph_buf_size = size_needed;
             }
    @@ -1226,8 +1226,7 @@
           *glyf_checksum += compute_ULong_sum( glyph_buf, glyph_size );
     
           /* Store x_mins, may be required to reconstruct `hmtx'. */
    -      if ( n_contours > 0 )
    -        info->x_mins[i] = (FT_Short)x_min;
    +      info->x_mins[i] = (FT_Short)x_min;
         }
     
         info->glyf_table->dst_length = dest_offset - info->glyf_table->dst_offset;
    @@ -1344,7 +1343,7 @@
         offset_size = index_format ? 4 : 2;
     
         /* Create `x_mins' array. */
    -    if ( FT_NEW_ARRAY( info->x_mins, num_glyphs ) )
    +    if ( FT_QNEW_ARRAY( info->x_mins, num_glyphs ) )
           return error;
     
         loca_offset = info->loca_table->src_offset;
    @@ -1432,8 +1431,8 @@
         if ( num_hmetrics < 1 )
           goto Fail;
     
    -    if ( FT_NEW_ARRAY( advance_widths, num_hmetrics ) ||
    -         FT_NEW_ARRAY( lsbs, num_glyphs )             )
    +    if ( FT_QNEW_ARRAY( advance_widths, num_hmetrics ) ||
    +         FT_QNEW_ARRAY( lsbs, num_glyphs )             )
           goto Fail;
     
         /* Read `advanceWidth' stream.  Always present. */
    @@ -1484,7 +1483,7 @@
     
         /* Build the hmtx table. */
         hmtx_table_size = 2 * num_hmetrics + 2 * num_glyphs;
    -    if ( FT_NEW_ARRAY( hmtx_table, hmtx_table_size ) )
    +    if ( FT_QALLOC( hmtx_table, hmtx_table_size ) )
           goto Fail;
     
         dst = hmtx_table;
    @@ -1541,10 +1540,10 @@
       {
         /* Memory management of `transformed_buf' is handled by the caller. */
     
    -    FT_Error   error       = FT_Err_Ok;
    -    FT_Stream  stream      = NULL;
    -    FT_Byte*   buf_cursor  = NULL;
    -    FT_Byte*   table_entry = NULL;
    +    FT_Error   error      = FT_Err_Ok;
    +    FT_Stream  stream     = NULL;
    +    FT_Byte*   buf_cursor = NULL;
    +    FT_Byte    table_entry[16];
     
         /* We are reallocating memory for `sfnt', so its pointer may change. */
         FT_Byte*   sfnt = *sfnt_bytes;
    @@ -1585,10 +1584,6 @@
           }
         }
     
    -    /* Create buffer for table entries. */
    -    if ( FT_NEW_ARRAY( table_entry, 16 ) )
    -      goto Fail;
    -
         /* Create a stream for the uncompressed buffer. */
         if ( FT_NEW( stream ) )
           goto Fail;
    @@ -1751,7 +1746,6 @@
         /* Set pointer of sfnt stream to its correct value. */
         *sfnt_bytes = sfnt;
     
    -    FT_FREE( table_entry );
         FT_Stream_Close( stream );
         FT_FREE( stream );
     
    @@ -1764,7 +1758,6 @@
         /* Set pointer of sfnt stream to its correct value. */
         *sfnt_bytes = sfnt;
     
    -    FT_FREE( table_entry );
         FT_Stream_Close( stream );
         FT_FREE( stream );
     
    @@ -1877,8 +1870,8 @@
         woff2.ttc_fonts = NULL;
     
         /* Read table directory. */
    -    if ( FT_NEW_ARRAY( tables, woff2.num_tables )  ||
    -         FT_NEW_ARRAY( indices, woff2.num_tables ) )
    +    if ( FT_QNEW_ARRAY( tables, woff2.num_tables )  ||
    +         FT_QNEW_ARRAY( indices, woff2.num_tables ) )
           goto Exit;
     
         FT_TRACE2(( "\n" ));
    @@ -1949,10 +1942,11 @@
             goto Exit;
           }
     
    +      table->flags      = flags;
           table->src_offset = src_offset;
           table->src_length = table->TransformLength;
           src_offset       += table->TransformLength;
    -      table->flags      = flags;
    +      table->dst_offset = 0;
     
           FT_TRACE2(( "  %c%c%c%c  %08d  %08d   %08ld    %08ld    %08ld\n",
                       (FT_Char)( table->Tag >> 24 ),
    @@ -2010,6 +2004,7 @@
     
           FT_TRACE4(( "Number of fonts in TTC: %d\n", woff2.num_fonts ));
     
    +      /* pre-zero pointers within in case of failure */
           if ( FT_NEW_ARRAY( woff2.ttc_fonts, woff2.num_fonts ) )
             goto Exit;
     
    @@ -2023,7 +2018,7 @@
             if ( FT_READ_ULONG( ttc_font->flavor ) )
               goto Exit;
     
    -        if ( FT_NEW_ARRAY( ttc_font->table_indices, ttc_font->num_tables ) )
    +        if ( FT_QNEW_ARRAY( ttc_font->table_indices, ttc_font->num_tables ) )
               goto Exit;
     
             FT_TRACE5(( "Number of tables in font %d: %d\n",
    @@ -2302,9 +2297,9 @@
         {
           FT_TRACE5(( "Trimming sfnt stream from %lu to %lu.\n",
                       sfnt_size, woff2.actual_sfnt_size ));
    -      if ( FT_REALLOC( sfnt,
    -                       (FT_ULong)( sfnt_size ),
    -                       (FT_ULong)( woff2.actual_sfnt_size ) ) )
    +      if ( FT_QREALLOC( sfnt,
    +                        (FT_ULong)( sfnt_size ),
    +                        (FT_ULong)( woff2.actual_sfnt_size ) ) )
             goto Exit;
         }
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h
    index e84982ed9c3..4901286ee08 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h
    @@ -4,7 +4,7 @@
      *
      *   WOFFF2 format management (specification).
      *
    - * Copyright (C) 2019-2022 by
    + * Copyright (C) 2019-2023 by
      * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c
    index bfeabacb7d2..820cd08e6d5 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c
    @@ -4,7 +4,7 @@
      *
      *   TrueType character mapping table (cmap) support (body).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -3879,13 +3879,14 @@
       }
     
     
    -  FT_LOCAL( FT_Error )
    +  FT_LOCAL_DEF( FT_Error )
       tt_get_cmap_info( FT_CharMap    charmap,
                         TT_CMapInfo  *cmap_info )
       {
         FT_CMap        cmap  = (FT_CMap)charmap;
         TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
     
    +
         if ( clazz->get_cmap_info )
           return clazz->get_cmap_info( charmap, cmap_info );
         else
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h
    index b10860b345e..ff52917ed5b 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h
    @@ -4,7 +4,7 @@
      *
      *   TrueType character mapping table (cmap) support (specification).
      *
    - * Copyright (C) 2002-2022 by
    + * Copyright (C) 2002-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h
    index 6822a9cd6b9..0af48c2478a 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h
    @@ -4,7 +4,7 @@
      *
      *   TT CMAP classes definitions (specification only).
      *
    - * Copyright (C) 2009-2022 by
    + * Copyright (C) 2009-2023 by
      * Oran Agra and Mickey Gabel.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c
    index d54231fd647..5d98dcab8ff 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c
    @@ -4,7 +4,7 @@
      *
      *   TrueType and OpenType colored glyph layer support (body).
      *
    - * Copyright (C) 2018-2022 by
    + * Copyright (C) 2018-2023 by
      * David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg.
      *
      * Originally written by Shao Yu Zhang .
    @@ -34,6 +34,9 @@
     #include 
     #include 
     
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +#include 
    +#endif
     
     #ifdef TT_CONFIG_OPTION_COLOR_LAYERS
     
    @@ -46,17 +49,42 @@
     #define LAYER_V1_LIST_PAINT_OFFSET_SIZE   4U
     #define LAYER_V1_LIST_NUM_LAYERS_SIZE     4U
     #define COLOR_STOP_SIZE                   6U
    +#define VAR_IDX_BASE_SIZE                 4U
     #define LAYER_SIZE                        4U
    -#define COLR_HEADER_SIZE                 14U
    +/* https://docs.microsoft.com/en-us/typography/opentype/spec/colr#colr-header */
    +/* 3 * uint16 + 2 * Offset32 */
    +#define COLRV0_HEADER_SIZE               14U
    +/* COLRV0_HEADER_SIZE + 5 * Offset32 */
    +#define COLRV1_HEADER_SIZE               34U
    +
    +
    +#define ENSURE_READ_BYTES( byte_size )                             \
    +  if ( p < colr->paints_start_v1                                || \
    +       p > (FT_Byte*)colr->table + colr->table_size - byte_size )  \
    +    return 0
     
     
       typedef enum  FT_PaintFormat_Internal_
       {
    -    FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER         = 18,
    -    FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM        = 20,
    -    FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER = 22,
    -    FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER        = 26,
    -    FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER          = 30
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID                = 3,
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_LINEAR_GRADIENT      = 5,
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_RADIAL_GRADIENT      = 7,
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SWEEP_GRADIENT       = 9,
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM            = 13,
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE            = 15,
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE                = 17,
    +    FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER             = 18,
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER         = 19,
    +    FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM            = 20,
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM        = 21,
    +    FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER     = 22,
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER = 23,
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE               = 25,
    +    FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER            = 26,
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER        = 27,
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW                 = 29,
    +    FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER              = 30,
    +    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER          = 31,
     
       } FT_PaintFormat_Internal;
     
    @@ -104,6 +132,12 @@
          */
         FT_Byte*  paints_start_v1;
     
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +    /* Item Variation Store for variable 'COLR' v1. */
    +    GX_ItemVarStoreRec    var_store;
    +    GX_DeltaSetIdxMapRec  delta_set_idx_map;
    +#endif
    +
         /* The memory that backs up the `COLR' table. */
         void*     table;
         FT_ULong  table_size;
    @@ -139,6 +173,9 @@
         FT_ULong  base_glyphs_offset_v1, num_base_glyphs_v1;
         FT_ULong  layer_offset_v1, num_layers_v1, clip_list_offset;
         FT_ULong  table_size;
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +    FT_ULong  colr_offset_in_stream;
    +#endif
     
     
         /* `COLR' always needs `CPAL' */
    @@ -149,8 +186,12 @@
         if ( error )
           goto NoColr;
     
    -    if ( table_size < COLR_HEADER_SIZE )
    -      goto InvalidTable;
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +    colr_offset_in_stream = FT_STREAM_POS();
    +#endif
    +
    +    if ( table_size < COLRV0_HEADER_SIZE )
    +      goto NoColr;
     
         if ( FT_FRAME_EXTRACT( table_size, table ) )
           goto NoColr;
    @@ -183,9 +224,12 @@
     
         if ( colr->version == 1 )
         {
    +      if ( table_size < COLRV1_HEADER_SIZE )
    +        goto InvalidTable;
    +
           base_glyphs_offset_v1 = FT_NEXT_ULONG( p );
     
    -      if ( base_glyphs_offset_v1 >= table_size )
    +      if ( base_glyphs_offset_v1 + 4 >= table_size )
             goto InvalidTable;
     
           p1                 = (FT_Byte*)( table + base_glyphs_offset_v1 );
    @@ -205,6 +249,9 @@
     
           if ( layer_offset_v1 )
           {
    +        if ( layer_offset_v1 + 4 >= table_size )
    +          goto InvalidTable;
    +
             p1            = (FT_Byte*)( table + layer_offset_v1 );
             num_layers_v1 = FT_PEEK_ULONG( p1 );
     
    @@ -239,6 +286,65 @@
             colr->clip_list = (FT_Byte*)( table + clip_list_offset );
           else
             colr->clip_list = 0;
    +
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +      colr->var_store.dataCount     = 0;
    +      colr->var_store.varData       = NULL;
    +      colr->var_store.axisCount     = 0;
    +      colr->var_store.regionCount   = 0;
    +      colr->var_store.varRegionList = 0;
    +
    +      colr->delta_set_idx_map.mapCount   = 0;
    +      colr->delta_set_idx_map.outerIndex = NULL;
    +      colr->delta_set_idx_map.innerIndex = NULL;
    +
    +      if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR )
    +      {
    +        FT_ULong  var_idx_map_offset, var_store_offset;
    +
    +        FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
    +
    +
    +        var_idx_map_offset = FT_NEXT_ULONG( p );
    +
    +        if ( var_idx_map_offset >= table_size )
    +          goto InvalidTable;
    +
    +        var_store_offset = FT_NEXT_ULONG( p );
    +        if ( var_store_offset >= table_size )
    +          goto InvalidTable;
    +
    +        if ( var_store_offset )
    +        {
    +          /* If variation info has not been initialized yet, try doing so, */
    +          /* otherwise loading the variation store will fail as it         */
    +          /* requires access to `blend` for checking the number of axes.   */
    +          if ( !face->blend )
    +            if ( mm->get_mm_var( FT_FACE( face ), NULL ) )
    +              goto InvalidTable;
    +
    +          /* Try loading `VarIdxMap` and `VarStore`. */
    +          error = mm->load_item_var_store(
    +                    FT_FACE( face ),
    +                    colr_offset_in_stream + var_store_offset,
    +                    &colr->var_store );
    +          if ( error != FT_Err_Ok )
    +            goto InvalidTable;
    +        }
    +
    +        if ( colr->var_store.axisCount && var_idx_map_offset )
    +        {
    +          error = mm->load_delta_set_idx_map(
    +                    FT_FACE( face ),
    +                    colr_offset_in_stream + var_idx_map_offset,
    +                    &colr->delta_set_idx_map,
    +                    &colr->var_store,
    +                    table_size );
    +          if ( error != FT_Err_Ok )
    +            goto InvalidTable;
    +        }
    +      }
    +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
         }
     
         colr->base_glyphs = (FT_Byte*)( table + base_glyph_offset );
    @@ -251,6 +357,18 @@
         return FT_Err_Ok;
     
       InvalidTable:
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +    {
    +      FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
    +
    +
    +      mm->done_delta_set_idx_map( FT_FACE( face ),
    +                                  &colr->delta_set_idx_map );
    +      mm->done_item_var_store( FT_FACE( face ),
    +                               &colr->var_store );
    +    }
    +#endif
    +
         error = FT_THROW( Invalid_Table );
     
       NoColr:
    @@ -272,6 +390,17 @@
     
         if ( colr )
         {
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +      {
    +        FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
    +
    +
    +        mm->done_delta_set_idx_map( FT_FACE( face ),
    +                                    &colr->delta_set_idx_map );
    +        mm->done_item_var_store( FT_FACE( face ),
    +                                 &colr->var_store );
    +      }
    +#endif
           FT_FRAME_RELEASE( colr->table );
           FT_FREE( colr );
         }
    @@ -354,7 +483,9 @@
           iterator->p = colr->layers + offset;
         }
     
    -    if ( iterator->layer >= iterator->num_layers )
    +    if ( iterator->layer >= iterator->num_layers                     ||
    +         iterator->p < colr->layers                                  ||
    +         iterator->p >= ( (FT_Byte*)colr->table + colr->table_size ) )
           return 0;
     
         *aglyph_index = FT_NEXT_USHORT( iterator->p );
    @@ -372,13 +503,17 @@
     
     
       static FT_Bool
    -  read_color_line( FT_Byte*      color_line_p,
    -                   FT_ColorLine  *colorline )
    +  read_color_line( Colr*          colr,
    +                   FT_Byte*       color_line_p,
    +                   FT_ColorLine*  colorline,
    +                   FT_Bool        read_variable )
       {
         FT_Byte*        p = color_line_p;
         FT_PaintExtend  paint_extend;
     
     
    +    ENSURE_READ_BYTES( 3 );
    +
         paint_extend = (FT_PaintExtend)FT_NEXT_BYTE( p );
         if ( paint_extend > FT_COLR_PAINT_EXTEND_REFLECT )
           return 0;
    @@ -388,6 +523,7 @@
         colorline->color_stop_iterator.num_color_stops    = FT_NEXT_USHORT( p );
         colorline->color_stop_iterator.p                  = p;
         colorline->color_stop_iterator.current_color_stop = 0;
    +    colorline->color_stop_iterator.read_variable      = read_variable;
     
         return 1;
       }
    @@ -413,6 +549,10 @@
         if ( !child_table_pointer )
           return 0;
     
    +    if ( *p < colr->paints_start_v1                            ||
    +         *p > (FT_Byte*)colr->table + colr->table_size - 1 - 3 )
    +      return 0;
    +
         paint_offset = FT_NEXT_UOFF3( *p );
         if ( !paint_offset )
           return 0;
    @@ -428,20 +568,85 @@
       }
     
     
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +
       static FT_Bool
    -  read_paint( Colr*           colr,
    +  get_deltas_for_var_index_base ( TT_Face           face,
    +                                  Colr*             colr,
    +                                  FT_ULong          var_index_base,
    +                                  FT_UInt           num_deltas,
    +                                  FT_ItemVarDelta*  deltas )
    +  {
    +    FT_UInt   outer_index    = 0;
    +    FT_UInt   inner_index    = 0;
    +    FT_ULong  loop_var_index = var_index_base;
    +
    +    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
    +
    +    FT_UInt  i = 0;
    +
    +
    +    if ( var_index_base == 0xFFFFFFFF )
    +    {
    +      for ( i = 0; i < num_deltas; ++i )
    +        deltas[i] = 0;
    +      return 1;
    +    }
    +
    +    for ( i = 0; i < num_deltas; ++i )
    +    {
    +      loop_var_index = var_index_base + i;
    +
    +      if ( colr->delta_set_idx_map.innerIndex )
    +      {
    +        if ( loop_var_index >= colr->delta_set_idx_map.mapCount )
    +          loop_var_index = colr->delta_set_idx_map.mapCount - 1;
    +
    +        outer_index = colr->delta_set_idx_map.outerIndex[loop_var_index];
    +        inner_index = colr->delta_set_idx_map.innerIndex[loop_var_index];
    +      }
    +      else
    +      {
    +        outer_index = 0;
    +        inner_index = loop_var_index;
    +      }
    +
    +      deltas[i] = mm->get_item_delta( FT_FACE( face ), &colr->var_store,
    +                                      outer_index, inner_index );
    +    }
    +
    +    return 1;
    +  }
    +
    +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
    +
    +
    +  static FT_Bool
    +  read_paint( TT_Face         face,
    +              Colr*           colr,
                   FT_Byte*        p,
                   FT_COLR_Paint*  apaint )
       {
    -    FT_Byte*  paint_base     = p;
    -    FT_Byte*  child_table_p  = NULL;
    +    FT_Byte*  paint_base    = p;
    +    FT_Byte*  child_table_p = NULL;
    +    FT_Bool   do_read_var   = FALSE;
    +
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +    FT_ULong         var_index_base = 0;
    +    /* Longest varIndexBase offset is 5 in the spec. */
    +    FT_ItemVarDelta  item_deltas[6] = { 0, 0, 0, 0, 0, 0 };
    +#else
    +    FT_UNUSED( face );
    +#endif
     
     
         if ( !p || !colr || !colr->table )
           return 0;
     
    -    if ( p < colr->paints_start_v1                         ||
    -         p >= ( (FT_Byte*)colr->table + colr->table_size ) )
    +    /* The last byte of the 'COLR' table is at 'size-1'; subtract 1 of    */
    +    /* that to account for the expected format byte we are going to read. */
    +    if ( p < colr->paints_start_v1                        ||
    +         p > (FT_Byte*)colr->table + colr->table_size - 2 )
           return 0;
     
         apaint->format = (FT_PaintFormat)FT_NEXT_BYTE( p );
    @@ -475,16 +680,37 @@
           return 1;
         }
     
    -    else if ( apaint->format == FT_COLR_PAINTFORMAT_SOLID )
    +    else if ( apaint->format == FT_COLR_PAINTFORMAT_SOLID ||
    +              (FT_PaintFormat_Internal)apaint->format ==
    +                 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID   )
         {
    +      ENSURE_READ_BYTES( 4 );
           apaint->u.solid.color.palette_index = FT_NEXT_USHORT( p );
           apaint->u.solid.color.alpha         = FT_NEXT_SHORT( p );
     
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +      if ( (FT_PaintFormat_Internal)apaint->format ==
    +              FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID )
    +      {
    +        ENSURE_READ_BYTES( 4 );
    +        var_index_base = FT_NEXT_ULONG( p );
    +
    +        if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 1,
    +                                             item_deltas ) )
    +          return 0;
    +
    +        apaint->u.solid.color.alpha += item_deltas[0];
    +      }
    +#endif
    +
    +      apaint->format = FT_COLR_PAINTFORMAT_SOLID;
    +
           return 1;
         }
     
         else if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_GLYPH )
         {
    +      ENSURE_READ_BYTES(2);
           apaint->u.colr_glyph.glyphID = FT_NEXT_USHORT( p );
     
           return 1;
    @@ -500,16 +726,23 @@
         if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) )
           return 0;
     
    -    if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT )
    +    if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT      ||
    +         ( do_read_var =
    +             ( (FT_PaintFormat_Internal)apaint->format ==
    +               FT_COLR_PAINTFORMAT_INTERNAL_VAR_LINEAR_GRADIENT ) ) )
         {
    -      if ( !read_color_line( child_table_p,
    -                             &apaint->u.linear_gradient.colorline ) )
    +      if ( !read_color_line( colr,
    +                             child_table_p,
    +                             &apaint->u.linear_gradient.colorline,
    +                             do_read_var ) )
             return 0;
     
           /*
    -       * In order to support variations expose these as FT_Fixed 16.16 values so
    -       * that we can support fractional values after interpolation.
    +       * In order to support variations expose these as FT_Fixed 16.16
    +       * values so that we can support fractional values after
    +       * interpolation.
            */
    +      ENSURE_READ_BYTES( 12 );
           apaint->u.linear_gradient.p0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
           apaint->u.linear_gradient.p0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
           apaint->u.linear_gradient.p1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    @@ -517,23 +750,52 @@
           apaint->u.linear_gradient.p2.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
           apaint->u.linear_gradient.p2.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
     
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +      if ( do_read_var )
    +      {
    +        ENSURE_READ_BYTES( 4 );
    +        var_index_base = FT_NEXT_ULONG ( p );
    +
    +        if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6,
    +                                             item_deltas ) )
    +          return 0;
    +
    +        apaint->u.linear_gradient.p0.x += INT_TO_FIXED( item_deltas[0] );
    +        apaint->u.linear_gradient.p0.y += INT_TO_FIXED( item_deltas[1] );
    +        apaint->u.linear_gradient.p1.x += INT_TO_FIXED( item_deltas[2] );
    +        apaint->u.linear_gradient.p1.y += INT_TO_FIXED( item_deltas[3] );
    +        apaint->u.linear_gradient.p2.x += INT_TO_FIXED( item_deltas[4] );
    +        apaint->u.linear_gradient.p2.y += INT_TO_FIXED( item_deltas[5] );
    +      }
    +#endif
    +
    +      apaint->format = FT_COLR_PAINTFORMAT_LINEAR_GRADIENT;
    +
           return 1;
         }
     
    -    else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT )
    +    else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT      ||
    +              ( do_read_var =
    +                  ( (FT_PaintFormat_Internal)apaint->format ==
    +                    FT_COLR_PAINTFORMAT_INTERNAL_VAR_RADIAL_GRADIENT ) ) )
         {
           FT_Pos  tmp;
     
     
    -      if ( !read_color_line( child_table_p,
    -                             &apaint->u.radial_gradient.colorline ) )
    +      if ( !read_color_line( colr,
    +                             child_table_p,
    +                             &apaint->u.radial_gradient.colorline,
    +                             do_read_var ) )
             return 0;
     
    +
           /* In the OpenType specification, `r0` and `r1` are defined as   */
           /* `UFWORD`.  Since FreeType doesn't have a corresponding 16.16  */
           /* format we convert to `FWORD` and replace negative values with */
           /* (32bit) `FT_INT_MAX`.                                         */
     
    +      ENSURE_READ_BYTES( 12 );
    +
           apaint->u.radial_gradient.c0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
           apaint->u.radial_gradient.c0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
     
    @@ -546,15 +808,47 @@
           tmp                          = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
           apaint->u.radial_gradient.r1 = tmp < 0 ? FT_INT_MAX : tmp;
     
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +      if ( do_read_var )
    +      {
    +        ENSURE_READ_BYTES( 4 );
    +        var_index_base = FT_NEXT_ULONG ( p );
    +
    +        if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6,
    +                                             item_deltas ) )
    +          return 0;
    +
    +        apaint->u.radial_gradient.c0.x += INT_TO_FIXED( item_deltas[0] );
    +        apaint->u.radial_gradient.c0.y += INT_TO_FIXED( item_deltas[1] );
    +
    +        // TODO: Anything to be done about UFWORD deltas here?
    +        apaint->u.radial_gradient.r0 += INT_TO_FIXED( item_deltas[2] );
    +
    +        apaint->u.radial_gradient.c1.x += INT_TO_FIXED( item_deltas[3] );
    +        apaint->u.radial_gradient.c1.y += INT_TO_FIXED( item_deltas[4] );
    +
    +        apaint->u.radial_gradient.r1 += INT_TO_FIXED( item_deltas[5] );
    +      }
    +#endif
    +
    +      apaint->format = FT_COLR_PAINTFORMAT_RADIAL_GRADIENT;
    +
           return 1;
         }
     
    -    else if ( apaint->format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT )
    +    else if ( apaint->format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT      ||
    +              ( do_read_var =
    +                  ( (FT_PaintFormat_Internal)apaint->format ==
    +                    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SWEEP_GRADIENT ) ) )
         {
    -      if ( !read_color_line( child_table_p,
    -                             &apaint->u.sweep_gradient.colorline ) )
    +      if ( !read_color_line( colr,
    +                             child_table_p,
    +                             &apaint->u.sweep_gradient.colorline,
    +                             do_read_var) )
             return 0;
     
    +      ENSURE_READ_BYTES( 8 );
    +
           apaint->u.sweep_gradient.center.x =
               INT_TO_FIXED( FT_NEXT_SHORT( p ) );
           apaint->u.sweep_gradient.center.y =
    @@ -565,11 +859,34 @@
           apaint->u.sweep_gradient.end_angle =
               F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
     
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +      if ( do_read_var )
    +      {
    +        ENSURE_READ_BYTES( 4 );
    +        var_index_base = FT_NEXT_ULONG ( p );
    +
    +        if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4,
    +                                             item_deltas ) )
    +          return 0;
    +
    +        // TODO: Handle overflow?
    +        apaint->u.sweep_gradient.center.x += INT_TO_FIXED( item_deltas[0] );
    +        apaint->u.sweep_gradient.center.y += INT_TO_FIXED( item_deltas[1] );
    +
    +        apaint->u.sweep_gradient.start_angle +=
    +          F2DOT14_TO_FIXED( item_deltas[2] );
    +        apaint->u.sweep_gradient.end_angle +=
    +          F2DOT14_TO_FIXED( item_deltas[3] );
    +      }
    +#endif
    +      apaint->format = FT_COLR_PAINTFORMAT_SWEEP_GRADIENT;
    +
           return 1;
         }
     
         if ( apaint->format == FT_COLR_PAINTFORMAT_GLYPH )
         {
    +      ENSURE_READ_BYTES( 2 );
           apaint->u.glyph.paint.p                     = child_table_p;
           apaint->u.glyph.paint.insert_root_transform = 0;
           apaint->u.glyph.glyphID                     = FT_NEXT_USHORT( p );
    @@ -577,7 +894,9 @@
           return 1;
         }
     
    -    else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSFORM )
    +    else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSFORM ||
    +              (FT_PaintFormat_Internal)apaint->format ==
    +                FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM    )
         {
           apaint->u.transform.paint.p                     = child_table_p;
           apaint->u.transform.paint.insert_root_transform = 0;
    @@ -591,6 +910,7 @@
            * The following matrix coefficients are encoded as
            * OpenType 16.16 fixed-point values.
            */
    +      ENSURE_READ_BYTES( 24 );
           apaint->u.transform.affine.xx = FT_NEXT_LONG( p );
           apaint->u.transform.affine.yx = FT_NEXT_LONG( p );
           apaint->u.transform.affine.xy = FT_NEXT_LONG( p );
    @@ -598,51 +918,101 @@
           apaint->u.transform.affine.dx = FT_NEXT_LONG( p );
           apaint->u.transform.affine.dy = FT_NEXT_LONG( p );
     
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +      if ( (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM )
    +      {
    +        ENSURE_READ_BYTES( 4 );
    +        var_index_base = FT_NEXT_ULONG( p );
    +
    +        if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6,
    +                                             item_deltas ) )
    +          return 0;
    +
    +        apaint->u.transform.affine.xx += (FT_Fixed)item_deltas[0];
    +        apaint->u.transform.affine.yx += (FT_Fixed)item_deltas[1];
    +        apaint->u.transform.affine.xy += (FT_Fixed)item_deltas[2];
    +        apaint->u.transform.affine.yy += (FT_Fixed)item_deltas[3];
    +        apaint->u.transform.affine.dx += (FT_Fixed)item_deltas[4];
    +        apaint->u.transform.affine.dy += (FT_Fixed)item_deltas[5];
    +      }
    +#endif
    +
    +      apaint->format = FT_COLR_PAINTFORMAT_TRANSFORM;
    +
           return 1;
         }
     
    -    else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSLATE )
    +    else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSLATE ||
    +              (FT_PaintFormat_Internal)apaint->format ==
    +                FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE    )
         {
           apaint->u.translate.paint.p                     = child_table_p;
           apaint->u.translate.paint.insert_root_transform = 0;
     
    +      ENSURE_READ_BYTES( 4 );
           apaint->u.translate.dx = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
           apaint->u.translate.dy = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
     
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +      if ( (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE )
    +      {
    +        ENSURE_READ_BYTES( 4 );
    +        var_index_base = FT_NEXT_ULONG( p );
    +
    +        if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2,
    +                                             item_deltas ) )
    +          return 0;
    +
    +        apaint->u.translate.dx += INT_TO_FIXED( item_deltas[0] );
    +        apaint->u.translate.dy += INT_TO_FIXED( item_deltas[1] );
    +      }
    +#endif
    +
    +      apaint->format = FT_COLR_PAINTFORMAT_TRANSLATE;
    +
           return 1;
         }
     
    -    else if ( apaint->format ==
    -                FT_COLR_PAINTFORMAT_SCALE                         ||
    -              (FT_PaintFormat_Internal)apaint->format ==
    -                FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER         ||
    -              (FT_PaintFormat_Internal)apaint->format ==
    -                FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM        ||
    -              (FT_PaintFormat_Internal)apaint->format ==
    -                FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER )
    +    else if ( apaint->format >= FT_COLR_PAINTFORMAT_SCALE             &&
    +              (FT_PaintFormat_Internal)apaint->format <=
    +                FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER )
         {
           apaint->u.scale.paint.p                     = child_table_p;
           apaint->u.scale.paint.insert_root_transform = 0;
     
           /* All scale paints get at least one scale value. */
    +      ENSURE_READ_BYTES( 2 );
           apaint->u.scale.scale_x = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
     
           /* Non-uniform ones read an extra y value. */
    -      if ( apaint->format ==
    -             FT_COLR_PAINTFORMAT_SCALE                 ||
    +      if ( apaint->format == FT_COLR_PAINTFORMAT_SCALE     ||
    +           (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE        ||
    +           (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER     ||
                (FT_PaintFormat_Internal)apaint->format ==
    -             FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER )
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER )
    +      {
    +        ENSURE_READ_BYTES( 2 );
             apaint->u.scale.scale_y = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
    +      }
           else
             apaint->u.scale.scale_y = apaint->u.scale.scale_x;
     
           /* Scale paints that have a center read center coordinates, */
           /* otherwise the center is (0,0).                           */
           if ( (FT_PaintFormat_Internal)apaint->format ==
    -             FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER         ||
    +             FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER             ||
    +           (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER         ||
                (FT_PaintFormat_Internal)apaint->format ==
    -             FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER )
    +             FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER     ||
    +           (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER )
           {
    +        ENSURE_READ_BYTES( 4 );
             apaint->u.scale.center_x = INT_TO_FIXED( FT_NEXT_SHORT ( p ) );
             apaint->u.scale.center_y = INT_TO_FIXED( FT_NEXT_SHORT ( p ) );
           }
    @@ -652,6 +1022,71 @@
             apaint->u.scale.center_y = 0;
           }
     
    +      /* Base values set, now handle variations. */
    +
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +      if ( (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE                ||
    +           (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER         ||
    +           (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM        ||
    +           (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER )
    +      {
    +        ENSURE_READ_BYTES( 4 );
    +        var_index_base = FT_NEXT_ULONG( p );
    +
    +        if ( (FT_PaintFormat_Internal)apaint->format ==
    +               FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE )
    +        {
    +          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2,
    +                                               item_deltas ) )
    +            return 0;
    +
    +          apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] );
    +          apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[1] );
    +        }
    +
    +        if ( (FT_PaintFormat_Internal)apaint->format ==
    +               FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER )
    +        {
    +          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4,
    +                                               item_deltas ) )
    +            return 0;
    +
    +          apaint->u.scale.scale_x  += F2DOT14_TO_FIXED( item_deltas[0] );
    +          apaint->u.scale.scale_y  += F2DOT14_TO_FIXED( item_deltas[1] );
    +          apaint->u.scale.center_x += INT_TO_FIXED( item_deltas[2] );
    +          apaint->u.scale.center_y += INT_TO_FIXED( item_deltas[3] );
    +        }
    +
    +        if ( (FT_PaintFormat_Internal)apaint->format ==
    +               FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM )
    +        {
    +          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 1,
    +                                               item_deltas ) )
    +            return 0;
    +
    +          apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] );
    +          apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[0] );
    +        }
    +
    +        if ( (FT_PaintFormat_Internal)apaint->format ==
    +               FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER )
    +        {
    +          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 3,
    +                                               item_deltas ) )
    +            return 0;
    +
    +          apaint->u.scale.scale_x  += F2DOT14_TO_FIXED( item_deltas[0] );
    +          apaint->u.scale.scale_y  += F2DOT14_TO_FIXED( item_deltas[0] );
    +          apaint->u.scale.center_x += INT_TO_FIXED( item_deltas[1] );
    +          apaint->u.scale.center_y += INT_TO_FIXED( item_deltas[2] );
    +        }
    +      }
    +#endif
    +
           /* FT 'COLR' v1 API output format always returns fully defined */
           /* structs; we thus set the format to the public API value.    */
           apaint->format = FT_COLR_PAINTFORMAT_SCALE;
    @@ -659,18 +1094,26 @@
           return 1;
         }
     
    -    else if ( apaint->format == FT_COLR_PAINTFORMAT_ROTATE ||
    +    else if ( apaint->format == FT_COLR_PAINTFORMAT_ROTATE     ||
    +              (FT_PaintFormat_Internal)apaint->format ==
    +                FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER     ||
                   (FT_PaintFormat_Internal)apaint->format ==
    -                FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER )
    +                FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE        ||
    +              (FT_PaintFormat_Internal)apaint->format ==
    +                FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER )
         {
           apaint->u.rotate.paint.p                     = child_table_p;
           apaint->u.rotate.paint.insert_root_transform = 0;
     
    +      ENSURE_READ_BYTES( 2 );
           apaint->u.rotate.angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
     
           if ( (FT_PaintFormat_Internal)apaint->format ==
    -           FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER )
    +             FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER     ||
    +           (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER )
           {
    +        ENSURE_READ_BYTES( 4 );
             apaint->u.rotate.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
             apaint->u.rotate.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
           }
    @@ -680,24 +1123,69 @@
             apaint->u.rotate.center_y = 0;
           }
     
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +      if ( (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE        ||
    +           (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER )
    +      {
    +        FT_UInt  num_deltas = 0;
    +
    +
    +        ENSURE_READ_BYTES( 4 );
    +        var_index_base = FT_NEXT_ULONG( p );
    +
    +        if ( (FT_PaintFormat_Internal)apaint->format ==
    +               FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER )
    +          num_deltas = 3;
    +        if ( (FT_PaintFormat_Internal)apaint->format ==
    +               FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE )
    +          num_deltas = 1;
    +
    +        if ( num_deltas > 0 )
    +        {
    +          if ( !get_deltas_for_var_index_base( face, colr, var_index_base,
    +                                               num_deltas, item_deltas ) )
    +            return 0;
    +
    +          apaint->u.rotate.angle += F2DOT14_TO_FIXED( item_deltas[0] );
    +
    +          if ( num_deltas == 3 )
    +          {
    +            apaint->u.rotate.center_x += INT_TO_FIXED( item_deltas[1] );
    +            apaint->u.rotate.center_y += INT_TO_FIXED( item_deltas[2] );
    +          }
    +        }
    +      }
    +#endif
    +
           apaint->format = FT_COLR_PAINTFORMAT_ROTATE;
     
    +
           return 1;
         }
     
    -    else if ( apaint->format == FT_COLR_PAINTFORMAT_SKEW ||
    +    else if ( apaint->format == FT_COLR_PAINTFORMAT_SKEW     ||
    +              (FT_PaintFormat_Internal)apaint->format ==
    +                FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW        ||
    +              (FT_PaintFormat_Internal)apaint->format ==
    +                FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER     ||
                   (FT_PaintFormat_Internal)apaint->format ==
    -                FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER )
    +                FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER )
         {
           apaint->u.skew.paint.p                     = child_table_p;
           apaint->u.skew.paint.insert_root_transform = 0;
     
    +      ENSURE_READ_BYTES( 4 );
           apaint->u.skew.x_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
           apaint->u.skew.y_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
     
           if ( (FT_PaintFormat_Internal)apaint->format ==
    -           FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER )
    +             FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER     ||
    +           (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER )
           {
    +        ENSURE_READ_BYTES( 4 );
             apaint->u.skew.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
             apaint->u.skew.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
           }
    @@ -707,6 +1195,42 @@
             apaint->u.skew.center_y = 0;
           }
     
    +
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +      if ( (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW        ||
    +           (FT_PaintFormat_Internal)apaint->format ==
    +             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER )
    +      {
    +        ENSURE_READ_BYTES( 4 );
    +        var_index_base = FT_NEXT_ULONG( p );
    +
    +        if ( (FT_PaintFormat_Internal)apaint->format ==
    +               FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW )
    +        {
    +          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2,
    +                                               item_deltas ) )
    +            return 0;
    +
    +          apaint->u.skew.x_skew_angle += F2DOT14_TO_FIXED( item_deltas[0] );
    +          apaint->u.skew.y_skew_angle += F2DOT14_TO_FIXED( item_deltas[1] );
    +        }
    +
    +        if ( (FT_PaintFormat_Internal)apaint->format ==
    +               FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER )
    +        {
    +          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4,
    +                                               item_deltas ) )
    +            return 0;
    +
    +          apaint->u.skew.x_skew_angle += F2DOT14_TO_FIXED( item_deltas[0] );
    +          apaint->u.skew.y_skew_angle += F2DOT14_TO_FIXED( item_deltas[1] );
    +          apaint->u.skew.center_x     += INT_TO_FIXED( item_deltas[2] );
    +          apaint->u.skew.center_y     += INT_TO_FIXED( item_deltas[3] );
    +        }
    +      }
    +#endif
    +
           apaint->format = FT_COLR_PAINTFORMAT_SKEW;
     
           return 1;
    @@ -720,6 +1244,7 @@
           apaint->u.composite.source_paint.p                     = child_table_p;
           apaint->u.composite.source_paint.insert_root_transform = 0;
     
    +      ENSURE_READ_BYTES( 1 );
           composite_mode = FT_NEXT_BYTE( p );
           if ( composite_mode >= FT_COLR_COMPOSITE_MAX )
             return 0;
    @@ -871,7 +1396,7 @@
         clip_list_format = FT_NEXT_BYTE ( p );
     
         /* Format byte used here to be able to upgrade ClipList for >16bit */
    -    /* glyph ids; for now we can expect it to be 0.                    */
    +    /* glyph ids; for now we can expect it to be 1.                    */
         if ( !( clip_list_format == 1 ) )
           return 0;
     
    @@ -899,7 +1424,7 @@
     
             format = FT_NEXT_BYTE( p1 );
     
    -        if ( format > 1 )
    +        if ( format > 2 )
               return 0;
     
             /* Check whether we can extract four `FWORD`. */
    @@ -913,11 +1438,40 @@
             font_clip_box.xMin = FT_MulFix( FT_NEXT_SHORT( p1 ),
                                             face->root.size->metrics.x_scale );
             font_clip_box.yMin = FT_MulFix( FT_NEXT_SHORT( p1 ),
    -                                        face->root.size->metrics.x_scale );
    +                                        face->root.size->metrics.y_scale );
             font_clip_box.xMax = FT_MulFix( FT_NEXT_SHORT( p1 ),
                                             face->root.size->metrics.x_scale );
             font_clip_box.yMax = FT_MulFix( FT_NEXT_SHORT( p1 ),
    -                                        face->root.size->metrics.x_scale );
    +                                        face->root.size->metrics.y_scale );
    +
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +        if ( format == 2 )
    +        {
    +          FT_ULong         var_index_base = 0;
    +          /* varIndexBase offset for clipbox is 3 at most. */
    +          FT_ItemVarDelta  item_deltas[4] = { 0, 0, 0, 0 };
    +
    +
    +          /* Check whether we can extract a 32-bit varIndexBase now. */
    +          if ( p1 > limit - 4 )
    +            return 0;
    +
    +          var_index_base = FT_NEXT_ULONG( p1 );
    +
    +          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4,
    +                                               item_deltas ) )
    +            return 0;
    +
    +          font_clip_box.xMin +=
    +            FT_MulFix( item_deltas[0], face->root.size->metrics.x_scale );
    +          font_clip_box.yMin +=
    +            FT_MulFix( item_deltas[1], face->root.size->metrics.y_scale );
    +          font_clip_box.xMax +=
    +            FT_MulFix( item_deltas[2], face->root.size->metrics.x_scale );
    +          font_clip_box.yMax +=
    +            FT_MulFix( item_deltas[3], face->root.size->metrics.y_scale );
    +        }
    +#endif
     
             /* Make 4 corner points (xMin, yMin), (xMax, yMax) and transform */
             /* them.  If we we would only transform two corner points and    */
    @@ -985,13 +1539,6 @@
          */
         p = iterator->p;
     
    -    /*
    -     * First ensure that p is within COLRv1.
    -     */
    -    if ( p < colr->layers_v1                               ||
    -         p >= ( (FT_Byte*)colr->table + colr->table_size ) )
    -      return 0;
    -
         /*
          * Do a cursor sanity check of the iterator.  Counting backwards from
          * where it stands, we need to end up at a position after the beginning
    @@ -1008,6 +1555,14 @@
                colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE ) )
           return 0;
     
    +    /*
    +     * Before reading, ensure that `p` is within 'COLR' v1 and we can read a
    +     * 4-byte ULONG.
    +     */
    +    if ( p < colr->layers_v1                              ||
    +         p > (FT_Byte*)colr->table + colr->table_size - 4 )
    +      return 0;
    +
         paint_offset =
           FT_NEXT_ULONG( p );
         opaque_paint->insert_root_transform =
    @@ -1037,29 +1592,67 @@
         Colr*  colr = (Colr*)face->colr;
     
         FT_Byte*  p;
    +    FT_ULong  var_index_base;
    +    FT_Byte*  last_entry_p = NULL;
    +    FT_UInt   entry_size   = COLOR_STOP_SIZE;
     
     
    -    if ( !colr || !colr->table )
    +    if ( !colr || !colr->table || !iterator )
           return 0;
     
         if ( iterator->current_color_stop >= iterator->num_color_stops )
           return 0;
     
    -    if ( iterator->p +
    -           ( ( iterator->num_color_stops - iterator->current_color_stop ) *
    -             COLOR_STOP_SIZE ) >
    -         ( (FT_Byte *)colr->table + colr->table_size ) )
    +    if ( iterator->read_variable )
    +      entry_size += VAR_IDX_BASE_SIZE;
    +
    +    /* Calculate the start pointer for the last to-be-read (Var)ColorStop */
    +    /* and check whether we can read a full (Var)ColorStop at that        */
    +    /* position by comparing it to the position that is the size of one   */
    +    /* (Var)ColorStop before the end of the 'COLR' table.                 */
    +    last_entry_p =
    +      iterator->p + ( iterator->num_color_stops - 1 -
    +                      iterator->current_color_stop ) * entry_size;
    +    if ( iterator->p < colr->paints_start_v1          ||
    +         last_entry_p > (FT_Byte*)colr->table +
    +                        colr->table_size - entry_size )
           return 0;
     
         /* Iterator points at first `ColorStop` of `ColorLine`. */
         p = iterator->p;
     
    -    color_stop->stop_offset = FT_NEXT_SHORT( p );
    +    color_stop->stop_offset = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
     
         color_stop->color.palette_index = FT_NEXT_USHORT( p );
     
         color_stop->color.alpha = FT_NEXT_SHORT( p );
     
    +    if ( iterator->read_variable )
    +    {
    +      /* Pointer p needs to be advanced independently of whether we intend */
    +      /* to take variable deltas into account or not.  Otherwise iteration */
    +      /* would fail due to wrong offsets.                                  */
    +      var_index_base = FT_NEXT_ULONG( p );
    +
    +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    +      {
    +        FT_Int  item_deltas[2];
    +
    +
    +        if ( !get_deltas_for_var_index_base( face, colr,
    +                                             var_index_base,
    +                                             2,
    +                                             item_deltas ) )
    +          return 0;
    +
    +        color_stop->stop_offset += F2DOT14_TO_FIXED( item_deltas[0] );
    +        color_stop->color.alpha += item_deltas[1];
    +      }
    +#else
    +      FT_UNUSED( var_index_base );
    +#endif
    +    }
    +
         iterator->p = p;
         iterator->current_color_stop++;
     
    @@ -1139,7 +1732,7 @@
           return 1;
         }
     
    -    return read_paint( colr, opaque_paint.p, paint );
    +    return read_paint( face, colr, opaque_paint.p, paint );
       }
     
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h
    index 4200cb29765..20c85f0359f 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h
    @@ -4,7 +4,7 @@
      *
      *   TrueType and OpenType colored glyph layer support (specification).
      *
    - * Copyright (C) 2018-2022 by
    + * Copyright (C) 2018-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * Originally written by Shao Yu Zhang .
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c
    index 9ae535cbda4..4279bc0bd10 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c
    @@ -4,7 +4,7 @@
      *
      *   TrueType and OpenType color palette support (body).
      *
    - * Copyright (C) 2018-2022 by
    + * Copyright (C) 2018-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * Originally written by Shao Yu Zhang .
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h
    index 4717d224fc8..8e9913f0ccd 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h
    @@ -4,7 +4,7 @@
      *
      *   TrueType and OpenType color palette support (specification).
      *
    - * Copyright (C) 2018-2022 by
    + * Copyright (C) 2018-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * Originally written by Shao Yu Zhang .
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c
    index ca1c5094065..a47d08bd6de 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c
    @@ -5,7 +5,7 @@
      *   Load the basic TrueType kerning table.  This doesn't handle
      *   kerning data within the GPOS table at the moment.
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h
    index f063558313e..960c7da4946 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h
    @@ -5,7 +5,7 @@
      *   Load the basic TrueType kerning table.  This doesn't handle
      *   kerning data within the GPOS table at the moment.
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c
    index c83bd197fe7..14f625c8243 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c
    @@ -5,7 +5,7 @@
      *   Load the basic TrueType tables, i.e., tables that can be either in
      *   TTF or OTF fonts (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -206,7 +206,7 @@
           if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) )
           {
             FT_TRACE2(( "check_table_dir:"
    -                    " can read only %d table%s in font (instead of %d)\n",
    +                    " can read only %hu table%s in font (instead of %hu)\n",
                         nn, nn == 1 ? "" : "s", sfnt->num_tables ));
             sfnt->num_tables = nn;
             break;
    @@ -216,7 +216,7 @@
     
           if ( table.Offset > stream->size )
           {
    -        FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
    +        FT_TRACE2(( "check_table_dir: table entry %hu invalid\n", nn ));
             continue;
           }
           else if ( table.Length > stream->size - table.Offset )
    @@ -231,7 +231,7 @@
               valid_entries++;
             else
             {
    -          FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
    +          FT_TRACE2(( "check_table_dir: table entry %hu invalid\n", nn ));
               continue;
             }
           }
    @@ -380,7 +380,7 @@
     
         /* load the table directory */
     
    -    FT_TRACE2(( "-- Number of tables: %10u\n",    sfnt.num_tables ));
    +    FT_TRACE2(( "-- Number of tables: %10hu\n",   sfnt.num_tables ));
         FT_TRACE2(( "-- Format version:   0x%08lx\n", sfnt.format_tag ));
     
         if ( sfnt.format_tag != TTAG_OTTO )
    @@ -671,8 +671,8 @@
         if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
           goto Exit;
     
    -    FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM ));
    -    FT_TRACE3(( "IndexToLoc:   %4d\n", header->Index_To_Loc_Format ));
    +    FT_TRACE3(( "Units per EM: %4hu\n", header->Units_Per_EM ));
    +    FT_TRACE3(( "IndexToLoc:   %4hd\n", header->Index_To_Loc_Format ));
     
       Exit:
         return error;
    @@ -802,7 +802,7 @@
           }
         }
     
    -    FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs ));
    +    FT_TRACE3(( "numGlyphs: %hu\n", maxProfile->numGlyphs ));
     
       Exit:
         return error;
    @@ -1265,11 +1265,11 @@
           }
         }
     
    -    FT_TRACE3(( "sTypoAscender:  %4d\n",   os2->sTypoAscender ));
    -    FT_TRACE3(( "sTypoDescender: %4d\n",   os2->sTypoDescender ));
    -    FT_TRACE3(( "usWinAscent:    %4u\n",   os2->usWinAscent ));
    -    FT_TRACE3(( "usWinDescent:   %4u\n",   os2->usWinDescent ));
    -    FT_TRACE3(( "fsSelection:    0x%2x\n", os2->fsSelection ));
    +    FT_TRACE3(( "sTypoAscender:  %4hd\n",   os2->sTypoAscender ));
    +    FT_TRACE3(( "sTypoDescender: %4hd\n",   os2->sTypoDescender ));
    +    FT_TRACE3(( "usWinAscent:    %4hu\n",   os2->usWinAscent ));
    +    FT_TRACE3(( "usWinDescent:   %4hu\n",   os2->usWinDescent ));
    +    FT_TRACE3(( "fsSelection:    0x%2hx\n", os2->fsSelection ));
     
       Exit:
         return error;
    @@ -1468,7 +1468,7 @@
           gasp_ranges[j].maxPPEM  = FT_GET_USHORT();
           gasp_ranges[j].gaspFlag = FT_GET_USHORT();
     
    -      FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n",
    +      FT_TRACE3(( "gaspRange %hu: rangeMaxPPEM %5hu, rangeGaspBehavior 0x%hx\n",
                       j,
                       gasp_ranges[j].maxPPEM,
                       gasp_ranges[j].gaspFlag ));
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h
    index 5368971c316..1499dd5735f 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h
    @@ -5,7 +5,7 @@
      *   Load the basic TrueType tables, i.e., tables that can be either in
      *   TTF or OTF fonts (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c
    index 88377327c61..5e53e6dd4a3 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c
    @@ -4,7 +4,7 @@
      *
      *   Load the metrics tables common to TTF and OTF fonts (body).
      *
    - * Copyright (C) 2006-2022 by
    + * Copyright (C) 2006-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -306,7 +306,7 @@
         }
     
     #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    -    if ( var )
    +    if ( var && face->blend )
         {
           FT_Face  f = FT_FACE( face );
           FT_Int   a = (FT_Int)*aadvance;
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h
    index 1e45b949a55..56d2b627661 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h
    @@ -4,7 +4,7 @@
      *
      *   Load the metrics tables common to TTF and OTF fonts (specification).
      *
    - * Copyright (C) 2006-2022 by
    + * Copyright (C) 2006-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c
    index 1a885a15c53..0e17c6f34ae 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c
    @@ -5,7 +5,7 @@
      *   PostScript name table processing for TrueType and OpenType fonts
      *   (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -58,7 +58,7 @@
     #define MAC_NAME( x )  (FT_String*)psnames->macintosh_name( (FT_UInt)(x) )
     
     
    -#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
    +#else /* !FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
     
     
        /* Otherwise, we ignore the `psnames' module, and provide our own  */
    @@ -152,7 +152,7 @@
       };
     
     
    -#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
    +#endif /* !FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
     
     
       static FT_Error
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h
    index bf9342a9f5e..528f1c5f2f2 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h
    @@ -5,7 +5,7 @@
      *   PostScript name table processing for TrueType and OpenType fonts
      *   (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c
    index bf73d04e540..3c069551315 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c
    @@ -4,7 +4,7 @@
      *
      *   TrueType and OpenType embedded bitmap support (body).
      *
    - * Copyright (C) 2005-2022 by
    + * Copyright (C) 2005-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * Copyright 2013 by Google, Inc.
    @@ -385,11 +385,9 @@
     
             /* set the scale values (in 16.16 units) so advances */
             /* from the hmtx and vmtx table are scaled correctly */
    -        metrics->x_scale = FT_MulDiv( metrics->x_ppem,
    -                                      64 * 0x10000,
    +        metrics->x_scale = FT_DivFix( metrics->x_ppem * 64,
                                           face->header.Units_Per_EM );
    -        metrics->y_scale = FT_MulDiv( metrics->y_ppem,
    -                                      64 * 0x10000,
    +        metrics->y_scale = FT_DivFix( metrics->y_ppem * 64,
                                           face->header.Units_Per_EM );
     
             return FT_Err_Ok;
    @@ -399,9 +397,9 @@
           {
             FT_Stream       stream = face->root.stream;
             FT_UInt         offset;
    -        FT_UShort       upem, ppem, resolution;
    +        FT_UShort       ppem, resolution;
             TT_HoriHeader  *hori;
    -        FT_Pos          ppem_; /* to reduce casts */
    +        FT_Fixed        scale;
     
             FT_Error  error;
             FT_Byte*  p;
    @@ -424,32 +422,23 @@
     
             FT_FRAME_EXIT();
     
    -        upem = face->header.Units_Per_EM;
    -        hori = &face->horizontal;
    -
             metrics->x_ppem = ppem;
             metrics->y_ppem = ppem;
     
    -        ppem_ = (FT_Pos)ppem;
    +        scale = FT_DivFix( ppem * 64, face->header.Units_Per_EM );
    +        hori  = &face->horizontal;
     
    -        metrics->ascender =
    -          FT_MulDiv( hori->Ascender, ppem_ * 64, upem );
    -        metrics->descender =
    -          FT_MulDiv( hori->Descender, ppem_ * 64, upem );
    -        metrics->height =
    -          FT_MulDiv( hori->Ascender - hori->Descender + hori->Line_Gap,
    -                     ppem_ * 64, upem );
    -        metrics->max_advance =
    -          FT_MulDiv( hori->advance_Width_Max, ppem_ * 64, upem );
    +        metrics->ascender    = FT_MulFix( hori->Ascender, scale );
    +        metrics->descender   = FT_MulFix( hori->Descender, scale );
    +        metrics->height      =
    +          FT_MulFix( hori->Ascender - hori->Descender + hori->Line_Gap,
    +                     scale );
    +        metrics->max_advance = FT_MulFix( hori->advance_Width_Max, scale );
     
             /* set the scale values (in 16.16 units) so advances */
             /* from the hmtx and vmtx table are scaled correctly */
    -        metrics->x_scale = FT_MulDiv( metrics->x_ppem,
    -                                      64 * 0x10000,
    -                                      face->header.Units_Per_EM );
    -        metrics->y_scale = FT_MulDiv( metrics->y_ppem,
    -                                      64 * 0x10000,
    -                                      face->header.Units_Per_EM );
    +        metrics->x_scale = scale;
    +        metrics->y_scale = scale;
     
             return error;
           }
    @@ -1204,7 +1193,7 @@
               goto Fail;
     
             p += 1;  /* skip padding */
    -        /* fall-through */
    +        FALL_THROUGH;
     
           case 9:
             loader = tt_sbit_decoder_load_compound;
    @@ -1604,7 +1593,7 @@
         return error;
       }
     
    -  FT_LOCAL( FT_Error )
    +  FT_LOCAL_DEF( FT_Error )
       tt_face_load_sbit_image( TT_Face              face,
                                FT_ULong             strike_index,
                                FT_UInt              glyph_index,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h
    index c967bffba3e..07e2db461a5 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h
    @@ -4,7 +4,7 @@
      *
      *   TrueType and OpenType embedded bitmap support (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c
    index 7d79fef39a8..7a0a351f06c 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c
    @@ -4,7 +4,7 @@
      *
      *   WOFF2 Font table tags (base).
      *
    - * Copyright (C) 2019-2022 by
    + * Copyright (C) 2019-2023 by
      * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h
    index 05df85aba02..1201848e5ec 100644
    --- a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h
    +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h
    @@ -4,7 +4,7 @@
      *
      *   WOFF2 Font table tags (specification).
      *
    - * Copyright (C) 2019-2022 by
    + * Copyright (C) 2019-2023 by
      * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c
    index 622035aa797..d9f20eef131 100644
    --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c
    +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c
    @@ -4,7 +4,7 @@
      *
      *   A new `perfect' anti-aliasing renderer (body).
      *
    - * Copyright (C) 2000-2022 by
    + * Copyright (C) 2000-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -418,21 +418,21 @@ typedef ptrdiff_t  FT_PtrDist;
     
       /* It is faster to write small spans byte-by-byte than calling     */
       /* `memset'.  This is mainly due to the cost of the function call. */
    -#define FT_GRAY_SET( d, s, count )                          \
    -  FT_BEGIN_STMNT                                            \
    -    unsigned char* q = d;                                   \
    -    switch ( count )                                        \
    -    {                                                       \
    -      case 7: *q++ = (unsigned char)s; /* fall through */   \
    -      case 6: *q++ = (unsigned char)s; /* fall through */   \
    -      case 5: *q++ = (unsigned char)s; /* fall through */   \
    -      case 4: *q++ = (unsigned char)s; /* fall through */   \
    -      case 3: *q++ = (unsigned char)s; /* fall through */   \
    -      case 2: *q++ = (unsigned char)s; /* fall through */   \
    -      case 1: *q   = (unsigned char)s; /* fall through */   \
    -      case 0: break;                                        \
    -      default: FT_MEM_SET( d, s, count );                   \
    -    }                                                       \
    +#define FT_GRAY_SET( d, s, count )                   \
    +  FT_BEGIN_STMNT                                     \
    +    unsigned char* q = d;                            \
    +    switch ( count )                                 \
    +    {                                                \
    +      case 7: *q++ = (unsigned char)s; FALL_THROUGH; \
    +      case 6: *q++ = (unsigned char)s; FALL_THROUGH; \
    +      case 5: *q++ = (unsigned char)s; FALL_THROUGH; \
    +      case 4: *q++ = (unsigned char)s; FALL_THROUGH; \
    +      case 3: *q++ = (unsigned char)s; FALL_THROUGH; \
    +      case 2: *q++ = (unsigned char)s; FALL_THROUGH; \
    +      case 1: *q   = (unsigned char)s; FALL_THROUGH; \
    +      case 0: break;                                 \
    +      default: FT_MEM_SET( d, s, count );            \
    +    }                                                \
       FT_END_STMNT
     
     
    @@ -1909,10 +1909,10 @@ typedef ptrdiff_t  FT_PtrDist;
     
     
       static int
    -  gray_convert_glyph_inner( RAS_ARG,
    +  gray_convert_glyph_inner( RAS_ARG_
                                 int  continued )
       {
    -    int  error;
    +    volatile int  error;
     
     
         if ( ft_setjmp( ras.jump_buffer ) == 0 )
    @@ -2004,7 +2004,7 @@ typedef ptrdiff_t  FT_PtrDist;
             ras.max_ey    = band[0];
             ras.count_ey  = width;
     
    -        error     = gray_convert_glyph_inner( RAS_VAR, continued );
    +        error     = gray_convert_glyph_inner( RAS_VAR_ continued );
             continued = 1;
     
             if ( !error )
    diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h
    index 13bf2baaa2b..a5001bf40d3 100644
    --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h
    +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h
    @@ -4,7 +4,7 @@
      *
      *   FreeType smooth renderer declaration
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h
    index 7bc60779881..f4ac93dc410 100644
    --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h
    +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h
    @@ -4,7 +4,7 @@
      *
      *   smooth renderer error codes (specification only).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c
    index df227c3758a..cdbc78c3e53 100644
    --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c
    +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c
    @@ -4,7 +4,7 @@
      *
      *   Anti-aliasing renderer interface (body).
      *
    - * Copyright (C) 2000-2022 by
    + * Copyright (C) 2000-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h
    index 87f09faea41..f8bdc9938b3 100644
    --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h
    +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h
    @@ -4,7 +4,7 @@
      *
      *   Anti-aliasing renderer interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c
    index 245d97cb585..4bea63ef843 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c
    @@ -4,7 +4,7 @@
      *
      *   TrueType font driver implementation (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -507,19 +507,34 @@
       FT_DEFINE_SERVICE_MULTIMASTERSREC(
         tt_service_gx_multi_masters,
     
    -    (FT_Get_MM_Func)             NULL,                  /* get_mm              */
    -    (FT_Set_MM_Design_Func)      NULL,                  /* set_mm_design       */
    -    (FT_Set_MM_Blend_Func)       TT_Set_MM_Blend,       /* set_mm_blend        */
    -    (FT_Get_MM_Blend_Func)       TT_Get_MM_Blend,       /* get_mm_blend        */
    -    (FT_Get_MM_Var_Func)         TT_Get_MM_Var,         /* get_mm_var          */
    -    (FT_Set_Var_Design_Func)     TT_Set_Var_Design,     /* set_var_design      */
    -    (FT_Get_Var_Design_Func)     TT_Get_Var_Design,     /* get_var_design      */
    -    (FT_Set_Instance_Func)       TT_Set_Named_Instance, /* set_instance        */
    -    (FT_Set_MM_WeightVector_Func)NULL,                  /* set_mm_weightvector */
    -    (FT_Get_MM_WeightVector_Func)NULL,                  /* get_mm_weightvector */
    -
    -    (FT_Get_Var_Blend_Func)      tt_get_var_blend,      /* get_var_blend       */
    -    (FT_Done_Blend_Func)         tt_done_blend          /* done_blend          */
    +    (FT_Get_MM_Func)        NULL,                  /* get_mm                    */
    +    (FT_Set_MM_Design_Func) NULL,                  /* set_mm_design             */
    +    (FT_Set_MM_Blend_Func)  TT_Set_MM_Blend,       /* set_mm_blend              */
    +    (FT_Get_MM_Blend_Func)  TT_Get_MM_Blend,       /* get_mm_blend              */
    +    (FT_Get_MM_Var_Func)    TT_Get_MM_Var,         /* get_mm_var                */
    +    (FT_Set_Var_Design_Func)TT_Set_Var_Design,     /* set_var_design            */
    +    (FT_Get_Var_Design_Func)TT_Get_Var_Design,     /* get_var_design            */
    +    (FT_Set_Instance_Func)  TT_Set_Named_Instance, /* set_instance              */
    +    (FT_Set_MM_WeightVector_Func)
    +                            NULL,                  /* set_mm_weightvector       */
    +    (FT_Get_MM_WeightVector_Func)
    +                            NULL,                  /* get_mm_weightvector       */
    +    (FT_Var_Load_Delta_Set_Idx_Map_Func)
    +                            tt_var_load_delta_set_index_mapping,
    +                                                   /* load_delta_set_idx_map    */
    +    (FT_Var_Load_Item_Var_Store_Func)
    +                            tt_var_load_item_variation_store,
    +                                                   /* load_item_variation_store */
    +    (FT_Var_Get_Item_Delta_Func)
    +                            tt_var_get_item_delta, /* get_item_delta            */
    +    (FT_Var_Done_Item_Var_Store_Func)
    +                            tt_var_done_item_variation_store,
    +                                                   /* done_item_variation_store */
    +    (FT_Var_Done_Delta_Set_Idx_Map_Func)
    +                            tt_var_done_delta_set_index_map,
    +                                                   /* done_delta_set_index_map  */
    +    (FT_Get_Var_Blend_Func) tt_get_var_blend,      /* get_var_blend             */
    +    (FT_Done_Blend_Func)    tt_done_blend          /* done_blend                */
       )
     
       FT_DEFINE_SERVICE_METRICSVARIATIONSREC(
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h
    index c477c0b1dd8..757a66f425d 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h
    @@ -4,7 +4,7 @@
      *
      *   High-level TrueType driver interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h b/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h
    index 2c95ea17b2f..008ee99853c 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h
    @@ -4,7 +4,7 @@
      *
      *   TrueType error codes (specification only).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c
    index 2ca63d65a3a..d33bdad6427 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c
    @@ -4,7 +4,7 @@
      *
      *   TrueType Glyph Loader (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -737,19 +737,19 @@
     
             if ( subglyph->flags & WE_HAVE_A_SCALE )
               FT_TRACE7(( "      scaling: %f\n",
    -                      subglyph->transform.xx / 65536.0 ));
    +                      (double)subglyph->transform.xx / 65536 ));
             else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
               FT_TRACE7(( "      scaling: x=%f, y=%f\n",
    -                      subglyph->transform.xx / 65536.0,
    -                      subglyph->transform.yy / 65536.0 ));
    +                      (double)subglyph->transform.xx / 65536,
    +                      (double)subglyph->transform.yy / 65536 ));
             else if ( subglyph->flags & WE_HAVE_A_2X2 )
             {
               FT_TRACE7(( "      scaling: xx=%f, yx=%f\n",
    -                      subglyph->transform.xx / 65536.0,
    -                      subglyph->transform.yx / 65536.0 ));
    +                      (double)subglyph->transform.xx / 65536,
    +                      (double)subglyph->transform.yx / 65536 ));
               FT_TRACE7(( "               xy=%f, yy=%f\n",
    -                      subglyph->transform.xy / 65536.0,
    -                      subglyph->transform.yy / 65536.0 ));
    +                      (double)subglyph->transform.xy / 65536,
    +                      (double)subglyph->transform.yy / 65536 ));
             }
     
             subglyph++;
    @@ -801,7 +801,7 @@
                        FT_UInt       start_point,
                        FT_UInt       start_contour )
       {
    -    zone->n_points    = (FT_UShort)load->outline.n_points -
    +    zone->n_points    = (FT_UShort)load->outline.n_points + 4 -
                               (FT_UShort)start_point;
         zone->n_contours  = load->outline.n_contours -
                               (FT_Short)start_contour;
    @@ -970,11 +970,6 @@
         outline->points[n_points + 2] = loader->pp3;
         outline->points[n_points + 3] = loader->pp4;
     
    -    outline->tags[n_points    ] = 0;
    -    outline->tags[n_points + 1] = 0;
    -    outline->tags[n_points + 2] = 0;
    -    outline->tags[n_points + 3] = 0;
    -
         n_points += 4;
     
     #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    @@ -985,24 +980,9 @@
             goto Exit;
     
           /* Deltas apply to the unscaled data. */
    -      error = TT_Vary_Apply_Glyph_Deltas( loader->face,
    -                                          loader->glyph_index,
    +      error = TT_Vary_Apply_Glyph_Deltas( loader,
                                               outline,
    -                                          unrounded,
    -                                          (FT_UInt)n_points );
    -
    -      /* recalculate linear horizontal and vertical advances */
    -      /* if we don't have HVAR and VVAR, respectively        */
    -
    -      /* XXX: change all FreeType modules to store `linear' and `vadvance' */
    -      /*      in 26.6 format before the `base' module scales them to 16.16 */
    -      if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
    -        loader->linear = FT_PIX_ROUND( unrounded[n_points - 3].x -
    -                                       unrounded[n_points - 4].x ) / 64;
    -      if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
    -        loader->vadvance = FT_PIX_ROUND( unrounded[n_points - 1].x -
    -                                         unrounded[n_points - 2].x ) / 64;
    -
    +                                          unrounded );
           if ( error )
             goto Exit;
         }
    @@ -1014,7 +994,7 @@
           tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
     
           FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
    -                     loader->zone.n_points + 4 );
    +                     loader->zone.n_points );
         }
     
         {
    @@ -1156,11 +1136,7 @@
         }
     
         if ( IS_HINTED( loader->load_flags ) )
    -    {
    -      loader->zone.n_points += 4;
    -
           error = TT_Hint_Glyph( loader, 0 );
    -    }
     
     #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
       Exit:
    @@ -1373,11 +1349,6 @@
         outline->points[outline->n_points + 2] = loader->pp3;
         outline->points[outline->n_points + 3] = loader->pp4;
     
    -    outline->tags[outline->n_points    ] = 0;
    -    outline->tags[outline->n_points + 1] = 0;
    -    outline->tags[outline->n_points + 2] = 0;
    -    outline->tags[outline->n_points + 3] = 0;
    -
     #ifdef TT_USE_BYTECODE_INTERPRETER
     
         {
    @@ -1436,11 +1407,9 @@
     
         /* Some points are likely touched during execution of  */
         /* instructions on components.  So let's untouch them. */
    -    for ( i = 0; i < loader->zone.n_points; i++ )
    +    for ( i = 0; i < loader->zone.n_points - 4U; i++ )
           loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
     
    -    loader->zone.n_points += 4;
    -
         return TT_Hint_Glyph( loader, 1 );
       }
     
    @@ -1761,57 +1730,29 @@
             /* a small outline structure with four elements for */
             /* communication with `TT_Vary_Apply_Glyph_Deltas'  */
             FT_Vector   points[4];
    -        char        tags[4]     = { 1, 1, 1, 1 };
    -        short       contours[4] = { 0, 1, 2, 3 };
             FT_Outline  outline;
     
             /* unrounded values */
             FT_Vector  unrounded[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
     
     
    -        points[0].x = loader->pp1.x;
    -        points[0].y = loader->pp1.y;
    -        points[1].x = loader->pp2.x;
    -        points[1].y = loader->pp2.y;
    -
    -        points[2].x = loader->pp3.x;
    -        points[2].y = loader->pp3.y;
    -        points[3].x = loader->pp4.x;
    -        points[3].y = loader->pp4.y;
    +        points[0] = loader->pp1;
    +        points[1] = loader->pp2;
    +        points[2] = loader->pp3;
    +        points[3] = loader->pp4;
     
    -        outline.n_points   = 4;
    -        outline.n_contours = 4;
    +        outline.n_points   = 0;
    +        outline.n_contours = 0;
             outline.points     = points;
    -        outline.tags       = tags;
    -        outline.contours   = contours;
    +        outline.tags       = NULL;
    +        outline.contours   = NULL;
     
             /* this must be done before scaling */
    -        error = TT_Vary_Apply_Glyph_Deltas( loader->face,
    -                                            glyph_index,
    +        error = TT_Vary_Apply_Glyph_Deltas( loader,
                                                 &outline,
    -                                            unrounded,
    -                                            (FT_UInt)outline.n_points );
    +                                            unrounded );
             if ( error )
               goto Exit;
    -
    -        loader->pp1.x = points[0].x;
    -        loader->pp1.y = points[0].y;
    -        loader->pp2.x = points[1].x;
    -        loader->pp2.y = points[1].y;
    -
    -        loader->pp3.x = points[2].x;
    -        loader->pp3.y = points[2].y;
    -        loader->pp4.x = points[3].x;
    -        loader->pp4.y = points[3].y;
    -
    -        /* recalculate linear horizontal and vertical advances */
    -        /* if we don't have HVAR and VVAR, respectively        */
    -        if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
    -          loader->linear = FT_PIX_ROUND( unrounded[1].x -
    -                                         unrounded[0].x ) / 64;
    -        if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
    -          loader->vadvance = FT_PIX_ROUND( unrounded[3].x -
    -                                           unrounded[2].x ) / 64;
           }
     
     #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
    @@ -1959,17 +1900,16 @@
     
             /* construct an outline structure for              */
             /* communication with `TT_Vary_Apply_Glyph_Deltas' */
    -        outline.n_points   = (short)( gloader->current.num_subglyphs + 4 );
    -        outline.n_contours = outline.n_points;
    +        outline.n_contours = outline.n_points = limit;
     
             outline.points   = NULL;
             outline.tags     = NULL;
             outline.contours = NULL;
     
    -        if ( FT_NEW_ARRAY( points, outline.n_points )    ||
    -             FT_NEW_ARRAY( tags, outline.n_points )      ||
    -             FT_NEW_ARRAY( contours, outline.n_points )  ||
    -             FT_NEW_ARRAY( unrounded, outline.n_points ) )
    +        if ( FT_NEW_ARRAY( points, limit + 4 )    ||
    +             FT_NEW_ARRAY( tags, limit + 4 )      ||
    +             FT_NEW_ARRAY( contours, limit + 4 )  ||
    +             FT_NEW_ARRAY( unrounded, limit + 4 ) )
               goto Exit1;
     
             subglyph = gloader->current.subglyphs;
    @@ -1985,28 +1925,10 @@
               contours[i] = i;
             }
     
    -        points[i].x = loader->pp1.x;
    -        points[i].y = loader->pp1.y;
    -        tags[i]     = 1;
    -        contours[i] = i;
    -
    -        i++;
    -        points[i].x = loader->pp2.x;
    -        points[i].y = loader->pp2.y;
    -        tags[i]     = 1;
    -        contours[i] = i;
    -
    -        i++;
    -        points[i].x = loader->pp3.x;
    -        points[i].y = loader->pp3.y;
    -        tags[i]     = 1;
    -        contours[i] = i;
    -
    -        i++;
    -        points[i].x = loader->pp4.x;
    -        points[i].y = loader->pp4.y;
    -        tags[i]     = 1;
    -        contours[i] = i;
    +        points[i++] = loader->pp1;
    +        points[i++] = loader->pp2;
    +        points[i++] = loader->pp3;
    +        points[i  ] = loader->pp4;
     
             outline.points   = points;
             outline.tags     = tags;
    @@ -2014,12 +1936,9 @@
     
             /* this call provides additional offsets */
             /* for each component's translation      */
    -        if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas(
    -                             face,
    -                             glyph_index,
    -                             &outline,
    -                             unrounded,
    -                             (FT_UInt)outline.n_points ) ) )
    +        if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas( loader,
    +                                                       &outline,
    +                                                       unrounded ) ) )
               goto Exit1;
     
             subglyph = gloader->current.subglyphs;
    @@ -2033,27 +1952,6 @@
               }
             }
     
    -        loader->pp1.x = points[i + 0].x;
    -        loader->pp1.y = points[i + 0].y;
    -        loader->pp2.x = points[i + 1].x;
    -        loader->pp2.y = points[i + 1].y;
    -
    -        loader->pp3.x = points[i + 2].x;
    -        loader->pp3.y = points[i + 2].y;
    -        loader->pp4.x = points[i + 3].x;
    -        loader->pp4.y = points[i + 3].y;
    -
    -        /* recalculate linear horizontal and vertical advances */
    -        /* if we don't have HVAR and VVAR, respectively        */
    -        if ( !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
    -          loader->linear =
    -            FT_PIX_ROUND( unrounded[outline.n_points - 3].x -
    -                          unrounded[outline.n_points - 4].x ) / 64;
    -        if ( !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
    -          loader->vadvance =
    -            FT_PIX_ROUND( unrounded[outline.n_points - 1].x -
    -                          unrounded[outline.n_points - 2].x ) / 64;
    -
           Exit1:
             FT_FREE( outline.points );
             FT_FREE( outline.tags );
    @@ -2229,12 +2127,11 @@
       compute_glyph_metrics( TT_Loader  loader,
                              FT_UInt    glyph_index )
       {
    -    TT_Face    face   = loader->face;
    -
    +    TT_Face       face  = loader->face;
    +    TT_Size       size  = loader->size;
    +    TT_GlyphSlot  glyph = loader->glyph;
         FT_BBox       bbox;
         FT_Fixed      y_scale;
    -    TT_GlyphSlot  glyph = loader->glyph;
    -    TT_Size       size  = loader->size;
     
     
         y_scale = 0x10000L;
    @@ -2372,17 +2269,13 @@
                        FT_UInt       glyph_index,
                        FT_Int32      load_flags )
       {
    -    TT_Face             face;
    -    SFNT_Service        sfnt;
    -    FT_Stream           stream;
    +    TT_Face             face   = (TT_Face)glyph->face;
    +    SFNT_Service        sfnt   = (SFNT_Service)face->sfnt;
    +    FT_Stream           stream = face->root.stream;
         FT_Error            error;
         TT_SBit_MetricsRec  sbit_metrics;
     
     
    -    face   = (TT_Face)glyph->face;
    -    sfnt   = (SFNT_Service)face->sfnt;
    -    stream = face->root.stream;
    -
         error = sfnt->load_sbit_image( face,
                                        size->strike_index,
                                        glyph_index,
    @@ -2433,22 +2326,19 @@
                       FT_Int32      load_flags,
                       FT_Bool       glyf_table_only )
       {
    -    TT_Face    face;
    -    FT_Stream  stream;
    +    TT_Face    face   = (TT_Face)glyph->face;
    +    FT_Stream  stream = face->root.stream;
     
     #ifdef TT_USE_BYTECODE_INTERPRETER
         FT_Error   error;
         FT_Bool    pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
     #if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
         defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
    -    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face );
    +    TT_Driver  driver   = (TT_Driver)FT_FACE_DRIVER( glyph->face );
     #endif
     #endif
     
     
    -    face   = (TT_Face)glyph->face;
    -    stream = face->root.stream;
    -
         FT_ZERO( loader );
     
     #ifdef TT_USE_BYTECODE_INTERPRETER
    @@ -2816,6 +2706,7 @@
                      FT_UInt       glyph_index,
                      FT_Int32      load_flags )
       {
    +    TT_Face       face = (TT_Face)glyph->face;
         FT_Error      error;
         TT_LoaderRec  loader;
     
    @@ -2840,8 +2731,6 @@
             /* if we have a bitmap-only font, return an empty glyph            */
             if ( !FT_IS_SCALABLE( glyph->face ) )
             {
    -          TT_Face  face = (TT_Face)glyph->face;
    -
               FT_Short  left_bearing = 0;
               FT_Short  top_bearing  = 0;
     
    @@ -2900,9 +2789,6 @@
             if ( FT_IS_SCALABLE( glyph->face ) ||
                  FT_HAS_SBIX( glyph->face )    )
             {
    -          TT_Face  face = (TT_Face)glyph->face;
    -
    -
               /* for the bbox we need the header only */
               (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
               (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
    @@ -2971,23 +2857,23 @@
     #ifdef FT_CONFIG_OPTION_SVG
     
         /* check for OT-SVG */
    -    if ( ( load_flags & FT_LOAD_COLOR ) && ( (TT_Face)glyph->face )->svg )
    +    if ( ( load_flags & FT_LOAD_COLOR ) && face->svg )
         {
    -      SFNT_Service  sfnt;
    -
    -      FT_Short   leftBearing;
    -      FT_Short   topBearing;
    -      FT_UShort  advanceX;
    -      FT_UShort  advanceY;
    +      SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
     
     
           FT_TRACE3(( "Trying to load SVG glyph\n" ));
    -      sfnt = (SFNT_Service)( (TT_Face)glyph->face )->sfnt;
     
           error = sfnt->load_svg_doc( glyph, glyph_index );
           if ( !error )
           {
    -        TT_Face  face = (TT_Face)glyph->face;
    +        FT_Fixed  x_scale = size->root.metrics.x_scale;
    +        FT_Fixed  y_scale = size->root.metrics.y_scale;
    +
    +        FT_Short   leftBearing;
    +        FT_Short   topBearing;
    +        FT_UShort  advanceX;
    +        FT_UShort  advanceY;
     
     
             FT_TRACE3(( "Successfully loaded SVG glyph\n" ));
    @@ -3005,15 +2891,11 @@
                                &topBearing,
                                &advanceY );
     
    -        advanceX = (FT_UShort)FT_MulDiv( advanceX,
    -                                         glyph->face->size->metrics.x_ppem,
    -                                         glyph->face->units_per_EM );
    -        advanceY = (FT_UShort)FT_MulDiv( advanceY,
    -                                         glyph->face->size->metrics.y_ppem,
    -                                         glyph->face->units_per_EM );
    +        glyph->linearHoriAdvance = advanceX;
    +        glyph->linearVertAdvance = advanceY;
     
    -        glyph->metrics.horiAdvance = advanceX << 6;
    -        glyph->metrics.vertAdvance = advanceY << 6;
    +        glyph->metrics.horiAdvance = FT_MulFix( advanceX, x_scale );
    +        glyph->metrics.vertAdvance = FT_MulFix( advanceY, y_scale );
     
             return error;
           }
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h
    index 3195351f78d..f18637dce33 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h
    @@ -4,7 +4,7 @@
      *
      *   TrueType Glyph Loader (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c
    index 6a0edef29bd..fc957320c84 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c
    @@ -4,7 +4,7 @@
      *
      *   TrueType GX Font Variation loader
      *
    - * Copyright (C) 2004-2022 by
    + * Copyright (C) 2004-2023 by
      * David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -42,6 +42,7 @@
     #include 
     #include 
     #include FT_CONFIG_CONFIG_H
    +#include 
     #include 
     #include 
     #include 
    @@ -353,15 +354,24 @@
       static void
       ft_var_load_avar( TT_Face  face )
       {
    -    FT_Stream       stream = FT_FACE_STREAM( face );
    -    FT_Memory       memory = stream->memory;
    +    FT_Error   error;
    +    FT_Stream  stream = FT_FACE_STREAM( face );
    +    FT_Memory  memory = stream->memory;
    +    FT_Int     i, j;
    +
         GX_Blend        blend  = face->blend;
         GX_AVarSegment  segment;
    -    FT_Error        error;
    -    FT_Long         version;
    -    FT_Long         axisCount;
    -    FT_Int          i, j;
    -    FT_ULong        table_len;
    +    GX_AVarTable    table;
    +
    +    FT_Long   version;
    +    FT_Long   axisCount;
    +    FT_ULong  table_len;
    +
    +#ifndef TT_CONFIG_OPTION_NO_BORING_EXPANSION
    +    FT_ULong  table_offset;
    +    FT_ULong  store_offset;
    +    FT_ULong  axisMap_offset;
    +#endif
     
     
         FT_TRACE2(( "AVAR " ));
    @@ -374,13 +384,21 @@
           return;
         }
     
    +#ifndef TT_CONFIG_OPTION_NO_BORING_EXPANSION
    +    table_offset = FT_STREAM_POS();
    +#endif
    +
         if ( FT_FRAME_ENTER( table_len ) )
           return;
     
         version   = FT_GET_LONG();
         axisCount = FT_GET_LONG();
     
    -    if ( version != 0x00010000L )
    +    if ( version != 0x00010000L
    +#ifndef TT_CONFIG_OPTION_NO_BORING_EXPANSION
    +         && version != 0x00020000L
    +#endif
    +       )
         {
           FT_TRACE2(( "bad table version\n" ));
           goto Exit;
    @@ -396,10 +414,14 @@
           goto Exit;
         }
     
    -    if ( FT_QNEW_ARRAY( blend->avar_segment, axisCount ) )
    +    if ( FT_NEW( blend->avar_table ) )
           goto Exit;
    +    table = blend->avar_table;
     
    -    segment = &blend->avar_segment[0];
    +    if ( FT_QNEW_ARRAY( table->avar_segment, axisCount ) )
    +      goto Exit;
    +
    +    segment = &table->avar_segment[0];
         for ( i = 0; i < axisCount; i++, segment++ )
         {
           FT_TRACE5(( "  axis %d:\n", i ));
    @@ -412,9 +434,9 @@
             /* it right now since loading the `avar' table is optional.   */
     
             for ( j = i - 1; j >= 0; j-- )
    -          FT_FREE( blend->avar_segment[j].correspondence );
    +          FT_FREE( table->avar_segment[j].correspondence );
     
    -        FT_FREE( blend->avar_segment );
    +        FT_FREE( table->avar_segment );
             goto Exit;
           }
     
    @@ -426,20 +448,51 @@
               FT_fdot14ToFixed( FT_GET_SHORT() );
     
             FT_TRACE5(( "    mapping %.5f to %.5f\n",
    -                    segment->correspondence[j].fromCoord / 65536.0,
    -                    segment->correspondence[j].toCoord / 65536.0 ));
    +                    (double)segment->correspondence[j].fromCoord / 65536,
    +                    (double)segment->correspondence[j].toCoord / 65536 ));
           }
     
           FT_TRACE5(( "\n" ));
         }
     
    +#ifndef TT_CONFIG_OPTION_NO_BORING_EXPANSION
    +    if ( version < 0x00020000L )
    +      goto Exit;
    +
    +    axisMap_offset = FT_GET_ULONG();
    +    store_offset   = FT_GET_ULONG();
    +
    +    if ( store_offset )
    +    {
    +      error = tt_var_load_item_variation_store(
    +                face,
    +                table_offset + store_offset,
    +                &table->itemStore );
    +      if ( error )
    +        goto Exit;
    +    }
    +
    +    if ( axisMap_offset )
    +    {
    +      error = tt_var_load_delta_set_index_mapping(
    +                face,
    +                table_offset + axisMap_offset,
    +                &table->axisMap,
    +                &table->itemStore,
    +                table_len );
    +      if ( error )
    +        goto Exit;
    +    }
    +#endif
    +
    +
       Exit:
         FT_FRAME_EXIT();
       }
     
     
    -  static FT_Error
    -  ft_var_load_item_variation_store( TT_Face          face,
    +  FT_LOCAL_DEF( FT_Error )
    +  tt_var_load_item_variation_store( TT_Face          face,
                                         FT_ULong         offset,
                                         GX_ItemVarStore  itemStore )
       {
    @@ -449,13 +502,15 @@
         FT_Error   error;
         FT_UShort  format;
         FT_ULong   region_offset;
    -    FT_UInt    i, j, k;
    -    FT_UInt    wordDeltaCount;
    -    FT_Bool    long_words;
     
    -    GX_Blend        blend = face->blend;
    -    GX_ItemVarData  varData;
    +    FT_UInt    data_count;
    +    FT_UShort  axis_count;
    +    FT_UInt    region_count;
    +
    +    FT_UInt  i, j, k;
    +    FT_Bool  long_words;
     
    +    GX_Blend   blend           = face->blend;
         FT_ULong*  dataOffsetArray = NULL;
     
     
    @@ -465,31 +520,31 @@
     
         if ( format != 1 )
         {
    -      FT_TRACE2(( "ft_var_load_item_variation_store: bad store format %d\n",
    +      FT_TRACE2(( "tt_var_load_item_variation_store: bad store format %d\n",
                       format ));
           error = FT_THROW( Invalid_Table );
           goto Exit;
         }
     
         /* read top level fields */
    -    if ( FT_READ_ULONG( region_offset )         ||
    -         FT_READ_USHORT( itemStore->dataCount ) )
    +    if ( FT_READ_ULONG( region_offset ) ||
    +         FT_READ_USHORT( data_count )   )
           goto Exit;
     
         /* we need at least one entry in `itemStore->varData' */
    -    if ( !itemStore->dataCount )
    +    if ( !data_count )
         {
    -      FT_TRACE2(( "ft_var_load_item_variation_store: missing varData\n" ));
    +      FT_TRACE2(( "tt_var_load_item_variation_store: missing varData\n" ));
           error = FT_THROW( Invalid_Table );
           goto Exit;
         }
     
         /* make temporary copy of item variation data offsets; */
         /* we will parse region list first, then come back     */
    -    if ( FT_QNEW_ARRAY( dataOffsetArray, itemStore->dataCount ) )
    +    if ( FT_QNEW_ARRAY( dataOffsetArray, data_count ) )
           goto Exit;
     
    -    for ( i = 0; i < itemStore->dataCount; i++ )
    +    for ( i = 0; i < data_count; i++ )
         {
           if ( FT_READ_ULONG( dataOffsetArray[i] ) )
             goto Exit;
    @@ -499,39 +554,40 @@
         if ( FT_STREAM_SEEK( offset + region_offset ) )
           goto Exit;
     
    -    if ( FT_READ_USHORT( itemStore->axisCount )   ||
    -         FT_READ_USHORT( itemStore->regionCount ) )
    +    if ( FT_READ_USHORT( axis_count )   ||
    +         FT_READ_USHORT( region_count ) )
           goto Exit;
     
    -    if ( itemStore->axisCount != (FT_Long)blend->mmvar->num_axis )
    +    if ( axis_count != (FT_Long)blend->mmvar->num_axis )
         {
    -      FT_TRACE2(( "ft_var_load_item_variation_store:"
    +      FT_TRACE2(( "tt_var_load_item_variation_store:"
                       " number of axes in item variation store\n" ));
           FT_TRACE2(( "                                 "
                       " and `fvar' table are different\n" ));
           error = FT_THROW( Invalid_Table );
           goto Exit;
         }
    +    itemStore->axisCount = axis_count;
     
         /* new constraint in OpenType 1.8.4 */
    -    if ( itemStore->regionCount >= 32768U )
    +    if ( region_count >= 32768U )
         {
    -      FT_TRACE2(( "ft_var_load_item_variation_store:"
    +      FT_TRACE2(( "tt_var_load_item_variation_store:"
                       " too many variation region tables\n" ));
           error = FT_THROW( Invalid_Table );
           goto Exit;
         }
     
    -    if ( FT_NEW_ARRAY( itemStore->varRegionList, itemStore->regionCount ) )
    +    if ( FT_NEW_ARRAY( itemStore->varRegionList, region_count ) )
           goto Exit;
    +    itemStore->regionCount = region_count;
     
         for ( i = 0; i < itemStore->regionCount; i++ )
         {
           GX_AxisCoords  axisCoords;
     
     
    -      if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList,
    -                         itemStore->axisCount ) )
    +      if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList, axis_count ) )
             goto Exit;
     
           axisCoords = itemStore->varRegionList[i].axisList;
    @@ -555,47 +611,53 @@
         /* end of region list parse */
     
         /* use dataOffsetArray now to parse varData items */
    -    if ( FT_NEW_ARRAY( itemStore->varData, itemStore->dataCount ) )
    +    if ( FT_NEW_ARRAY( itemStore->varData, data_count ) )
           goto Exit;
    +    itemStore->dataCount = data_count;
     
    -    for ( i = 0; i < itemStore->dataCount; i++ )
    +    for ( i = 0; i < data_count; i++ )
         {
    -      varData = &itemStore->varData[i];
    +      GX_ItemVarData  varData = &itemStore->varData[i];
    +
    +      FT_UInt  item_count;
    +      FT_UInt  word_delta_count;
    +      FT_UInt  region_idx_count;
    +
     
           if ( FT_STREAM_SEEK( offset + dataOffsetArray[i] ) )
             goto Exit;
     
    -      if ( FT_READ_USHORT( varData->itemCount )      ||
    -           FT_READ_USHORT( wordDeltaCount )          ||
    -           FT_READ_USHORT( varData->regionIdxCount ) )
    +      if ( FT_READ_USHORT( item_count )       ||
    +           FT_READ_USHORT( word_delta_count ) ||
    +           FT_READ_USHORT( region_idx_count ) )
             goto Exit;
     
    -      long_words      = !!( wordDeltaCount & 0x8000 );
    -      wordDeltaCount &= 0x7FFF;
    +      long_words        = !!( word_delta_count & 0x8000 );
    +      word_delta_count &= 0x7FFF;
     
           /* check some data consistency */
    -      if ( wordDeltaCount > varData->regionIdxCount )
    +      if ( word_delta_count > region_idx_count )
           {
             FT_TRACE2(( "bad short count %d or region count %d\n",
    -                    wordDeltaCount,
    -                    varData->regionIdxCount ));
    +                    word_delta_count,
    +                    region_idx_count ));
             error = FT_THROW( Invalid_Table );
             goto Exit;
           }
     
    -      if ( varData->regionIdxCount > itemStore->regionCount )
    +      if ( region_idx_count > itemStore->regionCount )
           {
             FT_TRACE2(( "inconsistent regionCount %d in varData[%d]\n",
    -                    varData->regionIdxCount,
    +                    region_idx_count,
                         i ));
             error = FT_THROW( Invalid_Table );
             goto Exit;
           }
     
           /* parse region indices */
    -      if ( FT_NEW_ARRAY( varData->regionIndices,
    -                         varData->regionIdxCount ) )
    +      if ( FT_NEW_ARRAY( varData->regionIndices, region_idx_count ) )
             goto Exit;
    +      varData->regionIdxCount = region_idx_count;
     
           for ( j = 0; j < varData->regionIdxCount; j++ )
           {
    @@ -611,54 +673,35 @@
             }
           }
     
    -      /* Parse delta set.                                                */
    -      /*                                                                 */
    -      /* On input, deltas are (wordDeltaCount + regionIdxCount) bytes    */
    -      /* each if `long_words` isn't set, and twice as much otherwise.    */
    -      /*                                                                 */
    -      /* On output, deltas are expanded to `regionIdxCount` shorts each. */
    -      if ( FT_NEW_ARRAY( varData->deltaSet,
    -                         varData->regionIdxCount * varData->itemCount ) )
    +      /* Parse delta set.                                                  */
    +      /*                                                                   */
    +      /* On input, deltas are (word_delta_count + region_idx_count) bytes  */
    +      /* each if `long_words` isn't set, and twice as much otherwise.      */
    +      /*                                                                   */
    +      /* On output, deltas are expanded to `region_idx_count` shorts each. */
    +      if ( FT_NEW_ARRAY( varData->deltaSet, item_count * region_idx_count ) )
             goto Exit;
    +      varData->itemCount = item_count;
     
    -      /* the delta set is stored as a 2-dimensional array of shorts */
    -      if ( long_words )
    +      for ( j = 0; j < item_count * region_idx_count; )
           {
    -        /* new in OpenType 1.9, currently for 'COLR' table only;          */
    -        /* the deltas are interpreted as 16.16 fixed-point scaling values */
    -
    -        /* not supported yet */
    -
    -        error = FT_THROW( Invalid_Table );
    -        goto Exit;
    -      }
    -      else
    -      {
    -        for ( j = 0; j < varData->itemCount * varData->regionIdxCount; )
    +        if ( long_words )
             {
    -          for ( k = 0; k < wordDeltaCount; k++, j++ )
    -          {
    -            /* read the short deltas */
    -            FT_Short  delta;
    -
    -
    -            if ( FT_READ_SHORT( delta ) )
    +          for ( k = 0; k < word_delta_count; k++, j++ )
    +            if ( FT_READ_LONG( varData->deltaSet[j] ) )
                   goto Exit;
    -
    -            varData->deltaSet[j] = delta;
    -          }
    -
    -          for ( ; k < varData->regionIdxCount; k++, j++ )
    -          {
    -            /* read the (signed) byte deltas */
    -            FT_Char  delta;
    -
    -
    -            if ( FT_READ_CHAR( delta ) )
    +          for ( ; k < region_idx_count; k++, j++ )
    +            if ( FT_READ_SHORT( varData->deltaSet[j] ) )
    +              goto Exit;
    +        }
    +        else
    +        {
    +          for ( k = 0; k < word_delta_count; k++, j++ )
    +            if ( FT_READ_SHORT( varData->deltaSet[j] ) )
    +              goto Exit;
    +          for ( ; k < region_idx_count; k++, j++ )
    +            if ( FT_READ_CHAR( varData->deltaSet[j] ) )
                   goto Exit;
    -
    -            varData->deltaSet[j] = delta;
    -          }
             }
           }
         }
    @@ -670,8 +713,8 @@
       }
     
     
    -  static FT_Error
    -  ft_var_load_delta_set_index_mapping( TT_Face            face,
    +  FT_LOCAL_DEF( FT_Error )
    +  tt_var_load_delta_set_index_mapping( TT_Face            face,
                                            FT_ULong           offset,
                                            GX_DeltaSetIdxMap  map,
                                            GX_ItemVarStore    itemStore,
    @@ -728,7 +771,7 @@
         /* rough sanity check */
         if ( map->mapCount * entrySize > table_len )
         {
    -      FT_TRACE1(( "ft_var_load_delta_set_index_mapping:"
    +      FT_TRACE1(( "tt_var_load_delta_set_index_mapping:"
                       " invalid number of delta-set index mappings\n" ));
           error = FT_THROW( Invalid_Table );
           goto Exit;
    @@ -758,6 +801,16 @@
             mapData = ( mapData << 8 ) | data;
           }
     
    +      /* new in OpenType 1.8.4 */
    +      if ( mapData == 0xFFFFFFFFUL )
    +      {
    +        /* no variation data for this item */
    +        map->outerIndex[i] = 0xFFFFU;
    +        map->innerIndex[i] = 0xFFFFU;
    +
    +        continue;
    +      }
    +
           outerIndex = mapData >> innerBitCount;
     
           if ( outerIndex >= itemStore->dataCount )
    @@ -887,7 +940,7 @@
           table = blend->hvar_table;
         }
     
    -    error = ft_var_load_item_variation_store(
    +    error = tt_var_load_item_variation_store(
                   face,
                   table_offset + store_offset,
                   &table->itemStore );
    @@ -896,7 +949,7 @@
     
         if ( widthMap_offset )
         {
    -      error = ft_var_load_delta_set_index_mapping(
    +      error = tt_var_load_delta_set_index_mapping(
                     face,
                     table_offset + widthMap_offset,
                     &table->widthMap,
    @@ -938,26 +991,47 @@
       }
     
     
    -  static FT_Int
    -  ft_var_get_item_delta( TT_Face          face,
    +  FT_LOCAL_DEF( FT_ItemVarDelta )
    +  tt_var_get_item_delta( TT_Face          face,
                              GX_ItemVarStore  itemStore,
                              FT_UInt          outerIndex,
                              FT_UInt          innerIndex )
       {
    -    GX_ItemVarData  varData;
    -    FT_Short*       deltaSet;
    +    FT_Stream  stream = FT_FACE_STREAM( face );
    +    FT_Memory  memory = stream->memory;
    +    FT_Error   error  = FT_Err_Ok;
    +
    +    GX_ItemVarData    varData;
    +    FT_ItemVarDelta*  deltaSet;
     
    -    FT_UInt   master, j;
    -    FT_Fixed  netAdjustment = 0;     /* accumulated adjustment */
    -    FT_Fixed  scaledDelta;
    -    FT_Fixed  delta;
    +    FT_UInt          master, j;
    +    FT_Fixed*        scalars = NULL;
    +    FT_ItemVarDelta  returnValue;
     
     
    +    if ( !face->blend || !face->blend->normalizedcoords )
    +      return 0;
    +
    +    /* OpenType 1.8.4+: No variation data for this item */
    +    /* as indices have special value 0xFFFF.            */
    +    if ( outerIndex == 0xFFFF && innerIndex == 0xFFFF )
    +      return 0;
    +
         /* See pseudo code from `Font Variations Overview' */
         /* in the OpenType specification.                  */
     
    +    if ( outerIndex >= itemStore->dataCount )
    +      return 0; /* Out of range. */
    +
         varData  = &itemStore->varData[outerIndex];
    -    deltaSet = &varData->deltaSet[varData->regionIdxCount * innerIndex];
    +    deltaSet = FT_OFFSET( varData->deltaSet,
    +                          varData->regionIdxCount * innerIndex );
    +
    +    if ( innerIndex >= varData->itemCount )
    +      return 0; /* Out of range. */
    +
    +    if ( FT_QNEW_ARRAY( scalars, varData->regionIdxCount ) )
    +      return 0;
     
         /* outer loop steps through master designs to be blended */
         for ( master = 0; master < varData->regionIdxCount; master++ )
    @@ -1008,18 +1082,33 @@
                 FT_MulDiv( scalar,
                            axis->endCoord - face->blend->normalizedcoords[j],
                            axis->endCoord - axis->peakCoord );
    -      } /* per-axis loop */
     
    -      /* get the scaled delta for this region */
    -      delta       = FT_intToFixed( deltaSet[master] );
    -      scaledDelta = FT_MulFix( scalar, delta );
    +      } /* per-axis loop */
     
    -      /* accumulate the adjustments from each region */
    -      netAdjustment = netAdjustment + scaledDelta;
    +      scalars[master] = scalar;
     
         } /* per-region loop */
     
    -    return FT_fixedToInt( netAdjustment );
    +
    +    /* Compute the scaled delta for this region.
    +     *
    +     * From: https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables:
    +     *
    +     *   `Fixed` is a 32-bit (16.16) type and, in the general case, requires
    +     *   32-bit deltas.  As described above, the `DeltaSet` record can
    +     *   accommodate deltas that are, logically, either 16-bit or 32-bit.
    +     *   When scaled deltas are applied to `Fixed` values, the `Fixed` value
    +     *   is treated like a 32-bit integer.
    +     *
    +     * `FT_MulAddFix` internally uses 64-bit precision; it thus can handle
    +     * deltas ranging from small 8-bit to large 32-bit values that are
    +     * applied to 16.16 `FT_Fixed` / OpenType `Fixed` values.
    +     */
    +    returnValue = FT_MulAddFix( scalars, deltaSet, varData->regionIdxCount );
    +
    +    FT_FREE( scalars );
    +
    +    return returnValue;
       }
     
     
    @@ -1112,35 +1201,27 @@
         }
         else
         {
    -      GX_ItemVarData  varData;
    -
    -
           /* no widthMap data */
           outerIndex = 0;
           innerIndex = gindex;
    -
    -      varData = &table->itemStore.varData[outerIndex];
    -      if ( gindex >= varData->itemCount )
    -      {
    -        FT_TRACE2(( "gindex %d out of range\n", gindex ));
    -        error = FT_THROW( Invalid_Argument );
    -        goto Exit;
    -      }
         }
     
    -    delta = ft_var_get_item_delta( face,
    +    delta = tt_var_get_item_delta( face,
                                        &table->itemStore,
                                        outerIndex,
                                        innerIndex );
     
    -    FT_TRACE5(( "%s value %d adjusted by %d unit%s (%s)\n",
    -                vertical ? "vertical height" : "horizontal width",
    -                *avalue,
    -                delta,
    -                delta == 1 ? "" : "s",
    -                vertical ? "VVAR" : "HVAR" ));
    -
    -    *avalue += delta;
    +    if ( delta )
    +    {
    +      FT_TRACE5(( "%s value %d adjusted by %d unit%s (%s)\n",
    +                  vertical ? "vertical height" : "horizontal width",
    +                  *avalue,
    +                  delta,
    +                  delta == 1 ? "" : "s",
    +                  vertical ? "VVAR" : "HVAR" ));
    +
    +      *avalue = ADD_INT( *avalue, delta );
    +    }
     
       Exit:
         return error;
    @@ -1307,7 +1388,7 @@
     
         records_offset = FT_STREAM_POS();
     
    -    error = ft_var_load_item_variation_store(
    +    error = tt_var_load_item_variation_store(
                   face,
                   table_offset + store_offset,
                   &blend->mvar_table->itemStore );
    @@ -1323,7 +1404,7 @@
           return;
     
         value     = blend->mvar_table->values;
    -    limit     = value + blend->mvar_table->valueCount;
    +    limit     = FT_OFFSET( value, blend->mvar_table->valueCount );
         itemStore = &blend->mvar_table->itemStore;
     
         for ( ; value < limit; value++ )
    @@ -1332,6 +1413,13 @@
           value->outerIndex = FT_GET_USHORT();
           value->innerIndex = FT_GET_USHORT();
     
    +      /* new in OpenType 1.8.4 */
    +      if ( value->outerIndex == 0xFFFFU && value->innerIndex == 0xFFFFU )
    +      {
    +        /* no variation data for this item */
    +        continue;
    +      }
    +
           if ( value->outerIndex >= itemStore->dataCount                  ||
                value->innerIndex >= itemStore->varData[value->outerIndex]
                                                       .itemCount          )
    @@ -1349,7 +1437,7 @@
         FT_TRACE2(( "loaded\n" ));
     
         value = blend->mvar_table->values;
    -    limit = value + blend->mvar_table->valueCount;
    +    limit = FT_OFFSET( value, blend->mvar_table->valueCount );
     
         /* save original values of the data MVAR is going to modify */
         for ( ; value < limit; value++ )
    @@ -1414,7 +1502,7 @@
           return;
     
         value = blend->mvar_table->values;
    -    limit = value + blend->mvar_table->valueCount;
    +    limit = FT_OFFSET( value, blend->mvar_table->valueCount );
     
         for ( ; value < limit; value++ )
         {
    @@ -1422,12 +1510,12 @@
           FT_Int     delta;
     
     
    -      delta = ft_var_get_item_delta( face,
    +      delta = tt_var_get_item_delta( face,
                                          &blend->mvar_table->itemStore,
                                          value->outerIndex,
                                          value->innerIndex );
     
    -      if ( p )
    +      if ( p && delta )
           {
             FT_TRACE5(( "value %c%c%c%c (%d unit%s) adjusted by %d unit%s (MVAR)\n",
                         (FT_Char)( value->tag >> 24 ),
    @@ -1725,7 +1813,7 @@
               blend->tuplecoords[i * gvar_head.axisCount + j] =
                 FT_fdot14ToFixed( FT_GET_SHORT() );
               FT_TRACE5(( "%.5f ",
    -            blend->tuplecoords[i * gvar_head.axisCount + j] / 65536.0 ));
    +            (double)blend->tuplecoords[i * gvar_head.axisCount + j] / 65536 ));
             }
             FT_TRACE5(( "]\n" ));
           }
    @@ -1796,7 +1884,7 @@
         for ( i = 0; i < blend->num_axis; i++ )
         {
           FT_TRACE6(( "    axis %d coordinate %.5f:\n",
    -                  i, blend->normalizedcoords[i] / 65536.0 ));
    +                  i, (double)blend->normalizedcoords[i] / 65536 ));
     
           /* It's not clear why (for intermediate tuples) we don't need     */
           /* to check against start/end -- the documentation says we don't. */
    @@ -1819,7 +1907,7 @@
           if ( blend->normalizedcoords[i] == tuple_coords[i] )
           {
             FT_TRACE6(( "      tuple coordinate %.5f fits perfectly\n",
    -                    tuple_coords[i] / 65536.0 ));
    +                    (double)tuple_coords[i] / 65536 ));
             /* `apply' does not change */
             continue;
           }
    @@ -1832,13 +1920,13 @@
                  blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) )
             {
               FT_TRACE6(( "      tuple coordinate %.5f is exceeded, stop\n",
    -                      tuple_coords[i] / 65536.0 ));
    +                      (double)tuple_coords[i] / 65536 ));
               apply = 0;
               break;
             }
     
             FT_TRACE6(( "      tuple coordinate %.5f fits\n",
    -                    tuple_coords[i] / 65536.0 ));
    +                    (double)tuple_coords[i] / 65536 ));
             apply = FT_MulDiv( apply,
                                blend->normalizedcoords[i],
                                tuple_coords[i] );
    @@ -1852,15 +1940,15 @@
             {
               FT_TRACE6(( "      intermediate tuple range ]%.5f;%.5f[ is exceeded,"
                           " stop\n",
    -                      im_start_coords[i] / 65536.0,
    -                      im_end_coords[i] / 65536.0 ));
    +                      (double)im_start_coords[i] / 65536,
    +                      (double)im_end_coords[i] / 65536 ));
               apply = 0;
               break;
             }
     
             FT_TRACE6(( "      intermediate tuple range ]%.5f;%.5f[ fits\n",
    -                    im_start_coords[i] / 65536.0,
    -                    im_end_coords[i] / 65536.0 ));
    +                    (double)im_start_coords[i] / 65536,
    +                    (double)im_end_coords[i] / 65536 ));
             if ( blend->normalizedcoords[i] < tuple_coords[i] )
               apply = FT_MulDiv( apply,
                                  blend->normalizedcoords[i] - im_start_coords[i],
    @@ -1872,7 +1960,7 @@
           }
         }
     
    -    FT_TRACE6(( "    apply factor is %.5f\n", apply / 65536.0 ));
    +    FT_TRACE6(( "    apply factor is %.5f\n", (double)apply / 65536 ));
     
         return apply;
       }
    @@ -1886,12 +1974,18 @@
                             FT_Fixed*  coords,
                             FT_Fixed*  normalized )
       {
    +    FT_Error   error  = FT_Err_Ok;
    +    FT_Memory  memory = face->root.memory;
    +    FT_UInt    i, j;
    +
         GX_Blend        blend;
         FT_MM_Var*      mmvar;
    -    FT_UInt         i, j;
         FT_Var_Axis*    a;
         GX_AVarSegment  av;
     
    +    FT_Fixed*  new_normalized = NULL;
    +    FT_Fixed*  old_normalized;
    +
     
         blend = face->blend;
         mmvar = blend->mmvar;
    @@ -1914,15 +2008,15 @@
           FT_Fixed  coord = coords[i];
     
     
    -      FT_TRACE5(( "    %d: %.5f\n", i, coord / 65536.0 ));
    +      FT_TRACE5(( "    %d: %.5f\n", i, (double)coord / 65536 ));
           if ( coord > a->maximum || coord < a->minimum )
           {
             FT_TRACE1(( "ft_var_to_normalized: design coordinate %.5f\n",
    -                    coord / 65536.0 ));
    +                    (double)coord / 65536 ));
             FT_TRACE1(( "                      is out of range [%.5f;%.5f];"
                         " clamping\n",
    -                    a->minimum / 65536.0,
    -                    a->maximum / 65536.0 ));
    +                    (double)a->minimum / 65536,
    +                    (double)a->maximum / 65536 ));
           }
     
           if ( coord > a->def )
    @@ -1942,30 +2036,91 @@
         for ( ; i < mmvar->num_axis; i++ )
           normalized[i] = 0;
     
    -    if ( blend->avar_segment )
    +    if ( blend->avar_table )
         {
    +      GX_AVarTable  table = blend->avar_table;
    +
    +
           FT_TRACE5(( "normalized design coordinates"
                       " before applying `avar' data:\n" ));
     
    -      av = blend->avar_segment;
    -      for ( i = 0; i < mmvar->num_axis; i++, av++ )
    +      if ( table->avar_segment )
           {
    -        for ( j = 1; j < (FT_UInt)av->pairCount; j++ )
    +        av = table->avar_segment;
    +
    +        for ( i = 0; i < mmvar->num_axis; i++, av++ )
             {
    -          if ( normalized[i] < av->correspondence[j].fromCoord )
    +          for ( j = 1; j < (FT_UInt)av->pairCount; j++ )
               {
    -            FT_TRACE5(( "  %.5f\n", normalized[i] / 65536.0 ));
    +            if ( normalized[i] < av->correspondence[j].fromCoord )
    +            {
    +              FT_TRACE5(( "  %.5f\n", (double)normalized[i] / 65536 ));
    +
    +              normalized[i] =
    +                FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord,
    +                           av->correspondence[j].toCoord -
    +                             av->correspondence[j - 1].toCoord,
    +                           av->correspondence[j].fromCoord -
    +                             av->correspondence[j - 1].fromCoord ) +
    +                av->correspondence[j - 1].toCoord;
    +              break;
    +            }
    +          }
    +        }
    +      }
     
    -            normalized[i] =
    -              FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord,
    -                         av->correspondence[j].toCoord -
    -                           av->correspondence[j - 1].toCoord,
    -                         av->correspondence[j].fromCoord -
    -                           av->correspondence[j - 1].fromCoord ) +
    -              av->correspondence[j - 1].toCoord;
    -            break;
    +      if ( table->itemStore.varData )
    +      {
    +        if ( FT_QNEW_ARRAY( new_normalized, mmvar->num_axis ) )
    +          return;
    +
    +        /* Install our half-normalized coordinates for the next */
    +        /* Item Variation Store to work with.                   */
    +        old_normalized                = face->blend->normalizedcoords;
    +        face->blend->normalizedcoords = normalized;
    +
    +        for ( i = 0; i < mmvar->num_axis; i++ )
    +        {
    +          FT_Fixed  v          = normalized[i];
    +          FT_UInt   innerIndex = i;
    +          FT_UInt   outerIndex = 0;
    +          FT_Int    delta;
    +
    +
    +          if ( table->axisMap.innerIndex )
    +          {
    +            FT_UInt  idx = i;
    +
    +
    +            if ( idx >= table->axisMap.mapCount )
    +              idx = table->axisMap.mapCount - 1;
    +
    +            outerIndex = table->axisMap.outerIndex[idx];
    +            innerIndex = table->axisMap.innerIndex[idx];
               }
    +
    +          delta = tt_var_get_item_delta( face,
    +                                         &table->itemStore,
    +                                         outerIndex,
    +                                         innerIndex );
    +
    +      v += delta << 2;
    +
    +      /* Clamp value range. */
    +      v = v >=  0x10000L ?  0x10000 : v;
    +      v = v <= -0x10000L ? -0x10000 : v;
    +
    +          new_normalized[i] = v;
    +        }
    +
    +        for ( i = 0; i < mmvar->num_axis; i++ )
    +        {
    +          normalized[i] = new_normalized[i];
             }
    +
    +        face->blend->normalizedcoords = old_normalized;
    +
    +        FT_FREE( new_normalized );
           }
         }
       }
    @@ -2003,9 +2158,9 @@
         for ( ; i < num_coords; i++ )
           design[i] = 0;
     
    -    if ( blend->avar_segment )
    +    if ( blend->avar_table && blend->avar_table->avar_segment )
         {
    -      GX_AVarSegment  av = blend->avar_segment;
    +      GX_AVarSegment  av = blend->avar_table->avar_segment;
     
     
           FT_TRACE5(( "design coordinates"
    @@ -2025,7 +2180,7 @@
                                av->correspondence[j - 1].toCoord ) +
                   av->correspondence[j - 1].fromCoord;
     
    -            FT_TRACE5(( "  %.5f\n", design[i] / 65536.0 ));
    +            FT_TRACE5(( "  %.5f\n", (double)design[i] / 65536 ));
                 break;
               }
             }
    @@ -2170,6 +2325,11 @@
           FT_FRAME_END
         };
     
    +    /* `num_instances` holds the number of all named instances including  */
    +    /* the default instance, which might be missing in the table of named */
    +    /* instances (in 'fvar').  This value is validated in `sfobjs.c` and  */
    +    /* may be reset to 0 if consistency checks fail.                      */
    +    num_instances = (FT_UInt)face->root.style_flags >> 16;
     
         /* read the font data and set up the internal representation */
         /* if not already done                                       */
    @@ -2180,20 +2340,6 @@
         {
           FT_TRACE2(( "FVAR " ));
     
    -      /* both `fvar' and `gvar' must be present */
    -      if ( FT_SET_ERROR( face->goto_table( face, TTAG_gvar,
    -                                           stream, &table_len ) ) )
    -      {
    -        /* CFF2 is an alternate to gvar here */
    -        if ( FT_SET_ERROR( face->goto_table( face, TTAG_CFF2,
    -                                             stream, &table_len ) ) )
    -        {
    -          FT_TRACE1(( "\n" ));
    -          FT_TRACE1(( "TT_Get_MM_Var: `gvar' or `CFF2' table is missing\n" ));
    -          goto Exit;
    -        }
    -      }
    -
           if ( FT_SET_ERROR( face->goto_table( face, TTAG_fvar,
                                                stream, &table_len ) ) )
           {
    @@ -2208,6 +2354,17 @@
           if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) )
             goto Exit;
     
    +      /* If `num_instances` is larger, synthetization of the default  */
    +      /* instance is required.  If `num_instances` is smaller,        */
    +      /* however, the value has been reset to 0 in `sfnt_init_face`   */
    +      /* (in `sfobjs.c`); in this case we have underallocated `mmvar` */
    +      /* structs.                                                     */
    +      if ( num_instances < fvar_head.instanceCount )
    +      {
    +        error = FT_THROW( Invalid_Table );
    +        goto Exit;
    +      }
    +
           usePsName = FT_BOOL( fvar_head.instanceSize ==
                                6 + 4 * fvar_head.axisCount );
     
    @@ -2226,11 +2383,6 @@
         else
           num_axes = face->blend->num_axis;
     
    -    /* `num_instances' holds the number of all named instances, */
    -    /* including the default instance which might be missing    */
    -    /* in fvar's table of named instances                       */
    -    num_instances = (FT_UInt)face->root.style_flags >> 16;
    -
         /* prepare storage area for MM data; this cannot overflow   */
         /* 32-bit arithmetic because of the size limits used in the */
         /* `fvar' table validity check in `sfnt_init_face'          */
    @@ -2358,9 +2510,9 @@
                         "  %10.5f  %10.5f  %10.5f  0x%04X%s\n",
                         i,
                         a->name,
    -                    a->minimum / 65536.0,
    -                    a->def / 65536.0,
    -                    a->maximum / 65536.0,
    +                    (double)a->minimum / 65536,
    +                    (double)a->def / 65536,
    +                    (double)a->maximum / 65536,
                         *axis_flags,
                         invalid ? " (invalid, disabled)" : "" ));
     #endif
    @@ -2561,6 +2713,8 @@
               a->name = (char*)"OpticalSize";
             else if ( a->tag == TTAG_slnt )
               a->name = (char*)"Slant";
    +        else if ( a->tag == TTAG_ital )
    +          a->name = (char*)"Italic";
     
             next_name += 5;
             a++;
    @@ -2622,11 +2776,11 @@
     
         for ( i = 0; i < num_coords; i++ )
         {
    -      FT_TRACE5(( "    %.5f\n", coords[i] / 65536.0 ));
    +      FT_TRACE5(( "    %.5f\n", (double)coords[i] / 65536 ));
           if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )
           {
             FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.5f\n",
    -                    coords[i] / 65536.0 ));
    +                    (double)coords[i] / 65536 ));
             FT_TRACE1(( "                 is out of range [-1;1]\n" ));
             error = FT_THROW( Invalid_Argument );
             goto Exit;
    @@ -2636,8 +2790,16 @@
         FT_TRACE5(( "\n" ));
     
         if ( !face->is_cff2 && !blend->glyphoffsets )
    -      if ( FT_SET_ERROR( ft_var_load_gvar( face ) ) )
    +    {
    +      /* While a missing 'gvar' table is acceptable, for example for */
    +      /* fonts that only vary metrics information or 'COLR' v1       */
    +      /* `PaintVar*` tables, an incorrect SFNT table offset or size  */
    +      /* for 'gvar', or an inconsistent 'gvar' table is not.         */
    +      error = ft_var_load_gvar( face );
    +      if ( error != FT_Err_Table_Missing && error != FT_Err_Ok )
             goto Exit;
    +      error = FT_Err_Ok;
    +    }
     
         if ( !blend->coords )
         {
    @@ -3503,10 +3665,10 @@
               {
                 FT_TRACE7(( "      %d: %f -> %f\n",
                             j,
    -                        ( FT_fdot6ToFixed( face->cvt[j] ) +
    -                          old_cvt_delta ) / 65536.0,
    -                        ( FT_fdot6ToFixed( face->cvt[j] ) +
    -                          cvt_deltas[j] ) / 65536.0 ));
    +                        (double)( FT_fdot6ToFixed( face->cvt[j] ) +
    +                                    old_cvt_delta ) / 65536,
    +                        (double)( FT_fdot6ToFixed( face->cvt[j] ) +
    +                                    cvt_deltas[j] ) / 65536 ));
                 count++;
               }
     #endif
    @@ -3545,10 +3707,10 @@
               {
                 FT_TRACE7(( "      %d: %f -> %f\n",
                             pindex,
    -                        ( FT_fdot6ToFixed( face->cvt[pindex] ) +
    -                          old_cvt_delta ) / 65536.0,
    -                        ( FT_fdot6ToFixed( face->cvt[pindex] ) +
    -                          cvt_deltas[pindex] ) / 65536.0 ));
    +                        (double)( FT_fdot6ToFixed( face->cvt[pindex] ) +
    +                                    old_cvt_delta ) / 65536,
    +                        (double)( FT_fdot6ToFixed( face->cvt[pindex] ) +
    +                                    cvt_deltas[pindex] ) / 65536 ));
                 count++;
               }
     #endif
    @@ -3813,20 +3975,12 @@
        * @Description:
        *   Apply the appropriate deltas to the current glyph.
        *
    -   * @Input:
    -   *   face ::
    -   *     A handle to the target face object.
    -   *
    -   *   glyph_index ::
    -   *     The index of the glyph being modified.
    -   *
    -   *   n_points ::
    -   *     The number of the points in the glyph, including
    -   *     phantom points.
    -   *
        * @InOut:
    +   *   loader ::
    +   *     A handle to the loader object.
    +   *
        *   outline ::
    -   *     The outline to change.
    +   *     The outline to change, with appended phantom points.
        *
        * @Output:
        *   unrounded ::
    @@ -3837,15 +3991,16 @@
        *   FreeType error code.  0 means success.
        */
       FT_LOCAL_DEF( FT_Error )
    -  TT_Vary_Apply_Glyph_Deltas( TT_Face      face,
    -                              FT_UInt      glyph_index,
    +  TT_Vary_Apply_Glyph_Deltas( TT_Loader    loader,
                                   FT_Outline*  outline,
    -                              FT_Vector*   unrounded,
    -                              FT_UInt      n_points )
    +                              FT_Vector*   unrounded )
       {
         FT_Error   error;
    -    FT_Stream  stream = face->root.stream;
    -    FT_Memory  memory = stream->memory;
    +    TT_Face    face        = loader->face;
    +    FT_Stream  stream      = face->root.stream;
    +    FT_Memory  memory      = stream->memory;
    +    FT_UInt    glyph_index = loader->glyph_index;
    +    FT_UInt    n_points    = (FT_UInt)outline->n_points + 4;
     
         FT_Vector*  points_org = NULL;  /* coordinates in 16.16 format */
         FT_Vector*  points_out = NULL;  /* coordinates in 16.16 format */
    @@ -4063,50 +4218,22 @@
               FT_Fixed  point_delta_y = FT_MulFix( deltas_y[j], apply );
     
     
    -          if ( j < n_points - 4 )
    -          {
    -            point_deltas_x[j] = old_point_delta_x + point_delta_x;
    -            point_deltas_y[j] = old_point_delta_y + point_delta_y;
    -          }
    -          else
    -          {
    -            /* To avoid double adjustment of advance width or height, */
    -            /* adjust phantom points only if there is no HVAR or VVAR */
    -            /* support, respectively.                                 */
    -            if ( j == ( n_points - 4 )        &&
    -                 !( face->variation_support &
    -                    TT_FACE_FLAG_VAR_LSB    ) )
    -              point_deltas_x[j] = old_point_delta_x + point_delta_x;
    -
    -            else if ( j == ( n_points - 3 )          &&
    -                      !( face->variation_support   &
    -                         TT_FACE_FLAG_VAR_HADVANCE ) )
    -              point_deltas_x[j] = old_point_delta_x + point_delta_x;
    -
    -            else if ( j == ( n_points - 2 )        &&
    -                      !( face->variation_support &
    -                         TT_FACE_FLAG_VAR_TSB    ) )
    -              point_deltas_y[j] = old_point_delta_y + point_delta_y;
    -
    -            else if ( j == ( n_points - 1 )          &&
    -                      !( face->variation_support   &
    -                         TT_FACE_FLAG_VAR_VADVANCE ) )
    -              point_deltas_y[j] = old_point_delta_y + point_delta_y;
    -          }
    +          point_deltas_x[j] = old_point_delta_x + point_delta_x;
    +          point_deltas_y[j] = old_point_delta_y + point_delta_y;
     
     #ifdef FT_DEBUG_LEVEL_TRACE
               if ( point_delta_x || point_delta_y )
               {
                 FT_TRACE7(( "      %d: (%f, %f) -> (%f, %f)\n",
                             j,
    -                        ( FT_intToFixed( outline->points[j].x ) +
    -                          old_point_delta_x ) / 65536.0,
    -                        ( FT_intToFixed( outline->points[j].y ) +
    -                          old_point_delta_y ) / 65536.0,
    -                        ( FT_intToFixed( outline->points[j].x ) +
    -                          point_deltas_x[j] ) / 65536.0,
    -                        ( FT_intToFixed( outline->points[j].y ) +
    -                          point_deltas_y[j] ) / 65536.0 ));
    +                        (double)( FT_intToFixed( outline->points[j].x ) +
    +                                    old_point_delta_x ) / 65536,
    +                        (double)( FT_intToFixed( outline->points[j].y ) +
    +                                    old_point_delta_y ) / 65536,
    +                        (double)( FT_intToFixed( outline->points[j].x ) +
    +                                    point_deltas_x[j] ) / 65536,
    +                        (double)( FT_intToFixed( outline->points[j].y ) +
    +                                    point_deltas_y[j] ) / 65536 ));
                 count++;
               }
     #endif
    @@ -4165,50 +4292,22 @@
               FT_Pos  point_delta_y = points_out[j].y - points_org[j].y;
     
     
    -          if ( j < n_points - 4 )
    -          {
    -            point_deltas_x[j] = old_point_delta_x + point_delta_x;
    -            point_deltas_y[j] = old_point_delta_y + point_delta_y;
    -          }
    -          else
    -          {
    -            /* To avoid double adjustment of advance width or height, */
    -            /* adjust phantom points only if there is no HVAR or VVAR */
    -            /* support, respectively.                                 */
    -            if ( j == ( n_points - 4 )        &&
    -                 !( face->variation_support &
    -                    TT_FACE_FLAG_VAR_LSB    ) )
    -              point_deltas_x[j] = old_point_delta_x + point_delta_x;
    -
    -            else if ( j == ( n_points - 3 )          &&
    -                      !( face->variation_support   &
    -                         TT_FACE_FLAG_VAR_HADVANCE ) )
    -              point_deltas_x[j] = old_point_delta_x + point_delta_x;
    -
    -            else if ( j == ( n_points - 2 )        &&
    -                      !( face->variation_support &
    -                         TT_FACE_FLAG_VAR_TSB    ) )
    -              point_deltas_y[j] = old_point_delta_y + point_delta_y;
    -
    -            else if ( j == ( n_points - 1 )          &&
    -                      !( face->variation_support   &
    -                         TT_FACE_FLAG_VAR_VADVANCE ) )
    -              point_deltas_y[j] = old_point_delta_y + point_delta_y;
    -          }
    +          point_deltas_x[j] = old_point_delta_x + point_delta_x;
    +          point_deltas_y[j] = old_point_delta_y + point_delta_y;
     
     #ifdef FT_DEBUG_LEVEL_TRACE
               if ( point_delta_x || point_delta_y )
               {
                 FT_TRACE7(( "      %d: (%f, %f) -> (%f, %f)\n",
                             j,
    -                        ( FT_intToFixed( outline->points[j].x ) +
    -                          old_point_delta_x ) / 65536.0,
    -                        ( FT_intToFixed( outline->points[j].y ) +
    -                          old_point_delta_y ) / 65536.0,
    -                        ( FT_intToFixed( outline->points[j].x ) +
    -                          point_deltas_x[j] ) / 65536.0,
    -                        ( FT_intToFixed( outline->points[j].y ) +
    -                          point_deltas_y[j] ) / 65536.0 ));
    +                        (double)( FT_intToFixed( outline->points[j].x ) +
    +                                    old_point_delta_x ) / 65536,
    +                        (double)( FT_intToFixed( outline->points[j].y ) +
    +                                    old_point_delta_y ) / 65536,
    +                        (double)( FT_intToFixed( outline->points[j].x ) +
    +                                    point_deltas_x[j] ) / 65536,
    +                        (double)( FT_intToFixed( outline->points[j].y ) +
    +                                    point_deltas_y[j] ) / 65536 ));
                 count++;
               }
     #endif
    @@ -4232,6 +4331,24 @@
     
         FT_TRACE5(( "\n" ));
     
    +    /* To avoid double adjustment of advance width or height, */
    +    /* do not move phantom points if there is HVAR or VVAR    */
    +    /* support, respectively.                                 */
    +    if ( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE )
    +    {
    +      point_deltas_x[n_points - 4] = 0;
    +      point_deltas_y[n_points - 4] = 0;
    +      point_deltas_x[n_points - 3] = 0;
    +      point_deltas_y[n_points - 3] = 0;
    +    }
    +    if ( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE )
    +    {
    +      point_deltas_x[n_points - 2] = 0;
    +      point_deltas_y[n_points - 2] = 0;
    +      point_deltas_x[n_points - 1] = 0;
    +      point_deltas_y[n_points - 1] = 0;
    +    }
    +
         for ( i = 0; i < n_points; i++ )
         {
           unrounded[i].x += FT_fixedToFdot6( point_deltas_x[i] );
    @@ -4241,6 +4358,24 @@
           outline->points[i].y += FT_fixedToInt( point_deltas_y[i] );
         }
     
    +    /* To avoid double adjustment of advance width or height, */
    +    /* adjust phantom points only if there is no HVAR or VVAR */
    +    /* support, respectively.                                 */
    +    if ( !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
    +    {
    +      loader->pp1      = outline->points[n_points - 4];
    +      loader->pp2      = outline->points[n_points - 3];
    +      loader->linear   = FT_PIX_ROUND( unrounded[n_points - 3].x -
    +                                       unrounded[n_points - 4].x ) / 64;
    +    }
    +    if ( !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
    +    {
    +      loader->pp3      = outline->points[n_points - 2];
    +      loader->pp4      = outline->points[n_points - 1];
    +      loader->vadvance = FT_PIX_ROUND( unrounded[n_points - 1].y -
    +                                       unrounded[n_points - 2].y ) / 64;
    +    }
    +
       Fail3:
         FT_FREE( point_deltas_x );
         FT_FREE( point_deltas_y );
    @@ -4305,8 +4440,8 @@
       }
     
     
    -  static void
    -  ft_var_done_item_variation_store( TT_Face          face,
    +  FT_LOCAL_DEF( void )
    +  tt_var_done_item_variation_store( TT_Face          face,
                                         GX_ItemVarStore  itemStore )
       {
         FT_Memory  memory = FT_FACE_MEMORY( face );
    @@ -4334,6 +4469,18 @@
       }
     
     
    +  FT_LOCAL_DEF( void )
    +  tt_var_done_delta_set_index_map( TT_Face            face,
    +                                   GX_DeltaSetIdxMap  deltaSetIdxMap )
    +  {
    +    FT_Memory  memory = FT_FACE_MEMORY( face );
    +
    +
    +    FT_FREE( deltaSetIdxMap->innerIndex );
    +    FT_FREE( deltaSetIdxMap->outerIndex );
    +  }
    +
    +
       /**************************************************************************
        *
        * @Function:
    @@ -4362,36 +4509,47 @@
           FT_FREE( blend->normalized_stylecoords );
           FT_FREE( blend->mmvar );
     
    -      if ( blend->avar_segment )
    +      if ( blend->avar_table )
           {
    -        for ( i = 0; i < num_axes; i++ )
    -          FT_FREE( blend->avar_segment[i].correspondence );
    -        FT_FREE( blend->avar_segment );
    +        if ( blend->avar_table->avar_segment )
    +        {
    +          for ( i = 0; i < num_axes; i++ )
    +            FT_FREE( blend->avar_table->avar_segment[i].correspondence );
    +          FT_FREE( blend->avar_table->avar_segment );
    +        }
    +
    +        tt_var_done_item_variation_store( face,
    +                                          &blend->avar_table->itemStore );
    +
    +        tt_var_done_delta_set_index_map( face,
    +                                         &blend->avar_table->axisMap );
    +
    +        FT_FREE( blend->avar_table );
           }
     
           if ( blend->hvar_table )
           {
    -        ft_var_done_item_variation_store( face,
    +        tt_var_done_item_variation_store( face,
                                               &blend->hvar_table->itemStore );
     
    -        FT_FREE( blend->hvar_table->widthMap.innerIndex );
    -        FT_FREE( blend->hvar_table->widthMap.outerIndex );
    +        tt_var_done_delta_set_index_map( face,
    +                                         &blend->hvar_table->widthMap );
             FT_FREE( blend->hvar_table );
           }
     
           if ( blend->vvar_table )
           {
    -        ft_var_done_item_variation_store( face,
    +        tt_var_done_item_variation_store( face,
                                               &blend->vvar_table->itemStore );
     
    -        FT_FREE( blend->vvar_table->widthMap.innerIndex );
    -        FT_FREE( blend->vvar_table->widthMap.outerIndex );
    +        tt_var_done_delta_set_index_map( face,
    +                                         &blend->vvar_table->widthMap );
             FT_FREE( blend->vvar_table );
           }
     
           if ( blend->mvar_table )
           {
    -        ft_var_done_item_variation_store( face,
    +        tt_var_done_item_variation_store( face,
                                               &blend->mvar_table->itemStore );
     
             FT_FREE( blend->mvar_table->values );
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h
    index 17915f00d3e..4fec980dcc0 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h
    @@ -4,7 +4,7 @@
      *
      *   TrueType GX Font Variation loader (specification)
      *
    - * Copyright (C) 2004-2022 by
    + * Copyright (C) 2004-2023 by
      * David Turner, Robert Wilhelm, Werner Lemberg and George Williams.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -20,6 +20,7 @@
     #define TTGXVAR_H_
     
     
    +#include 
     #include "ttobjs.h"
     
     
    @@ -62,55 +63,21 @@ FT_BEGIN_HEADER
       } GX_AVarSegmentRec, *GX_AVarSegment;
     
     
    -  typedef struct  GX_ItemVarDataRec_
    -  {
    -    FT_UInt    itemCount;      /* number of delta sets per item         */
    -    FT_UInt    regionIdxCount; /* number of region indices in this data */
    -    FT_UInt*   regionIndices;  /* array of `regionCount' indices;       */
    -                               /* these index `varRegionList'           */
    -    FT_Short*  deltaSet;       /* array of `itemCount' deltas           */
    -                               /* use `innerIndex' for this array       */
    -
    -  } GX_ItemVarDataRec, *GX_ItemVarData;
    -
    -
    -  /* contribution of one axis to a region */
    -  typedef struct  GX_AxisCoordsRec_
    -  {
    -    FT_Fixed  startCoord;
    -    FT_Fixed  peakCoord;      /* zero means no effect (factor = 1) */
    -    FT_Fixed  endCoord;
    -
    -  } GX_AxisCoordsRec, *GX_AxisCoords;
    -
    -
    -  typedef struct  GX_VarRegionRec_
    -  {
    -    GX_AxisCoords  axisList;               /* array of axisCount records */
    -
    -  } GX_VarRegionRec, *GX_VarRegion;
    -
    -
    -  /* item variation store */
    -  typedef struct  GX_ItemVarStoreRec_
    -  {
    -    FT_UInt         dataCount;
    -    GX_ItemVarData  varData;            /* array of dataCount records;     */
    -                                        /* use `outerIndex' for this array */
    -    FT_UShort     axisCount;
    -    FT_UInt       regionCount;          /* total number of regions defined */
    -    GX_VarRegion  varRegionList;
    -
    -  } GX_ItemVarStoreRec, *GX_ItemVarStore;
    -
    -
    -  typedef struct  GX_DeltaSetIdxMapRec_
    +  /**************************************************************************
    +   *
    +   * @Struct:
    +   *   GX_AVarTableRec
    +   *
    +   * @Description:
    +   *   Data from the `avar' table.
    +   */
    +  typedef struct  GX_AVarTableRec_
       {
    -    FT_ULong  mapCount;
    -    FT_UInt*  outerIndex;               /* indices to item var data */
    -    FT_UInt*  innerIndex;               /* indices to delta set     */
    +    GX_AVarSegment        avar_segment;   /* avar_segment[num_axis] */
    +    GX_ItemVarStoreRec    itemStore;      /* Item Variation Store   */
    +    GX_DeltaSetIdxMapRec  axisMap;        /* Axis Mapping           */
     
    -  } GX_DeltaSetIdxMapRec, *GX_DeltaSetIdxMap;
    +  } GX_AVarTableRec, *GX_AVarTable;
     
     
       /**************************************************************************
    @@ -245,7 +212,7 @@ FT_BEGIN_HEADER
        *     A Boolean; if set, FreeType tried to load (and parse) the `avar'
        *     table.
        *
    -   *   avar_segment ::
    +   *   avar_table ::
        *     Data from the `avar' table.
        *
        *   hvar_loaded ::
    @@ -310,7 +277,7 @@ FT_BEGIN_HEADER
                           /* normalized_stylecoords[num_namedstyles][num_axis] */
     
         FT_Bool         avar_loaded;
    -    GX_AVarSegment  avar_segment;                /* avar_segment[num_axis] */
    +    GX_AVarTable    avar_table;
     
         FT_Bool         hvar_loaded;
         FT_Bool         hvar_checked;
    @@ -376,6 +343,7 @@ FT_BEGIN_HEADER
     #define TTAG_wdth  FT_MAKE_TAG( 'w', 'd', 't', 'h' )
     #define TTAG_opsz  FT_MAKE_TAG( 'o', 'p', 's', 'z' )
     #define TTAG_slnt  FT_MAKE_TAG( 's', 'l', 'n', 't' )
    +#define TTAG_ital  FT_MAKE_TAG( 'i', 't', 'a', 'l' )
     
     
       FT_LOCAL( FT_Error )
    @@ -412,11 +380,9 @@ FT_BEGIN_HEADER
     
     
       FT_LOCAL( FT_Error )
    -  TT_Vary_Apply_Glyph_Deltas( TT_Face      face,
    -                              FT_UInt      glyph_index,
    +  TT_Vary_Apply_Glyph_Deltas( TT_Loader    loader,
                                   FT_Outline*  outline,
    -                              FT_Vector*   unrounded,
    -                              FT_UInt      n_points );
    +                              FT_Vector*   unrounded );
     
       FT_LOCAL( FT_Error )
       tt_hadvance_adjust( TT_Face  face,
    @@ -431,6 +397,34 @@ FT_BEGIN_HEADER
       FT_LOCAL( void )
       tt_apply_mvar( TT_Face  face );
     
    +
    +  FT_LOCAL( FT_Error )
    +  tt_var_load_item_variation_store( TT_Face          face,
    +                                    FT_ULong         offset,
    +                                    GX_ItemVarStore  itemStore );
    +
    +  FT_LOCAL( FT_Error )
    +  tt_var_load_delta_set_index_mapping( TT_Face            face,
    +                                       FT_ULong           offset,
    +                                       GX_DeltaSetIdxMap  map,
    +                                       GX_ItemVarStore    itemStore,
    +                                       FT_ULong           table_len );
    +
    +  FT_LOCAL( FT_ItemVarDelta )
    +  tt_var_get_item_delta( TT_Face          face,
    +                         GX_ItemVarStore  itemStore,
    +                         FT_UInt          outerIndex,
    +                         FT_UInt          innerIndex );
    +
    +  FT_LOCAL( void )
    +  tt_var_done_item_variation_store( TT_Face          face,
    +                                    GX_ItemVarStore  itemStore );
    +
    +  FT_LOCAL( void )
    +  tt_var_done_delta_set_index_map( TT_Face            face,
    +                                   GX_DeltaSetIdxMap  deltaSetIdxMap );
    +
    +
       FT_LOCAL( FT_Error )
       tt_get_var_blend( TT_Face      face,
                         FT_UInt     *num_coords,
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c
    index e16565c3a57..4fcfaa3e430 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c
    @@ -4,7 +4,7 @@
      *
      *   TrueType bytecode interpreter (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -1527,9 +1527,8 @@
       static void
       Modify_CVT_Check( TT_ExecContext  exc )
       {
    -    /* TT_RunIns sets origCvt and restores cvt to origCvt when done. */
         if ( exc->iniRange == tt_coderange_glyph &&
    -         exc->cvt == exc->origCvt            )
    +         exc->cvt != exc->glyfCvt            )
         {
           exc->error = Update_Max( exc->memory,
                                    &exc->glyfCvtSize,
    @@ -3115,10 +3114,8 @@
         }
         else
         {
    -      /* TT_RunIns sets origStorage and restores storage to origStorage */
    -      /* when done.                                                     */
           if ( exc->iniRange == tt_coderange_glyph &&
    -           exc->storage == exc->origStorage    )
    +           exc->storage != exc->glyfStorage    )
           {
             FT_ULong  tmp = (FT_ULong)exc->glyfStoreSize;
     
    @@ -6874,7 +6871,7 @@
     
     
       static void
    -  _iup_worker_shift( IUP_Worker  worker,
    +  iup_worker_shift_( IUP_Worker  worker,
                          FT_UInt     p1,
                          FT_UInt     p2,
                          FT_UInt     p )
    @@ -6896,7 +6893,7 @@
     
     
       static void
    -  _iup_worker_interpolate( IUP_Worker  worker,
    +  iup_worker_interpolate_( IUP_Worker  worker,
                                FT_UInt     p1,
                                FT_UInt     p2,
                                FT_UInt     ref1,
    @@ -7090,7 +7087,7 @@
             {
               if ( ( exc->pts.tags[point] & mask ) != 0 )
               {
    -            _iup_worker_interpolate( &V,
    +            iup_worker_interpolate_( &V,
                                          cur_touched + 1,
                                          point - 1,
                                          cur_touched,
    @@ -7102,17 +7099,17 @@
             }
     
             if ( cur_touched == first_touched )
    -          _iup_worker_shift( &V, first_point, end_point, cur_touched );
    +          iup_worker_shift_( &V, first_point, end_point, cur_touched );
             else
             {
    -          _iup_worker_interpolate( &V,
    +          iup_worker_interpolate_( &V,
                                        (FT_UShort)( cur_touched + 1 ),
                                        end_point,
                                        cur_touched,
                                        first_touched );
     
               if ( first_touched > 0 )
    -            _iup_worker_interpolate( &V,
    +            iup_worker_interpolate_( &V,
                                          first_point,
                                          first_touched - 1,
                                          cur_touched,
    @@ -7832,8 +7829,6 @@
           exc->func_move_cvt  = Move_CVT;
         }
     
    -    exc->origCvt     = exc->cvt;
    -    exc->origStorage = exc->storage;
         exc->iniRange    = exc->curRange;
     
         Compute_Funcs( exc );
    @@ -8570,7 +8565,8 @@
     
           /* increment instruction counter and check if we didn't */
           /* run this program for too long (e.g. infinite loops). */
    -      if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES ) {
    +      if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES )
    +      {
             exc->error = FT_THROW( Execution_Too_Long );
             goto LErrorLabel_;
           }
    @@ -8593,9 +8589,6 @@
                     ins_counter,
                     ins_counter == 1 ? "" : "s" ));
     
    -    exc->cvt     = exc->origCvt;
    -    exc->storage = exc->origStorage;
    -
         return FT_Err_Ok;
     
       LErrorCodeOverflow_:
    @@ -8605,9 +8598,6 @@
         if ( exc->error && !exc->instruction_trap )
           FT_TRACE1(( "  The interpreter returned error 0x%x\n", exc->error ));
     
    -    exc->cvt     = exc->origCvt;
    -    exc->storage = exc->origStorage;
    -
         return exc->error;
       }
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h
    index 48f618dc9d4..c54c053b29e 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h
    @@ -4,7 +4,7 @@
      *
      *   TrueType bytecode interpreter (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -193,7 +193,6 @@ FT_BEGIN_HEADER
         FT_Long*           cvt;       /* ! */
         FT_ULong           glyfCvtSize;
         FT_Long*           glyfCvt;   /* cvt working copy for glyph */
    -    FT_Long*           origCvt;
     
         FT_UInt            glyphSize; /* ! glyph instructions buffer size */
         FT_Byte*           glyphIns;  /* ! glyph instructions buffer      */
    @@ -224,7 +223,6 @@ FT_BEGIN_HEADER
         FT_Long*           storage;      /* ! storage area            */
         FT_UShort          glyfStoreSize;
         FT_Long*           glyfStorage;  /* storage working copy for glyph */
    -    FT_Long*           origStorage;
     
         FT_F26Dot6         period;     /* values used for the */
         FT_F26Dot6         phase;      /* `SuperRounding'     */
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c
    index f4f3c69336a..4a8873fd8c8 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c
    @@ -4,7 +4,7 @@
      *
      *   Objects manager (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -1004,7 +1004,7 @@
         {
           size->cvt[i] = FT_MulFix( face->cvt[i], scale );
           FT_TRACE6(( "  %3d: %f (%f)\n",
    -                  i, face->cvt[i] / 64.0, size->cvt[i] / 64.0 ));
    +                  i, (double)face->cvt[i] / 64, (double)size->cvt[i] / 64 ));
         }
         FT_TRACE6(( "\n" ));
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h
    index 5fa239d43aa..bc6fbe7f196 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h
    @@ -4,7 +4,7 @@
      *
      *   Objects manager (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c
    index 6982c717aba..e08bf309e3c 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c
    @@ -4,7 +4,7 @@
      *
      *   TrueType-specific tables loader (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h
    index fa5d96ed35c..939e02fe4f1 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h
    @@ -4,7 +4,7 @@
      *
      *   TrueType-specific tables loader (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.c
    index 2438d3a2a29..d811beef0df 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.c
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.c
    @@ -4,7 +4,7 @@
      *
      *   TrueType Subpixel Hinting.
      *
    - * Copyright (C) 2010-2022 by
    + * Copyright (C) 2010-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.h
    index 181f83810ce..62af4c272d1 100644
    --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.h
    +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.h
    @@ -4,7 +4,7 @@
      *
      *   TrueType Subpixel Hinting.
      *
    - * Copyright (C) 2010-2022 by
    + * Copyright (C) 2010-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c
    index 6009e9ee2ee..608582c9a57 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c
    @@ -4,7 +4,7 @@
      *
      *   AFM support for Type 1 fonts (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -178,7 +178,6 @@
         /* temporarily.  If we find no PostScript charmap, then just use    */
         /* the default and hope it is the right one.                        */
         oldcharmap = t1_face->charmap;
    -    charmap    = NULL;
     
         for ( n = 0; n < t1_face->num_charmaps; n++ )
         {
    @@ -186,9 +185,7 @@
           /* check against PostScript pseudo platform */
           if ( charmap->platform_id == 7 )
           {
    -        error = FT_Set_Charmap( t1_face, charmap );
    -        if ( error )
    -          goto Exit;
    +        t1_face->charmap = charmap;
             break;
           }
         }
    @@ -209,10 +206,7 @@
           kp++;
         }
     
    -    if ( oldcharmap )
    -      error = FT_Set_Charmap( t1_face, oldcharmap );
    -    if ( error )
    -      goto Exit;
    +    t1_face->charmap = oldcharmap;
     
         /* now, sort the kern pairs according to their glyph indices */
         ft_qsort( fi->KernPairs, fi->NumKernPair, sizeof ( AFM_KernPairRec ),
    @@ -302,9 +296,14 @@
           t1_face->bbox.xMax = ( fi->FontBBox.xMax + 0xFFFF ) >> 16;
           t1_face->bbox.yMax = ( fi->FontBBox.yMax + 0xFFFF ) >> 16;
     
    -      /* no `U' suffix here to 0x8000! */
    -      t1_face->ascender  = (FT_Short)( ( fi->Ascender  + 0x8000 ) >> 16 );
    -      t1_face->descender = (FT_Short)( ( fi->Descender + 0x8000 ) >> 16 );
    +      /* ascender and descender are optional and could both be zero */
    +      /* check if values are meaningful before overriding defaults  */
    +      if ( fi->Ascender > fi->Descender )
    +      {
    +        /* no `U' suffix here to 0x8000! */
    +        t1_face->ascender  = (FT_Short)( ( fi->Ascender  + 0x8000 ) >> 16 );
    +        t1_face->descender = (FT_Short)( ( fi->Descender + 0x8000 ) >> 16 );
    +      }
     
           if ( fi->NumKernPair )
           {
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h
    index 040ed682981..e0d5aa5a882 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h
    @@ -4,7 +4,7 @@
      *
      *   AFM support for Type 1 fonts (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c
    index dd31545cf62..ded3b264e85 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c
    @@ -4,7 +4,7 @@
      *
      *   Type 1 driver interface (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -121,19 +121,30 @@
     #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
       static const FT_Service_MultiMastersRec  t1_service_multi_masters =
       {
    -    (FT_Get_MM_Func)             T1_Get_Multi_Master,    /* get_mm              */
    -    (FT_Set_MM_Design_Func)      T1_Set_MM_Design,       /* set_mm_design       */
    -    (FT_Set_MM_Blend_Func)       T1_Set_MM_Blend,        /* set_mm_blend        */
    -    (FT_Get_MM_Blend_Func)       T1_Get_MM_Blend,        /* get_mm_blend        */
    -    (FT_Get_MM_Var_Func)         T1_Get_MM_Var,          /* get_mm_var          */
    -    (FT_Set_Var_Design_Func)     T1_Set_Var_Design,      /* set_var_design      */
    -    (FT_Get_Var_Design_Func)     T1_Get_Var_Design,      /* get_var_design      */
    -    (FT_Set_Instance_Func)       T1_Reset_MM_Blend,      /* set_instance        */
    -    (FT_Set_MM_WeightVector_Func)T1_Set_MM_WeightVector, /* set_mm_weightvector */
    -    (FT_Get_MM_WeightVector_Func)T1_Get_MM_WeightVector, /* get_mm_weightvector */
    -
    -    (FT_Get_Var_Blend_Func)      NULL,                   /* get_var_blend       */
    -    (FT_Done_Blend_Func)         T1_Done_Blend           /* done_blend          */
    +    (FT_Get_MM_Func)        T1_Get_Multi_Master,    /* get_mm                    */
    +    (FT_Set_MM_Design_Func) T1_Set_MM_Design,       /* set_mm_design             */
    +    (FT_Set_MM_Blend_Func)  T1_Set_MM_Blend,        /* set_mm_blend              */
    +    (FT_Get_MM_Blend_Func)  T1_Get_MM_Blend,        /* get_mm_blend              */
    +    (FT_Get_MM_Var_Func)    T1_Get_MM_Var,          /* get_mm_var                */
    +    (FT_Set_Var_Design_Func)T1_Set_Var_Design,      /* set_var_design            */
    +    (FT_Get_Var_Design_Func)T1_Get_Var_Design,      /* get_var_design            */
    +    (FT_Set_Instance_Func)  T1_Reset_MM_Blend,      /* set_instance              */
    +    (FT_Set_MM_WeightVector_Func)
    +                            T1_Set_MM_WeightVector, /* set_mm_weightvector       */
    +    (FT_Get_MM_WeightVector_Func)
    +                            T1_Get_MM_WeightVector, /* get_mm_weightvector       */
    +    (FT_Var_Load_Delta_Set_Idx_Map_Func)
    +                            NULL,                   /* load_delta_set_idx_map    */
    +    (FT_Var_Load_Item_Var_Store_Func)
    +                            NULL,                   /* load_item_variation_store */
    +    (FT_Var_Get_Item_Delta_Func)
    +                            NULL,                   /* get_item_delta            */
    +    (FT_Var_Done_Item_Var_Store_Func)
    +                            NULL,                   /* done_item_variation_store */
    +    (FT_Var_Done_Delta_Set_Idx_Map_Func)
    +                            NULL,                   /* done_delta_set_index_map  */
    +    (FT_Get_Var_Blend_Func) NULL,                   /* get_var_blend             */
    +    (FT_Done_Blend_Func)    T1_Done_Blend           /* done_blend                */
       };
     #endif
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h
    index 9fe19403343..ee7fcf43e01 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h
    @@ -4,7 +4,7 @@
      *
      *   High-level Type 1 driver interface (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h b/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h
    index 1b87c42f18b..2fbd1e513f3 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h
    @@ -4,7 +4,7 @@
      *
      *   Type 1 error codes (specification only).
      *
    - * Copyright (C) 2001-2022 by
    + * Copyright (C) 2001-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c
    index 540231561c1..a32a4649d6d 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c
    @@ -4,7 +4,7 @@
      *
      *   Type 1 Glyph Loader (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -264,7 +264,7 @@
         }
     
         FT_TRACE6(( "T1_Compute_Max_Advance: max advance: %f\n",
    -                *max_advance / 65536.0 ));
    +                (double)*max_advance / 65536 ));
     
         psaux->t1_decoder_funcs->done( &decoder );
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h
    index fdb985264f9..c06484758a5 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h
    @@ -4,7 +4,7 @@
      *
      *   Type 1 Glyph Loader (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1load.c b/src/java.desktop/share/native/libfreetype/src/type1/t1load.c
    index 66bebd560f3..5a1afd8d9f5 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1load.c
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1load.c
    @@ -4,7 +4,7 @@
      *
      *   Type 1 font loader (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -355,6 +355,10 @@
             mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' );
           else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 )
             mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' );
    +      else if ( ft_strcmp( mmvar->axis[i].name, "Slant" ) == 0 )
    +        mmvar->axis[i].tag = FT_MAKE_TAG( 's', 'l', 'n', 't' );
    +      else if ( ft_strcmp( mmvar->axis[i].name, "Italic" ) == 0 )
    +        mmvar->axis[i].tag = FT_MAKE_TAG( 'i', 't', 'a', 'l' );
         }
     
         mm_weights_unmap( blend->default_weight_vector,
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1load.h b/src/java.desktop/share/native/libfreetype/src/type1/t1load.h
    index a6d46eb1e4a..f8511cccf60 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1load.h
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1load.h
    @@ -4,7 +4,7 @@
      *
      *   Type 1 font loader (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c
    index 847ae0e64bf..1bb2f15f3a8 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c
    @@ -4,7 +4,7 @@
      *
      *   Type 1 objects manager (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -146,7 +146,9 @@
       FT_LOCAL_DEF( void )
       T1_GlyphSlot_Done( FT_GlyphSlot  slot )
       {
    -    slot->internal->glyph_hints = NULL;
    +    /* `slot->internal` might be NULL in out-of-memory situations. */
    +    if ( slot->internal )
    +      slot->internal->glyph_hints = NULL;
       }
     
     
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h
    index e632fb58bdc..03847b27e96 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h
    @@ -4,7 +4,7 @@
      *
      *   Type 1 objects manager (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c
    index 95dc97d79ac..6dec6c16c3e 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c
    @@ -4,7 +4,7 @@
      *
      *   Type 1 parser (body).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    @@ -330,50 +330,25 @@
           /* the private dict.  Otherwise, simply overwrite into the base  */
           /* dictionary block in the heap.                                 */
     
    -      /* first of all, look at the `eexec' keyword */
    +      /* First look for the `eexec' keyword. Ensure `eexec' is real -- */
    +      /* it could be in a comment or string (as e.g. in u003043t.gsf   */
    +      /* from ghostscript).                                            */
           FT_Byte*    cur   = parser->base_dict;
           FT_Byte*    limit = cur + parser->base_len;
           FT_Pointer  pos_lf;
           FT_Bool     test_cr;
     
     
    -    Again:
    -      for (;;)
    -      {
    -        if ( cur[0] == 'e'   &&
    -             cur + 9 < limit )      /* 9 = 5 letters for `eexec' + */
    -                                    /* whitespace + 4 chars        */
    -        {
    -          if ( cur[1] == 'e' &&
    -               cur[2] == 'x' &&
    -               cur[3] == 'e' &&
    -               cur[4] == 'c' )
    -            break;
    -        }
    -        cur++;
    -        if ( cur >= limit )
    -        {
    -          FT_ERROR(( "T1_Get_Private_Dict:"
    -                     " could not find `eexec' keyword\n" ));
    -          error = FT_THROW( Invalid_File_Format );
    -          goto Exit;
    -        }
    -      }
    -
    -      /* check whether `eexec' was real -- it could be in a comment */
    -      /* or string (as e.g. in u003043t.gsf from ghostscript)       */
    -
           parser->root.cursor = parser->base_dict;
    -      /* set limit to `eexec' + whitespace + 4 characters */
    -      parser->root.limit  = cur + 10;
    +      parser->root.limit  = parser->base_dict + parser->base_len;
     
           cur   = parser->root.cursor;
           limit = parser->root.limit;
     
           while ( cur < limit )
           {
    -        if ( cur[0] == 'e'   &&
    -             cur + 5 < limit )
    +        /* 9 = 5 letters for `eexec' + whitespace + 4 chars */
    +        if ( cur[0] == 'e' && cur + 9 < limit )
             {
               if ( cur[1] == 'e' &&
                    cur[2] == 'x' &&
    @@ -389,21 +364,9 @@
             cur = parser->root.cursor;
           }
     
    -      /* we haven't found the correct `eexec'; go back and continue */
    -      /* searching                                                  */
    -
    -      cur   = limit;
    -      limit = parser->base_dict + parser->base_len;
    -
    -      if ( cur >= limit )
    -      {
    -        FT_ERROR(( "T1_Get_Private_Dict:"
    -                   " premature end in private dictionary\n" ));
    -        error = FT_THROW( Invalid_File_Format );
    -        goto Exit;
    -      }
    -
    -      goto Again;
    +      FT_ERROR(( "T1_Get_Private_Dict: could not find `eexec' keyword\n" ));
    +      error = FT_THROW( Invalid_File_Format );
    +      goto Exit;
     
           /* now determine where to write the _encrypted_ binary private  */
           /* dictionary.  We overwrite the base dictionary for disk-based */
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h
    index d9c7e3b56ad..0d9a2865df0 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h
    @@ -4,7 +4,7 @@
      *
      *   Type 1 parser (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h
    index 79080d9e4db..40f36092622 100644
    --- a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h
    +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h
    @@ -4,7 +4,7 @@
      *
      *   Type 1 tokenizer (specification).
      *
    - * Copyright (C) 1996-2022 by
    + * Copyright (C) 1996-2023 by
      * David Turner, Robert Wilhelm, and Werner Lemberg.
      *
      * This file is part of the FreeType project, and may only be used,
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh
    index c286ee3c908..e7c34a83fd6 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh
    @@ -40,7 +40,6 @@
      */
     #define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
     
    -
     namespace OT {
     struct hb_paint_context_t;
     }
    @@ -242,10 +241,15 @@ struct Variable
       void closurev1 (hb_colrv1_closure_context_t* c) const
       { value.closurev1 (c); }
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer) const
       {
         TRACE_SUBSET (this);
    -    if (!value.subset (c)) return_trace (false);
    +    if (!value.subset (c, instancer, varIdxBase)) return_trace (false);
    +    if (c->plan->all_axes_pinned)
    +      return_trace (true);
    +
    +    //TODO: update varIdxBase for partial-instancing
         return_trace (c->serializer->embed (varIdxBase));
       }
     
    @@ -296,10 +300,11 @@ struct NoVariable
       void closurev1 (hb_colrv1_closure_context_t* c) const
       { value.closurev1 (c); }
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer) const
       {
         TRACE_SUBSET (this);
    -    return_trace (value.subset (c));
    +    return_trace (value.subset (c, instancer, varIdxBase));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -337,11 +342,20 @@ struct ColorStop
       void closurev1 (hb_colrv1_closure_context_t* c) const
       { c->add_palette_index (paletteIndex); }
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (*this);
         if (unlikely (!out)) return_trace (false);
    +
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +    {
    +      out->stopOffset.set_float (stopOffset.to_float(instancer (varIdxBase, 0)));
    +      out->alpha.set_float (alpha.to_float (instancer (varIdxBase, 1)));
    +    }
    +
         return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes.get (paletteIndex),
                                                    HB_SERIALIZE_ERROR_INT_OVERFLOW));
       }
    @@ -390,7 +404,8 @@ struct ColorLine
           stop.closurev1 (c);
       }
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->start_embed (this);
    @@ -402,7 +417,7 @@ struct ColorLine
     
         for (const auto& stop : stops.iter ())
         {
    -      if (!stop.subset (c)) return_trace (false);
    +      if (!stop.subset (c, instancer)) return_trace (false);
         }
         return_trace (true);
       }
    @@ -523,6 +538,25 @@ struct Affine2x3
         return_trace (c->check_struct (this));
       }
     
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
    +  {
    +    TRACE_SUBSET (this);
    +    auto *out = c->serializer->embed (*this);
    +    if (unlikely (!out)) return_trace (false);
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +    {
    +      out->xx.set_float (xx.to_float(instancer (varIdxBase, 0)));
    +      out->yx.set_float (yx.to_float(instancer (varIdxBase, 1)));
    +      out->xy.set_float (xy.to_float(instancer (varIdxBase, 2)));
    +      out->yy.set_float (yy.to_float(instancer (varIdxBase, 3)));
    +      out->dx.set_float (dx.to_float(instancer (varIdxBase, 4)));
    +      out->dy.set_float (dy.to_float(instancer (varIdxBase, 5)));
    +    }
    +    return_trace (true);
    +  }
    +
       void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
       {
         c->funcs->push_transform (c->data,
    @@ -548,7 +582,8 @@ struct PaintColrLayers
     {
       void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer HB_UNUSED) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
    @@ -579,11 +614,20 @@ struct PaintSolid
       void closurev1 (hb_colrv1_closure_context_t* c) const
       { c->add_palette_index (paletteIndex); }
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (*this);
         if (unlikely (!out)) return_trace (false);
    +
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +      out->alpha.set_float (alpha.to_float (instancer (varIdxBase, 0)));
    +
    +    if (format == 3 && c->plan->all_axes_pinned)
    +        out->format = 2;
    +
         return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes.get (paletteIndex),
                                                    HB_SERIALIZE_ERROR_INT_OVERFLOW));
       }
    @@ -618,13 +662,28 @@ struct PaintLinearGradient
       void closurev1 (hb_colrv1_closure_context_t* c) const
       { (this+colorLine).closurev1 (c); }
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
     
    -    return_trace (out->colorLine.serialize_subset (c, colorLine, this));
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +    {
    +      out->x0 = x0 + (int) roundf (instancer (varIdxBase, 0));
    +      out->y0 = y0 + (int) roundf (instancer (varIdxBase, 1));
    +      out->x1 = x1 + (int) roundf (instancer (varIdxBase, 2));
    +      out->y1 = y1 + (int) roundf (instancer (varIdxBase, 3));
    +      out->x2 = x2 + (int) roundf (instancer (varIdxBase, 4));
    +      out->y2 = y2 + (int) roundf (instancer (varIdxBase, 5));
    +    }
    +
    +    if (format == 5 && c->plan->all_axes_pinned)
    +        out->format = 4;
    +
    +    return_trace (out->colorLine.serialize_subset (c, colorLine, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -669,13 +728,28 @@ struct PaintRadialGradient
       void closurev1 (hb_colrv1_closure_context_t* c) const
       { (this+colorLine).closurev1 (c); }
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
     
    -    return_trace (out->colorLine.serialize_subset (c, colorLine, this));
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +    {
    +      out->x0 = x0 + (int) roundf (instancer (varIdxBase, 0));
    +      out->y0 = y0 + (int) roundf (instancer (varIdxBase, 1));
    +      out->radius0 = radius0 + (unsigned) roundf (instancer (varIdxBase, 2));
    +      out->x1 = x1 + (int) roundf (instancer (varIdxBase, 3));
    +      out->y1 = y1 + (int) roundf (instancer (varIdxBase, 4));
    +      out->radius1 = radius1 + (unsigned) roundf (instancer (varIdxBase, 5));
    +    }
    +
    +    if (format == 7 && c->plan->all_axes_pinned)
    +        out->format = 6;
    +
    +    return_trace (out->colorLine.serialize_subset (c, colorLine, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -720,13 +794,26 @@ struct PaintSweepGradient
       void closurev1 (hb_colrv1_closure_context_t* c) const
       { (this+colorLine).closurev1 (c); }
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
     
    -    return_trace (out->colorLine.serialize_subset (c, colorLine, this));
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +    {
    +      out->centerX = centerX + (int) roundf (instancer (varIdxBase, 0));
    +      out->centerY = centerY + (int) roundf (instancer (varIdxBase, 1));
    +      out->startAngle.set_float (startAngle.to_float (instancer (varIdxBase, 2)));
    +      out->endAngle.set_float (endAngle.to_float (instancer (varIdxBase, 3)));
    +    }
    +
    +    if (format == 9 && c->plan->all_axes_pinned)
    +        out->format = 8;
    +
    +    return_trace (out->colorLine.serialize_subset (c, colorLine, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -746,8 +833,8 @@ struct PaintSweepGradient
         c->funcs->sweep_gradient (c->data, &cl,
                                   centerX + c->instancer (varIdxBase, 0),
                                   centerY + c->instancer (varIdxBase, 1),
    -                              (startAngle.to_float (c->instancer (varIdxBase, 2)) + 1) * (float) M_PI,
    -                              (endAngle.to_float   (c->instancer (varIdxBase, 3)) + 1) * (float) M_PI);
    +                              (startAngle.to_float (c->instancer (varIdxBase, 2)) + 1) * HB_PI,
    +                              (endAngle.to_float   (c->instancer (varIdxBase, 3)) + 1) * HB_PI);
       }
     
       HBUINT8                       format; /* format = 8(noVar) or 9 (Var) */
    @@ -766,7 +853,8 @@ struct PaintGlyph
     {
       void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
    @@ -776,7 +864,7 @@ struct PaintGlyph
                                            HB_SERIALIZE_ERROR_INT_OVERFLOW))
           return_trace (false);
     
    -    return_trace (out->paint.serialize_subset (c, paint, this));
    +    return_trace (out->paint.serialize_subset (c, paint, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -807,7 +895,8 @@ struct PaintColrGlyph
     {
       void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer HB_UNUSED) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
    @@ -836,13 +925,16 @@ struct PaintTransform
     {
       HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
    -    if (!out->transform.serialize_copy (c->serializer, transform, this)) return_trace (false);
    -    return_trace (out->src.serialize_subset (c, src, this));
    +    if (!out->transform.serialize_subset (c, transform, this, instancer)) return_trace (false);
    +    if (format == 13 && c->plan->all_axes_pinned)
    +      out->format = 12;
    +    return_trace (out->src.serialize_subset (c, src, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -871,13 +963,24 @@ struct PaintTranslate
     {
       HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
     
    -    return_trace (out->src.serialize_subset (c, src, this));
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +    {
    +      out->dx = dx + (int) roundf (instancer (varIdxBase, 0));
    +      out->dy = dy + (int) roundf (instancer (varIdxBase, 1));
    +    }
    +
    +    if (format == 15 && c->plan->all_axes_pinned)
    +        out->format = 14;
    +
    +    return_trace (out->src.serialize_subset (c, src, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -908,13 +1011,24 @@ struct PaintScale
     {
       HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
     
    -    return_trace (out->src.serialize_subset (c, src, this));
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +    {
    +      out->scaleX.set_float (scaleX.to_float (instancer (varIdxBase, 0)));
    +      out->scaleY.set_float (scaleY.to_float (instancer (varIdxBase, 1)));
    +    }
    +
    +    if (format == 17 && c->plan->all_axes_pinned)
    +        out->format = 16;
    +
    +    return_trace (out->src.serialize_subset (c, src, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -945,13 +1059,26 @@ struct PaintScaleAroundCenter
     {
       HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
     
    -    return_trace (out->src.serialize_subset (c, src, this));
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +    {
    +      out->scaleX.set_float (scaleX.to_float (instancer (varIdxBase, 0)));
    +      out->scaleY.set_float (scaleY.to_float (instancer (varIdxBase, 1)));
    +      out->centerX = centerX + (int) roundf (instancer (varIdxBase, 2));
    +      out->centerY = centerY + (int) roundf (instancer (varIdxBase, 3));
    +    }
    +
    +    if (format == 19 && c->plan->all_axes_pinned)
    +        out->format = 18;
    +
    +    return_trace (out->src.serialize_subset (c, src, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -990,13 +1117,21 @@ struct PaintScaleUniform
     {
       HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
     
    -    return_trace (out->src.serialize_subset (c, src, this));
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +      out->scale.set_float (scale.to_float (instancer (varIdxBase, 0)));
    +
    +    if (format == 21 && c->plan->all_axes_pinned)
    +        out->format = 20;
    +
    +    return_trace (out->src.serialize_subset (c, src, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -1025,13 +1160,25 @@ struct PaintScaleUniformAroundCenter
     {
       HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
     
    -    return_trace (out->src.serialize_subset (c, src, this));
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +    {
    +      out->scale.set_float (scale.to_float (instancer (varIdxBase, 0)));
    +      out->centerX = centerX + (int) roundf (instancer (varIdxBase, 1));
    +      out->centerY = centerY + (int) roundf (instancer (varIdxBase, 2));
    +    }
    +
    +    if (format == 23 && c->plan->all_axes_pinned)
    +        out->format = 22;
    +
    +    return_trace (out->src.serialize_subset (c, src, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -1068,13 +1215,21 @@ struct PaintRotate
     {
       HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
     
    -    return_trace (out->src.serialize_subset (c, src, this));
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +      out->angle.set_float (angle.to_float (instancer (varIdxBase, 0)));
    +
    +    if (format == 25 && c->plan->all_axes_pinned)
    +      out->format = 24;
    +
    +    return_trace (out->src.serialize_subset (c, src, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -1103,13 +1258,25 @@ struct PaintRotateAroundCenter
     {
       HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
     
    -    return_trace (out->src.serialize_subset (c, src, this));
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +    {
    +      out->angle.set_float (angle.to_float (instancer (varIdxBase, 0)));
    +      out->centerX = centerX + (int) roundf (instancer (varIdxBase, 1));
    +      out->centerY = centerY + (int) roundf (instancer (varIdxBase, 2));
    +    }
    +
    +    if (format ==27 && c->plan->all_axes_pinned)
    +        out->format = 26;
    +
    +    return_trace (out->src.serialize_subset (c, src, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -1146,13 +1313,24 @@ struct PaintSkew
     {
       HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
     
    -    return_trace (out->src.serialize_subset (c, src, this));
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +    {
    +      out->xSkewAngle.set_float (xSkewAngle.to_float (instancer (varIdxBase, 0)));
    +      out->ySkewAngle.set_float (ySkewAngle.to_float (instancer (varIdxBase, 1)));
    +    }
    +
    +    if (format == 29 && c->plan->all_axes_pinned)
    +        out->format = 28;
    +
    +    return_trace (out->src.serialize_subset (c, src, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -1183,13 +1361,26 @@ struct PaintSkewAroundCenter
     {
       HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
     
    -    return_trace (out->src.serialize_subset (c, src, this));
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +    {
    +      out->xSkewAngle.set_float (xSkewAngle.to_float (instancer (varIdxBase, 0)));
    +      out->ySkewAngle.set_float (ySkewAngle.to_float (instancer (varIdxBase, 1)));
    +      out->centerX = centerX + (int) roundf (instancer (varIdxBase, 2));
    +      out->centerY = centerY + (int) roundf (instancer (varIdxBase, 3));
    +    }
    +
    +    if (format == 31 && c->plan->all_axes_pinned)
    +        out->format = 30;
    +
    +    return_trace (out->src.serialize_subset (c, src, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -1228,14 +1419,15 @@ struct PaintComposite
     {
       void closurev1 (hb_colrv1_closure_context_t* c) const;
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->embed (this);
         if (unlikely (!out)) return_trace (false);
     
    -    if (!out->src.serialize_subset (c, src, this)) return_trace (false);
    -    return_trace (out->backdrop.serialize_subset (c, backdrop, this));
    +    if (!out->src.serialize_subset (c, src, this, instancer)) return_trace (false);
    +    return_trace (out->backdrop.serialize_subset (c, backdrop, this, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c) const
    @@ -1283,6 +1475,28 @@ struct ClipBoxFormat1
         clip_box.yMax = yMax;
       }
     
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer,
    +               uint32_t varIdxBase) const
    +  {
    +    TRACE_SUBSET (this);
    +    auto *out = c->serializer->embed (*this);
    +    if (unlikely (!out)) return_trace (false);
    +
    +    if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
    +    {
    +      out->xMin = xMin + (int) roundf (instancer (varIdxBase, 0));
    +      out->yMin = yMin + (int) roundf (instancer (varIdxBase, 1));
    +      out->xMax = xMax + (int) roundf (instancer (varIdxBase, 2));
    +      out->yMax = yMax + (int) roundf (instancer (varIdxBase, 3));
    +    }
    +
    +    if (format == 2 && c->plan->all_axes_pinned)
    +        out->format = 1;
    +
    +    return_trace (true);
    +  }
    +
       public:
       HBUINT8       format; /* format = 1(noVar) or 2(Var)*/
       FWORD         xMin;
    @@ -1310,13 +1524,14 @@ struct ClipBoxFormat2 : Variable
     
     struct ClipBox
     {
    -  ClipBox* copy (hb_serialize_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer) const
       {
    -    TRACE_SERIALIZE (this);
    +    TRACE_SUBSET (this);
         switch (u.format) {
    -    case 1: return_trace (reinterpret_cast (c->embed (u.format1)));
    -    case 2: return_trace (reinterpret_cast (c->embed (u.format2)));
    -    default:return_trace (nullptr);
    +    case 1: return_trace (u.format1.subset (c, instancer, VarIdx::NO_VARIATION));
    +    case 2: return_trace (u.format2.subset (c, instancer));
    +    default:return_trace (c->default_return_value ());
         }
       }
     
    @@ -1367,13 +1582,15 @@ struct ClipRecord
       int cmp (hb_codepoint_t g) const
       { return g < startGlyphID ? -1 : g <= endGlyphID ? 0 : +1; }
     
    -  ClipRecord* copy (hb_serialize_context_t *c, const void *base) const
    +  bool subset (hb_subset_context_t *c,
    +               const void *base,
    +               const VarStoreInstancer &instancer) const
       {
    -    TRACE_SERIALIZE (this);
    -    auto *out = c->embed (this);
    -    if (unlikely (!out)) return_trace (nullptr);
    -    if (!out->clipBox.serialize_copy (c, clipBox, base)) return_trace (nullptr);
    -    return_trace (out);
    +    TRACE_SUBSET (this);
    +    auto *out = c->serializer->embed (*this);
    +    if (unlikely (!out)) return_trace (false);
    +
    +    return_trace (out->clipBox.serialize_subset (c, clipBox, base, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c, const void *base) const
    @@ -1400,7 +1617,8 @@ DECLARE_NULL_NAMESPACE_BYTES (OT, ClipRecord);
     
     struct ClipList
     {
    -  unsigned serialize_clip_records (hb_serialize_context_t *c,
    +  unsigned serialize_clip_records (hb_subset_context_t *c,
    +                                   const VarStoreInstancer &instancer,
                                        const hb_set_t& gids,
                                        const hb_map_t& gid_offset_map) const
       {
    @@ -1432,7 +1650,7 @@ struct ClipList
           record.endGlyphID = prev_gid;
           record.clipBox = prev_offset;
     
    -      if (!c->copy (record, this)) return_trace (0);
    +      if (!record.subset (c, this, instancer)) return_trace (0);
           count++;
     
           start_gid = _;
    @@ -1446,13 +1664,14 @@ struct ClipList
           record.startGlyphID = start_gid;
           record.endGlyphID = prev_gid;
           record.clipBox = prev_offset;
    -      if (!c->copy (record, this)) return_trace (0);
    +      if (!record.subset (c, this, instancer)) return_trace (0);
           count++;
         }
         return_trace (count);
       }
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->start_embed (*this);
    @@ -1477,7 +1696,7 @@ struct ClipList
           }
         }
     
    -    unsigned count = serialize_clip_records (c->serializer, new_gids, new_gid_offset_map);
    +    unsigned count = serialize_clip_records (c, instancer, new_gids, new_gid_offset_map);
         if (!count) return_trace (false);
         return_trace (c->serializer->check_assign (out->clips.len, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
       }
    @@ -1611,7 +1830,8 @@ struct BaseGlyphPaintRecord
       { return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
     
       bool serialize (hb_serialize_context_t *s, const hb_map_t* glyph_map,
    -                  const void* src_base, hb_subset_context_t *c) const
    +                  const void* src_base, hb_subset_context_t *c,
    +                  const VarStoreInstancer &instancer) const
       {
         TRACE_SERIALIZE (this);
         auto *out = s->embed (this);
    @@ -1620,7 +1840,7 @@ struct BaseGlyphPaintRecord
                               HB_SERIALIZE_ERROR_INT_OVERFLOW))
           return_trace (false);
     
    -    return_trace (out->paint.serialize_subset (c, paint, src_base));
    +    return_trace (out->paint.serialize_subset (c, paint, src_base, instancer));
       }
     
       bool sanitize (hb_sanitize_context_t *c, const void *base) const
    @@ -1639,7 +1859,8 @@ struct BaseGlyphPaintRecord
     
     struct BaseGlyphList : SortedArray32Of
     {
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->start_embed (this);
    @@ -1651,7 +1872,7 @@ struct BaseGlyphList : SortedArray32Of
           unsigned gid = _.glyphId;
           if (!glyphset->has (gid)) continue;
     
    -      if (_.serialize (c->serializer, c->plan->glyph_map, this, c)) out->len++;
    +      if (_.serialize (c->serializer, c->plan->glyph_map, this, c, instancer)) out->len++;
           else return_trace (false);
         }
     
    @@ -1670,7 +1891,8 @@ struct LayerList : Array32OfOffset32To
       const Paint& get_paint (unsigned i) const
       { return this+(*this)[i]; }
     
    -  bool subset (hb_subset_context_t *c) const
    +  bool subset (hb_subset_context_t *c,
    +               const VarStoreInstancer &instancer) const
       {
         TRACE_SUBSET (this);
         auto *out = c->serializer->start_embed (this);
    @@ -1681,7 +1903,7 @@ struct LayerList : Array32OfOffset32To
     
         {
           auto *o = out->serialize_append (c->serializer);
    -      if (unlikely (!o) || !o->serialize_subset (c, _.second, this))
    +      if (unlikely (!o) || !o->serialize_subset (c, _.second, this, instancer))
             return_trace (false);
         }
         return_trace (true);
    @@ -1883,7 +2105,6 @@ struct COLR
       bool subset (hb_subset_context_t *c) const
       {
         TRACE_SUBSET (this);
    -
         const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map;
         const hb_set_t& glyphset = c->plan->_glyphset_colred;
     
    @@ -1954,7 +2175,12 @@ struct COLR
     
         auto snap = c->serializer->snapshot ();
         if (!c->serializer->allocate_size (5 * HBUINT32::static_size)) return_trace (false);
    -    if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this))
    +
    +    VarStoreInstancer instancer (varStore ? &(this+varStore) : nullptr,
    +                                 varIdxMap ? &(this+varIdxMap) : nullptr,
    +                                 c->plan->normalized_coords.as_array ());
    +
    +    if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this, instancer))
         {
           if (c->serializer->in_error ()) return_trace (false);
           //no more COLRv1 glyphs: downgrade to version 0
    @@ -1964,8 +2190,11 @@ struct COLR
     
         if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false);
     
    -    colr_prime->layerList.serialize_subset (c, layerList, this);
    -    colr_prime->clipList.serialize_subset (c, clipList, this);
    +    colr_prime->layerList.serialize_subset (c, layerList, this, instancer);
    +    colr_prime->clipList.serialize_subset (c, clipList, this, instancer);
    +    if (!varStore || c->plan->all_axes_pinned)
    +      return_trace (true);
    +
         colr_prime->varIdxMap.serialize_copy (c->serializer, varIdxMap, this);
         colr_prime->varStore.serialize_copy (c->serializer, varStore, this);
         return_trace (true);
    @@ -1984,14 +2213,15 @@ struct COLR
           return nullptr;
       }
     
    +#ifndef HB_NO_PAINT
       bool
       get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
       {
         if (version != 1)
           return false;
     
    -    VarStoreInstancer instancer (this+varStore,
    -                                 this+varIdxMap,
    +    VarStoreInstancer instancer (&(this+varStore),
    +                                 &(this+varIdxMap),
                                      hb_array (font->coords, font->num_coords));
     
         if (get_clip (glyph, extents, instancer))
    @@ -2022,6 +2252,7 @@ struct COLR
     
         return ret;
       }
    +#endif
     
       bool
       has_paint_for_glyph (hb_codepoint_t glyph) const
    @@ -2045,11 +2276,12 @@ struct COLR
                                             instancer);
       }
     
    +#ifndef HB_NO_PAINT
       bool
       paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, unsigned int palette_index, hb_color_t foreground, bool clip = true) const
       {
    -    VarStoreInstancer instancer (this+varStore,
    -                                 this+varIdxMap,
    +    VarStoreInstancer instancer (&(this+varStore),
    +                                 &(this+varIdxMap),
                                      hb_array (font->coords, font->num_coords));
         hb_paint_context_t c (this, funcs, data, font, palette_index, foreground, instancer);
     
    @@ -2060,8 +2292,8 @@ struct COLR
           {
             // COLRv1 glyph
     
    -        VarStoreInstancer instancer (this+varStore,
    -                                     this+varIdxMap,
    +        VarStoreInstancer instancer (&(this+varStore),
    +                                     &(this+varIdxMap),
                                          hb_array (font->coords, font->num_coords));
     
             bool is_bounded = true;
    @@ -2131,6 +2363,7 @@ struct COLR
     
         return false;
       }
    +#endif
     
       protected:
       HBUINT16      version;        /* Table version number (starts at 0). */
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh
    index e177190710c..ed8f5957e96 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh
    @@ -73,6 +73,30 @@ struct CPALV1Tail
       }
     
       public:
    +  void collect_name_ids (const void *base,
    +                         unsigned palette_count,
    +                         unsigned color_count,
    +                         const hb_map_t *color_index_map,
    +                         hb_set_t *nameids_to_retain /* OUT */) const
    +  {
    +    if (paletteLabelsZ)
    +    {
    +      + (base+paletteLabelsZ).as_array (palette_count)
    +      | hb_sink (nameids_to_retain)
    +      ;
    +    }
    +
    +    if (colorLabelsZ)
    +    {
    +      const hb_array_t colorLabels = (base+colorLabelsZ).as_array (color_count);
    +      for (unsigned i = 0; i < color_count; i++)
    +      {
    +        if (!color_index_map->has (i)) continue;
    +        nameids_to_retain->add (colorLabels[i]);
    +      }
    +    }
    +  }
    +
       bool serialize (hb_serialize_context_t *c,
                       unsigned palette_count,
                       unsigned color_count,
    @@ -95,13 +119,10 @@ struct CPALV1Tail
         if (colorLabelsZ)
         {
           c->push ();
    -      for (const auto _ : colorLabels)
    +      for (unsigned i = 0; i < color_count; i++)
           {
    -        const hb_codepoint_t *v;
    -        if (!color_index_map->has (_, &v)) continue;
    -        NameID new_color_idx;
    -        new_color_idx = *v;
    -        if (!c->copy (new_color_idx))
    +        if (!color_index_map->has (i)) continue;
    +        if (!c->copy (colorLabels[i]))
             {
               c->pop_discard ();
               return_trace (false);
    @@ -189,6 +210,13 @@ struct CPAL
         return numColors;
       }
     
    +  void collect_name_ids (const hb_map_t *color_index_map,
    +                         hb_set_t *nameids_to_retain /* OUT */) const
    +  {
    +    if (version == 1)
    +      v1 ().collect_name_ids (this, numPalettes, numColors, color_index_map, nameids_to_retain);
    +  }
    +
       private:
       const CPALV1Tail& v1 () const
       {
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/MarkLigPosFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/MarkLigPosFormat1.hh
    index 4accd8166ba..30bba4b0d8c 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/MarkLigPosFormat1.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/MarkLigPosFormat1.hh
    @@ -126,15 +126,15 @@ struct MarkLigPosFormat1_2
           return_trace (false);
         }
     
    -    j = (unsigned) c->last_base;
    +    unsigned idx = (unsigned) c->last_base;
     
         /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
    -    //if (!_hb_glyph_info_is_ligature (&buffer->info[j])) { return_trace (false); }
    +    //if (!_hb_glyph_info_is_ligature (&buffer->info[idx])) { return_trace (false); }
     
    -    unsigned int lig_index = (this+ligatureCoverage).get_coverage  (buffer->info[j].codepoint);
    +    unsigned int lig_index = (this+ligatureCoverage).get_coverage  (buffer->info[idx].codepoint);
         if (lig_index == NOT_COVERED)
         {
    -      buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
    +      buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
           return_trace (false);
         }
     
    @@ -145,7 +145,7 @@ struct MarkLigPosFormat1_2
         unsigned int comp_count = lig_attach.rows;
         if (unlikely (!comp_count))
         {
    -      buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
    +      buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
           return_trace (false);
         }
     
    @@ -154,7 +154,7 @@ struct MarkLigPosFormat1_2
          * can directly use the component index.  If not, we attach the mark
          * glyph to the last component of the ligature. */
         unsigned int comp_index;
    -    unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
    +    unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[idx]);
         unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
         unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
         if (lig_id && lig_id == mark_id && mark_comp > 0)
    @@ -162,7 +162,7 @@ struct MarkLigPosFormat1_2
         else
           comp_index = comp_count - 1;
     
    -    return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
    +    return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, idx));
       }
     
       bool subset (hb_subset_context_t *c) const
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh
    index ec9475d113f..468eccfd501 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh
    @@ -55,7 +55,7 @@ struct PairPosFormat1_3
     
         if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4)
         {
    -      for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
    +      for (hb_codepoint_t g : glyphs->iter())
           {
             unsigned i = cov.get_coverage (g);
             if ((this+pairSet[i]).intersects (glyphs, valueFormat))
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat1.hh
    index 53aff9f3dfc..47391c77028 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat1.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat1.hh
    @@ -28,7 +28,15 @@ struct SinglePosFormat1
         TRACE_SANITIZE (this);
         return_trace (c->check_struct (this) &&
                       coverage.sanitize (c, this) &&
    +                  /* The coverage  table may use a range to represent a set
    +                   * of glyphs, which means a small number of bytes can
    +                   * generate a large glyph set. Manually modify the
    +                   * sanitizer max ops to take this into account.
    +                   *
    +                   * Note: This check *must* be right after coverage sanitize. */
    +                  c->check_ops ((this + coverage).get_population () >> 1) &&
                       valueFormat.sanitize_value (c, this, values));
    +
       }
     
       bool intersects (const hb_set_t *glyphs) const
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/Ligature.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/Ligature.hh
    index b0fdd91dc22..308da587d1e 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/Ligature.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/Ligature.hh
    @@ -29,6 +29,9 @@ struct Ligature
       bool intersects (const hb_set_t *glyphs) const
       { return hb_all (component, glyphs); }
     
    +  bool intersects_lig_glyph (const hb_set_t *glyphs) const
    +  { return glyphs->has(ligGlyph); }
    +
       void closure (hb_closure_context_t *c) const
       {
         if (!intersects (c->glyphs)) return;
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSet.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSet.hh
    index 637cec71377..2b232622802 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSet.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSet.hh
    @@ -34,6 +34,18 @@ struct LigatureSet
         ;
       }
     
    +  bool intersects_lig_glyph (const hb_set_t *glyphs) const
    +  {
    +    return
    +    + hb_iter (ligature)
    +    | hb_map (hb_add (this))
    +    | hb_map ([glyphs] (const Ligature &_) {
    +      return _.intersects_lig_glyph (glyphs) && _.intersects (glyphs);
    +    })
    +    | hb_any
    +    ;
    +  }
    +
       void closure (hb_closure_context_t *c) const
       {
         + hb_iter (ligature)
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSubstFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSubstFormat1.hh
    index 32b642c38ad..5c7df97d13a 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSubstFormat1.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSubstFormat1.hh
    @@ -130,7 +130,7 @@ struct LigatureSubstFormat1_2
         + hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
         | hb_filter (glyphset, hb_first)
         | hb_filter ([&] (const LigatureSet& _) {
    -      return _.intersects (&glyphset);
    +      return _.intersects_lig_glyph (&glyphset);
         }, hb_second)
         | hb_map (hb_first)
         | hb_sink (new_coverage);
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat1.hh
    index 1fe9488e212..268487c5ae7 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat1.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat1.hh
    @@ -25,7 +25,15 @@ struct SingleSubstFormat1_3
       bool sanitize (hb_sanitize_context_t *c) const
       {
         TRACE_SANITIZE (this);
    -    return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
    +    return_trace (c->check_struct (this) &&
    +                  coverage.sanitize (c, this) &&
    +                  /* The coverage  table may use a range to represent a set
    +                   * of glyphs, which means a small number of bytes can
    +                   * generate a large glyph set. Manually modify the
    +                   * sanitizer max ops to take this into account.
    +                   *
    +                   * Note: This check *must* be right after coverage sanitize. */
    +                  c->check_ops ((this + coverage).get_population () >> 1));
       }
     
       hb_codepoint_t get_mask () const
    @@ -87,6 +95,34 @@ struct SingleSubstFormat1_3
       bool would_apply (hb_would_apply_context_t *c) const
       { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
     
    +  unsigned
    +  get_glyph_alternates (hb_codepoint_t  glyph_id,
    +                        unsigned        start_offset,
    +                        unsigned       *alternate_count  /* IN/OUT.  May be NULL. */,
    +                        hb_codepoint_t *alternate_glyphs /* OUT.     May be NULL. */) const
    +  {
    +    unsigned int index = (this+coverage).get_coverage (glyph_id);
    +    if (likely (index == NOT_COVERED))
    +    {
    +      if (alternate_count)
    +        *alternate_count = 0;
    +      return 0;
    +    }
    +
    +    if (alternate_count && *alternate_count)
    +    {
    +      hb_codepoint_t d = deltaGlyphID;
    +      hb_codepoint_t mask = get_mask ();
    +
    +      glyph_id = (glyph_id + d) & mask;
    +
    +      *alternate_glyphs = glyph_id;
    +      *alternate_count = 1;
    +    }
    +
    +    return 1;
    +  }
    +
       bool apply (hb_ot_apply_context_t *c) const
       {
         TRACE_APPLY (this);
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat2.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat2.hh
    index 908cc2af158..51890011671 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat2.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat2.hh
    @@ -75,6 +75,31 @@ struct SingleSubstFormat2_4
       bool would_apply (hb_would_apply_context_t *c) const
       { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
     
    +  unsigned
    +  get_glyph_alternates (hb_codepoint_t  glyph_id,
    +                        unsigned        start_offset,
    +                        unsigned       *alternate_count  /* IN/OUT.  May be NULL. */,
    +                        hb_codepoint_t *alternate_glyphs /* OUT.     May be NULL. */) const
    +  {
    +    unsigned int index = (this+coverage).get_coverage (glyph_id);
    +    if (likely (index == NOT_COVERED))
    +    {
    +      if (alternate_count)
    +        *alternate_count = 0;
    +      return 0;
    +    }
    +
    +    if (alternate_count && *alternate_count)
    +    {
    +      glyph_id = substitute[index];
    +
    +      *alternate_glyphs = glyph_id;
    +      *alternate_count = 1;
    +    }
    +
    +    return 1;
    +  }
    +
       bool apply (hb_ot_apply_context_t *c) const
       {
         TRACE_APPLY (this);
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/CompositeGlyph.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/CompositeGlyph.hh
    index e24f3408ca6..94cb61abc07 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/CompositeGlyph.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/CompositeGlyph.hh
    @@ -87,27 +87,34 @@ struct CompositeGlyphRecord
         }
       }
     
    -  void transform_points (contour_point_vector_t &points) const
    +  void transform_points (contour_point_vector_t &points,
    +                         const float (&matrix)[4],
    +                         const contour_point_t &trans) const
       {
    -    float matrix[4];
    -    contour_point_t trans;
    -    if (get_transformation (matrix, trans))
    +    if (scaled_offsets ())
         {
    -      if (scaled_offsets ())
    -      {
    -        points.translate (trans);
    -        points.transform (matrix);
    -      }
    -      else
    -      {
    -        points.transform (matrix);
    -        points.translate (trans);
    -      }
    +      points.translate (trans);
    +      points.transform (matrix);
    +    }
    +    else
    +    {
    +      points.transform (matrix);
    +      points.translate (trans);
         }
       }
     
    -  unsigned compile_with_deltas (const contour_point_t &p_delta,
    -                                char *out) const
    +  bool get_points (contour_point_vector_t &points) const
    +  {
    +    float matrix[4];
    +    contour_point_t trans;
    +    get_transformation (matrix, trans);
    +    if (unlikely (!points.resize (points.length + 1))) return false;
    +    points[points.length - 1] = trans;
    +    return true;
    +  }
    +
    +  unsigned compile_with_point (const contour_point_t &point,
    +                               char *out) const
       {
         const HBINT8 *p = &StructAfter (flags);
     #ifndef HB_NO_BEYOND_64K
    @@ -121,18 +128,17 @@ struct CompositeGlyphRecord
         unsigned len_before_val = (const char *)p - (const char *)this;
         if (flags & ARG_1_AND_2_ARE_WORDS)
         {
    -      // no overflow, copy and update value with deltas
    +      // no overflow, copy value
           hb_memcpy (out, this, len);
     
    -      const HBINT16 *px = reinterpret_cast (p);
           HBINT16 *o = reinterpret_cast (out + len_before_val);
    -      o[0] = px[0] + roundf (p_delta.x);
    -      o[1] = px[1] + roundf (p_delta.y);
    +      o[0] = roundf (point.x);
    +      o[1] = roundf (point.y);
         }
         else
         {
    -      int new_x = p[0] + roundf (p_delta.x);
    -      int new_y = p[1] + roundf (p_delta.y);
    +      int new_x = roundf (point.x);
    +      int new_y = roundf (point.y);
           if (new_x <= 127 && new_x >= -128 &&
               new_y <= 127 && new_y >= -128)
           {
    @@ -143,7 +149,7 @@ struct CompositeGlyphRecord
           }
           else
           {
    -        // int8 overflows after deltas applied
    +        // new point value has an int8 overflow
             hb_memcpy (out, this, len_before_val);
     
             //update flags
    @@ -171,6 +177,7 @@ struct CompositeGlyphRecord
       bool scaled_offsets () const
       { return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
     
    +  public:
       bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
       {
         matrix[0] = matrix[3] = 1.f;
    @@ -225,7 +232,6 @@ struct CompositeGlyphRecord
         return tx || ty;
       }
     
    -  public:
       hb_codepoint_t get_gid () const
       {
     #ifndef HB_NO_BEYOND_64K
    @@ -246,6 +252,27 @@ struct CompositeGlyphRecord
           StructAfter (flags) = gid;
       }
     
    +#ifndef HB_NO_BEYOND_64K
    +  void lower_gid_24_to_16 ()
    +  {
    +    hb_codepoint_t gid = get_gid ();
    +    if (!(flags & GID_IS_24BIT) || gid > 0xFFFFu)
    +      return;
    +
    +    /* Lower the flag and move the rest of the struct down. */
    +
    +    unsigned size = get_size ();
    +    char *end = (char *) this + size;
    +    char *p = &StructAfter (flags);
    +    p += HBGlyphID24::static_size;
    +
    +    flags = flags & ~GID_IS_24BIT;
    +    set_gid (gid);
    +
    +    memmove (p - HBGlyphID24::static_size + HBGlyphID16::static_size, p, end - p);
    +  }
    +#endif
    +
       protected:
       HBUINT16      flags;
       HBUINT24      pad;
    @@ -304,7 +331,7 @@ struct CompositeGlyph
       }
     
       bool compile_bytes_with_deltas (const hb_bytes_t &source_bytes,
    -                                  const contour_point_vector_t &deltas,
    +                                  const contour_point_vector_t &points_with_deltas,
                                       hb_bytes_t &dest_bytes /* OUT */)
       {
         if (source_bytes.length <= GlyphHeader::static_size ||
    @@ -319,7 +346,7 @@ struct CompositeGlyph
         /* try to allocate more memories than source glyph bytes
          * in case that there might be an overflow for int8 value
          * and we would need to use int16 instead */
    -    char *o = (char *) hb_calloc (source_len + source_len/2, sizeof (char));
    +    char *o = (char *) hb_calloc (source_len * 2, sizeof (char));
         if (unlikely (!o)) return false;
     
         const CompositeGlyphRecord *c = reinterpret_cast (source_bytes.arrayZ + GlyphHeader::static_size);
    @@ -329,8 +356,11 @@ struct CompositeGlyph
         unsigned i = 0, source_comp_len = 0;
         for (const auto &component : it)
         {
    -      /* last 4 points in deltas are phantom points and should not be included */
    -      if (i >= deltas.length - 4) return false;
    +      /* last 4 points in points_with_deltas are phantom points and should not be included */
    +      if (i >= points_with_deltas.length - 4) {
    +        free (o);
    +        return false;
    +      }
     
           unsigned comp_len = component.get_size ();
           if (component.is_anchored ())
    @@ -340,7 +370,7 @@ struct CompositeGlyph
           }
           else
           {
    -        unsigned new_len = component.compile_with_deltas (deltas[i], p);
    +        unsigned new_len = component.compile_with_point (points_with_deltas[i], p);
             p += new_len;
           }
           i++;
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/Glyph.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/Glyph.hh
    index 7cd1f571bbc..1ebaaa3f831 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/Glyph.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/Glyph.hh
    @@ -29,7 +29,14 @@ enum phantom_point_index_t
     
     struct Glyph
     {
    -  enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE, VAR_COMPOSITE };
    +  enum glyph_type_t {
    +    EMPTY,
    +    SIMPLE,
    +    COMPOSITE,
    +#ifndef HB_NO_VAR_COMPOSITES
    +    VAR_COMPOSITE,
    +#endif
    +  };
     
       public:
       composite_iter_t get_composite_iterator () const
    @@ -39,15 +46,23 @@ struct Glyph
       }
       var_composite_iter_t get_var_composite_iterator () const
       {
    +#ifndef HB_NO_VAR_COMPOSITES
         if (type != VAR_COMPOSITE) return var_composite_iter_t ();
         return VarCompositeGlyph (*header, bytes).iter ();
    +#else
    +    return var_composite_iter_t ();
    +#endif
       }
     
       const hb_bytes_t trim_padding () const
       {
         switch (type) {
    +#ifndef HB_NO_VAR_COMPOSITES
    +    case VAR_COMPOSITE: return VarCompositeGlyph (*header, bytes).trim_padding ();
    +#endif
         case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
         case SIMPLE:    return SimpleGlyph (*header, bytes).trim_padding ();
    +    case EMPTY:     return bytes;
         default:        return bytes;
         }
       }
    @@ -55,27 +70,36 @@ struct Glyph
       void drop_hints ()
       {
         switch (type) {
    +#ifndef HB_NO_VAR_COMPOSITES
    +    case VAR_COMPOSITE: return; // No hinting
    +#endif
         case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
         case SIMPLE:    SimpleGlyph (*header, bytes).drop_hints (); return;
    -    default:        return;
    +    case EMPTY:     return;
         }
       }
     
       void set_overlaps_flag ()
       {
         switch (type) {
    +#ifndef HB_NO_VAR_COMPOSITES
    +    case VAR_COMPOSITE: return; // No overlaps flag
    +#endif
         case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
         case SIMPLE:    SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
    -    default:        return;
    +    case EMPTY:     return;
         }
       }
     
       void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
       {
         switch (type) {
    +#ifndef HB_NO_VAR_COMPOSITES
    +    case VAR_COMPOSITE: return; // No hinting
    +#endif
         case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
         case SIMPLE:    SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
    -    default:        return;
    +    case EMPTY:     return;
         }
       }
     
    @@ -181,7 +205,7 @@ struct Glyph
                                       hb_bytes_t &dest_start,  /* IN/OUT */
                                       hb_bytes_t &dest_end /* OUT */)
       {
    -    contour_point_vector_t all_points, deltas;
    +    contour_point_vector_t all_points, points_with_deltas;
         unsigned composite_contours = 0;
         head_maxp_info_t *head_maxp_info_p = &plan->head_maxp_info;
         unsigned *composite_contours_p = &composite_contours;
    @@ -195,7 +219,7 @@ struct Glyph
           composite_contours_p = nullptr;
         }
     
    -    if (!get_points (font, glyf, all_points, &deltas, head_maxp_info_p, composite_contours_p, false, false))
    +    if (!get_points (font, glyf, all_points, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
           return false;
     
         // .notdef, set type to empty so we only update metrics and don't compile bytes for
    @@ -209,11 +233,20 @@ struct Glyph
         }
     
         //dont compile bytes when pinned at default, just recalculate bounds
    -    if (!plan->pinned_at_default) {
    -      switch (type) {
    +    if (!plan->pinned_at_default)
    +    {
    +      switch (type)
    +      {
    +#ifndef HB_NO_VAR_COMPOSITES
    +      case VAR_COMPOSITE:
    +        // TODO
    +        dest_end = hb_bytes_t ();
    +        break;
    +#endif
    +
           case COMPOSITE:
             if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
    -                                                                        deltas,
    +                                                                        points_with_deltas,
                                                                             dest_end))
               return false;
             break;
    @@ -223,7 +256,7 @@ struct Glyph
                                                                          dest_end))
               return false;
             break;
    -      default:
    +      case EMPTY:
             /* set empty bytes for empty glyph
              * do not use source glyph's pointers */
             dest_start = hb_bytes_t ();
    @@ -247,7 +280,7 @@ struct Glyph
       template 
       bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
                        contour_point_vector_t &all_points /* OUT */,
    -                   contour_point_vector_t *deltas = nullptr, /* OUT */
    +                   contour_point_vector_t *points_with_deltas = nullptr, /* OUT */
                        head_maxp_info_t * head_maxp_info = nullptr, /* OUT */
                        unsigned *composite_contours = nullptr, /* OUT */
                        bool shift_points_hori = true,
    @@ -287,9 +320,8 @@ struct Glyph
           break;
         case COMPOSITE:
         {
    -      /* pseudo component points for each component in composite glyph */
    -      unsigned num_points = hb_len (CompositeGlyph (*header, bytes).iter ());
    -      if (unlikely (!points.resize (num_points))) return false;
    +      for (auto &item : get_composite_iterator ())
    +        if (unlikely (!item.get_points (points))) return false;
           break;
         }
     #ifndef HB_NO_VAR_COMPOSITES
    @@ -299,7 +331,7 @@ struct Glyph
             if (unlikely (!item.get_points (points))) return false;
         }
     #endif
    -    default:
    +    case EMPTY:
           break;
         }
     
    @@ -327,17 +359,11 @@ struct Glyph
     #endif
                            ;
           phantoms[PHANTOM_LEFT].x = h_delta;
    -      phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
    +      phantoms[PHANTOM_RIGHT].x = (int) h_adv + h_delta;
           phantoms[PHANTOM_TOP].y = v_orig;
           phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
         }
     
    -    if (deltas != nullptr && depth == 0 && type == COMPOSITE)
    -    {
    -      if (unlikely (!deltas->resize (points.length))) return false;
    -      deltas->copy_vector (points);
    -    }
    -
     #ifndef HB_NO_VAR
         glyf_accelerator.gvar->apply_deltas_to_points (gid,
                                                        coords,
    @@ -346,13 +372,10 @@ struct Glyph
     
         // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
         // with child glyphs' points
    -    if (deltas != nullptr && depth == 0 && type == COMPOSITE)
    +    if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE)
         {
    -      for (unsigned i = 0 ; i < points.length; i++)
    -      {
    -        deltas->arrayZ[i].x = points.arrayZ[i].x - deltas->arrayZ[i].x;
    -        deltas->arrayZ[i].y = points.arrayZ[i].y - deltas->arrayZ[i].y;
    -      }
    +      if (unlikely (!points_with_deltas->resize (points.length))) return false;
    +      points_with_deltas->copy_vector (points);
         }
     
         switch (type) {
    @@ -373,7 +396,7 @@ struct Glyph
                                            .get_points (font,
                                                         glyf_accelerator,
                                                         comp_points,
    -                                                    deltas,
    +                                                    points_with_deltas,
                                                         head_maxp_info,
                                                         composite_contours,
                                                         shift_points_hori,
    @@ -389,11 +412,12 @@ struct Glyph
               for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
                 phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
     
    -        /* Apply component transformation & translation */
    -        item.transform_points (comp_points);
    +        float matrix[4];
    +        contour_point_t default_trans;
    +        item.get_transformation (matrix, default_trans);
     
    -        /* Apply translation from gvar */
    -        comp_points.translate (points[comp_index]);
    +        /* Apply component transformation & translation (with deltas applied) */
    +        item.transform_points (comp_points, matrix, points[comp_index]);
     
             if (item.is_anchored ())
             {
    @@ -433,7 +457,8 @@ struct Glyph
           hb_array_t points_left = points.as_array ();
           for (auto &item : get_var_composite_iterator ())
           {
    -        hb_array_t record_points = points_left.sub_array (0, item.get_num_points ());
    +        unsigned item_num_points = item.get_num_points ();
    +        hb_array_t record_points = points_left.sub_array (0, item_num_points);
     
             comp_points.reset ();
     
    @@ -448,7 +473,7 @@ struct Glyph
                                            .get_points (font,
                                                         glyf_accelerator,
                                                         comp_points,
    -                                                    deltas,
    +                                                    points_with_deltas,
                                                         head_maxp_info,
                                                         nullptr,
                                                         shift_points_hori,
    @@ -472,12 +497,12 @@ struct Glyph
             if (all_points.length > HB_GLYF_MAX_POINTS)
               return false;
     
    -        points_left += item.get_num_points ();
    +        points_left += item_num_points;
           }
           all_points.extend (phantoms);
         } break;
     #endif
    -    default:
    +    case EMPTY:
           all_points.extend (phantoms);
           break;
         }
    @@ -503,6 +528,8 @@ struct Glyph
       }
     
       hb_bytes_t get_bytes () const { return bytes; }
    +  glyph_type_t get_type () const { return type; }
    +  const GlyphHeader *get_header () const { return header; }
     
       Glyph () : bytes (),
                  header (bytes.as ()),
    @@ -518,7 +545,9 @@ struct Glyph
         int num_contours = header->numberOfContours;
         if (unlikely (num_contours == 0)) type = EMPTY;
         else if (num_contours > 0) type = SIMPLE;
    +#ifndef HB_NO_VAR_COMPOSITES
         else if (num_contours == -2) type = VAR_COMPOSITE;
    +#endif
         else type = COMPOSITE; /* negative numbers */
       }
     
    @@ -526,7 +555,7 @@ struct Glyph
       hb_bytes_t bytes;
       const GlyphHeader *header;
       hb_codepoint_t gid;
    -  unsigned type;
    +  glyph_type_t type;
     };
     
     
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/SimpleGlyph.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/SimpleGlyph.hh
    index 432f368079f..bed9fc81d81 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/SimpleGlyph.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/SimpleGlyph.hh
    @@ -34,6 +34,11 @@ struct SimpleGlyph
       unsigned int length (unsigned int instruction_len) const
       { return instruction_len_offset () + 2 + instruction_len; }
     
    +  bool has_instructions_length () const
    +  {
    +    return instruction_len_offset () + 2 <= bytes.length;
    +  }
    +
       unsigned int instructions_length () const
       {
         unsigned int instruction_length_offset = instruction_len_offset ();
    @@ -94,6 +99,7 @@ struct SimpleGlyph
       /* zero instruction length */
       void drop_hints ()
       {
    +    if (!has_instructions_length ()) return;
         GlyphHeader &glyph_header = const_cast (header);
         (HBUINT16 &) StructAtOffset (&glyph_header, instruction_len_offset ()) = 0;
       }
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/SubsetGlyph.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/SubsetGlyph.hh
    index 9d1c8e22776..d6ce5be07bb 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/SubsetGlyph.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/SubsetGlyph.hh
    @@ -18,6 +18,7 @@ struct SubsetGlyph
       Glyph source_glyph;
       hb_bytes_t dest_start;  /* region of source_glyph to copy first */
       hb_bytes_t dest_end;    /* region of source_glyph to copy second */
    +  bool allocated;
     
       bool serialize (hb_serialize_context_t *c,
                       bool use_short_loca,
    @@ -26,7 +27,12 @@ struct SubsetGlyph
         TRACE_SERIALIZE (this);
     
         hb_bytes_t dest_glyph = dest_start.copy (c);
    -    dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
    +    hb_bytes_t end_copy = dest_end.copy (c);
    +    if (!end_copy.arrayZ || !dest_glyph.arrayZ) {
    +      return false;
    +    }
    +
    +    dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + end_copy.length);
         unsigned int pad_length = use_short_loca ? padding () : 0;
         DEBUG_MSG (SUBSET, nullptr, "serialize %u byte glyph, width %u pad %u", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
     
    @@ -40,13 +46,68 @@ struct SubsetGlyph
     
         if (unlikely (!dest_glyph.length)) return_trace (true);
     
    -    /* update components gids */
    +    /* update components gids. */
         for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
         {
           hb_codepoint_t new_gid;
           if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
             const_cast (_).set_gid (new_gid);
         }
    +#ifndef HB_NO_VAR_COMPOSITES
    +    for (auto &_ : Glyph (dest_glyph).get_var_composite_iterator ())
    +    {
    +      hb_codepoint_t new_gid;
    +      if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
    +        const_cast (_).set_gid (new_gid);
    +    }
    +#endif
    +
    +#ifndef HB_NO_BEYOND_64K
    +    auto it = Glyph (dest_glyph).get_composite_iterator ();
    +    if (it)
    +    {
    +      /* lower GID24 to GID16 in components if possible.
    +       *
    +       * TODO: VarComposite. Not as critical, since VarComposite supports
    +       * gid24 from the first version. */
    +      char *p = it ? (char *) &*it : nullptr;
    +      char *q = p;
    +      const char *end = dest_glyph.arrayZ + dest_glyph.length;
    +      while (it)
    +      {
    +        auto &rec = const_cast (*it);
    +        ++it;
    +
    +        q += rec.get_size ();
    +
    +        rec.lower_gid_24_to_16 ();
    +
    +        unsigned size = rec.get_size ();
    +
    +        memmove (p, &rec, size);
    +
    +        p += size;
    +      }
    +      memmove (p, q, end - q);
    +      p += end - q;
    +
    +      /* We want to shorten the glyph, but we can't do that without
    +       * updating the length in the loca table, which is already
    +       * written out :-(.  So we just fill the rest of the glyph with
    +       * harmless instructions, since that's what they will be
    +       * interpreted as.
    +       *
    +       * Should move the lowering to _populate_subset_glyphs() to
    +       * fix this issue. */
    +
    +      hb_memset (p, 0x7A /* TrueType instruction ROFF; harmless */, end - p);
    +      p += end - p;
    +      dest_glyph = hb_bytes_t (dest_glyph.arrayZ, p - (char *) dest_glyph.arrayZ);
    +
    +      // TODO: Padding; & trim serialized bytes.
    +      // TODO: Update length in loca. Ugh.
    +    }
    +#endif
     
         if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
           Glyph (dest_glyph).drop_hints ();
    @@ -60,12 +121,18 @@ struct SubsetGlyph
       bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
                                       hb_font_t *font,
                                       const glyf_accelerator_t &glyf)
    -  { return source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end); }
    +  {
    +    allocated = source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end);
    +    return allocated;
    +  }
     
       void free_compiled_bytes ()
       {
    -    dest_start.fini ();
    -    dest_end.fini ();
    +    if (likely (allocated)) {
    +      allocated = false;
    +      dest_start.fini ();
    +      dest_end.fini ();
    +    }
       }
     
       void drop_hints_bytes ()
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/VarCompositeGlyph.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/VarCompositeGlyph.hh
    index 2b2d25f05cd..f2dcb065e26 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/VarCompositeGlyph.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/VarCompositeGlyph.hh
    @@ -27,7 +27,7 @@ struct VarCompositeGlyphRecord
         HAVE_SKEW_Y                 = 0x0200,
         HAVE_TCENTER_X              = 0x0400,
         HAVE_TCENTER_Y              = 0x0800,
    -    GID_IS_24                   = 0x1000,
    +    GID_IS_24BIT                = 0x1000,
         AXES_HAVE_VARIATION         = 0x2000,
         RESET_UNSPECIFIED_AXES      = 0x4000,
       };
    @@ -43,7 +43,7 @@ struct VarCompositeGlyphRecord
     
         // gid
         size += 2;
    -    if (flags & GID_IS_24)              size += 1;
    +    if (flags & GID_IS_24BIT)           size += 1;
     
         if (flags & HAVE_TRANSLATE_X)       size += 2;
         if (flags & HAVE_TRANSLATE_Y)       size += 2;
    @@ -65,12 +65,20 @@ struct VarCompositeGlyphRecord
     
       hb_codepoint_t get_gid () const
       {
    -    if (flags & GID_IS_24)
    +    if (flags & GID_IS_24BIT)
           return StructAfter (numAxes);
         else
           return StructAfter (numAxes);
       }
     
    +  void set_gid (hb_codepoint_t gid)
    +  {
    +    if (flags & GID_IS_24BIT)
    +      StructAfter (numAxes) = gid;
    +    else
    +      StructAfter (numAxes) = gid;
    +  }
    +
       unsigned get_numAxes () const
       {
         return numAxes;
    @@ -145,7 +153,7 @@ struct VarCompositeGlyphRecord
                           float rotation)
       {
         // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
    -    rotation = rotation * float (M_PI);
    +    rotation = rotation * HB_PI;
         float c = cosf (rotation);
         float s = sinf (rotation);
         float other[6] = {c, s, -s, c, 0.f, 0.f};
    @@ -156,8 +164,8 @@ struct VarCompositeGlyphRecord
                         float skewX, float skewY)
       {
         // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
    -    skewX = skewX * float (M_PI);
    -    skewY = skewY * float (M_PI);
    +    skewX = skewX * HB_PI;
    +    skewY = skewY * HB_PI;
         float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f};
         transform (matrix, trans, other);
       }
    @@ -174,16 +182,18 @@ struct VarCompositeGlyphRecord
         float tCenterX = 0.f;
         float tCenterY = 0.f;
     
    -    if (unlikely (!points.resize (points.length + get_num_points ()))) return false;
    +    unsigned num_points = get_num_points ();
    +
    +    if (unlikely (!points.resize (points.length + num_points))) return false;
     
         unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
         unsigned axes_size = numAxes * axis_width;
     
         const F2DOT14 *q = (const F2DOT14 *) (axes_size +
    -                                          (flags & GID_IS_24 ? 3 : 2) +
    +                                          (flags & GID_IS_24BIT ? 3 : 2) +
                                               &StructAfter (numAxes));
     
    -    hb_array_t rec_points = points.as_array ().sub_array (points.length - get_num_points ());
    +    hb_array_t rec_points = points.as_array ().sub_array (points.length - num_points);
     
         unsigned count = numAxes;
         if (flags & AXES_HAVE_VARIATION)
    @@ -308,8 +318,8 @@ struct VarCompositeGlyphRecord
         bool have_variations = flags & AXES_HAVE_VARIATION;
         unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
     
    -    const HBUINT8  *p = (const HBUINT8 *)  (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24 ? 3 : 2));
    -    const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24 ? 3 : 2));
    +    const HBUINT8  *p = (const HBUINT8 *)  (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2));
    +    const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2));
     
         const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + numAxes) : (HBUINT8 *) (q + numAxes)));
     
    @@ -344,6 +354,13 @@ struct VarCompositeGlyph
       var_composite_iter_t iter () const
       { return var_composite_iter_t (bytes, &StructAfter (header)); }
     
    +  const hb_bytes_t trim_padding () const
    +  {
    +    unsigned length = GlyphHeader::static_size;
    +    for (auto &comp : iter ())
    +      length += comp.get_size ();
    +    return bytes.sub_array (0, length);
    +  }
     };
     
     
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh
    index 7a25f07d328..d2a93a56d85 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh
    @@ -31,6 +31,12 @@ struct glyf
     
       static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
     
    +  static bool has_valid_glyf_format(const hb_face_t* face)
    +  {
    +    const OT::head &head = *face->table.head;
    +    return head.indexToLocFormat <= 1 && head.glyphDataFormat <= 1;
    +  }
    +
       bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
       {
         TRACE_SANITIZE (this);
    @@ -72,6 +78,13 @@ struct glyf
       {
         TRACE_SUBSET (this);
     
    +    if (!has_valid_glyf_format (c->plan->source)) {
    +      // glyf format is unknown don't attempt to subset it.
    +      DEBUG_MSG (SUBSET, nullptr,
    +                 "unkown glyf format, dropping from subset.");
    +      return_trace (false);
    +    }
    +
         glyf *glyf_prime = c->serializer->start_embed  ();
         if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
     
    @@ -85,11 +98,17 @@ struct glyf
         hb_vector_t padded_offsets;
         unsigned num_glyphs = c->plan->num_output_glyphs ();
         if (unlikely (!padded_offsets.resize (num_glyphs)))
    +    {
    +      hb_font_destroy (font);
           return false;
    +    }
     
         hb_vector_t glyphs;
         if (!_populate_subset_glyphs (c->plan, font, glyphs))
    +    {
    +      hb_font_destroy (font);
           return false;
    +    }
     
         if (font)
           hb_font_destroy (font);
    @@ -112,7 +131,7 @@ struct glyf
     
         bool result = glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan);
         if (c->plan->normalized_coords && !c->plan->pinned_at_default)
    -      _free_compiled_subset_glyphs (glyphs, glyphs.length - 1);
    +      _free_compiled_subset_glyphs (glyphs);
     
         if (!result) return false;
     
    @@ -131,9 +150,9 @@ struct glyf
       hb_font_t *
       _create_font_for_instancing (const hb_subset_plan_t *plan) const;
     
    -  void _free_compiled_subset_glyphs (hb_vector_t &glyphs, unsigned index) const
    +  void _free_compiled_subset_glyphs (hb_vector_t &glyphs) const
       {
    -    for (unsigned i = 0; i <= index && i < glyphs.length; i++)
    +    for (unsigned i = 0; i < glyphs.length; i++)
           glyphs[i].free_compiled_bytes ();
       }
     
    @@ -162,7 +181,7 @@ struct glyf_accelerator_t
         vmtx = nullptr;
     #endif
         const OT::head &head = *face->table.head;
    -    if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
    +    if (!glyf::has_valid_glyf_format (face))
           /* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
           return;
         short_offset = 0 == head.indexToLocFormat;
    @@ -222,6 +241,8 @@ struct glyf_accelerator_t
         return true;
       }
     
    +  public:
    +
     #ifndef HB_NO_VAR
       struct points_aggregator_t
       {
    @@ -285,7 +306,6 @@ struct glyf_accelerator_t
         contour_point_t *get_phantoms_sink () { return phantoms; }
       };
     
    -  public:
       unsigned
       get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
       {
    @@ -327,6 +347,15 @@ struct glyf_accelerator_t
       }
     #endif
     
    +  bool get_leading_bearing_without_var_unscaled (hb_codepoint_t gid, bool is_vertical, int *lsb) const
    +  {
    +    if (unlikely (gid >= num_glyphs)) return false;
    +    if (is_vertical) return false; // TODO Humm, what to do here?
    +
    +    *lsb = glyph_for_gid (gid).get_header ()->xMin;
    +    return true;
    +  }
    +
       public:
       bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
       {
    @@ -405,7 +434,6 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t   *plan,
       unsigned num_glyphs = plan->num_output_glyphs ();
       if (!glyphs.resize (num_glyphs)) return false;
     
    -  unsigned idx = 0;
       for (auto p : plan->glyph_map->iter ())
       {
         unsigned new_gid = p.second;
    @@ -433,11 +461,10 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t   *plan,
           if (unlikely (!subset_glyph.compile_bytes_with_deltas (plan, font, glyf)))
           {
             // when pinned at default, only bounds are updated, thus no need to free
    -        if (!plan->pinned_at_default && idx > 0)
    -          _free_compiled_subset_glyphs (glyphs, idx - 1);
    +        if (!plan->pinned_at_default)
    +          _free_compiled_subset_glyphs (glyphs);
             return false;
           }
    -      idx++;
         }
       }
       return true;
    @@ -451,7 +478,10 @@ glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
     
       hb_vector_t vars;
       if (unlikely (!vars.alloc (plan->user_axes_location.get_population (), true)))
    +  {
    +    hb_font_destroy (font);
         return nullptr;
    +  }
     
       for (auto _ : plan->user_axes_location)
       {
    diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/path-builder.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/path-builder.hh
    index ed410e2b16f..6a476204f10 100644
    --- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/path-builder.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/path-builder.hh
    @@ -26,13 +26,13 @@ struct path_builder_t
     
         optional_point_t lerp (optional_point_t p, float t)
         { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
    -  } first_oncurve, first_offcurve, last_offcurve, last_offcurve2;
    +  } first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2;
     
       path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
       {
         font = font_;
         draw_session = &draw_session_;
    -    first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
    +    first_oncurve = first_offcurve = first_offcurve2 = last_offcurve = last_offcurve2 = optional_point_t ();
       }
     
       /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
    @@ -40,7 +40,7 @@ struct path_builder_t
          * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
          * https://stackoverflow.com/a/20772557
          *
    -     * Cubic support added (incomplete). */
    +     * Cubic support added. */
       void consume_point (const contour_point_t &point)
       {
         bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
    @@ -59,7 +59,12 @@ struct path_builder_t
           }
           else
           {
    -        if (first_offcurve)
    +        if (is_cubic && !first_offcurve2)
    +        {
    +          first_offcurve2 = first_offcurve;
    +          first_offcurve = p;
    +        }
    +        else if (first_offcurve)
             {
               optional_point_t mid = first_offcurve.lerp (p, .5f);
               first_oncurve = mid;
    @@ -126,16 +131,30 @@ struct path_builder_t
         {
           if (first_offcurve && last_offcurve)
           {
    -        optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
    -        draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
    -                                   mid.x, mid.y);
    +        optional_point_t mid = last_offcurve.lerp (first_offcurve2 ?
    +                                                   first_offcurve2 :
    +                                                   first_offcurve, .5f);
    +        if (last_offcurve2)
    +          draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
    +                                  last_offcurve.x, last_offcurve.y,
    +                                  mid.x, mid.y);
    +        else
    +          draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
    +                                     mid.x, mid.y);
             last_offcurve = optional_point_t ();
    -        /* now check the rest */
           }
    +      /* now check the rest */
     
           if (first_offcurve && first_oncurve)
    -        draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
    -                                   first_oncurve.x, first_oncurve.y);
    +      {
    +        if (first_offcurve2)
    +          draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
    +                                  first_offcurve.x, first_offcurve.y,
    +                                  first_oncurve.x, first_oncurve.y);
    +        else
    +          draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
    +                                     first_oncurve.x, first_oncurve.y);
    +      }
           else if (last_offcurve && first_oncurve)
           {
             if (last_offcurve2)
    diff --git a/src/java.desktop/share/native/libharfbuzz/UPDATING.txt b/src/java.desktop/share/native/libharfbuzz/UPDATING.txt
    index 8beacde4b61..6b4e7ccc4fe 100644
    --- a/src/java.desktop/share/native/libharfbuzz/UPDATING.txt
    +++ b/src/java.desktop/share/native/libharfbuzz/UPDATING.txt
    @@ -81,6 +81,7 @@ STEP 5: REPLACE TABS & REMOVE TRAILING SPACES
       To clean up the extra spaces and tabs run the following script at
       each folder level within libharfbuzz.
     
    +  shopt -s nullglob
       for f in *.c *.h *.cc *.hh;
           do
               # replace tabs with spaces
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh
    index 3d633845a0f..8230cba7c94 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh
    @@ -464,7 +464,8 @@ enum { DELETED_GLYPH = 0xFFFF };
     template 
     struct Entry
     {
    -  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
    +  // This does seem like it's ever called.
    +  bool sanitize (hb_sanitize_context_t *c) const
       {
         TRACE_SANITIZE (this);
         /* Note, we don't recurse-sanitize data because we don't access it.
    @@ -492,7 +493,8 @@ struct Entry
     template <>
     struct Entry
     {
    -  bool sanitize (hb_sanitize_context_t *c, unsigned int count /*XXX Unused?*/) const
    +  // This does seem like it's ever called.
    +  bool sanitize (hb_sanitize_context_t *c) const
       {
         TRACE_SANITIZE (this);
         return_trace (c->check_struct (this));
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-algs.hh b/src/java.desktop/share/native/libharfbuzz/hb-algs.hh
    index 0080b380850..e2b970f968f 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-algs.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-algs.hh
    @@ -110,9 +110,10 @@ struct BEInt
       constexpr operator Type () const
       {
     #if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
    -    ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
         defined(__BYTE_ORDER) && \
    -    (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
    +    (__BYTE_ORDER == __BIG_ENDIAN || \
    +     (__BYTE_ORDER == __LITTLE_ENDIAN && \
    +      hb_has_builtin(__builtin_bswap16)))
         /* Spoon-feed the compiler a big-endian integer with alignment 1.
          * https://github.com/harfbuzz/harfbuzz/pull/1398 */
     #if __BYTE_ORDER == __LITTLE_ENDIAN
    @@ -155,9 +156,10 @@ struct BEInt
       struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
       constexpr operator Type () const {
     #if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
    -    ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
         defined(__BYTE_ORDER) && \
    -    (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
    +    (__BYTE_ORDER == __BIG_ENDIAN || \
    +     (__BYTE_ORDER == __LITTLE_ENDIAN && \
    +      hb_has_builtin(__builtin_bswap32)))
         /* Spoon-feed the compiler a big-endian integer with alignment 1.
          * https://github.com/harfbuzz/harfbuzz/pull/1398 */
     #if __BYTE_ORDER == __LITTLE_ENDIAN
    @@ -598,13 +600,17 @@ template 
     static inline unsigned int
     hb_popcount (T v)
     {
    -#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
    +#if hb_has_builtin(__builtin_popcount)
       if (sizeof (T) <= sizeof (unsigned int))
         return __builtin_popcount (v);
    +#endif
     
    +#if hb_has_builtin(__builtin_popcountl)
       if (sizeof (T) <= sizeof (unsigned long))
         return __builtin_popcountl (v);
    +#endif
     
    +#if hb_has_builtin(__builtin_popcountll)
       if (sizeof (T) <= sizeof (unsigned long long))
         return __builtin_popcountll (v);
     #endif
    @@ -641,13 +647,17 @@ hb_bit_storage (T v)
     {
       if (unlikely (!v)) return 0;
     
    -#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
    +#if hb_has_builtin(__builtin_clz)
       if (sizeof (T) <= sizeof (unsigned int))
         return sizeof (unsigned int) * 8 - __builtin_clz (v);
    +#endif
     
    +#if hb_has_builtin(__builtin_clzl)
       if (sizeof (T) <= sizeof (unsigned long))
         return sizeof (unsigned long) * 8 - __builtin_clzl (v);
    +#endif
     
    +#if hb_has_builtin(__builtin_clzll)
       if (sizeof (T) <= sizeof (unsigned long long))
         return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
     #endif
    @@ -715,13 +725,17 @@ hb_ctz (T v)
     {
       if (unlikely (!v)) return 8 * sizeof (T);
     
    -#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
    +#if hb_has_builtin(__builtin_ctz)
       if (sizeof (T) <= sizeof (unsigned int))
         return __builtin_ctz (v);
    +#endif
     
    +#if hb_has_builtin(__builtin_ctzl)
       if (sizeof (T) <= sizeof (unsigned long))
         return __builtin_ctzl (v);
    +#endif
     
    +#if hb_has_builtin(__builtin_ctzll)
       if (sizeof (T) <= sizeof (unsigned long long))
         return __builtin_ctzll (v);
     #endif
    @@ -875,8 +889,7 @@ hb_in_ranges (T u, T lo1, T hi1, Ts... ds)
     static inline bool
     hb_unsigned_mul_overflows (unsigned int count, unsigned int size, unsigned *result = nullptr)
     {
    -/* avoid with xlc16 clang on AIX; it sets the gcc macros */
    -#if (defined(__GNUC__) && !defined(AIX) && (__GNUC__ >= 4)) || (defined(__clang__) && (__clang_major__ >= 8))
    +#if hb_has_builtin(__builtin_mul_overflow)
       unsigned stack_result;
       if (!result)
         result = &stack_result;
    @@ -1331,4 +1344,62 @@ struct
     HB_FUNCOBJ (hb_dec);
     
     
    +/* Adapted from kurbo implementation with extra parameters added,
    + * and finding for a particular range instead of 0.
    + *
    + * For documentation and implementation see:
    + *
    + * [ITP method]: https://en.wikipedia.org/wiki/ITP_Method
    + * [An Enhancement of the Bisection Method Average Performance Preserving Minmax Optimality]: https://dl.acm.org/doi/10.1145/3423597
    + * https://docs.rs/kurbo/0.8.1/kurbo/common/fn.solve_itp.html
    + * https://github.com/linebender/kurbo/blob/fd839c25ea0c98576c7ce5789305822675a89938/src/common.rs#L162-L248
    + */
    +template 
    +double solve_itp (func_t f,
    +                  double a, double b,
    +                  double epsilon,
    +                  double min_y, double max_y,
    +                  double &ya, double &yb, double &y)
    +{
    +  unsigned n1_2 = (unsigned) (hb_max (ceil (log2 ((b - a) / epsilon)) - 1.0, 0.0));
    +  const unsigned n0 = 1; // Hardwired
    +  const double k1 = 0.2 / (b - a); // Hardwired.
    +  unsigned nmax = n0 + n1_2;
    +  double scaled_epsilon = epsilon * double (1llu << nmax);
    +  double _2_epsilon = 2.0 * epsilon;
    +  while (b - a > _2_epsilon)
    +  {
    +    double x1_2 = 0.5 * (a + b);
    +    double r = scaled_epsilon - 0.5 * (b - a);
    +    double xf = (yb * a - ya * b) / (yb - ya);
    +    double sigma = x1_2 - xf;
    +    double b_a = b - a;
    +    // This has k2 = 2 hardwired for efficiency.
    +    double b_a_k2 = b_a * b_a;
    +    double delta = k1 * b_a_k2;
    +    int sigma_sign = sigma >= 0 ? +1 : -1;
    +    double xt = delta <= fabs (x1_2 - xf) ? xf + delta * sigma_sign : x1_2;
    +    double xitp = fabs (xt - x1_2) <= r ? xt : x1_2 - r * sigma_sign;
    +    double yitp = f (xitp);
    +    if (yitp > max_y)
    +    {
    +      b = xitp;
    +      yb = yitp;
    +    }
    +    else if (yitp < min_y)
    +    {
    +      a = xitp;
    +      ya = yitp;
    +    }
    +    else
    +    {
    +      y = yitp;
    +      return xitp;
    +    }
    +    scaled_epsilon *= 0.5;
    +  }
    +  return 0.5 * (a + b);
    +}
    +
    +
     #endif /* HB_ALGS_HH */
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-bimap.hh b/src/java.desktop/share/native/libharfbuzz/hb-bimap.hh
    index 8e8c988716d..9edefd97106 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-bimap.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-bimap.hh
    @@ -83,9 +83,15 @@ struct hb_bimap_t
     
       unsigned int get_population () const { return forw_map.get_population (); }
     
    +
       protected:
       hb_map_t  forw_map;
       hb_map_t  back_map;
    +
    +  public:
    +  auto keys () const HB_AUTO_RETURN (+ forw_map.keys())
    +  auto values () const HB_AUTO_RETURN (+ forw_map.values())
    +  auto iter () const HB_AUTO_RETURN (+ forw_map.iter())
     };
     
     /* Inremental bimap: only lhs is given, rhs is incrementally assigned */
    @@ -108,6 +114,9 @@ struct hb_inc_bimap_t : hb_bimap_t
       hb_codepoint_t skip ()
       { return next_value++; }
     
    +  hb_codepoint_t skip (unsigned count)
    +  { return next_value += count; }
    +
       hb_codepoint_t get_next_value () const
       { return next_value; }
     
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh b/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh
    index 337bbe6b632..31ee52f6096 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh
    @@ -194,7 +194,7 @@ struct hb_bit_set_t
           unsigned int end = major_start (m + 1);
           do
           {
    -        if (v || page) /* The v check is to optimize out the page check if v is true. */
    +        if (g != INVALID && (v || page)) /* The v check is to optimize out the page check if v is true. */
               page->set (g, v);
     
             array = &StructAtOffsetUnaligned (array, stride);
    @@ -238,7 +238,7 @@ struct hb_bit_set_t
             if (g < last_g) return false;
             last_g = g;
     
    -        if (v || page) /* The v check is to optimize out the page check if v is true. */
    +        if (g != INVALID && (v || page)) /* The v check is to optimize out the page check if v is true. */
               page->add (g);
     
             array = &StructAtOffsetUnaligned (array, stride);
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-blob.h b/src/java.desktop/share/native/libharfbuzz/hb-blob.h
    index b737665d93f..1761e6534ca 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-blob.h
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-blob.h
    @@ -63,7 +63,7 @@ HB_BEGIN_DECLS
      *   HarfBuzz and doing that just once (no reuse!),
      *
      * - If the font is mmap()ed, it's okay to use
    - *   @HB_MEMORY_READONLY_MAY_MAKE_WRITABLE, however, using that mode
    + *   @HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, however, using that mode
      *   correctly is very tricky.  Use @HB_MEMORY_MODE_READONLY instead.
      **/
     typedef enum {
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc b/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc
    index 3532917631d..69d8c961930 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc
    @@ -40,6 +40,11 @@
      * Buffers serve a dual role in HarfBuzz; before shaping, they hold
      * the input characters that are passed to hb_shape(), and after
      * shaping they hold the output glyphs.
    + *
    + * The input buffer is a sequence of Unicode codepoints, with
    + * associated attributes such as direction and script.  The output
    + * buffer is a sequence of glyphs, with associated attributes such
    + * as position and cluster.
      **/
     
     
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-cache.hh b/src/java.desktop/share/native/libharfbuzz/hb-cache.hh
    index eb4a510fbf6..f40c8610dbb 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-cache.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-cache.hh
    @@ -30,7 +30,19 @@
     #include "hb.hh"
     
     
    -/* Implements a lockfree cache for int->int functions. */
    +/* Implements a lockfree cache for int->int functions.
    + *
    + * The cache is a fixed-size array of 16-bit or 32-bit integers.
    + * The key is split into two parts: the cache index and the rest.
    + *
    + * The cache index is used to index into the array.  The rest is used
    + * to store the key and the value.
    + *
    + * The value is stored in the least significant bits of the integer.
    + * The key is stored in the most significant bits of the integer.
    + * The key is shifted by cache_bits to the left to make room for the
    + * value.
    + */
     
     template Note: If the blob font format is not a collection, @index
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-face.hh b/src/java.desktop/share/native/libharfbuzz/hb-face.hh
    index 738f7ecdc72..4c6b252e88e 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-face.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-face.hh
    @@ -76,7 +76,7 @@ struct hb_face_t
         if (unlikely (!reference_table_func))
           return hb_blob_get_empty ();
     
    -    blob = reference_table_func (/*XXX*/const_cast (this), tag, user_data);
    +    blob = reference_table_func (/*Oh, well.*/const_cast (this), tag, user_data);
         if (unlikely (!blob))
           return hb_blob_get_empty ();
     
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-font.cc b/src/java.desktop/share/native/libharfbuzz/hb-font.cc
    index d118deb9285..5cfed3b0490 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-font.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-font.cc
    @@ -59,6 +59,11 @@
      *
      * HarfBuzz provides a built-in set of lightweight default
      * functions for each method in #hb_font_funcs_t.
    + *
    + * The default font functions are implemented in terms of the
    + * #hb_font_funcs_t methods of the parent font object.  This allows
    + * client programs to override only the methods they need to, and
    + * otherwise inherit the parent font's implementation, if any.
      **/
     
     
    @@ -1387,7 +1392,7 @@ hb_font_get_glyph_from_name (hb_font_t      *font,
     /**
      * hb_font_get_glyph_shape:
      * @font: #hb_font_t to work upon
    - * @glyph: : The glyph ID
    + * @glyph: The glyph ID
      * @dfuncs: #hb_draw_funcs_t to draw to
      * @draw_data: User data to pass to draw callbacks
      *
    @@ -1409,7 +1414,7 @@ hb_font_get_glyph_shape (hb_font_t *font,
     /**
      * hb_font_draw_glyph:
      * @font: #hb_font_t to work upon
    - * @glyph: : The glyph ID
    + * @glyph: The glyph ID
      * @dfuncs: #hb_draw_funcs_t to draw to
      * @draw_data: User data to pass to draw callbacks
      *
    @@ -2649,6 +2654,79 @@ hb_font_set_variations (hb_font_t            *font,
       _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
     }
     
    +/**
    + * hb_font_set_variation:
    + * @font: #hb_font_t to work upon
    + * @tag: The #hb_tag_t tag of the variation-axis name
    + * @value: The value of the variation axis
    + *
    + * Change the value of one variation axis on the font.
    + *
    + * Note: This function is expensive to be called repeatedly.
    + *   If you want to set multiple variation axes at the same time,
    + *   use hb_font_set_variations() instead.
    + *
    + * Since: 7.1.0
    + */
    +void
    +hb_font_set_variation (hb_font_t *font,
    +                       hb_tag_t tag,
    +                       float    value)
    +{
    +  if (hb_object_is_immutable (font))
    +    return;
    +
    +  font->serial_coords = ++font->serial;
    +
    +  // TODO Share some of this code with set_variations()
    +
    +  const OT::fvar &fvar = *font->face->table.fvar;
    +  auto axes = fvar.get_axes ();
    +  const unsigned coords_length = axes.length;
    +
    +  int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
    +  float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
    +
    +  if (unlikely (coords_length && !(normalized && design_coords)))
    +  {
    +    hb_free (normalized);
    +    hb_free (design_coords);
    +    return;
    +  }
    +
    +  /* Initialize design coords. */
    +  if (font->design_coords)
    +  {
    +    assert (coords_length == font->num_coords);
    +    for (unsigned int i = 0; i < coords_length; i++)
    +      design_coords[i] = font->design_coords[i];
    +  }
    +  else
    +  {
    +    for (unsigned int i = 0; i < coords_length; i++)
    +      design_coords[i] = axes[i].get_default ();
    +    if (font->instance_index != HB_FONT_NO_VAR_NAMED_INSTANCE)
    +    {
    +      unsigned count = coords_length;
    +      /* This may fail if index is out-of-range;
    +       * That's why we initialize design_coords from fvar above
    +       * unconditionally. */
    +      hb_ot_var_named_instance_get_design_coords (font->face, font->instance_index,
    +                                                  &count, design_coords);
    +    }
    +  }
    +
    +  for (unsigned axis_index = 0; axis_index < coords_length; axis_index++)
    +    if (axes[axis_index].axisTag == tag)
    +      design_coords[axis_index] = value;
    +
    +  font->face->table.avar->map_coords (normalized, coords_length);
    +
    +  hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized);
    +  _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
    +
    +}
    +
     /**
      * hb_font_set_var_coords_design:
      * @font: #hb_font_t to work upon
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-font.h b/src/java.desktop/share/native/libharfbuzz/hb-font.h
    index 77baf74d191..23301c13fc8 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-font.h
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-font.h
    @@ -1150,6 +1150,11 @@ hb_font_set_variations (hb_font_t *font,
                             const hb_variation_t *variations,
                             unsigned int variations_length);
     
    +HB_EXTERN void
    +hb_font_set_variation (hb_font_t *font,
    +                       hb_tag_t tag,
    +                       float    value);
    +
     HB_EXTERN void
     hb_font_set_var_coords_design (hb_font_t *font,
                                    const float *coords,
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ft.cc b/src/java.desktop/share/native/libharfbuzz/hb-ft.cc
    index 93ef3b02d47..9b1fa8d53f2 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ft.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ft.cc
    @@ -85,7 +85,7 @@
      */
     
     
    -using hb_ft_advance_cache_t = hb_cache_t<16, 8, 8, false>;
    +using hb_ft_advance_cache_t = hb_cache_t<16, 24, 8, false>;
     
     struct hb_ft_font_t
     {
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-map.cc b/src/java.desktop/share/native/libharfbuzz/hb-map.cc
    index 863a43aa704..48913a6a10d 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-map.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-map.cc
    @@ -399,7 +399,7 @@ void
     hb_map_keys (const hb_map_t *map,
                  hb_set_t *keys)
     {
    -  map->keys (*keys);
    +  hb_copy (map->keys() , *keys);
     }
     
     /**
    @@ -415,5 +415,5 @@ void
     hb_map_values (const hb_map_t *map,
                    hb_set_t *values)
     {
    -  map->values (*values);
    +  hb_copy (map->values() , *values);
     }
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-map.hh b/src/java.desktop/share/native/libharfbuzz/hb-map.hh
    index 5c351e2c8a0..3b24dc9455a 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-map.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-map.hh
    @@ -317,16 +317,6 @@ struct hb_hashmap_t
         hb_copy (other, *this);
       }
     
    -  void keys (hb_set_t &keys_) const
    -  {
    -    hb_copy (keys() , keys_);
    -  }
    -
    -  void values (hb_set_t &values_) const
    -  {
    -    hb_copy (values() , values_);
    -  }
    -
       /*
        * Iterator
        */
    @@ -353,7 +343,8 @@ struct hb_hashmap_t
       )
       auto keys () const HB_AUTO_RETURN
       (
    -    + keys_ref ()
    +    + iter_items ()
    +    | hb_map (&item_t::key)
         | hb_map (hb_ridentity)
       )
       auto values_ref () const HB_AUTO_RETURN
    @@ -363,7 +354,8 @@ struct hb_hashmap_t
       )
       auto values () const HB_AUTO_RETURN
       (
    -    + values_ref ()
    +    + iter_items ()
    +    | hb_map (&item_t::value)
         | hb_map (hb_ridentity)
       )
     
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh
    index 4a7a693e201..eb1dd2bc0d1 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh
    @@ -404,7 +404,7 @@ struct CmapSubtableFormat4
                      unsigned distance) const
             {
               if (k > last) return +1;
    -          if (k < (&last)[distance]) return -1;
    +          if (k < (&last)[distance]/*first*/) return -1;
               return 0;
             }
             HBUINT16 last;
    @@ -413,7 +413,7 @@ struct CmapSubtableFormat4
           const HBUINT16 *found = hb_bsearch (codepoint,
                                               this->endCount,
                                               this->segCount,
    -                                          2,
    +                                          sizeof (CustomRange),
                                               _hb_cmp_method,
                                               this->segCount + 1);
           if (unlikely (!found))
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh
    index c9da36c1bb5..b552dfdd9da 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh
    @@ -93,6 +93,7 @@ HB_OT_ACCELERATOR (OT, cff2)
     #ifndef HB_NO_VAR
     HB_OT_CORE_TABLE (OT, fvar)
     HB_OT_CORE_TABLE (OT, avar)
    +HB_OT_CORE_TABLE (OT, cvar)
     HB_OT_ACCELERATOR (OT, gvar)
     HB_OT_CORE_TABLE (OT, MVAR)
     #endif
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc
    index f1e882ed938..884cea0f6b3 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc
    @@ -413,7 +413,7 @@ hb_ot_get_glyph_extents (hb_font_t *font,
       if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
       if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
     #endif
    -#if !defined(HB_NO_COLOR)
    +#if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT)
       if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
     #endif
       if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
    @@ -633,20 +633,4 @@ hb_ot_font_set_funcs (hb_font_t *font)
                          _hb_ot_font_destroy);
     }
     
    -#ifndef HB_NO_VAR
    -bool
    -_glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical,
    -                                             int *lsb)
    -{
    -  return font->face->table.glyf->get_leading_bearing_with_var_unscaled (font, glyph, is_vertical, lsb);
    -}
    -
    -unsigned
    -_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
    -{
    -  return font->face->table.glyf->get_advance_with_var_unscaled (font, glyph, is_vertical);
    -}
    -#endif
    -
    -
     #endif
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh
    index 9346641ac35..e13321ee6fa 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh
    @@ -76,7 +76,7 @@ struct DeviceRecord
       HBUINT8                       maxWidth;       /* Maximum width. */
       UnsizedArrayOf       widthsZ;        /* Array of widths (numGlyphs is from the 'maxp' table). */
       public:
    -  DEFINE_SIZE_ARRAY (2, widthsZ);
    +  DEFINE_SIZE_UNBOUNDED (2);
     };
     
     
    @@ -87,14 +87,6 @@ struct hdmx
       unsigned int get_size () const
       { return min_size + numRecords * sizeDeviceRecord; }
     
    -  const DeviceRecord& operator [] (unsigned int i) const
    -  {
    -    /* XXX Null(DeviceRecord) is NOT safe as it's num-glyphs lengthed.
    -     * https://github.com/harfbuzz/harfbuzz/issues/1300 */
    -    if (unlikely (i >= numRecords)) return Null (DeviceRecord);
    -    return StructAtOffset (&this->firstDeviceRecord, i * sizeDeviceRecord);
    -  }
    -
       template
       bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it)
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh
    index 22bd5fa255e..ab057fcfe4f 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh
    @@ -63,7 +63,25 @@ struct head
       bool subset (hb_subset_context_t *c) const
       {
         TRACE_SUBSET (this);
    -    return_trace (serialize (c->serializer));
    +    head *out = c->serializer->embed (this);
    +    if (unlikely (!out)) return_trace (false);
    +
    +    if (c->plan->normalized_coords)
    +    {
    +      if (unlikely (!c->serializer->check_assign (out->xMin, c->plan->head_maxp_info.xMin,
    +                                                  HB_SERIALIZE_ERROR_INT_OVERFLOW)))
    +        return_trace (false);
    +      if (unlikely (!c->serializer->check_assign (out->xMax, c->plan->head_maxp_info.xMax,
    +                                                  HB_SERIALIZE_ERROR_INT_OVERFLOW)))
    +        return_trace (false);
    +      if (unlikely (!c->serializer->check_assign (out->yMin, c->plan->head_maxp_info.yMin,
    +                                                  HB_SERIALIZE_ERROR_INT_OVERFLOW)))
    +        return_trace (false);
    +      if (unlikely (!c->serializer->check_assign (out->yMax, c->plan->head_maxp_info.yMax,
    +                                                  HB_SERIALIZE_ERROR_INT_OVERFLOW)))
    +        return_trace (false);
    +    }
    +    return_trace (true);
       }
     
       enum mac_style_flag_t {
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh
    index 4ef88053f29..e830fd09cf0 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh
    @@ -50,6 +50,9 @@ _glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t gly
     HB_INTERNAL unsigned
     _glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
     
    +HB_INTERNAL bool
    +_glyf_get_leading_bearing_without_var_unscaled (hb_face_t *face, hb_codepoint_t gid, bool is_vertical, int *lsb);
    +
     
     namespace OT {
     
    @@ -92,7 +95,7 @@ struct hmtxvmtx
     
         unsigned int length;
         H *table = (H *) hb_blob_get_data (dest_blob, &length);
    -    table->numberOfLongMetrics = num_hmetrics;
    +    c->serializer->check_assign (table->numberOfLongMetrics, num_hmetrics, HB_SERIALIZE_ERROR_INT_OVERFLOW);
     
     #ifndef HB_NO_VAR
         if (c->plan->normalized_coords)
    @@ -165,12 +168,19 @@ struct hmtxvmtx
             lm.sb = _.second;
             if (unlikely (!c->embed (&lm))) return;
           }
    -      else
    +      else if (idx < 0x10000u)
           {
             FWORD *sb = c->allocate_size (FWORD::static_size);
             if (unlikely (!sb)) return;
             *sb = _.second;
           }
    +      else
    +      {
    +        // TODO: This does not do tail optimization.
    +        UFWORD *adv = c->allocate_size (UFWORD::static_size);
    +        if (unlikely (!adv)) return;
    +        *adv = _.first;
    +      }
           idx++;
         }
       }
    @@ -189,7 +199,7 @@ struct hmtxvmtx
           /* Determine num_long_metrics to encode. */
           auto& plan = c->plan;
     
    -      num_long_metrics = plan->num_output_glyphs ();
    +      num_long_metrics = hb_min (plan->num_output_glyphs (), 0xFFFFu);
           unsigned int last_advance = get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 1, _mtx);
           while (num_long_metrics > 1 &&
                  last_advance == get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 2, _mtx))
    @@ -208,7 +218,8 @@ struct hmtxvmtx
                       if (!c->plan->old_gid_for_new_gid (_, &old_gid))
                         return hb_pair (0u, 0);
                       int lsb = 0;
    -                  (void) _mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb);
    +                  if (!_mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb))
    +                    (void) _glyf_get_leading_bearing_without_var_unscaled (c->plan->source, old_gid, !T::is_horizontal, &lsb);
                       return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb);
                     }
                     return mtx_map->get (_);
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh
    index 73cf84ed39d..1ff697b1b63 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh
    @@ -529,6 +529,9 @@ struct FeatureParamsSize
           return_trace (true);
       }
     
    +  void collect_name_ids (hb_set_t *nameids_to_retain /* OUT */) const
    +  { nameids_to_retain->add (subfamilyNameID); }
    +
       bool subset (hb_subset_context_t *c) const
       {
         TRACE_SUBSET (this);
    @@ -585,6 +588,9 @@ struct FeatureParamsStylisticSet
         return_trace (c->check_struct (this));
       }
     
    +  void collect_name_ids (hb_set_t *nameids_to_retain /* OUT */) const
    +  { nameids_to_retain->add (uiNameID); }
    +
       bool subset (hb_subset_context_t *c) const
       {
         TRACE_SUBSET (this);
    @@ -632,6 +638,20 @@ struct FeatureParamsCharacterVariants
       unsigned get_size () const
       { return min_size + characters.len * HBUINT24::static_size; }
     
    +  void collect_name_ids (hb_set_t *nameids_to_retain /* OUT */) const
    +  {
    +    if (featUILableNameID) nameids_to_retain->add (featUILableNameID);
    +    if (featUITooltipTextNameID) nameids_to_retain->add (featUITooltipTextNameID);
    +    if (sampleTextNameID) nameids_to_retain->add (sampleTextNameID);
    +
    +    if (!firstParamUILabelNameID || !numNamedParameters || numNamedParameters >= 0x7FFF)
    +      return;
    +
    +    unsigned last_name_id = (unsigned) firstParamUILabelNameID + (unsigned) numNamedParameters - 1;
    +    if (last_name_id >= 256 && last_name_id <= 32767)
    +      nameids_to_retain->add_range (firstParamUILabelNameID, last_name_id);
    +  }
    +
       bool subset (hb_subset_context_t *c) const
       {
         TRACE_SUBSET (this);
    @@ -694,6 +714,19 @@ struct FeatureParams
         return_trace (true);
       }
     
    +  void collect_name_ids (hb_tag_t tag, hb_set_t *nameids_to_retain /* OUT */) const
    +  {
    +#ifdef HB_NO_LAYOUT_FEATURE_PARAMS
    +    return;
    +#endif
    +    if (tag == HB_TAG ('s','i','z','e'))
    +      return (u.size.collect_name_ids (nameids_to_retain));
    +    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
    +      return (u.stylisticSet.collect_name_ids (nameids_to_retain));
    +    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
    +      return (u.characterVariants.collect_name_ids (nameids_to_retain));
    +  }
    +
       bool subset (hb_subset_context_t *c, const Tag* tag) const
       {
         TRACE_SUBSET (this);
    @@ -762,6 +795,12 @@ struct Feature
       bool intersects_lookup_indexes (const hb_map_t *lookup_indexes) const
       { return lookupIndex.intersects (lookup_indexes); }
     
    +  void collect_name_ids (hb_tag_t tag, hb_set_t *nameids_to_retain /* OUT */) const
    +  {
    +    if (featureParams)
    +      get_feature_params ().collect_name_ids (tag, nameids_to_retain);
    +  }
    +
       bool subset (hb_subset_context_t         *c,
                    hb_subset_layout_context_t  *l,
                    const Tag                   *tag = nullptr) const
    @@ -2233,19 +2272,20 @@ struct VarRegionAxis
     {
       float evaluate (int coord) const
       {
    -    int start = startCoord.to_int (), peak = peakCoord.to_int (), end = endCoord.to_int ();
    +    int peak = peakCoord.to_int ();
    +    if (peak == 0 || coord == peak)
    +      return 1.f;
    +
    +    int start = startCoord.to_int (), end = endCoord.to_int ();
     
         /* TODO Move these to sanitize(). */
         if (unlikely (start > peak || peak > end))
    -      return 1.;
    +      return 1.f;
         if (unlikely (start < 0 && end > 0 && peak != 0))
    -      return 1.;
    -
    -    if (peak == 0 || coord == peak)
    -      return 1.;
    +      return 1.f;
     
         if (coord <= start || end <= coord)
    -      return 0.;
    +      return 0.f;
     
         /* Interpolate */
         if (coord < peak)
    @@ -2462,10 +2502,9 @@ struct VarData
         {
           for (r = 0; r < src_word_count; r++)
           {
    -        for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
    +        for (unsigned old_gid : inner_map.keys())
             {
    -          unsigned int old = inner_map.backward (i);
    -          int32_t delta = src->get_item_delta_fast (old, r, src_delta_bytes, src_row_size);
    +          int32_t delta = src->get_item_delta_fast (old_gid, r, src_delta_bytes, src_row_size);
               if (delta < -65536 || 65535 < delta)
               {
                 has_long = true;
    @@ -2482,10 +2521,9 @@ struct VarData
           bool short_circuit = src_long_words == has_long && src_word_count <= r;
     
           delta_sz[r] = kZero;
    -      for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
    +      for (unsigned old_gid : inner_map.keys())
           {
    -        unsigned int old = inner_map.backward (i);
    -        int32_t delta = src->get_item_delta_fast (old, r, src_delta_bytes, src_row_size);
    +        int32_t delta = src->get_item_delta_fast (old_gid, r, src_delta_bytes, src_row_size);
             if (delta < min_threshold || max_threshold < delta)
             {
               delta_sz[r] = kWord;
    @@ -2546,8 +2584,8 @@ struct VarData
         {
           unsigned int region = regionIndices.arrayZ[r];
           if (region_indices.has (region)) continue;
    -      for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
    -        if (get_item_delta_fast (inner_map.backward (i), r, delta_bytes, row_size) != 0)
    +      for (hb_codepoint_t old_gid : inner_map.keys())
    +        if (get_item_delta_fast (old_gid, r, delta_bytes, row_size) != 0)
             {
               region_indices.add (region);
               break;
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh
    index 58a01e9a2df..29efba4b9c7 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh
    @@ -487,7 +487,8 @@ struct hb_ot_apply_context_t :
           /* Ignore ZWJ if we are matching context, or asked to. */
           matcher.set_ignore_zwj  (context_match || c->auto_zwj);
           matcher.set_mask (context_match ? -1 : c->lookup_mask);
    -      matcher.set_per_syllable (c->per_syllable);
    +      /* Per syllable matching is only for GSUB. */
    +      matcher.set_per_syllable (c->table_index == 0 && c->per_syllable);
         }
         void set_lookup_props (unsigned int lookup_props)
         {
    @@ -4461,6 +4462,18 @@ struct GSUBGPOS
         }
       }
     
    +  void collect_name_ids (const hb_map_t *feature_index_map,
    +                         hb_set_t *nameids_to_retain /* OUT */) const
    +  {
    +    unsigned count = get_feature_count ();
    +    for (unsigned i = 0 ; i < count; i++)
    +    {
    +      if (!feature_index_map->has (i)) continue;
    +      hb_tag_t tag = get_feature_tag (i);
    +      get_feature (i).collect_name_ids (tag, nameids_to_retain);
    +    }
    +  }
    +
       template 
       struct accelerator_t
       {
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc
    index 74ffb50d79f..39431fdf1e5 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc
    @@ -64,6 +64,8 @@ using OT::Layout::GPOS;
      * @include: hb-ot.h
      *
      * Functions for querying OpenType Layout features in the font face.
    + * See the OpenType
    + * specification for details.
      **/
     
     
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-maxp-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-maxp-table.hh
    index e43e4f56474..f7f2e860e4a 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-maxp-table.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-maxp-table.hh
    @@ -100,7 +100,7 @@ struct maxp
         maxp *maxp_prime = c->serializer->embed (this);
         if (unlikely (!maxp_prime)) return_trace (false);
     
    -    maxp_prime->numGlyphs = c->plan->num_output_glyphs ();
    +    maxp_prime->numGlyphs = hb_min (c->plan->num_output_glyphs (), 0xFFFFu);
         if (maxp_prime->version.major == 1)
         {
           const maxpV1Tail *src_v1 = &StructAfter (*this);
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-name.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-name.cc
    index 4ef43d5cfbd..bc78f98c401 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-name.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-name.cc
    @@ -181,6 +181,4 @@ hb_ot_name_get_utf32 (hb_face_t       *face,
       return hb_ot_name_get_utf (face, name_id, language, text_size, text);
     }
     
    -#include "hb-ot-name-language-static.hh"
    -
     #endif
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh
    index e3bad10ae06..4426ededf30 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh
    @@ -99,6 +99,10 @@ struct post
         post *post_prime = c->serializer->start_embed ();
         if (unlikely (!post_prime)) return_trace (false);
     
    +    bool glyph_names = c->plan->flags & HB_SUBSET_FLAGS_GLYPH_NAMES;
    +    if (!serialize (c->serializer, glyph_names))
    +      return_trace (false);
    +
     #ifndef HB_NO_VAR
         if (c->plan->normalized_coords)
         {
    @@ -110,10 +114,6 @@ struct post
         }
     #endif
     
    -    bool glyph_names = c->plan->flags & HB_SUBSET_FLAGS_GLYPH_NAMES;
    -    if (!serialize (c->serializer, glyph_names))
    -      return_trace (false);
    -
         if (c->plan->user_axes_location.has (HB_TAG ('s','l','n','t')) &&
             !c->plan->pinned_at_default)
         {
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc
    index 2cc176e279c..20007df8963 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc
    @@ -1067,12 +1067,15 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
                   base = i;
                   while (base < end && is_halant (info[base]))
                     base++;
    -              info[base].indic_position() = POS_BASE_C;
    +              if (base < end)
    +                info[base].indic_position() = POS_BASE_C;
     
                   try_pref = false;
                 }
                 break;
               }
    +        if (base == end)
    +          break;
           }
           /* For Malayalam, skip over unformed below- (but NOT post-) forms. */
           if (buffer->props.script == HB_SCRIPT_MALAYALAM)
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-stat-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-stat-table.hh
    index b354e292280..448d03eb303 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-stat-table.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-stat-table.hh
    @@ -536,6 +536,8 @@ struct STAT
         | hb_map (&AxisValue::get_value_name_id)
         | hb_sink (nameids_to_retain)
         ;
    +
    +    nameids_to_retain->add (elidedFallbackNameID);
       }
     
       bool subset (hb_subset_context_t *c) const
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-common.hh
    index 18f07bdedb0..97d2a4b3fcc 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-common.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-common.hh
    @@ -222,21 +222,371 @@ struct DeltaSetIndexMap
     
     struct VarStoreInstancer
     {
    -  VarStoreInstancer (const VariationStore &varStore,
    -                     const DeltaSetIndexMap &varIdxMap,
    +  VarStoreInstancer (const VariationStore *varStore,
    +                     const DeltaSetIndexMap *varIdxMap,
                          hb_array_t coords) :
         varStore (varStore), varIdxMap (varIdxMap), coords (coords) {}
     
    -  operator bool () const { return bool (coords); }
    +  operator bool () const { return varStore && bool (coords); }
     
    +  /* according to the spec, if colr table has varStore but does not have
    +   * varIdxMap, then an implicit identity mapping is used */
       float operator() (uint32_t varIdx, unsigned short offset = 0) const
    -  { return varStore.get_delta (varIdxMap.map (VarIdx::add (varIdx, offset)), coords); }
    +  { return varStore->get_delta (varIdxMap ? varIdxMap->map (VarIdx::add (varIdx, offset)) : varIdx + offset, coords); }
     
    -  const VariationStore &varStore;
    -  const DeltaSetIndexMap &varIdxMap;
    +  const VariationStore *varStore;
    +  const DeltaSetIndexMap *varIdxMap;
       hb_array_t coords;
     };
     
    +/* https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader */
    +struct TupleVariationHeader
    +{
    +  unsigned get_size (unsigned axis_count) const
    +  { return min_size + get_all_tuples (axis_count).get_size (); }
    +
    +  unsigned get_data_size () const { return varDataSize; }
    +
    +  const TupleVariationHeader &get_next (unsigned axis_count) const
    +  { return StructAtOffset (this, get_size (axis_count)); }
    +
    +  float calculate_scalar (hb_array_t coords, unsigned int coord_count,
    +                          const hb_array_t shared_tuples,
    +                          const hb_vector_t *shared_tuple_active_idx = nullptr) const
    +  {
    +    const F2DOT14 *peak_tuple;
    +
    +    unsigned start_idx = 0;
    +    unsigned end_idx = coord_count;
    +
    +    if (has_peak ())
    +      peak_tuple = get_peak_tuple (coord_count).arrayZ;
    +    else
    +    {
    +      unsigned int index = get_index ();
    +      if (unlikely ((index + 1) * coord_count > shared_tuples.length))
    +        return 0.f;
    +      peak_tuple = shared_tuples.sub_array (coord_count * index, coord_count).arrayZ;
    +
    +      if (shared_tuple_active_idx)
    +      {
    +        assert (index < shared_tuple_active_idx->length);
    +        int v = (*shared_tuple_active_idx).arrayZ[index];
    +        if (v != -1)
    +        {
    +          start_idx = v;
    +          end_idx = start_idx + 1;
    +        }
    +      }
    +    }
    +
    +    const F2DOT14 *start_tuple = nullptr;
    +    const F2DOT14 *end_tuple = nullptr;
    +    bool has_interm = has_intermediate ();
    +    if (has_interm)
    +    {
    +      start_tuple = get_start_tuple (coord_count).arrayZ;
    +      end_tuple = get_end_tuple (coord_count).arrayZ;
    +    }
    +
    +    float scalar = 1.f;
    +    for (unsigned int i = start_idx; i < end_idx; i++)
    +    {
    +      int peak = peak_tuple[i].to_int ();
    +      if (!peak) continue;
    +
    +      int v = coords[i];
    +      if (v == peak) continue;
    +
    +      if (has_interm)
    +      {
    +        int start = start_tuple[i].to_int ();
    +        int end = end_tuple[i].to_int ();
    +        if (unlikely (start > peak || peak > end ||
    +                      (start < 0 && end > 0 && peak))) continue;
    +        if (v < start || v > end) return 0.f;
    +        if (v < peak)
    +        { if (peak != start) scalar *= (float) (v - start) / (peak - start); }
    +        else
    +        { if (peak != end) scalar *= (float) (end - v) / (end - peak); }
    +      }
    +      else if (!v || v < hb_min (0, peak) || v > hb_max (0, peak)) return 0.f;
    +      else
    +        scalar *= (float) v / peak;
    +    }
    +    return scalar;
    +  }
    +
    +  bool           has_peak () const { return tupleIndex & TuppleIndex::EmbeddedPeakTuple; }
    +  bool   has_intermediate () const { return tupleIndex & TuppleIndex::IntermediateRegion; }
    +  bool has_private_points () const { return tupleIndex & TuppleIndex::PrivatePointNumbers; }
    +  unsigned      get_index () const { return tupleIndex & TuppleIndex::TupleIndexMask; }
    +
    +  protected:
    +  struct TuppleIndex : HBUINT16
    +  {
    +    enum Flags {
    +      EmbeddedPeakTuple   = 0x8000u,
    +      IntermediateRegion  = 0x4000u,
    +      PrivatePointNumbers = 0x2000u,
    +      TupleIndexMask      = 0x0FFFu
    +    };
    +
    +    DEFINE_SIZE_STATIC (2);
    +  };
    +
    +  hb_array_t get_all_tuples (unsigned axis_count) const
    +  { return StructAfter> (tupleIndex).as_array ((has_peak () + has_intermediate () * 2) * axis_count); }
    +  hb_array_t get_peak_tuple (unsigned axis_count) const
    +  { return get_all_tuples (axis_count).sub_array (0, axis_count); }
    +  hb_array_t get_start_tuple (unsigned axis_count) const
    +  { return get_all_tuples (axis_count).sub_array (has_peak () * axis_count, axis_count); }
    +  hb_array_t get_end_tuple (unsigned axis_count) const
    +  { return get_all_tuples (axis_count).sub_array (has_peak () * axis_count + axis_count, axis_count); }
    +
    +  HBUINT16      varDataSize;    /* The size in bytes of the serialized
    +                                 * data for this tuple variation table. */
    +  TuppleIndex   tupleIndex;     /* A packed field. The high 4 bits are flags (see below).
    +                                   The low 12 bits are an index into a shared tuple
    +                                   records array. */
    +  /* UnsizedArrayOf peakTuple - optional */
    +                                /* Peak tuple record for this tuple variation table — optional,
    +                                 * determined by flags in the tupleIndex value.
    +                                 *
    +                                 * Note that this must always be included in the 'cvar' table. */
    +  /* UnsizedArrayOf intermediateStartTuple - optional */
    +                                /* Intermediate start tuple record for this tuple variation table — optional,
    +                                   determined by flags in the tupleIndex value. */
    +  /* UnsizedArrayOf intermediateEndTuple - optional */
    +                                /* Intermediate end tuple record for this tuple variation table — optional,
    +                                 * determined by flags in the tupleIndex value. */
    +  public:
    +  DEFINE_SIZE_MIN (4);
    +};
    +
    +struct TupleVariationData
    +{
    +  bool sanitize (hb_sanitize_context_t *c) const
    +  {
    +    TRACE_SANITIZE (this);
    +    // here check on min_size only, TupleVariationHeader and var data will be
    +    // checked while accessing through iterator.
    +    return_trace (c->check_struct (this));
    +  }
    +
    +  unsigned get_size (unsigned axis_count) const
    +  {
    +    unsigned total_size = min_size;
    +    unsigned count = tupleVarCount;
    +    const TupleVariationHeader *tuple_var_header = &(get_tuple_var_header());
    +    for (unsigned i = 0; i < count; i++)
    +    {
    +      total_size += tuple_var_header->get_size (axis_count) + tuple_var_header->get_data_size ();
    +      tuple_var_header = &tuple_var_header->get_next (axis_count);
    +    }
    +
    +    return total_size;
    +  }
    +
    +  const TupleVariationHeader &get_tuple_var_header (void) const
    +  { return StructAfter (data); }
    +
    +  struct tuple_iterator_t
    +  {
    +    void init (hb_bytes_t var_data_bytes_, unsigned int axis_count_, const void *table_base_)
    +    {
    +      var_data_bytes = var_data_bytes_;
    +      var_data = var_data_bytes_.as ();
    +      index = 0;
    +      axis_count = axis_count_;
    +      current_tuple = &var_data->get_tuple_var_header ();
    +      data_offset = 0;
    +      table_base = table_base_;
    +    }
    +
    +    bool get_shared_indices (hb_vector_t &shared_indices /* OUT */)
    +    {
    +      if (var_data->has_shared_point_numbers ())
    +      {
    +        const HBUINT8 *base = &(table_base+var_data->data);
    +        const HBUINT8 *p = base;
    +        if (!unpack_points (p, shared_indices, (const HBUINT8 *) (var_data_bytes.arrayZ + var_data_bytes.length))) return false;
    +        data_offset = p - base;
    +      }
    +      return true;
    +    }
    +
    +    bool is_valid () const
    +    {
    +      return (index < var_data->tupleVarCount.get_count ()) &&
    +             var_data_bytes.check_range (current_tuple, TupleVariationHeader::min_size) &&
    +             var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (),
    +                                                                current_tuple->get_size (axis_count)));
    +    }
    +
    +    bool move_to_next ()
    +    {
    +      data_offset += current_tuple->get_data_size ();
    +      current_tuple = ¤t_tuple->get_next (axis_count);
    +      index++;
    +      return is_valid ();
    +    }
    +
    +    const HBUINT8 *get_serialized_data () const
    +    { return &(table_base+var_data->data) + data_offset; }
    +
    +    private:
    +    const TupleVariationData *var_data;
    +    unsigned int index;
    +    unsigned int axis_count;
    +    unsigned int data_offset;
    +    const void *table_base;
    +
    +    public:
    +    hb_bytes_t var_data_bytes;
    +    const TupleVariationHeader *current_tuple;
    +  };
    +
    +  static bool get_tuple_iterator (hb_bytes_t var_data_bytes, unsigned axis_count,
    +                                  const void *table_base,
    +                                  hb_vector_t &shared_indices /* OUT */,
    +                                  tuple_iterator_t *iterator /* OUT */)
    +  {
    +    iterator->init (var_data_bytes, axis_count, table_base);
    +    if (!iterator->get_shared_indices (shared_indices))
    +      return false;
    +    return iterator->is_valid ();
    +  }
    +
    +  bool has_shared_point_numbers () const { return tupleVarCount.has_shared_point_numbers (); }
    +
    +  static bool unpack_points (const HBUINT8 *&p /* IN/OUT */,
    +                             hb_vector_t &points /* OUT */,
    +                             const HBUINT8 *end)
    +  {
    +    enum packed_point_flag_t
    +    {
    +      POINTS_ARE_WORDS     = 0x80,
    +      POINT_RUN_COUNT_MASK = 0x7F
    +    };
    +
    +    if (unlikely (p + 1 > end)) return false;
    +
    +    unsigned count = *p++;
    +    if (count & POINTS_ARE_WORDS)
    +    {
    +      if (unlikely (p + 1 > end)) return false;
    +      count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++;
    +    }
    +    if (unlikely (!points.resize (count, false))) return false;
    +
    +    unsigned n = 0;
    +    unsigned i = 0;
    +    while (i < count)
    +    {
    +      if (unlikely (p + 1 > end)) return false;
    +      unsigned control = *p++;
    +      unsigned run_count = (control & POINT_RUN_COUNT_MASK) + 1;
    +      unsigned stop = i + run_count;
    +      if (unlikely (stop > count)) return false;
    +      if (control & POINTS_ARE_WORDS)
    +      {
    +        if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
    +        for (; i < stop; i++)
    +        {
    +          n += *(const HBUINT16 *)p;
    +          points.arrayZ[i] = n;
    +          p += HBUINT16::static_size;
    +        }
    +      }
    +      else
    +      {
    +        if (unlikely (p + run_count > end)) return false;
    +        for (; i < stop; i++)
    +        {
    +          n += *p++;
    +          points.arrayZ[i] = n;
    +        }
    +      }
    +    }
    +    return true;
    +  }
    +
    +  static bool unpack_deltas (const HBUINT8 *&p /* IN/OUT */,
    +                             hb_vector_t &deltas /* IN/OUT */,
    +                             const HBUINT8 *end)
    +  {
    +    enum packed_delta_flag_t
    +    {
    +      DELTAS_ARE_ZERO      = 0x80,
    +      DELTAS_ARE_WORDS     = 0x40,
    +      DELTA_RUN_COUNT_MASK = 0x3F
    +    };
    +
    +    unsigned i = 0;
    +    unsigned count = deltas.length;
    +    while (i < count)
    +    {
    +      if (unlikely (p + 1 > end)) return false;
    +      unsigned control = *p++;
    +      unsigned run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
    +      unsigned stop = i + run_count;
    +      if (unlikely (stop > count)) return false;
    +      if (control & DELTAS_ARE_ZERO)
    +      {
    +        for (; i < stop; i++)
    +          deltas.arrayZ[i] = 0;
    +      }
    +      else if (control & DELTAS_ARE_WORDS)
    +      {
    +        if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
    +        for (; i < stop; i++)
    +        {
    +          deltas.arrayZ[i] = * (const HBINT16 *) p;
    +          p += HBUINT16::static_size;
    +        }
    +      }
    +      else
    +      {
    +        if (unlikely (p + run_count > end)) return false;
    +        for (; i < stop; i++)
    +        {
    +          deltas.arrayZ[i] = * (const HBINT8 *) p++;
    +        }
    +      }
    +    }
    +    return true;
    +  }
    +
    +  bool has_data () const { return tupleVarCount; }
    +
    +  protected:
    +  struct TupleVarCount : HBUINT16
    +  {
    +    bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers); }
    +    unsigned int get_count () const { return (*this) & CountMask; }
    +
    +    protected:
    +    enum Flags
    +    {
    +      SharedPointNumbers= 0x8000u,
    +      CountMask         = 0x0FFFu
    +    };
    +    public:
    +    DEFINE_SIZE_STATIC (2);
    +  };
    +
    +  TupleVarCount tupleVarCount;  /* A packed field. The high 4 bits are flags, and the
    +                                 * low 12 bits are the number of tuple variation tables
    +                                 * for this glyph. The number of tuple variation tables
    +                                 * can be any number between 1 and 4095. */
    +  Offset16To
    +                data;           /* Offset from the start of the base table
    +                                 * to the serialized data. */
    +  /* TupleVariationHeader tupleVariationHeaders[] *//* Array of tuple variation headers. */
    +  public:
    +  DEFINE_SIZE_MIN (4);
    +};
     
     } /* namespace OT */
     
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-cvar-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-cvar-table.hh
    new file mode 100644
    index 00000000000..8a281dd72d5
    --- /dev/null
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-cvar-table.hh
    @@ -0,0 +1,158 @@
    +/*
    + * Copyright © 2023  Google, Inc.
    + *
    + *  This is part of HarfBuzz, a text shaping library.
    + *
    + * Permission is hereby granted, without written agreement and without
    + * license or royalty fees, to use, copy, modify, and distribute this
    + * software and its documentation for any purpose, provided that the
    + * above copyright notice and the following two paragraphs appear in
    + * all copies of this software.
    + *
    + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
    + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
    + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
    + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
    + * DAMAGE.
    + *
    + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
    + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    + * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
    + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
    + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
    + *
    + */
    +
    +#ifndef HB_OT_VAR_CVAR_TABLE_HH
    +#define HB_OT_VAR_CVAR_TABLE_HH
    +
    +#include "hb-ot-var-common.hh"
    +
    +
    +namespace OT {
    +/*
    + * cvar -- control value table (CVT) Variations
    + * https://docs.microsoft.com/en-us/typography/opentype/spec/cvar
    + */
    +#define HB_OT_TAG_cvar HB_TAG('c','v','a','r')
    +
    +struct cvar
    +{
    +  static constexpr hb_tag_t tableTag = HB_OT_TAG_cvar;
    +
    +  bool sanitize (hb_sanitize_context_t *c) const
    +  {
    +    TRACE_SANITIZE (this);
    +    return_trace (c->check_struct (this) &&
    +                  version.sanitize (c) && likely (version.major == 1) &&
    +                  tupleVariationData.sanitize (c));
    +  }
    +
    +  const TupleVariationData* get_tuple_var_data (void) const
    +  { return &tupleVariationData; }
    +
    +  static bool calculate_cvt_deltas (unsigned axis_count,
    +                                    hb_array_t coords,
    +                                    unsigned num_cvt_item,
    +                                    const TupleVariationData *tuple_var_data,
    +                                    const void *base,
    +                                    hb_vector_t& cvt_deltas /* OUT */)
    +  {
    +    if (!coords) return true;
    +    hb_vector_t shared_indices;
    +    TupleVariationData::tuple_iterator_t iterator;
    +    unsigned var_data_length = tuple_var_data->get_size (axis_count);
    +    hb_bytes_t var_data_bytes = hb_bytes_t (reinterpret_cast (tuple_var_data), var_data_length);
    +    if (!TupleVariationData::get_tuple_iterator (var_data_bytes, axis_count, base,
    +                                                 shared_indices, &iterator))
    +      return true; /* isn't applied at all */
    +
    +    hb_array_t shared_tuples = hb_array ();
    +    hb_vector_t private_indices;
    +    hb_vector_t unpacked_deltas;
    +
    +    do
    +    {
    +      float scalar = iterator.current_tuple->calculate_scalar (coords, axis_count, shared_tuples);
    +      if (scalar == 0.f) continue;
    +      const HBUINT8 *p = iterator.get_serialized_data ();
    +      unsigned int length = iterator.current_tuple->get_data_size ();
    +      if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
    +        return false;
    +
    +      const HBUINT8 *end = p + length;
    +
    +      bool has_private_points = iterator.current_tuple->has_private_points ();
    +      if (has_private_points &&
    +          !TupleVariationData::unpack_points (p, private_indices, end))
    +        return false;
    +      const hb_vector_t &indices = has_private_points ? private_indices : shared_indices;
    +
    +      bool apply_to_all = (indices.length == 0);
    +      unsigned num_deltas = apply_to_all ? num_cvt_item : indices.length;
    +      if (unlikely (!unpacked_deltas.resize (num_deltas, false))) return false;
    +      if (unlikely (!TupleVariationData::unpack_deltas (p, unpacked_deltas, end))) return false;
    +
    +      for (unsigned int i = 0; i < num_deltas; i++)
    +      {
    +        unsigned int idx = apply_to_all ? i : indices[i];
    +        if (unlikely (idx >= num_cvt_item)) continue;
    +        if (scalar != 1.0f) cvt_deltas[idx] += unpacked_deltas[i] * scalar ;
    +        else cvt_deltas[idx] += unpacked_deltas[i];
    +      }
    +    } while (iterator.move_to_next ());
    +
    +    return true;
    +  }
    +
    +  static bool add_cvt_and_apply_deltas (hb_subset_plan_t *plan,
    +                                        const TupleVariationData *tuple_var_data,
    +                                        const void *base)
    +  {
    +    const hb_tag_t cvt = HB_TAG('c','v','t',' ');
    +    hb_blob_t *cvt_blob = hb_face_reference_table (plan->source, cvt);
    +    hb_blob_t *cvt_prime_blob = hb_blob_copy_writable_or_fail (cvt_blob);
    +    hb_blob_destroy (cvt_blob);
    +
    +    if (unlikely (!cvt_prime_blob))
    +      return false;
    +
    +    unsigned cvt_blob_length = hb_blob_get_length (cvt_prime_blob);
    +    unsigned num_cvt_item = cvt_blob_length / FWORD::static_size;
    +
    +    hb_vector_t cvt_deltas;
    +    if (unlikely (!cvt_deltas.resize (num_cvt_item)))
    +    {
    +      hb_blob_destroy (cvt_prime_blob);
    +      return false;
    +    }
    +    hb_memset (cvt_deltas.arrayZ, 0, cvt_deltas.get_size ());
    +
    +    if (!calculate_cvt_deltas (plan->normalized_coords.length, plan->normalized_coords.as_array (),
    +                               num_cvt_item, tuple_var_data, base, cvt_deltas))
    +    {
    +      hb_blob_destroy (cvt_prime_blob);
    +      return false;
    +    }
    +
    +    FWORD *cvt_prime = (FWORD *) hb_blob_get_data_writable (cvt_prime_blob, nullptr);
    +    for (unsigned i = 0; i < num_cvt_item; i++)
    +      cvt_prime[i] += (int) roundf (cvt_deltas[i]);
    +
    +    bool success = plan->add_table (cvt, cvt_prime_blob);
    +    hb_blob_destroy (cvt_prime_blob);
    +    return success;
    +  }
    +
    +  protected:
    +  FixedVersion<>version;                /* Version of the CVT variation table
    +                                         * initially set to 0x00010000u */
    +  TupleVariationData tupleVariationData; /* TupleVariationDate for cvar table */
    +  public:
    +  DEFINE_SIZE_MIN (8);
    +};
    +
    +} /* namespace OT */
    +
    +
    +#endif /* HB_OT_VAR_CVAR_TABLE_HH */
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh
    index 2deae640fd3..caf4a1cf406 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh
    @@ -29,6 +29,7 @@
     #define HB_OT_VAR_GVAR_TABLE_HH
     
     #include "hb-open-type.hh"
    +#include "hb-ot-var-common.hh"
     
     /*
      * gvar -- Glyph Variation Table
    @@ -90,311 +91,8 @@ struct contour_point_vector_t : hb_vector_t
       }
     };
     
    -/* https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader */
    -struct TupleVariationHeader
    -{
    -  unsigned get_size (unsigned axis_count) const
    -  { return min_size + get_all_tuples (axis_count).get_size (); }
    -
    -  unsigned get_data_size () const { return varDataSize; }
    -
    -  const TupleVariationHeader &get_next (unsigned axis_count) const
    -  { return StructAtOffset (this, get_size (axis_count)); }
    -
    -  float calculate_scalar (hb_array_t coords, unsigned int coord_count,
    -                          const hb_array_t shared_tuples) const
    -  {
    -    hb_array_t peak_tuple;
    -
    -    if (has_peak ())
    -      peak_tuple = get_peak_tuple (coord_count);
    -    else
    -    {
    -      unsigned int index = get_index ();
    -      if (unlikely (index * coord_count >= shared_tuples.length))
    -        return 0.f;
    -      peak_tuple = shared_tuples.sub_array (coord_count * index, coord_count);
    -    }
    -
    -    hb_array_t start_tuple;
    -    hb_array_t end_tuple;
    -    if (has_intermediate ())
    -    {
    -      start_tuple = get_start_tuple (coord_count);
    -      end_tuple = get_end_tuple (coord_count);
    -    }
    -
    -    float scalar = 1.f;
    -    for (unsigned int i = 0; i < coord_count; i++)
    -    {
    -      int v = coords[i];
    -      int peak = peak_tuple[i].to_int ();
    -      if (!peak || v == peak) continue;
    -
    -      if (has_intermediate ())
    -      {
    -        int start = start_tuple[i].to_int ();
    -        int end = end_tuple[i].to_int ();
    -        if (unlikely (start > peak || peak > end ||
    -                      (start < 0 && end > 0 && peak))) continue;
    -        if (v < start || v > end) return 0.f;
    -        if (v < peak)
    -        { if (peak != start) scalar *= (float) (v - start) / (peak - start); }
    -        else
    -        { if (peak != end) scalar *= (float) (end - v) / (end - peak); }
    -      }
    -      else if (!v || v < hb_min (0, peak) || v > hb_max (0, peak)) return 0.f;
    -      else
    -        scalar *= (float) v / peak;
    -    }
    -    return scalar;
    -  }
    -
    -  bool           has_peak () const { return tupleIndex & TuppleIndex::EmbeddedPeakTuple; }
    -  bool   has_intermediate () const { return tupleIndex & TuppleIndex::IntermediateRegion; }
    -  bool has_private_points () const { return tupleIndex & TuppleIndex::PrivatePointNumbers; }
    -  unsigned      get_index () const { return tupleIndex & TuppleIndex::TupleIndexMask; }
    -
    -  protected:
    -  struct TuppleIndex : HBUINT16
    -  {
    -    enum Flags {
    -      EmbeddedPeakTuple   = 0x8000u,
    -      IntermediateRegion  = 0x4000u,
    -      PrivatePointNumbers = 0x2000u,
    -      TupleIndexMask      = 0x0FFFu
    -    };
    -
    -    DEFINE_SIZE_STATIC (2);
    -  };
    -
    -  hb_array_t get_all_tuples (unsigned axis_count) const
    -  { return StructAfter> (tupleIndex).as_array ((has_peak () + has_intermediate () * 2) * axis_count); }
    -  hb_array_t get_peak_tuple (unsigned axis_count) const
    -  { return get_all_tuples (axis_count).sub_array (0, axis_count); }
    -  hb_array_t get_start_tuple (unsigned axis_count) const
    -  { return get_all_tuples (axis_count).sub_array (has_peak () * axis_count, axis_count); }
    -  hb_array_t get_end_tuple (unsigned axis_count) const
    -  { return get_all_tuples (axis_count).sub_array (has_peak () * axis_count + axis_count, axis_count); }
    -
    -  HBUINT16      varDataSize;    /* The size in bytes of the serialized
    -                                 * data for this tuple variation table. */
    -  TuppleIndex   tupleIndex;     /* A packed field. The high 4 bits are flags (see below).
    -                                   The low 12 bits are an index into a shared tuple
    -                                   records array. */
    -  /* UnsizedArrayOf peakTuple - optional */
    -                                /* Peak tuple record for this tuple variation table — optional,
    -                                 * determined by flags in the tupleIndex value.
    -                                 *
    -                                 * Note that this must always be included in the 'cvar' table. */
    -  /* UnsizedArrayOf intermediateStartTuple - optional */
    -                                /* Intermediate start tuple record for this tuple variation table — optional,
    -                                   determined by flags in the tupleIndex value. */
    -  /* UnsizedArrayOf intermediateEndTuple - optional */
    -                                /* Intermediate end tuple record for this tuple variation table — optional,
    -                                 * determined by flags in the tupleIndex value. */
    -  public:
    -  DEFINE_SIZE_MIN (4);
    -};
    -
    -struct GlyphVariationData
    -{
    -  const TupleVariationHeader &get_tuple_var_header (void) const
    -  { return StructAfter (data); }
    -
    -  struct tuple_iterator_t
    -  {
    -    void init (hb_bytes_t var_data_bytes_, unsigned int axis_count_)
    -    {
    -      var_data_bytes = var_data_bytes_;
    -      var_data = var_data_bytes_.as ();
    -      index = 0;
    -      axis_count = axis_count_;
    -      current_tuple = &var_data->get_tuple_var_header ();
    -      data_offset = 0;
    -    }
    -
    -    bool get_shared_indices (hb_vector_t &shared_indices /* OUT */)
    -    {
    -      if (var_data->has_shared_point_numbers ())
    -      {
    -        const HBUINT8 *base = &(var_data+var_data->data);
    -        const HBUINT8 *p = base;
    -        if (!unpack_points (p, shared_indices, (const HBUINT8 *) (var_data_bytes.arrayZ + var_data_bytes.length))) return false;
    -        data_offset = p - base;
    -      }
    -      return true;
    -    }
    -
    -    bool is_valid () const
    -    {
    -      return (index < var_data->tupleVarCount.get_count ()) &&
    -             var_data_bytes.check_range (current_tuple, TupleVariationHeader::min_size) &&
    -             var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (),
    -                                                                current_tuple->get_size (axis_count)));
    -    }
    -
    -    bool move_to_next ()
    -    {
    -      data_offset += current_tuple->get_data_size ();
    -      current_tuple = ¤t_tuple->get_next (axis_count);
    -      index++;
    -      return is_valid ();
    -    }
    -
    -    const HBUINT8 *get_serialized_data () const
    -    { return &(var_data+var_data->data) + data_offset; }
    -
    -    private:
    -    const GlyphVariationData *var_data;
    -    unsigned int index;
    -    unsigned int axis_count;
    -    unsigned int data_offset;
    -
    -    public:
    -    hb_bytes_t var_data_bytes;
    -    const TupleVariationHeader *current_tuple;
    -  };
    -
    -  static bool get_tuple_iterator (hb_bytes_t var_data_bytes, unsigned axis_count,
    -                                  hb_vector_t &shared_indices /* OUT */,
    -                                  tuple_iterator_t *iterator /* OUT */)
    -  {
    -    iterator->init (var_data_bytes, axis_count);
    -    if (!iterator->get_shared_indices (shared_indices))
    -      return false;
    -    return iterator->is_valid ();
    -  }
    -
    -  bool has_shared_point_numbers () const { return tupleVarCount.has_shared_point_numbers (); }
    -
    -  static bool unpack_points (const HBUINT8 *&p /* IN/OUT */,
    -                             hb_vector_t &points /* OUT */,
    -                             const HBUINT8 *end)
    -  {
    -    enum packed_point_flag_t
    -    {
    -      POINTS_ARE_WORDS     = 0x80,
    -      POINT_RUN_COUNT_MASK = 0x7F
    -    };
    -
    -    if (unlikely (p + 1 > end)) return false;
    -
    -    unsigned count = *p++;
    -    if (count & POINTS_ARE_WORDS)
    -    {
    -      if (unlikely (p + 1 > end)) return false;
    -      count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++;
    -    }
    -    if (unlikely (!points.resize (count, false))) return false;
    -
    -    unsigned n = 0;
    -    unsigned i = 0;
    -    while (i < count)
    -    {
    -      if (unlikely (p + 1 > end)) return false;
    -      unsigned control = *p++;
    -      unsigned run_count = (control & POINT_RUN_COUNT_MASK) + 1;
    -      if (unlikely (i + run_count > count)) return false;
    -      unsigned j;
    -      if (control & POINTS_ARE_WORDS)
    -      {
    -        if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
    -        for (j = 0; j < run_count; j++, i++)
    -        {
    -          n += *(const HBUINT16 *)p;
    -          points.arrayZ[i] = n;
    -          p += HBUINT16::static_size;
    -        }
    -      }
    -      else
    -      {
    -        if (unlikely (p + run_count > end)) return false;
    -        for (j = 0; j < run_count; j++, i++)
    -        {
    -          n += *p++;
    -          points.arrayZ[i] = n;
    -        }
    -      }
    -    }
    -    return true;
    -  }
    -
    -  static bool unpack_deltas (const HBUINT8 *&p /* IN/OUT */,
    -                             hb_vector_t &deltas /* IN/OUT */,
    -                             const HBUINT8 *end)
    -  {
    -    enum packed_delta_flag_t
    -    {
    -      DELTAS_ARE_ZERO      = 0x80,
    -      DELTAS_ARE_WORDS     = 0x40,
    -      DELTA_RUN_COUNT_MASK = 0x3F
    -    };
    -
    -    unsigned i = 0;
    -    unsigned count = deltas.length;
    -    while (i < count)
    -    {
    -      if (unlikely (p + 1 > end)) return false;
    -      unsigned control = *p++;
    -      unsigned run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
    -      if (unlikely (i + run_count > count)) return false;
    -      unsigned j;
    -      if (control & DELTAS_ARE_ZERO)
    -      {
    -        for (j = 0; j < run_count; j++, i++)
    -          deltas.arrayZ[i] = 0;
    -      }
    -      else if (control & DELTAS_ARE_WORDS)
    -      {
    -        if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
    -        for (j = 0; j < run_count; j++, i++)
    -        {
    -          deltas.arrayZ[i] = * (const HBINT16 *) p;
    -          p += HBUINT16::static_size;
    -        }
    -      }
    -      else
    -      {
    -        if (unlikely (p + run_count > end)) return false;
    -        for (j = 0; j < run_count; j++, i++)
    -        {
    -          deltas.arrayZ[i] = * (const HBINT8 *) p++;
    -        }
    -      }
    -    }
    -    return true;
    -  }
    -
    -  bool has_data () const { return tupleVarCount; }
    -
    -  protected:
    -  struct TupleVarCount : HBUINT16
    -  {
    -    bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers); }
    -    unsigned int get_count () const { return (*this) & CountMask; }
    -
    -    protected:
    -    enum Flags
    -    {
    -      SharedPointNumbers= 0x8000u,
    -      CountMask         = 0x0FFFu
    -    };
    -    public:
    -    DEFINE_SIZE_STATIC (2);
    -  };
    -
    -  TupleVarCount tupleVarCount;  /* A packed field. The high 4 bits are flags, and the
    -                                 * low 12 bits are the number of tuple variation tables
    -                                 * for this glyph. The number of tuple variation tables
    -                                 * can be any number between 1 and 4095. */
    -  Offset16To
    -                data;           /* Offset from the start of the GlyphVariationData table
    -                                 * to the serialized data. */
    -  /* TupleVariationHeader tupleVariationHeaders[] *//* Array of tuple variation headers. */
    -  public:
    -  DEFINE_SIZE_MIN (4);
    -};
    +struct GlyphVariationData : TupleVariationData
    +{};
     
     struct gvar
     {
    @@ -406,8 +104,8 @@ struct gvar
         return_trace (c->check_struct (this) && (version.major == 1) &&
                       sharedTuples.sanitize (c, this, axisCount * sharedTupleCount) &&
                       (is_long_offset () ?
    -                     c->check_array (get_long_offset_array (), glyphCount+1) :
    -                     c->check_array (get_short_offset_array (), glyphCount+1)));
    +                     c->check_array (get_long_offset_array (), c->get_num_glyphs () + 1) :
    +                     c->check_array (get_short_offset_array (), c->get_num_glyphs () + 1)));
       }
     
       /* GlyphVariationData not sanitized here; must be checked while accessing each glyph variation data */
    @@ -418,6 +116,8 @@ struct gvar
       {
         TRACE_SUBSET (this);
     
    +    unsigned glyph_count = version.to_int () ? c->plan->source->get_num_glyphs () : 0;
    +
         gvar *out = c->serializer->allocate_min ();
         if (unlikely (!out)) return_trace (false);
     
    @@ -427,7 +127,7 @@ struct gvar
         out->sharedTupleCount = sharedTupleCount;
     
         unsigned int num_glyphs = c->plan->num_output_glyphs ();
    -    out->glyphCount = num_glyphs;
    +    out->glyphCountX = hb_min (0xFFFFu, num_glyphs);
     
         unsigned int subset_data_size = 0;
         for (hb_codepoint_t gid = (c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE) ? 0 : 1;
    @@ -436,7 +136,7 @@ struct gvar
         {
           hb_codepoint_t old_gid;
           if (!c->plan->old_gid_for_new_gid (gid, &old_gid)) continue;
    -      subset_data_size += get_glyph_var_data_bytes (c->source_blob, old_gid).length;
    +      subset_data_size += get_glyph_var_data_bytes (c->source_blob, glyph_count, old_gid).length;
         }
     
         bool long_offset = subset_data_size & ~0xFFFFu;
    @@ -468,7 +168,9 @@ struct gvar
         {
           hb_codepoint_t old_gid;
           hb_bytes_t var_data_bytes = c->plan->old_gid_for_new_gid (gid, &old_gid)
    -                                ? get_glyph_var_data_bytes (c->source_blob, old_gid)
    +                                ? get_glyph_var_data_bytes (c->source_blob,
    +                                                            glyph_count,
    +                                                            old_gid)
                                     : hb_bytes_t ();
     
           if (long_offset)
    @@ -490,10 +192,12 @@ struct gvar
       }
     
       protected:
    -  const hb_bytes_t get_glyph_var_data_bytes (hb_blob_t *blob, hb_codepoint_t glyph) const
    +  const hb_bytes_t get_glyph_var_data_bytes (hb_blob_t *blob,
    +                                             unsigned glyph_count,
    +                                             hb_codepoint_t glyph) const
       {
    -    unsigned start_offset = get_offset (glyph);
    -    unsigned end_offset = get_offset (glyph+1);
    +    unsigned start_offset = get_offset (glyph_count, glyph);
    +    unsigned end_offset = get_offset (glyph_count, glyph+1);
         if (unlikely (end_offset < start_offset)) return hb_bytes_t ();
         unsigned length = end_offset - start_offset;
         hb_bytes_t var_data = blob->as_bytes ().sub_array (((unsigned) dataZ) + start_offset, length);
    @@ -502,9 +206,9 @@ struct gvar
     
       bool is_long_offset () const { return flags & 1; }
     
    -  unsigned get_offset (unsigned i) const
    +  unsigned get_offset (unsigned glyph_count, unsigned i) const
       {
    -    if (unlikely (i > glyphCount)) return 0;
    +    if (unlikely (i > glyph_count)) return 0;
         _hb_compiler_memory_r_barrier ();
         return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2;
       }
    @@ -516,7 +220,38 @@ struct gvar
       struct accelerator_t
       {
         accelerator_t (hb_face_t *face)
    -    { table = hb_sanitize_context_t ().reference_table (face); }
    +    {
    +      table = hb_sanitize_context_t ().reference_table (face);
    +      /* If sanitize failed, set glyphCount to 0. */
    +      glyphCount = table->version.to_int () ? face->get_num_glyphs () : 0;
    +
    +      /* For shared tuples that only have one axis active, shared the index of
    +       * that axis as a cache. This will speed up caclulate_scalar() a lot
    +       * for fonts with lots of axes and many "monovar" tuples. */
    +      hb_array_t shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount);
    +      unsigned count = table->sharedTupleCount;
    +      if (unlikely (!shared_tuple_active_idx.resize (count, false))) return;
    +      unsigned axis_count = table->axisCount;
    +      for (unsigned i = 0; i < count; i++)
    +      {
    +        hb_array_t tuple = shared_tuples.sub_array (axis_count * i, axis_count);
    +        int idx = -1;
    +        for (unsigned j = 0; j < axis_count; j++)
    +        {
    +          F2DOT14 peak = tuple.arrayZ[j];
    +          if (peak.to_int () != 0)
    +          {
    +            if (idx != -1)
    +            {
    +              idx = -1;
    +              break;
    +            }
    +            idx = j;
    +          }
    +        }
    +        shared_tuple_active_idx[i] = idx;
    +      }
    +    }
         ~accelerator_t () { table.destroy (); }
     
         private:
    @@ -554,30 +289,26 @@ struct gvar
         {
           if (!coords) return true;
     
    -      if (unlikely (glyph >= table->glyphCount)) return true;
    +      if (unlikely (glyph >= glyphCount)) return true;
     
    -      hb_bytes_t var_data_bytes = table->get_glyph_var_data_bytes (table.get_blob (), glyph);
    +      hb_bytes_t var_data_bytes = table->get_glyph_var_data_bytes (table.get_blob (), glyphCount, glyph);
           if (!var_data_bytes.as ()->has_data ()) return true;
           hb_vector_t shared_indices;
           GlyphVariationData::tuple_iterator_t iterator;
           if (!GlyphVariationData::get_tuple_iterator (var_data_bytes, table->axisCount,
    +                                                   var_data_bytes.arrayZ,
                                                        shared_indices, &iterator))
             return true; /* so isn't applied at all */
     
           /* Save original points for inferred delta calculation */
    -      contour_point_vector_t orig_points_vec;
    -      orig_points_vec.extend (points);
    -      if (unlikely (orig_points_vec.in_error ())) return false;
    +      contour_point_vector_t orig_points_vec; // Populated lazily
           auto orig_points = orig_points_vec.as_array ();
     
    -      contour_point_vector_t deltas_vec; /* flag is used to indicate referenced point */
    -      if (unlikely (!deltas_vec.resize (points.length, false))) return false;
    +      /* flag is used to indicate referenced point */
    +      contour_point_vector_t deltas_vec; // Populated lazily
           auto deltas = deltas_vec.as_array ();
     
    -      hb_vector_t end_points;
    -      for (unsigned i = 0; i < points.length; ++i)
    -        if (points.arrayZ[i].is_end_point)
    -          end_points.push (i);
    +      hb_vector_t end_points; // Populated lazily
     
           unsigned num_coords = table->axisCount;
           hb_array_t shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount);
    @@ -585,15 +316,23 @@ struct gvar
           hb_vector_t private_indices;
           hb_vector_t x_deltas;
           hb_vector_t y_deltas;
    +      bool flush = false;
           do
           {
    -        float scalar = iterator.current_tuple->calculate_scalar (coords, num_coords, shared_tuples);
    +        float scalar = iterator.current_tuple->calculate_scalar (coords, num_coords, shared_tuples,
    +                                                                 shared_tuple_active_idx.in_error () ? nullptr : &shared_tuple_active_idx);
             if (scalar == 0.f) continue;
             const HBUINT8 *p = iterator.get_serialized_data ();
             unsigned int length = iterator.current_tuple->get_data_size ();
             if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
               return false;
     
    +        if (!deltas)
    +        {
    +          if (unlikely (!deltas_vec.resize (points.length))) return false;
    +          deltas = deltas_vec.as_array ();
    +        }
    +
             const HBUINT8 *end = p + length;
     
             bool has_private_points = iterator.current_tuple->has_private_points ();
    @@ -609,16 +348,37 @@ struct gvar
             if (unlikely (!y_deltas.resize (num_deltas, false))) return false;
             if (unlikely (!GlyphVariationData::unpack_deltas (p, y_deltas, end))) return false;
     
    -        hb_memset (deltas.arrayZ, 0, deltas.get_size ());
    +        if (!apply_to_all)
    +        {
    +          if (!orig_points)
    +          {
    +            orig_points_vec.extend (points);
    +            if (unlikely (orig_points_vec.in_error ())) return false;
    +            orig_points = orig_points_vec.as_array ();
    +          }
    +
    +          if (flush)
    +          {
    +            for (unsigned int i = 0; i < points.length; i++)
    +              points.arrayZ[i].translate (deltas.arrayZ[i]);
    +            flush = false;
    +
    +          }
    +          hb_memset (deltas.arrayZ, 0, deltas.get_size ());
    +        }
     
    -        unsigned ref_points = 0;
             if (scalar != 1.0f)
               for (unsigned int i = 0; i < num_deltas; i++)
               {
    -            unsigned int pt_index = apply_to_all ? i : indices[i];
    -            if (unlikely (pt_index >= deltas.length)) continue;
    +            unsigned int pt_index;
    +            if (apply_to_all)
    +              pt_index = i;
    +            else
    +            {
    +              pt_index = indices[i];
    +              if (unlikely (pt_index >= deltas.length)) continue;
    +            }
                 auto &delta = deltas.arrayZ[pt_index];
    -            ref_points += !delta.flag;
                 delta.flag = 1;     /* this point is referenced, i.e., explicit deltas specified */
                 delta.x += x_deltas.arrayZ[i] * scalar;
                 delta.y += y_deltas.arrayZ[i] * scalar;
    @@ -626,23 +386,34 @@ struct gvar
             else
               for (unsigned int i = 0; i < num_deltas; i++)
               {
    -            unsigned int pt_index = apply_to_all ? i : indices[i];
    -            if (unlikely (pt_index >= deltas.length)) continue;
    +            unsigned int pt_index;
    +            if (apply_to_all)
    +              pt_index = i;
    +            else
    +            {
    +              pt_index = indices[i];
    +              if (unlikely (pt_index >= deltas.length)) continue;
    +            }
                 auto &delta = deltas.arrayZ[pt_index];
    -            ref_points += !delta.flag;
                 delta.flag = 1;     /* this point is referenced, i.e., explicit deltas specified */
                 delta.x += x_deltas.arrayZ[i];
                 delta.y += y_deltas.arrayZ[i];
               }
     
             /* infer deltas for unreferenced points */
    -        if (ref_points && ref_points < orig_points.length)
    +        if (!apply_to_all)
             {
    -          unsigned start_point = 0;
    -          for (unsigned c = 0; c < end_points.length; c++)
    +          if (!end_points)
               {
    -            unsigned end_point = end_points.arrayZ[c];
    +            for (unsigned i = 0; i < points.length; ++i)
    +              if (points.arrayZ[i].is_end_point)
    +                end_points.push (i);
    +            if (unlikely (end_points.in_error ())) return false;
    +          }
     
    +          unsigned start_point = 0;
    +          for (unsigned end_point : end_points)
    +          {
                 /* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */
                 unsigned unref_count = 0;
                 for (unsigned i = start_point; i < end_point + 1; i++)
    @@ -689,14 +460,14 @@ struct gvar
               }
             }
     
    -        /* apply specified / inferred deltas to points */
    -        for (unsigned int i = 0; i < points.length; i++)
    -        {
    -          points.arrayZ[i].x += deltas.arrayZ[i].x;
    -          points.arrayZ[i].y += deltas.arrayZ[i].y;
    -        }
    +        flush = true;
    +
           } while (iterator.move_to_next ());
     
    +      if (flush)
    +        for (unsigned int i = 0; i < points.length; i++)
    +          points.arrayZ[i].translate (deltas.arrayZ[i]);
    +
           return true;
         }
     
    @@ -704,6 +475,8 @@ struct gvar
     
         private:
         hb_blob_ptr_t table;
    +    unsigned glyphCount;
    +    hb_vector_t shared_tuple_active_idx;
       };
     
       protected:
    @@ -719,7 +492,7 @@ struct gvar
       NNOffset32To>
                     sharedTuples;   /* Offset from the start of this table to the shared tuple records.
                                      * Array of tuple records shared across all glyph variation data tables. */
    -  HBUINT16      glyphCount;     /* The number of glyphs in this font. This must match the number of
    +  HBUINT16      glyphCountX;    /* The number of glyphs in this font. This must match the number of
                                      * glyphs stored elsewhere in the font. */
       HBUINT16      flags;          /* Bit-field that gives the format of the offset array that follows.
                                      * If bit 0 is clear, the offsets are uint16; if bit 0 is set, the
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-hvar-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-hvar-table.hh
    index 3590dfa4ee8..9fc3752b05a 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-hvar-table.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-hvar-table.hh
    @@ -185,12 +185,8 @@ struct hvarvvar_subset_plan_t
         {
           retain_adv_map = plan->flags & HB_SUBSET_FLAGS_RETAIN_GIDS;
           outer_map.add (0);
    -      for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++)
    -      {
    -        hb_codepoint_t old_gid;
    -        if (plan->old_gid_for_new_gid (gid, &old_gid))
    -          inner_sets[0]->add (old_gid);
    -      }
    +      for (hb_codepoint_t old_gid : plan->glyphset()->iter())
    +        inner_sets[0]->add (old_gid);
           hb_set_union (adv_set, inner_sets[0]);
         }
     
    @@ -202,10 +198,12 @@ struct hvarvvar_subset_plan_t
         if (retain_adv_map)
         {
           for (hb_codepoint_t gid = 0; gid < plan->num_output_glyphs (); gid++)
    +      {
             if (inner_sets[0]->has (gid))
               inner_maps[0].add (gid);
             else
               inner_maps[0].skip ();
    +      }
         }
         else
         {
    @@ -265,6 +263,9 @@ struct HVARVVAR
                       rsbMap.sanitize (c, this));
       }
     
    +  const VariationStore& get_var_store () const
    +  { return this+varStore; }
    +
       void listup_index_maps (hb_vector_t &index_maps) const
       {
         index_maps.push (&(this+advMap));
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-outline.cc b/src/java.desktop/share/native/libharfbuzz/hb-outline.cc
    index e8df9cb6670..a0a6ea156c3 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-outline.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-outline.cc
    @@ -4,7 +4,6 @@
      * Copyright © 2005  Werner Lemberg
      * Copyright © 2013-2015  Alexei Podtelezhnikov
      *
    - *
      *  This is part of HarfBuzz, a text shaping library.
      *
      * Permission is hereby granted, without written agreement and without
    @@ -85,7 +84,7 @@ void hb_outline_t::replay (hb_draw_funcs_t *pen, void *pen_data) const
       }
     }
     
    -float hb_outline_t::area () const
    +float hb_outline_t::control_area () const
     {
       float a = 0;
       unsigned first = 0;
    @@ -118,7 +117,7 @@ void hb_outline_t::embolden (float x_strength, float y_strength,
       x_strength /= 2.f;
       y_strength /= 2.f;
     
    -  bool orientation_negative = area () < 0;
    +  bool orientation_negative = control_area () < 0;
     
       signed first = 0;
       for (unsigned c = 0; c < contours.length; c++)
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-outline.hh b/src/java.desktop/share/native/libharfbuzz/hb-outline.hh
    index a2eba122c9f..c44625da2e1 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-outline.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-outline.hh
    @@ -68,7 +68,7 @@ struct hb_outline_t
       void reset () { points.shrink (0, false); contours.resize (0); }
     
       HB_INTERNAL void replay (hb_draw_funcs_t *pen, void *pen_data) const;
    -  HB_INTERNAL float area () const;
    +  HB_INTERNAL float control_area () const;
       HB_INTERNAL void embolden (float x_strength, float y_strength,
                                  float x_shift, float y_shift);
     
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-paint.h b/src/java.desktop/share/native/libharfbuzz/hb-paint.h
    index 9421e02c73a..96fec72ad77 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-paint.h
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-paint.h
    @@ -616,7 +616,7 @@ typedef enum {
       HB_PAINT_COMPOSITE_MODE_HSL_HUE,
       HB_PAINT_COMPOSITE_MODE_HSL_SATURATION,
       HB_PAINT_COMPOSITE_MODE_HSL_COLOR,
    -  HB_PAINT_COMPOSITE_MODE_HSL_LUMINOSITY,
    +  HB_PAINT_COMPOSITE_MODE_HSL_LUMINOSITY
     } hb_paint_composite_mode_t;
     
     /**
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-paint.hh b/src/java.desktop/share/native/libharfbuzz/hb-paint.hh
    index 3fda7bd04eb..2f81b5f359d 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-paint.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-paint.hh
    @@ -203,8 +203,8 @@ struct hb_paint_funcs_t
         if (!a)
           return false;
     
    -    float cc = cosf (a * (float) M_PI);
    -    float ss = sinf (a * (float) M_PI);
    +    float cc = cosf (a * HB_PI);
    +    float ss = sinf (a * HB_PI);
         push_transform (paint_data, cc, ss, -ss, cc, 0.f, 0.f);
         return true;
       }
    @@ -216,8 +216,8 @@ struct hb_paint_funcs_t
         if (!sx && !sy)
           return false;
     
    -    float x = tanf (-sx * (float) M_PI);
    -    float y = tanf (+sy * (float) M_PI);
    +    float x = tanf (-sx * HB_PI);
    +    float y = tanf (+sy * HB_PI);
         push_transform (paint_data, 1.f, y, x, 1.f, 0.f, 0.f);
         return true;
       }
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-pool.hh b/src/java.desktop/share/native/libharfbuzz/hb-pool.hh
    index f9d50cd0b1c..66de27f8fef 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-pool.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-pool.hh
    @@ -29,7 +29,16 @@
     
     #include "hb.hh"
     
    -/* Memory pool for persistent allocation of small objects. */
    +/* Memory pool for persistent allocation of small objects.
    + *
    + * Some AI musings on this, not necessarily true:
    + *
    + * This is a very simple implementation, but it's good enough for our
    + * purposes.  It's not thread-safe.  It's not very fast.  It's not
    + * very memory efficient.  It's not very cache efficient.  It's not
    + * very anything efficient.  But it's simple and it works.  And it's
    + * good enough for our purposes.  If you need something more
    + * sophisticated, use a real allocator.  Or use a real language. */
     
     template 
     struct hb_pool_t
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-priority-queue.hh b/src/java.desktop/share/native/libharfbuzz/hb-priority-queue.hh
    index 93a7842eb0a..bf1b282d3d8 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-priority-queue.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-priority-queue.hh
    @@ -35,6 +35,12 @@
      *
      * Priority queue implemented as a binary heap. Supports extract minimum
      * and insert operations.
    + *
    + * The priority queue is implemented as a binary heap, which is a complete
    + * binary tree. The root of the tree is the minimum element. The heap
    + * property is that the priority of a node is less than or equal to the
    + * priority of its children. The heap is stored in an array, with the
    + * children of node i stored at indices 2i + 1 and 2i + 2.
      */
     struct hb_priority_queue_t
     {
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-sanitize.hh b/src/java.desktop/share/native/libharfbuzz/hb-sanitize.hh
    index b5975bd652b..5949afbd46f 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-sanitize.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-sanitize.hh
    @@ -228,6 +228,18 @@ struct hb_sanitize_context_t :
     
       unsigned get_edit_count () { return edit_count; }
     
    +
    +  bool check_ops(unsigned count)
    +  {
    +    /* Avoid underflow */
    +    if (unlikely (this->max_ops < 0 || count >= (unsigned) this->max_ops))
    +    {
    +      this->max_ops = -1;
    +      return false;
    +    }
    +    return (this->max_ops -= (int) count) > 0;
    +  }
    +
       bool check_range (const void *base,
                         unsigned int len) const
       {
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-shape.cc b/src/java.desktop/share/native/libharfbuzz/hb-shape.cc
    index 0456e1ac0ab..6dbbf7306c7 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-shape.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-shape.cc
    @@ -196,4 +196,250 @@ hb_shape (hb_font_t           *font,
     }
     
     
    +#ifdef HB_EXPERIMENTAL_API
    +
    +static float
    +buffer_advance (hb_buffer_t *buffer)
    +{
    +  float a = 0;
    +  auto *pos = buffer->pos;
    +  unsigned count = buffer->len;
    +  if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
    +    for (unsigned i = 0; i < count; i++)
    +      a += pos[i].x_advance;
    +  else
    +    for (unsigned i = 0; i < count; i++)
    +      a += pos[i].y_advance;
    +  return a;
    +}
    +
    +static void
    +reset_buffer (hb_buffer_t *buffer,
    +              hb_array_t text)
    +{
    +  assert (buffer->ensure (text.length));
    +  buffer->have_positions = false;
    +  buffer->len = text.length;
    +  memcpy (buffer->info, text.arrayZ, text.length * sizeof (buffer->info[0]));
    +  hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
    +}
    +
    +/**
    + * hb_shape_justify:
    + * @font: a mutable #hb_font_t to use for shaping
    + * @buffer: an #hb_buffer_t to shape
    + * @features: (array length=num_features) (nullable): an array of user
    + *    specified #hb_feature_t or `NULL`
    + * @num_features: the length of @features array
    + * @shaper_list: (array zero-terminated=1) (nullable): a `NULL`-terminated
    + *    array of shapers to use or `NULL`
    + * @min_target_advance: Minimum advance width/height to aim for.
    + * @max_target_advance: Maximum advance width/height to aim for.
    + * @advance: (inout): Input/output advance width/height of the buffer.
    + * @var_tag: (out): Variation-axis tag used for justification.
    + * @var_value: (out): Variation-axis value used to reach target justification.
    + *
    + * See hb_shape_full() for basic details. If @shaper_list is not `NULL`, the specified
    + * shapers will be used in the given order, otherwise the default shapers list
    + * will be used.
    + *
    + * In addition, justify the shaping results such that the shaping results reach
    + * the target advance width/height, depending on the buffer direction.
    + *
    + * If the advance of the buffer shaped with hb_shape_full() is already known,
    + * put that in *advance. Otherwise set *advance to zero.
    + *
    + * This API is currently experimental and will probably change in the future.
    + *
    + * Return value: false if all shapers failed, true otherwise
    + *
    + * XSince: EXPERIMENTAL
    + **/
    +hb_bool_t
    +hb_shape_justify (hb_font_t          *font,
    +                  hb_buffer_t        *buffer,
    +                  const hb_feature_t *features,
    +                  unsigned int        num_features,
    +                  const char * const *shaper_list,
    +                  float               min_target_advance,
    +                  float               max_target_advance,
    +                  float              *advance, /* IN/OUT */
    +                  hb_tag_t           *var_tag, /* OUT */
    +                  float              *var_value /* OUT */)
    +{
    +  // TODO Negative font scales?
    +
    +  /* If default advance already matches target, nothing to do. Shape and return. */
    +  if (min_target_advance <= *advance && *advance <= max_target_advance)
    +  {
    +    *var_tag = HB_TAG_NONE;
    +    *var_value = 0.0f;
    +    return hb_shape_full (font, buffer,
    +                          features, num_features,
    +                          shaper_list);
    +  }
    +
    +  hb_face_t *face = font->face;
    +
    +  /* Choose variation tag to use for justification. */
    +
    +  hb_tag_t tag = HB_TAG_NONE;
    +  hb_ot_var_axis_info_t axis_info;
    +
    +  hb_tag_t tags[] =
    +  {
    +    HB_TAG ('j','s','t','f'),
    +    HB_TAG ('w','d','t','h'),
    +  };
    +  for (unsigned i = 0; i < ARRAY_LENGTH (tags); i++)
    +    if (hb_ot_var_find_axis_info (face, tags[i], &axis_info))
    +    {
    +      tag = *var_tag = tags[i];
    +      break;
    +    }
    +
    +  /* If no suitable variation axis found, can't justify.  Just shape and return. */
    +  if (!tag)
    +  {
    +    *var_tag = HB_TAG_NONE;
    +    *var_value = 0.0f;
    +    if (hb_shape_full (font, buffer,
    +                       features, num_features,
    +                       shaper_list))
    +    {
    +      *advance = buffer_advance (buffer);
    +      return true;
    +    }
    +    else
    +      return false;
    +  }
    +
    +  /* Copy buffer text as we need it so we can shape multiple times. */
    +  unsigned text_len = buffer->len;
    +  auto *text_info = (hb_glyph_info_t *) hb_malloc (text_len * sizeof (buffer->info[0]));
    +  if (unlikely (text_len && !text_info))
    +    return false;
    +  hb_memcpy (text_info, buffer->info, text_len * sizeof (buffer->info[0]));
    +  auto text = hb_array (text_info, text_len);
    +
    +  /* If default advance was not provided to us, calculate it. */
    +  if (!*advance)
    +  {
    +    hb_font_set_variation (font, tag, axis_info.default_value);
    +    if (!hb_shape_full (font, buffer,
    +                        features, num_features,
    +                        shaper_list))
    +      return false;
    +    *advance = buffer_advance (buffer);
    +  }
    +
    +  /* If default advance already matches target, nothing to do. Shape and return.
    +   * Do this again, in case advance was just calculated.
    +   */
    +  if (min_target_advance <= *advance && *advance <= max_target_advance)
    +  {
    +    *var_tag = HB_TAG_NONE;
    +    *var_value = 0.0f;
    +    return true;
    +  }
    +
    +  /* Prepare for running the solver. */
    +  double a, b, ya, yb;
    +  if (*advance < min_target_advance)
    +  {
    +    /* Need to expand. */
    +    ya = (double) *advance;
    +    a = (double) axis_info.default_value;
    +    b = (double) axis_info.max_value;
    +
    +    /* Shape buffer for maximum expansion to use as other
    +     * starting point for the solver. */
    +    hb_font_set_variation (font, tag, (float) b);
    +    reset_buffer (buffer, text);
    +    if (!hb_shape_full (font, buffer,
    +                        features, num_features,
    +                        shaper_list))
    +      return false;
    +    yb = (double) buffer_advance (buffer);
    +    /* If the maximum expansion is less than max target,
    +     * there's nothing to solve for. Just return it. */
    +    if (yb <= (double) max_target_advance)
    +    {
    +      *var_value = (float) b;
    +      *advance = (float) yb;
    +      return true;
    +    }
    +  }
    +  else
    +  {
    +    /* Need to shrink. */
    +    yb = (double) *advance;
    +    a = (double) axis_info.min_value;
    +    b = (double) axis_info.default_value;
    +
    +    /* Shape buffer for maximum shrinkate to use as other
    +     * starting point for the solver. */
    +    hb_font_set_variation (font, tag, (float) a);
    +    reset_buffer (buffer, text);
    +    if (!hb_shape_full (font, buffer,
    +                        features, num_features,
    +                        shaper_list))
    +      return false;
    +    ya = (double) buffer_advance (buffer);
    +    /* If the maximum shrinkate is more than min target,
    +     * there's nothing to solve for. Just return it. */
    +    if (ya >= (double) min_target_advance)
    +    {
    +      *var_value = (float) a;
    +      *advance = (float) ya;
    +      return true;
    +    }
    +  }
    +
    +  /* Run the solver to find a var axis value that hits
    +   * the desired width. */
    +
    +  double epsilon = (b - a) / (1<<14);
    +  bool failed = false;
    +
    +  auto f = [&] (double x)
    +  {
    +    hb_font_set_variation (font, tag, (float) x);
    +    reset_buffer (buffer, text);
    +    if (unlikely (!hb_shape_full (font, buffer,
    +                                  features, num_features,
    +                                  shaper_list)))
    +    {
    +      failed = true;
    +      return (double) min_target_advance;
    +    }
    +
    +    double w = (double) buffer_advance (buffer);
    +    DEBUG_MSG (JUSTIFY, nullptr, "Trying '%c%c%c%c' axis parameter %f. Advance %g. Target: min %g max %g",
    +               HB_UNTAG (tag), x, w,
    +               (double) min_target_advance, (double) max_target_advance);
    +    return w;
    +  };
    +
    +  double y = 0;
    +  double itp = solve_itp (f,
    +                          a, b,
    +                          epsilon,
    +                          (double) min_target_advance, (double) max_target_advance,
    +                          ya, yb, y);
    +
    +  hb_free (text_info);
    +
    +  if (failed)
    +    return false;
    +
    +  *var_value = (float) itp;
    +  *advance = (float) y;
    +
    +  return true;
    +}
    +
    +#endif
    +
    +
     #endif
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-shape.h b/src/java.desktop/share/native/libharfbuzz/hb-shape.h
    index 90e7e754cb3..bf7eafd2b4f 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-shape.h
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-shape.h
    @@ -53,6 +53,18 @@ hb_shape_full (hb_font_t          *font,
                    unsigned int        num_features,
                    const char * const *shaper_list);
     
    +HB_EXTERN hb_bool_t
    +hb_shape_justify (hb_font_t          *font,
    +                  hb_buffer_t        *buffer,
    +                  const hb_feature_t *features,
    +                  unsigned int        num_features,
    +                  const char * const *shaper_list,
    +                  float               min_target_advance,
    +                  float               max_target_advance,
    +                  float              *advance, /* IN/OUT */
    +                  hb_tag_t           *var_tag, /* OUT */
    +                  float              *var_value /* OUT */);
    +
     HB_EXTERN const char **
     hb_shape_list_shapers (void);
     
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-shaper-list.hh b/src/java.desktop/share/native/libharfbuzz/hb-shaper-list.hh
    index 0d63933a766..4158b7094c9 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-shaper-list.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-shaper-list.hh
    @@ -39,7 +39,7 @@ HB_SHAPER_IMPLEMENT (graphite2)
     #endif
     
     #ifndef HB_NO_OT_SHAPE
    -HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */
    +HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main shaper. */
     #endif
     
     #ifdef HAVE_UNISCRIBE
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-static.cc b/src/java.desktop/share/native/libharfbuzz/hb-static.cc
    index 5f647c6ad9b..041d378bf92 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-static.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-static.cc
    @@ -36,9 +36,11 @@
     #include "OT/Color/COLR/COLR.hh"
     #include "hb-ot-glyf-table.hh"
     #include "hb-ot-head-table.hh"
    +#include "hb-ot-hmtx-table.hh"
     #include "hb-ot-maxp-table.hh"
     
     #ifndef HB_NO_VISIBILITY
    +#include "hb-ot-name-language-static.hh"
     
     uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
     /*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
    @@ -108,4 +110,26 @@ hb_face_t::load_upem () const
     }
     
     
    +#ifndef HB_NO_VAR
    +bool
    +_glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical,
    +                                             int *lsb)
    +{
    +  return font->face->table.glyf->get_leading_bearing_with_var_unscaled (font, glyph, is_vertical, lsb);
    +}
    +
    +unsigned
    +_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
    +{
    +  return font->face->table.glyf->get_advance_with_var_unscaled (font, glyph, is_vertical);
    +}
    +#endif
    +
    +bool
    +_glyf_get_leading_bearing_without_var_unscaled (hb_face_t *face, hb_codepoint_t gid, bool is_vertical, int *lsb)
    +{
    +  return face->table.glyf->get_leading_bearing_without_var_unscaled (gid, is_vertical, lsb);
    +}
    +
    +
     #endif
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-style.cc b/src/java.desktop/share/native/libharfbuzz/hb-style.cc
    index 97d256d16e3..20d4696b926 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-style.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-style.cc
    @@ -46,13 +46,13 @@
     static inline float
     _hb_angle_to_ratio (float a)
     {
    -  return tanf (a * float (-M_PI / 180.));
    +  return tanf (a * -HB_PI / 180.f);
     }
     
     static inline float
     _hb_ratio_to_angle (float r)
     {
    -  return atanf (r) * float (-180. / M_PI);
    +  return atanf (r) * -180.f / HB_PI;
     }
     
     /**
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc b/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc
    index 4dac92fe90f..3cdb89a17cd 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc
    @@ -71,7 +71,6 @@ hb_subset_input_t::hb_subset_input_t ()
       hb_tag_t default_no_subset_tables[] = {
         HB_TAG ('a', 'v', 'a', 'r'),
         HB_TAG ('g', 'a', 's', 'p'),
    -    HB_TAG ('c', 'v', 't', ' '),
         HB_TAG ('f', 'p', 'g', 'm'),
         HB_TAG ('p', 'r', 'e', 'p'),
         HB_TAG ('V', 'D', 'M', 'X'),
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc b/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc
    index 5a91a3babf8..be30601a413 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc
    @@ -36,8 +36,10 @@
     #include "hb-ot-layout-gpos-table.hh"
     #include "hb-ot-layout-gsub-table.hh"
     #include "hb-ot-cff1-table.hh"
    +#include "hb-ot-cff2-table.hh"
     #include "OT/Color/COLR/COLR.hh"
     #include "OT/Color/COLR/colrv1-closure.hh"
    +#include "OT/Color/CPAL/CPAL.hh"
     #include "hb-ot-var-fvar-table.hh"
     #include "hb-ot-var-avar-table.hh"
     #include "hb-ot-stat-table.hh"
    @@ -293,7 +295,7 @@ _closure_glyphs_lookups_features (hb_subset_plan_t   *plan,
                                   feature_record_cond_idx_map,
                                   feature_substitutes_map);
     
    -  if (table_tag == HB_OT_TAG_GSUB)
    +  if (table_tag == HB_OT_TAG_GSUB && !(plan->flags & HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE))
         hb_ot_layout_lookups_substitute_closure (plan->source,
                                                  &lookup_indices,
                                                  gids_to_retain);
    @@ -345,7 +347,10 @@ _get_hb_font_with_variations (const hb_subset_plan_t *plan)
       hb_font_t *font = hb_font_create (plan->source);
     
       hb_vector_t vars;
    -  vars.alloc (plan->user_axes_location.get_population ());
    +  if (!vars.alloc (plan->user_axes_location.get_population ())) {
    +    hb_font_destroy (font);
    +    return nullptr;
    +  }
     
       for (auto _ : plan->user_axes_location)
       {
    @@ -381,7 +386,13 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan)
       bool collect_delta = plan->pinned_at_default ? false : true;
       if (collect_delta)
       {
    -    font = _get_hb_font_with_variations (plan);
    +    if (unlikely (!plan->check_success (font = _get_hb_font_with_variations (plan)))) {
    +      hb_font_destroy (font);
    +      gdef.destroy ();
    +      gpos.destroy ();
    +      return;
    +    }
    +
         if (gdef->has_var_store ())
         {
           var_store = &(gdef->get_var_store ());
    @@ -555,9 +566,12 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
             if (plan->codepoint_to_glyph->has (cp))
               continue;
     
    -        hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
    -        plan->codepoint_to_glyph->set (cp, gid);
    -        plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
    +        hb_codepoint_t *gid;
    +        if (!unicode_glyphid_map->has(cp, &gid))
    +          continue;
    +
    +        plan->codepoint_to_glyph->set (cp, *gid);
    +        plan->unicode_to_new_gid_list.push (hb_pair (cp, *gid));
           }
           plan->unicode_to_new_gid_list.qsort ();
         }
    @@ -609,7 +623,7 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
     
       gids_to_retain->add (gid);
     
    -  for (auto item : glyf.glyph_for_gid (gid).get_composite_iterator ())
    +  for (auto &item : glyf.glyph_for_gid (gid).get_composite_iterator ())
         operation_count =
           _glyf_add_gid_and_children (glyf,
                                       item.get_gid (),
    @@ -617,9 +631,53 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
                                       operation_count,
                                       depth);
     
    +#ifndef HB_NO_VAR_COMPOSITES
    +  for (auto &item : glyf.glyph_for_gid (gid).get_var_composite_iterator ())
    +   {
    +    operation_count =
    +      _glyf_add_gid_and_children (glyf,
    +                                  item.get_gid (),
    +                                  gids_to_retain,
    +                                  operation_count,
    +                                  depth);
    +   }
    +#endif
    +
       return operation_count;
     }
     
    +static void
    +_nameid_closure (hb_subset_plan_t* plan,
    +                 hb_set_t* drop_tables)
    +{
    +#ifndef HB_NO_STYLE
    +  plan->source->table.STAT->collect_name_ids (&plan->user_axes_location, &plan->name_ids);
    +#endif
    +#ifndef HB_NO_VAR
    +  if (!plan->all_axes_pinned)
    +    plan->source->table.fvar->collect_name_ids (&plan->user_axes_location, &plan->name_ids);
    +#endif
    +#ifndef HB_NO_COLOR
    +  if (!drop_tables->has (HB_OT_TAG_CPAL))
    +    plan->source->table.CPAL->collect_name_ids (&plan->colr_palettes, &plan->name_ids);
    +#endif
    +
    +#ifndef HB_NO_SUBSET_LAYOUT
    +  if (!drop_tables->has (HB_OT_TAG_GPOS))
    +  {
    +    hb_blob_ptr_t gpos = plan->source_table ();
    +    gpos->collect_name_ids (&plan->gpos_features, &plan->name_ids);
    +    gpos.destroy ();
    +  }
    +  if (!drop_tables->has (HB_OT_TAG_GSUB))
    +  {
    +    hb_blob_ptr_t gsub = plan->source_table ();
    +    gsub->collect_name_ids (&plan->gsub_features, &plan->name_ids);
    +    gsub.destroy ();
    +  }
    +#endif
    +}
    +
     static void
     _populate_gids_to_retain (hb_subset_plan_t* plan,
                               hb_set_t* drop_tables)
    @@ -673,6 +731,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
     
       plan->_glyphset_colred = cur_glyphset;
     
    +  _nameid_closure (plan, drop_tables);
       /* Populate a full set of glyphs to retain by adding all referenced
        * composite glyphs. */
       if (glyf.has_data ())
    @@ -756,21 +815,6 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
       ;
     }
     
    -static void
    -_nameid_closure (hb_face_t *face,
    -                 hb_set_t  *nameids,
    -                 bool all_axes_pinned,
    -                 hb_hashmap_t *user_axes_location)
    -{
    -#ifndef HB_NO_STYLE
    -  face->table.STAT->collect_name_ids (user_axes_location, nameids);
    -#endif
    -#ifndef HB_NO_VAR
    -  if (!all_axes_pinned)
    -    face->table.fvar->collect_name_ids (user_axes_location, nameids);
    -#endif
    -}
    -
     #ifndef HB_NO_VAR
     static void
     _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
    @@ -783,12 +827,15 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
     
       bool has_avar = face->table.avar->has_data ();
       const OT::SegmentMaps *seg_maps = nullptr;
    +  unsigned avar_axis_count = 0;
       if (has_avar)
    +  {
         seg_maps = face->table.avar->get_segment_maps ();
    +    avar_axis_count = face->table.avar->get_axis_count();
    +  }
     
       bool axis_not_pinned = false;
       unsigned old_axis_idx = 0, new_axis_idx = 0;
    -  unsigned int i = 0;
       for (const auto& axis : axes)
       {
         hb_tag_t axis_tag = axis.get_axis_tag ();
    @@ -803,7 +850,7 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
         else
         {
           int normalized_v = axis.normalize_axis_value (plan->user_axes_location.get (axis_tag));
    -      if (has_avar && old_axis_idx < face->table.avar->get_axis_count ())
    +      if (has_avar && old_axis_idx < avar_axis_count)
           {
             normalized_v = seg_maps->map (normalized_v);
           }
    @@ -811,17 +858,99 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
           if (normalized_v != 0)
             plan->pinned_at_default = false;
     
    -      plan->normalized_coords[i] = normalized_v;
    +      plan->normalized_coords[old_axis_idx] = normalized_v;
         }
    -    if (has_avar)
    -      seg_maps = &StructAfter (*seg_maps);
     
         old_axis_idx++;
     
    -    i++;
    +    if (has_avar && old_axis_idx < avar_axis_count)
    +      seg_maps = &StructAfter (*seg_maps);
       }
       plan->all_axes_pinned = !axis_not_pinned;
     }
    +
    +static void
    +_update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan)
    +{
    +  if (!plan->normalized_coords) return;
    +  OT::cff2::accelerator_t cff2 (plan->source);
    +  if (!cff2.is_valid ()) return;
    +
    +  hb_font_t *font = nullptr;
    +  if (unlikely (!plan->check_success (font = _get_hb_font_with_variations (plan))))
    +  {
    +    hb_font_destroy (font);
    +    return;
    +  }
    +
    +  hb_glyph_extents_t extents = {0x7FFF, -0x7FFF};
    +  OT::hmtx_accelerator_t _hmtx (plan->source);
    +  float *hvar_store_cache = nullptr;
    +  if (_hmtx.has_data () && _hmtx.var_table.get_length ())
    +    hvar_store_cache = _hmtx.var_table->get_var_store ().create_cache ();
    +
    +  OT::vmtx_accelerator_t _vmtx (plan->source);
    +  float *vvar_store_cache = nullptr;
    +  if (_vmtx.has_data () && _vmtx.var_table.get_length ())
    +    vvar_store_cache = _vmtx.var_table->get_var_store ().create_cache ();
    +
    +  for (auto p : *plan->glyph_map)
    +  {
    +    hb_codepoint_t old_gid = p.first;
    +    hb_codepoint_t new_gid = p.second;
    +    if (!cff2.get_extents (font, old_gid, &extents)) continue;
    +    bool has_bounds_info = true;
    +    if (extents.x_bearing == 0 && extents.width == 0 &&
    +        extents.height == 0 && extents.y_bearing == 0)
    +      has_bounds_info = false;
    +
    +    if (has_bounds_info)
    +    {
    +      plan->head_maxp_info.xMin = hb_min (plan->head_maxp_info.xMin, extents.x_bearing);
    +      plan->head_maxp_info.xMax = hb_max (plan->head_maxp_info.xMax, extents.x_bearing + extents.width);
    +      plan->head_maxp_info.yMax = hb_max (plan->head_maxp_info.yMax, extents.y_bearing);
    +      plan->head_maxp_info.yMin = hb_min (plan->head_maxp_info.yMin, extents.y_bearing + extents.height);
    +    }
    +
    +    if (_hmtx.has_data ())
    +    {
    +      int hori_aw = _hmtx.get_advance_without_var_unscaled (old_gid);
    +      if (_hmtx.var_table.get_length ())
    +        hori_aw += (int) roundf (_hmtx.var_table->get_advance_delta_unscaled (old_gid, font->coords, font->num_coords,
    +                                                                              hvar_store_cache));
    +      int lsb = extents.x_bearing;
    +      if (!has_bounds_info)
    +      {
    +        if (!_hmtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb))
    +          continue;
    +      }
    +      plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb));
    +      plan->bounds_width_map.set (new_gid, extents.width);
    +    }
    +
    +    if (_vmtx.has_data ())
    +    {
    +      int vert_aw = _vmtx.get_advance_without_var_unscaled (old_gid);
    +      if (_vmtx.var_table.get_length ())
    +        vert_aw += (int) roundf (_vmtx.var_table->get_advance_delta_unscaled (old_gid, font->coords, font->num_coords,
    +                                                                              vvar_store_cache));
    +
    +      int tsb = extents.y_bearing;
    +      if (!has_bounds_info)
    +      {
    +        if (!_vmtx.get_leading_bearing_without_var_unscaled (old_gid, &tsb))
    +          continue;
    +      }
    +      plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb));
    +      plan->bounds_height_map.set (new_gid, extents.height);
    +    }
    +  }
    +  hb_font_destroy (font);
    +  if (hvar_store_cache)
    +    _hmtx.var_table->get_var_store ().destroy_cache (hvar_store_cache);
    +  if (vvar_store_cache)
    +    _vmtx.var_table->get_var_store ().destroy_cache (vvar_store_cache);
    +}
     #endif
     
     hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
    @@ -884,6 +1013,8 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
       _populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, this);
     
       _populate_gids_to_retain (this, input->sets.drop_tables);
    +  if (unlikely (in_error ()))
    +    return;
     
       _create_old_gid_to_new_gid_map (face,
                                       input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS,
    @@ -905,10 +1036,13 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
             glyph_map->get(unicode_to_new_gid_list.arrayZ[i].second);
       }
     
    -  _nameid_closure (face, &name_ids, all_axes_pinned, &user_axes_location);
       if (unlikely (in_error ()))
         return;
     
    +#ifndef HB_NO_VAR
    +  _update_instance_metrics_map_from_cff2 (this);
    +#endif
    +
       if (attach_accelerator_data)
       {
         hb_multimap_t gid_to_unicodes;
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh b/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh
    index 3f36bfa94ad..8f2ac23b180 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh
    @@ -211,7 +211,7 @@ struct hb_subset_plan_t
       template
       hb_blob_ptr_t source_table()
       {
    -    hb_lock_t (accelerator ? &accelerator->sanitized_table_cache_lock : nullptr);
    +    hb_lock_t lock (accelerator ? &accelerator->sanitized_table_cache_lock : nullptr);
     
         auto *cache = accelerator ? &accelerator->sanitized_table_cache : &sanitized_table_cache;
         if (cache
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset.cc b/src/java.desktop/share/native/libharfbuzz/hb-subset.cc
    index b2539de7432..538f4ec64bf 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-subset.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-subset.cc
    @@ -54,6 +54,7 @@
     #include "hb-ot-name-table.hh"
     #include "hb-ot-layout-gsub-table.hh"
     #include "hb-ot-layout-gpos-table.hh"
    +#include "hb-ot-var-cvar-table.hh"
     #include "hb-ot-var-fvar-table.hh"
     #include "hb-ot-var-gvar-table.hh"
     #include "hb-ot-var-hvar-table.hh"
    @@ -482,6 +483,16 @@ _subset_table (hb_subset_plan_t *plan,
         if (plan->all_axes_pinned) return _subset (plan, buf);
         else return _passthrough (plan, tag);
     
    +  case HB_TAG ('c', 'v', 't', ' '):
    +#ifndef HB_NO_VAR
    +    if (_is_table_present (plan->source, HB_OT_TAG_cvar) &&
    +        plan->normalized_coords && !plan->pinned_at_default)
    +    {
    +      auto &cvar = *plan->source->table.cvar;
    +      return OT::cvar::add_cvt_and_apply_deltas (plan, cvar.get_tuple_var_data (), &cvar);
    +    }
    +#endif
    +    return _passthrough (plan, tag);
       default:
         if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED)
           return _passthrough (plan, tag);
    @@ -630,8 +641,3 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
     end:
       return success ? hb_face_reference (plan->dest) : nullptr;
     }
    -
    -#ifndef HB_NO_VISIBILITY
    -/* If NO_VISIBILITY, libharfbuzz has this. */
    -#include "hb-ot-name-language-static.hh"
    -#endif
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset.h b/src/java.desktop/share/native/libharfbuzz/hb-subset.h
    index 2d1ff0c2639..410fd90a421 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-subset.h
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-subset.h
    @@ -71,6 +71,8 @@ typedef struct hb_subset_plan_t hb_subset_plan_t;
      * in the final subset.
      * @HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in
      * OS/2 will not be recalculated.
    + * @HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE: If set don't perform glyph closure on layout
    + * substitution rules (GSUB). Since: 7.2.0.
      *
      * List of boolean properties that can be configured on the subset input.
      *
    @@ -87,6 +89,7 @@ typedef enum { /*< flags >*/
       HB_SUBSET_FLAGS_NOTDEF_OUTLINE =           0x00000040u,
       HB_SUBSET_FLAGS_GLYPH_NAMES =              0x00000080u,
       HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES =  0x00000100u,
    +  HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE =        0x00000200u,
     } hb_subset_flags_t;
     
     /**
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-unicode.h b/src/java.desktop/share/native/libharfbuzz/hb-unicode.h
    index 82f10501a0c..18ae0d34116 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-unicode.h
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-unicode.h
    @@ -164,7 +164,7 @@ typedef enum
      * @HB_UNICODE_COMBINING_CLASS_CCC122: [Lao]
      * @HB_UNICODE_COMBINING_CLASS_CCC129: [Tibetan]
      * @HB_UNICODE_COMBINING_CLASS_CCC130: [Tibetan]
    - * @HB_UNICODE_COMBINING_CLASS_CCC133: [Tibetan]
    + * @HB_UNICODE_COMBINING_CLASS_CCC132: [Tibetan] Since: 7.2.0
      * @HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT: Marks attached at the bottom left
      * @HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW: Marks attached directly below
      * @HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE: Marks attached directly above
    @@ -246,7 +246,7 @@ typedef enum
       /* Tibetan */
       HB_UNICODE_COMBINING_CLASS_CCC129     = 129,
       HB_UNICODE_COMBINING_CLASS_CCC130     = 130,
    -  HB_UNICODE_COMBINING_CLASS_CCC133     = 132,
    +  HB_UNICODE_COMBINING_CLASS_CCC132     = 132,
     
     
       HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT        = 200,
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb-version.h b/src/java.desktop/share/native/libharfbuzz/hb-version.h
    index 03ce9b6903c..1dc7a6b0975 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-version.h
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-version.h
    @@ -47,20 +47,20 @@ HB_BEGIN_DECLS
      *
      * The minor component of the library version available at compile-time.
      */
    -#define HB_VERSION_MINOR 0
    +#define HB_VERSION_MINOR 2
     /**
      * HB_VERSION_MICRO:
      *
      * The micro component of the library version available at compile-time.
      */
    -#define HB_VERSION_MICRO 1
    +#define HB_VERSION_MICRO 0
     
     /**
      * HB_VERSION_STRING:
      *
      * A string literal containing the library version available at compile-time.
      */
    -#define HB_VERSION_STRING "7.0.1"
    +#define HB_VERSION_STRING "7.2.0"
     
     /**
      * HB_VERSION_ATLEAST:
    diff --git a/src/java.desktop/share/native/libharfbuzz/hb.hh b/src/java.desktop/share/native/libharfbuzz/hb.hh
    index 1807f1af01c..4a6d99e7a1e 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb.hh
    @@ -246,7 +246,15 @@ extern "C" void  hb_free_impl(void *ptr);
      * Compiler attributes
      */
     
    -#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
    +// gcc 10 has __has_builtin but not earlier versions. Sanction any gcc >= 5
    +// clang defines it so no need.
    +#ifdef __has_builtin
    +#define hb_has_builtin __has_builtin
    +#else
    +#define hb_has_builtin(x) ((defined(__GNUC__) && __GNUC__ >= 5))
    +#endif
    +
    +#if defined(__OPTIMIZE__) && hb_has_builtin(__builtin_expect)
     #define likely(expr) (__builtin_expect (!!(expr), 1))
     #define unlikely(expr) (__builtin_expect (!!(expr), 0))
     #else
    @@ -501,6 +509,12 @@ static_assert ((sizeof (hb_mask_t) == 4), "");
     static_assert ((sizeof (hb_var_int_t) == 4), "");
     
     
    +/* Pie time. */
    +// https://github.com/harfbuzz/harfbuzz/issues/4166
    +#define HB_PI 3.14159265358979f
    +#define HB_2_PI (2.f * HB_PI)
    +
    +
     /* Headers we include for everyone.  Keep topologically sorted by dependency.
      * They express dependency amongst themselves, but no other file should include
      * them directly.*/
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
    index 9a86869681b..468e1119a10 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
    @@ -6109,6 +6109,18 @@ Version 1.6.38 [September 14, 2022]
       Implemented many stability improvements across all platforms.
       Updated the internal documentation.
     
    +Version 1.6.39 [November 20, 2022]
    +  Changed the error handler of oversized chunks (i.e. larger than
    +    PNG_USER_CHUNK_MALLOC_MAX) from png_chunk_error to png_benign_error.
    +  Fixed a buffer overflow error in contrib/tools/pngfix.
    +  Fixed a memory leak (CVE-2019-6129) in contrib/tools/pngcp.
    +  Disabled the ARM Neon optimizations by default in the CMake file,
    +    following the default behavior of the configure script.
    +  Allowed configure.ac to work with the trunk version of autoconf.
    +  Removed the support for "install" targets from the legacy makefiles;
    +    removed the obsolete makefile.cegcc.
    +  Cleaned up the code and updated the internal documentation.
    +
     Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
     Subscription is required; visit
     https://lists.sourceforge.net/lists/listinfo/png-mng-implement
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE b/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
    index c8ad24eecf7..7ac90160ede 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
    @@ -131,4 +131,4 @@ The Contributing Authors and Group 42, Inc. specifically permit,
     without fee, and encourage the use of this source code as a component
     to supporting the PNG file format in commercial products.  If you use
     this source code in a product, acknowledgment is not required but would
    -be appreciated.
    +be appreciated.
    \ No newline at end of file
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/README b/src/java.desktop/share/native/libsplashscreen/libpng/README
    index e6e72aa5472..097a3c21841 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/README
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/README
    @@ -1,4 +1,4 @@
    -README for libpng version 1.6.38
    +README for libpng version 1.6.39
     ================================
     
     See the note about version numbers near the top of png.h.
    @@ -106,73 +106,74 @@ subscribe).
     
     Files in this distribution:
     
    -      ANNOUNCE      =>  Announcement of this version, with recent changes
    -      AUTHORS       =>  List of contributing authors
    -      CHANGES       =>  Description of changes between libpng versions
    -      KNOWNBUG      =>  List of known bugs and deficiencies
    -      LICENSE       =>  License to use and redistribute libpng
    -      README        =>  This file
    -      TODO          =>  Things not implemented in the current library
    -      TRADEMARK     =>  Trademark information
    -      example.c     =>  Example code for using libpng functions
    -      libpng.3      =>  manual page for libpng (includes libpng-manual.txt)
    -      libpng-manual.txt  =>  Description of libpng and its functions
    -      libpngpf.3    =>  manual page for libpng's private functions
    -      png.5         =>  manual page for the PNG format
    -      png.c         =>  Basic interface functions common to library
    -      png.h         =>  Library function and interface declarations (public)
    -      pngpriv.h     =>  Library function and interface declarations (private)
    -      pngconf.h     =>  System specific library configuration (public)
    -      pngstruct.h   =>  png_struct declaration (private)
    -      pnginfo.h     =>  png_info struct declaration (private)
    -      pngdebug.h    =>  debugging macros (private)
    -      pngerror.c    =>  Error/warning message I/O functions
    -      pngget.c      =>  Functions for retrieving info from struct
    -      pngmem.c      =>  Memory handling functions
    -      pngbar.png    =>  PNG logo, 88x31
    -      pngnow.png    =>  PNG logo, 98x31
    -      pngpread.c    =>  Progressive reading functions
    -      pngread.c     =>  Read data/helper high-level functions
    -      pngrio.c      =>  Lowest-level data read I/O functions
    -      pngrtran.c    =>  Read data transformation functions
    -      pngrutil.c    =>  Read data utility functions
    -      pngset.c      =>  Functions for storing data into the info_struct
    -      pngtest.c     =>  Library test program
    -      pngtest.png   =>  Library test sample image
    -      pngtrans.c    =>  Common data transformation functions
    -      pngwio.c      =>  Lowest-level write I/O functions
    -      pngwrite.c    =>  High-level write functions
    -      pngwtran.c    =>  Write data transformations
    -      pngwutil.c    =>  Write utility functions
    -      arm           =>  Contains optimized code for the ARM platform
    -      powerpc       =>  Contains optimized code for the PowerPC platform
    -      contrib       =>  Contributions
    -       arm-neon         =>  Optimized code for ARM-NEON platform
    -       powerpc-vsx      =>  Optimized code for POWERPC-VSX platform
    -       examples         =>  Example programs
    -       gregbook         =>  source code for PNG reading and writing, from
    -                            Greg Roelofs' "PNG: The Definitive Guide",
    -                            O'Reilly, 1999
    -       libtests         =>  Test programs
    -       mips-msa         =>  Optimized code for MIPS-MSA platform
    -       pngminim         =>  Minimal decoder, encoder, and progressive decoder
    -                            programs demonstrating use of pngusr.dfa
    -       pngminus         =>  Simple pnm2png and png2pnm programs
    -       pngsuite         =>  Test images
    -       testpngs
    -       tools            =>  Various tools
    -       visupng          =>  Contains a MSVC workspace for VisualPng
    -      intel             =>  Optimized code for INTEL-SSE2 platform
    -      mips              =>  Optimized code for MIPS platform
    -      projects      =>  Contains project files and workspaces for
    -                        building a DLL
    -       owatcom          =>  Contains a WATCOM project for building libpng
    -       visualc71        =>  Contains a Microsoft Visual C++ (MSVC)
    -                            workspace for building libpng and zlib
    -       vstudio          =>  Contains a Microsoft Visual C++ (MSVC)
    -                            workspace for building libpng and zlib
    -      scripts       =>  Directory containing scripts for building libpng:
    -                            (see scripts/README.txt for the list of scripts)
    +    ANNOUNCE      =>  Announcement of this version, with recent changes
    +    AUTHORS       =>  List of contributing authors
    +    CHANGES       =>  Description of changes between libpng versions
    +    INSTALL       =>  Instructions to install libpng
    +    LICENSE       =>  License to use and redistribute libpng
    +    README        =>  This file
    +    TODO          =>  Things not implemented in the current library
    +    TRADEMARK     =>  Trademark information
    +    example.c     =>  Example code for using libpng functions
    +    libpng.3      =>  Manual page for libpng (includes libpng-manual.txt)
    +    libpng-manual.txt  =>  Description of libpng and its functions
    +    libpngpf.3    =>  Manual page for libpng's private functions (deprecated)
    +    png.5         =>  Manual page for the PNG format
    +    png.c         =>  Basic interface functions common to library
    +    png.h         =>  Library function and interface declarations (public)
    +    pngpriv.h     =>  Library function and interface declarations (private)
    +    pngconf.h     =>  System specific library configuration (public)
    +    pngstruct.h   =>  png_struct declaration (private)
    +    pnginfo.h     =>  png_info struct declaration (private)
    +    pngdebug.h    =>  debugging macros (private)
    +    pngerror.c    =>  Error/warning message I/O functions
    +    pngget.c      =>  Functions for retrieving info from struct
    +    pngmem.c      =>  Memory handling functions
    +    pngbar.png    =>  PNG logo, 88x31
    +    pngnow.png    =>  PNG logo, 98x31
    +    pngpread.c    =>  Progressive reading functions
    +    pngread.c     =>  Read data/helper high-level functions
    +    pngrio.c      =>  Lowest-level data read I/O functions
    +    pngrtran.c    =>  Read data transformation functions
    +    pngrutil.c    =>  Read data utility functions
    +    pngset.c      =>  Functions for storing data into the info_struct
    +    pngtest.c     =>  Library test program
    +    pngtest.png   =>  Library test sample image
    +    pngtrans.c    =>  Common data transformation functions
    +    pngwio.c      =>  Lowest-level write I/O functions
    +    pngwrite.c    =>  High-level write functions
    +    pngwtran.c    =>  Write data transformations
    +    pngwutil.c    =>  Write utility functions
    +    arm/          =>  Optimized code for the ARM platform
    +    intel/        =>  Optimized code for the INTEL-SSE2 platform
    +    mips/         =>  Optimized code for the MIPS platform
    +    powerpc/      =>  Optimized code for the PowerPC platform
    +    ci/           =>  Scripts for continuous integration
    +    contrib/      =>  External contributions
    +        arm-neon/     =>  Optimized code for the ARM-NEON platform
    +        mips-msa/     =>  Optimized code for the MIPS-MSA platform
    +        powerpc-vsx/  =>  Optimized code for the POWERPC-VSX platform
    +        examples/     =>  Example programs
    +        gregbook/     =>  Source code for PNG reading and writing, from
    +                          "PNG: The Definitive Guide" by Greg Roelofs,
    +                          O'Reilly, 1999
    +        libtests/     =>  Test programs
    +        oss-fuzz/     =>  Files used by the OSS-Fuzz project for fuzz-testing
    +                          libpng
    +        pngminim/     =>  Minimal decoder, encoder, and progressive decoder
    +                          programs demonstrating the use of pngusr.dfa
    +        pngminus/     =>  Simple pnm2png and png2pnm programs
    +        pngsuite/     =>  Test images
    +        testpngs/     =>  Test images
    +        tools/        =>  Various tools
    +        visupng/      =>  VisualPng, a Windows viewer for PNG images
    +    projects/     =>  Project files and workspaces for various IDEs
    +        owatcom/      =>  OpenWatcom project
    +        visualc71/    =>  Microsoft Visual C++ 7.1 workspace
    +        vstudio/      =>  Microsoft Visual Studio workspace
    +    scripts/      =>  Scripts and makefiles for building libpng
    +                      (see scripts/README.txt for the complete list)
    +    tests/        =>  Test scripts
     
     Good luck, and happy coding!
     
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.c b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
    index ba608f128ab..30181b6ff7c 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/png.c
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
    @@ -42,7 +42,7 @@
     #include "pngpriv.h"
     
     /* Generate a compiler error if there is an old png.h in the search path. */
    -typedef png_libpng_version_1_6_38 Your_png_h_is_not_version_1_6_38;
    +typedef png_libpng_version_1_6_39 Your_png_h_is_not_version_1_6_39;
     
     #ifdef __GNUC__
     /* The version tests may need to be added to, but the problem warning has
    @@ -843,7 +843,7 @@ png_get_copyright(png_const_structrp png_ptr)
        return PNG_STRING_COPYRIGHT
     #else
        return PNG_STRING_NEWLINE \
    -      "libpng version 1.6.38" PNG_STRING_NEWLINE \
    +      "libpng version 1.6.39" PNG_STRING_NEWLINE \
           "Copyright (c) 2018-2022 Cosmin Truta" PNG_STRING_NEWLINE \
           "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
           PNG_STRING_NEWLINE \
    @@ -2738,7 +2738,7 @@ png_check_IHDR(png_const_structrp png_ptr,
     
     int /* PRIVATE */
     png_check_fp_number(png_const_charp string, size_t size, int *statep,
    -    png_size_tp whereami)
    +    size_t *whereami)
     {
        int state = *statep;
        size_t i = *whereami;
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.h b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
    index aeff31573c7..3d9fa03de66 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/png.h
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
    @@ -29,7 +29,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * libpng version 1.6.38 - September 14, 2022
    + * libpng version 1.6.39 - November 20, 2022
      *
      * Copyright (c) 2018-2022 Cosmin Truta
      * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
    @@ -43,7 +43,7 @@
      *   libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
      *   libpng versions 0.97, January 1998, through 1.6.35, July 2018:
      *     Glenn Randers-Pehrson
    - *   libpng versions 1.6.36, December 2018, through 1.6.38, September 2022:
    + *   libpng versions 1.6.36, December 2018, through 1.6.39, November 2022:
      *     Cosmin Truta
      *   See also "Contributing Authors", below.
      */
    @@ -267,7 +267,7 @@
      *    ...
      *    1.5.30                  15    10530  15.so.15.30[.0]
      *    ...
    - *    1.6.38                  16    10638  16.so.16.38[.0]
    + *    1.6.39                  16    10639  16.so.16.39[.0]
      *
      *    Henceforth the source version will match the shared-library major and
      *    minor numbers; the shared-library major version number will be used for
    @@ -306,8 +306,8 @@
      */
     
     /* Version information for png.h - this should match the version in png.c */
    -#define PNG_LIBPNG_VER_STRING "1.6.38"
    -#define PNG_HEADER_VERSION_STRING " libpng version 1.6.38 - September 14, 2022\n"
    +#define PNG_LIBPNG_VER_STRING "1.6.39"
    +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.39 - November 20, 2022\n"
     
     #define PNG_LIBPNG_VER_SONUM   16
     #define PNG_LIBPNG_VER_DLLNUM  16
    @@ -315,7 +315,7 @@
     /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
     #define PNG_LIBPNG_VER_MAJOR   1
     #define PNG_LIBPNG_VER_MINOR   6
    -#define PNG_LIBPNG_VER_RELEASE 38
    +#define PNG_LIBPNG_VER_RELEASE 39
     
     /* This should be zero for a public release, or non-zero for a
      * development version.  [Deprecated]
    @@ -346,7 +346,7 @@
      * From version 1.0.1 it is:
      * XXYYZZ, where XX=major, YY=minor, ZZ=release
      */
    -#define PNG_LIBPNG_VER 10638 /* 1.6.38 */
    +#define PNG_LIBPNG_VER 10639 /* 1.6.39 */
     
     /* Library configuration: these options cannot be changed after
      * the library has been built.
    @@ -456,7 +456,7 @@ extern "C" {
     /* This triggers a compiler error in png.c, if png.c and png.h
      * do not agree upon the version number.
      */
    -typedef char* png_libpng_version_1_6_38;
    +typedef char* png_libpng_version_1_6_39;
     
     /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
      *
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
    index e95fa34ad7a..d11e9ac346a 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
    @@ -29,7 +29,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * libpng version 1.6.38
    + * libpng version 1.6.39
      *
      * Copyright (c) 2018-2022 Cosmin Truta
      * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
    index b3dc39a45be..f6923c01e9f 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
    @@ -31,7 +31,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      */
    -/* libpng version 1.6.38 */
    +/* libpng version 1.6.39 */
     
     /* Copyright (c) 2018-2022 Cosmin Truta */
     /* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
    index ed44512ef20..ec473298068 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
    @@ -1974,7 +1974,7 @@ PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr,
      * the problem character.)  This has not been tested within libpng.
      */
     PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string,
    -   size_t size, int *statep, png_size_tp whereami),PNG_EMPTY);
    +   size_t size, int *statep, size_t *whereami),PNG_EMPTY);
     
     /* This is the same but it checks a complete string and returns true
      * only if it just contains a floating point number.  As of 1.5.4 this
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
    index d41a6d09b27..524297c5a10 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
    @@ -3214,7 +3214,7 @@ png_check_chunk_length(png_const_structrp png_ptr, png_uint_32 length)
        {
           png_debug2(0," length = %lu, limit = %lu",
              (unsigned long)length,(unsigned long)limit);
    -      png_chunk_error(png_ptr, "chunk data is too large");
    +      png_benign_error(png_ptr, "chunk data is too large");
        }
     }
     
    diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c b/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c
    index d4a74fa85c3..781e81782f9 100644
    --- a/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c
    +++ b/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c
    @@ -331,6 +331,11 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_nativeFinishPainting(
     {
         jint transparency;
         gint *buffer = (gint*) (*env)->GetPrimitiveArrayCritical(env, dest, 0);
    +    if (buffer == 0) {
    +        (*env)->ExceptionClear(env);
    +        JNU_ThrowOutOfMemoryError(env, "Could not get image buffer");
    +        return -1;
    +    }
         gtk->gdk_threads_enter();
         transparency = gtk->copy_image(buffer, width, height);
         gtk->gdk_threads_leave();
    diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WClipboard.java b/src/java.desktop/windows/classes/sun/awt/windows/WClipboard.java
    index 3e82560a5cf..e16b1805295 100644
    --- a/src/java.desktop/windows/classes/sun/awt/windows/WClipboard.java
    +++ b/src/java.desktop/windows/classes/sun/awt/windows/WClipboard.java
    @@ -83,13 +83,7 @@ protected void setContentsNative(Transferable contents) {
                             translateTransferable(contents, flavor, format);
                         publishClipboardData(format, bytes);
                     } catch (IOException e) {
    -                    // Fix 4696186: don't print exception if data with
    -                    // javaJVMLocalObjectMimeType failed to serialize.
    -                    // May remove this if-check when 5078787 is fixed.
    -                    if (!(flavor.isMimeTypeEqual(DataFlavor.javaJVMLocalObjectMimeType) &&
    -                          e instanceof java.io.NotSerializableException)) {
    -                        e.printStackTrace();
    -                    }
    +                    // Cannot be translated in this format, skip
                     }
                 }
             } finally {
    diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WScrollPanePeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WScrollPanePeer.java
    index 2c7667f25ef..d5b80b9a632 100644
    --- a/src/java.desktop/windows/classes/sun/awt/windows/WScrollPanePeer.java
    +++ b/src/java.desktop/windows/classes/sun/awt/windows/WScrollPanePeer.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -24,7 +24,13 @@
      */
     package sun.awt.windows;
     
    -import java.awt.*;
    +import java.awt.Adjustable;
    +import java.awt.Component;
    +import java.awt.Dimension;
    +import java.awt.Insets;
    +import java.awt.Point;
    +import java.awt.ScrollPane;
    +import java.awt.ScrollPaneAdjustable;
     import java.awt.event.AdjustmentEvent;
     import java.awt.peer.ScrollPanePeer;
     
    @@ -105,7 +111,6 @@ public void childResized(int width, int height) {
             ScrollPane sp = (ScrollPane)target;
             Dimension vs = sp.getSize();
             setSpans(vs.width, vs.height, width, height);
    -        setInsets();
         }
     
         synchronized native void setSpans(int viewWidth, int viewHeight,
    diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBadHardware.h b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBadHardware.h
    index 115626c857c..e154fa7bb49 100644
    --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBadHardware.h
    +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBadHardware.h
    @@ -54,6 +54,9 @@ static const ADAPTER_INFO badHardware[] = {
         // All Intel Chips.
         { 0x8086, ALL_DEVICEIDS, NO_VERSION, OS_ALL },
     
    +    // Microsoft Basic Render Driver (as maybe used in VMs such as VirtualBox)
    +    { 0x1414, 0x008c, NO_VERSION, OS_ALL },
    +
         // ATI Mobility Radeon X1600, X1400, X1450, X1300, X1350
         // Reason: workaround for 6613066, 6687166
         // X1300 (four sub ids)
    diff --git a/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp b/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp
    index 99ca918a500..e05bd4f4db9 100644
    --- a/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp
    +++ b/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp
    @@ -475,10 +475,11 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_ThemeReader_paintBackground
             GdiFlush();
             // Copy the resulting pixels to our Java BufferedImage.
             pDstBits = (int *)env->GetPrimitiveArrayCritical(array, 0);
    -        BOOL transparent = FALSE;
    -        transparent = IsThemeBackgroundPartiallyTransparent(hTheme,part,state);
    -        copyDIBToBufferedImage(pDstBits, pSrcBits, transparent, w, h, stride);
    -        env->ReleasePrimitiveArrayCritical(array, pDstBits, 0);
    +        if (pDstBits != NULL) {
    +            BOOL transparent = IsThemeBackgroundPartiallyTransparent(hTheme, part, state);
    +            copyDIBToBufferedImage(pDstBits, pSrcBits, transparent, w, h, stride);
    +            env->ReleasePrimitiveArrayCritical(array, pDstBits, 0);
    +        }
         }
     
         // Delete resources.
    diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DataTransferer.cpp b/src/java.desktop/windows/native/libawt/windows/awt_DataTransferer.cpp
    index 9ebc2c60eee..90eac6eef53 100644
    --- a/src/java.desktop/windows/native/libawt/windows/awt_DataTransferer.cpp
    +++ b/src/java.desktop/windows/native/libawt/windows/awt_DataTransferer.cpp
    @@ -163,6 +163,10 @@ AwtDataTransferer::GetPaletteBytes(HGDIOBJ hGdiObj, DWORD dwGdiObjType,
     
         LOGPALETTE* pLogPalette =
             (LOGPALETTE*)env->GetPrimitiveArrayCritical(paletteBytes, NULL);
    +    if (pLogPalette == NULL) {
    +        env->DeleteLocalRef(paletteBytes);
    +        return NULL;
    +    }
         PALETTEENTRY* pPalEntries = (PALETTEENTRY*)pLogPalette->palPalEntry;
     
         pLogPalette->palVersion = 0x300;
    diff --git a/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.cpp b/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.cpp
    index 1e4091bd505..717bf42e63a 100644
    --- a/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.cpp
    +++ b/src/java.desktop/windows/native/libawt/windows/awt_ScrollPane.cpp
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -524,6 +524,7 @@ void AwtScrollPane::_SetSpans(void *param)
             DTRACE_PRINTLN5("%x: WScrollPanePeer.setSpans(%d, %d, %d, %d)", self,
                 parentWidth, parentHeight, childWidth, childHeight);
             s->RecalcSizes(parentWidth, parentHeight, childWidth, childHeight);
    +        s->SetInsets(env);
             s->VerifyState();
         }
     ret:
    @@ -701,7 +702,7 @@ Java_sun_awt_windows_WScrollPanePeer_getOffset(JNIEnv *env, jobject self,
         gos->scrollpane = env->NewGlobalRef(self);
         gos->orient = orient;
     
    -    return static_cast(reinterpret_cast(AwtToolkit::GetInstance().SyncCall(
    +    return static_cast(reinterpret_cast(AwtToolkit::GetInstance().InvokeFunction(
             (void *(*)(void *))AwtScrollPane::_GetOffset, gos)));
         // global ref and gos are deleted in _GetOffset()
     
    @@ -718,7 +719,7 @@ Java_sun_awt_windows_WScrollPanePeer_setInsets(JNIEnv *env, jobject self)
     {
         TRY
     
    -    AwtToolkit::GetInstance().SyncCall(AwtScrollPane::_SetInsets,
    +    AwtToolkit::GetInstance().InvokeFunction(AwtScrollPane::_SetInsets,
             env->NewGlobalRef(self));
         // global ref is deleted in _SetInsets()
     
    @@ -742,7 +743,7 @@ Java_sun_awt_windows_WScrollPanePeer_setScrollPosition(JNIEnv *env,
         ssps->x = x;
         ssps->y = y;
     
    -    AwtToolkit::GetInstance().SyncCall(AwtScrollPane::_SetScrollPos, ssps);
    +    AwtToolkit::GetInstance().InvokeFunctionLater(AwtScrollPane::_SetScrollPos, ssps);
         // global ref and ssps are deleted in _SetScrollPos()
     
         CATCH_BAD_ALLOC;
    @@ -803,7 +804,7 @@ Java_sun_awt_windows_WScrollPanePeer_setSpans(JNIEnv *env, jobject self,
         sss->childWidth = childWidth;
         sss->childHeight = childHeight;
     
    -    AwtToolkit::GetInstance().SyncCall(AwtScrollPane::_SetSpans, sss);
    +    AwtToolkit::GetInstance().InvokeFunction(AwtScrollPane::_SetSpans, sss);
         // global ref and sss are deleted in _SetSpans
     
         CATCH_BAD_ALLOC;
    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 40207c674aa..0535340b30d 100644
    --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp
    +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp
    @@ -2876,8 +2876,10 @@ Java_sun_awt_windows_WToolkit_loadSystemColors(JNIEnv *env, jobject self,
         jint* colorsPtr = NULL;
         try {
             colorsPtr = (jint *)env->GetPrimitiveArrayCritical(colors, 0);
    -        for (int i = 0; i < (sizeof indexMap)/(sizeof *indexMap) && i < colorLen; i++) {
    -            colorsPtr[i] = DesktopColor2RGB(indexMap[i]);
    +        if (colorsPtr != NULL) {
    +            for (int i = 0; i < (sizeof indexMap)/(sizeof *indexMap) && i < colorLen; i++) {
    +                colorsPtr[i] = DesktopColor2RGB(indexMap[i]);
    +            }
             }
         } catch (...) {
             if (colorsPtr != NULL) {
    diff --git a/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java b/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java
    index 5b7e821269f..d438341ac62 100644
    --- a/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java
    +++ b/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -44,6 +44,7 @@
     import javax.naming.CommunicationException;
     import javax.naming.ldap.InitialLdapContext;
     import javax.naming.ldap.LdapContext;
    +import javax.naming.ldap.LdapName;
     import javax.security.auth.x500.X500Principal;
     
     import com.sun.jndi.ldap.LdapReferralException;
    @@ -62,8 +63,6 @@ final class LDAPCertStoreImpl {
     
         private static final Debug debug = Debug.getInstance("certpath");
     
    -    private final static boolean DEBUG = false;
    -
         /**
          * LDAP attribute identifiers.
          */
    @@ -72,7 +71,6 @@ final class LDAPCertStoreImpl {
         private static final String CROSS_CERT = "crossCertificatePair;binary";
         private static final String CRL = "certificateRevocationList;binary";
         private static final String ARL = "authorityRevocationList;binary";
    -    private static final String DELTA_CRL = "deltaRevocationList;binary";
     
         // Constants for various empty values
         private final static String[] STRING0 = new String[0];
    @@ -113,6 +111,7 @@ final class LDAPCertStoreImpl {
          * their binary stored form.
          */
         private CertificateFactory cf;
    +
         /**
          * The JNDI directory context.
          */
    @@ -200,6 +199,49 @@ private void createInitialDirContext(String server, int port)
             }
         }
     
    +    private static String checkName(String name) throws CertStoreException {
    +        if (name == null) {
    +            throw new CertStoreException("Name absent");
    +        }
    +        try {
    +            if (new CompositeName(name).size() > 1) {
    +                throw new CertStoreException("Invalid name: " + name);
    +            }
    +        } catch (InvalidNameException ine) {
    +            throw new CertStoreException("Invalid name: " + name, ine);
    +        }
    +        return name;
    +    }
    +
    +    /**
    +     * Get the values for the given attribute. If the attribute is null
    +     * or does not contain any values, a zero length byte array is
    +     * returned. NOTE that it is assumed that all values are byte arrays.
    +     */
    +    private static byte[][] getAttributeValues(Attribute attr)
    +            throws NamingException {
    +        byte[][] values;
    +        if (attr == null) {
    +            values = BB0;
    +        } else {
    +            values = new byte[attr.size()][];
    +            int i = 0;
    +            NamingEnumeration enum_ = attr.getAll();
    +            while (enum_.hasMore()) {
    +                Object obj = enum_.next();
    +                if (debug != null) {
    +                    if (obj instanceof String) {
    +                        debug.println("LDAPCertStore.getAttrValues() "
    +                            + "enum.next is a string!: " + obj);
    +                    }
    +                }
    +                byte[] value = (byte[])obj;
    +                values[i++] = value;
    +            }
    +        }
    +        return values;
    +    }
    +
         /**
          * Private class encapsulating the actual LDAP operations and cache
          * handling. Use:
    @@ -218,31 +260,20 @@ private void createInitialDirContext(String server, int port)
          */
         private class LDAPRequest {
     
    -        private final String name;
    +        private final LdapName name;
             private Map valueMap;
             private final List requestedAttributes;
     
             LDAPRequest(String name) throws CertStoreException {
    -            this.name = checkName(name);
    -            requestedAttributes = new ArrayList<>(5);
    -        }
    -
    -        private String checkName(String name) throws CertStoreException {
    -            if (name == null) {
    -                throw new CertStoreException("Name absent");
    -            }
                 try {
    -                if (new CompositeName(name).size() > 1) {
    -                    throw new CertStoreException("Invalid name: " + name);
    -                }
    +                // Convert DN to an LdapName so that it is not treated as a
    +                // composite name by JNDI. In JNDI, using a string name is
    +                // equivalent to calling new CompositeName(stringName).
    +                this.name = new LdapName(name);
                 } catch (InvalidNameException ine) {
                     throw new CertStoreException("Invalid name: " + name, ine);
                 }
    -            return name;
    -        }
    -
    -        String getName() {
    -            return name;
    +            requestedAttributes = new ArrayList<>(5);
             }
     
             void addRequestedAttribute(String attrId) {
    @@ -260,9 +291,9 @@ void addRequestedAttribute(String attrId) {
              * @throws NamingException      if a naming exception occurs
              */
             byte[][] getValues(String attrId) throws NamingException {
    -            if (DEBUG && ((cacheHits + cacheMisses) % 50 == 0)) {
    -                System.out.println("Cache hits: " + cacheHits + "; misses: "
    -                        + cacheMisses);
    +            if (debug != null && Debug.isVerbose() && ((cacheHits + cacheMisses) % 50 == 0)) {
    +                debug.println("LDAPRequest Cache hits: " + cacheHits +
    +                    "; misses: " + cacheMisses);
                 }
                 String cacheKey = name + "|" + attrId;
                 byte[][] values = valueCache.get(cacheKey);
    @@ -294,11 +325,11 @@ private Map getValueMap() throws NamingException {
                 if (valueMap != null) {
                     return valueMap;
                 }
    -            if (DEBUG) {
    -                System.out.println("Request: " + name + ":" + requestedAttributes);
    +            if (debug != null && Debug.isVerbose()) {
    +                debug.println("LDAPRequest: " + name + ":" + requestedAttributes);
                     requests++;
                     if (requests % 5 == 0) {
    -                    System.out.println("LDAP requests: " + requests);
    +                    debug.println("LDAP requests: " + requests);
                     }
                 }
                 valueMap = new HashMap<>(8);
    @@ -325,6 +356,9 @@ private Map getValueMap() throws NamingException {
                             if (newDn != null && newDn.charAt(0) == '/') {
                                 newDn = newDn.substring(1);
                             }
    +                        // In JNDI, it is not possible to use an LdapName for
    +                        // the referral DN, so we must validate the syntax of
    +                        // the string DN.
                             checkName(newDn);
                         } catch (Exception e) {
                             throw new NamingException("Cannot follow referral to "
    @@ -369,36 +403,6 @@ private void cacheAttribute(String attrId, byte[][] values) {
                 String cacheKey = name + "|" + attrId;
                 valueCache.put(cacheKey, values);
             }
    -
    -        /**
    -         * Get the values for the given attribute. If the attribute is null
    -         * or does not contain any values, a zero length byte array is
    -         * returned. NOTE that it is assumed that all values are byte arrays.
    -         */
    -        private byte[][] getAttributeValues(Attribute attr)
    -                throws NamingException {
    -            byte[][] values;
    -            if (attr == null) {
    -                values = BB0;
    -            } else {
    -                values = new byte[attr.size()][];
    -                int i = 0;
    -                NamingEnumeration enum_ = attr.getAll();
    -                while (enum_.hasMore()) {
    -                    Object obj = enum_.next();
    -                    if (debug != null) {
    -                        if (obj instanceof String) {
    -                            debug.println("LDAPCertStore.getAttrValues() "
    -                                + "enum.next is a string!: " + obj);
    -                        }
    -                    }
    -                    byte[] value = (byte[])obj;
    -                    values[i++] = value;
    -                }
    -            }
    -            return values;
    -        }
    -
         }
     
         /*
    diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java b/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java
    index 4cabddad6cc..5b8321ae3d1 100644
    --- a/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java
    +++ b/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java
    @@ -34,6 +34,7 @@
     import java.net.URL;
     import java.util.Base64;
     import java.util.LinkedList;
    +import java.util.List;
     import java.util.Objects;
     import java.util.WeakHashMap;
     import java.net.http.HttpHeaders;
    @@ -261,23 +262,21 @@ public HttpRequestImpl response(Response r) throws IOException {
     
             boolean proxy = status == PROXY_UNAUTHORIZED;
             String authname = proxy ? "Proxy-Authenticate" : "WWW-Authenticate";
    -        String authval = hdrs.firstValue(authname).orElse(null);
    -        if (authval == null) {
    -            if (exchange.client().authenticator().isPresent()) {
    -                throw new IOException(authname + " header missing for response code " + status);
    -            } else {
    -                // No authenticator? let the caller deal with this.
    -                return null;
    +        List authvals = hdrs.allValues(authname);
    +        if (authvals.isEmpty() && exchange.client().authenticator().isPresent()) {
    +            throw new IOException(authname + " header missing for response code " + status);
    +        }
    +        String authval = null;
    +        for (String aval : authvals) {
    +            HeaderParser parser = new HeaderParser(aval);
    +            String scheme = parser.findKey(0);
    +            if (scheme.equalsIgnoreCase("Basic")) {
    +                authval = aval;
    +                break;
                 }
             }
    -
    -        HeaderParser parser = new HeaderParser(authval);
    -        String scheme = parser.findKey(0);
    -
    -        // TODO: Need to generalise from Basic only. Delegate to a provider class etc.
    -
    -        if (!scheme.equalsIgnoreCase("Basic")) {
    -            return null;   // error gets returned to app
    +        if (authval == null) {
    +            return null;
             }
     
             if (proxy) {
    diff --git a/src/java.security.jgss/share/classes/org/ietf/jgss/Oid.java b/src/java.security.jgss/share/classes/org/ietf/jgss/Oid.java
    index 25a255faa2e..05794c7927e 100644
    --- a/src/java.security.jgss/share/classes/org/ietf/jgss/Oid.java
    +++ b/src/java.security.jgss/share/classes/org/ietf/jgss/Oid.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2000, 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
    @@ -65,7 +65,7 @@ public class Oid {
         public Oid(String strOid) throws GSSException {
     
             try {
    -            oid = new ObjectIdentifier(strOid);
    +            oid = ObjectIdentifier.of(strOid);
                 derEncoding = null;
             } catch (Exception e) {
                 throw new GSSException(GSSException.FAILURE,
    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 088185d2040..97783739296 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
    @@ -132,6 +132,11 @@ public NegotiatorImpl(HttpCallerInfo hci) throws IOException {
                             "fallback to other scheme if allowed. Reason:");
                     e.printStackTrace();
                 }
    +            try {
    +                disposeContext();
    +            } catch (Exception ex) {
    +                //dispose context silently
    +            }
                 IOException ioe = new IOException("Negotiate support not initiated");
                 ioe.initCause(e);
                 throw ioe;
    @@ -156,6 +161,9 @@ public byte[] firstToken() {
         @Override
         public byte[] nextToken(byte[] token) throws IOException {
             try {
    +            if (context == null) {
    +                throw new IOException("Negotiate support cannot continue. Context is invalidated");
    +            }
                 return context.initSecContext(token, 0, token.length);
             } catch (GSSException e) {
                 if (DEBUG) {
    @@ -167,4 +175,26 @@ public byte[] nextToken(byte[] token) throws IOException {
                 throw ioe;
             }
         }
    +
    +    /**
    +     * Releases any system resources and cryptographic information stored in
    +     * the context object and invalidates the context.
    +     *
    +     * @throws IOException containing a reason of failure in the cause
    +     */
    +    @Override
    +    public void disposeContext() throws IOException {
    +        try {
    +            if (context != null) {
    +                context.dispose();
    +            }
    +        } catch (GSSException e) {
    +            if (DEBUG) {
    +                System.out.println("Cannot release resources. Reason:");
    +                e.printStackTrace();
    +            }
    +            throw new IOException("Cannot release resources", e);
    +        };
    +        context = null;
    +    }
     }
    diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/GSSContextImpl.java b/src/java.security.jgss/share/classes/sun/security/jgss/GSSContextImpl.java
    index 9521a33d6e3..e262b545b20 100644
    --- a/src/java.security.jgss/share/classes/sun/security/jgss/GSSContextImpl.java
    +++ b/src/java.security.jgss/share/classes/sun/security/jgss/GSSContextImpl.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2000, 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
    @@ -241,7 +241,7 @@ public int initSecContext(InputStream inStream,
                     mechCtxt.setChannelBinding(channelBindings);
                     mechCtxt.requestDelegPolicy(reqDelegPolicyState);
     
    -                objId = new ObjectIdentifier(mechOid.toString());
    +                objId = ObjectIdentifier.of(mechOid.toString());
     
                     currentState = IN_PROGRESS;
                     firstToken = true;
    diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/GSSNameImpl.java b/src/java.security.jgss/share/classes/sun/security/jgss/GSSNameImpl.java
    index e1e89059c5f..cb6248e81b3 100644
    --- a/src/java.security.jgss/share/classes/sun/security/jgss/GSSNameImpl.java
    +++ b/src/java.security.jgss/share/classes/sun/security/jgss/GSSNameImpl.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2000, 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
    @@ -412,7 +412,7 @@ public byte[] export() throws GSSException {
             ObjectIdentifier oid = null;
     
             try {
    -            oid = new ObjectIdentifier
    +            oid = ObjectIdentifier.of
                     (mechElement.getMechanism().toString());
             } catch (IOException e) {
                 throw new GSSExceptionImpl(GSSException.FAILURE,
    diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Token.java b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Token.java
    index ef812dab831..72f98f73107 100644
    --- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Token.java
    +++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Token.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2000, 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
    @@ -77,7 +77,7 @@ abstract class Krb5Token extends GSSToken {
     
         static {
             try {
    -            OID = new ObjectIdentifier(Krb5MechFactory.
    +            OID = ObjectIdentifier.of(Krb5MechFactory.
                                            GSS_KRB5_MECH_OID.toString());
             } catch (IOException ioe) {
               // should not happen
    diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoToken.java b/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoToken.java
    index 8683520227f..03ffcbe5cd0 100644
    --- a/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoToken.java
    +++ b/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoToken.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2005, 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
    @@ -68,7 +68,7 @@ static enum NegoResult {
     
         static {
             try {
    -            OID = new ObjectIdentifier(SpNegoMechFactory.
    +            OID = ObjectIdentifier.of(SpNegoMechFactory.
                                            GSS_SPNEGO_MECH_OID.toString());
             } catch (IOException ioe) {
               // should not happen
    diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java
    index 88274c1601b..7508eb14989 100644
    --- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java
    +++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2005, 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
    @@ -130,7 +130,7 @@ private GSSNameElement() {
                     DerOutputStream dout = new DerOutputStream();
                     Oid mech = cStub.getMech();
                     try {
    -                    dout.putOID(new ObjectIdentifier(mech.toString()));
    +                    dout.putOID(ObjectIdentifier.of(mech.toString()));
                     } catch (IOException e) {
                         throw new GSSExceptionImpl(GSSException.FAILURE, e);
                     }
    diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java
    index d2d5367f1b8..2779e1c7bf3 100644
    --- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java
    +++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2005, 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
    @@ -160,7 +160,7 @@ private byte[] retrieveToken(InputStream is, int mechTokenLen)
                     SunNativeProvider.debug("Precomputed mechToken length: " +
                                              mechTokenLen);
                     GSSHeader gssHeader = new GSSHeader
    -                    (new ObjectIdentifier(cStub.getMech().toString()),
    +                    (ObjectIdentifier.of(cStub.getMech().toString()),
                          mechTokenLen);
                     ByteArrayOutputStream baos = new ByteArrayOutputStream(600);
     
    diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java b/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java
    index cabaf0bcafd..25601885e00 100644
    --- a/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java
    +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java
    @@ -257,9 +257,14 @@ private byte[] sendIfPossible(byte[] obuf, String tempKdc, boolean useTCP)
                 } catch (Exception e) {
                     // OK
                 }
    -            if (ke != null && ke.getErrorCode() ==
    +            if (ke != null) {
    +                if (ke.getErrorCode() ==
                         Krb5.KRB_ERR_RESPONSE_TOO_BIG) {
    -                ibuf = send(obuf, tempKdc, true);
    +                    ibuf = send(obuf, tempKdc, true);
    +                } else if (ke.getErrorCode() ==
    +                        Krb5.KDC_ERR_SVC_UNAVAILABLE) {
    +                    throw new KrbException("A service is not available");
    +                }
                 }
                 KdcAccessibility.removeBad(tempKdc);
                 return ibuf;
    diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java
    index 8c0e813fe18..d0ebcc3f36b 100644
    --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java
    +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java
    @@ -248,6 +248,7 @@ public class Krb5 {
         public static final int KDC_ERR_KEY_EXPIRED          = 23;   //Password has expired - change password to reset
         public static final int KDC_ERR_PREAUTH_FAILED       = 24;   //Pre-authentication information was invalid
         public static final int KDC_ERR_PREAUTH_REQUIRED     = 25;   //Additional pre-authentication required
    +    public static final int KDC_ERR_SVC_UNAVAILABLE      = 29;   //A service is not available
         public static final int KRB_AP_ERR_BAD_INTEGRITY     = 31;   //Integrity check on decrypted field failed
         public static final int KRB_AP_ERR_TKT_EXPIRED       = 32;   //Ticket expired
         public static final int KRB_AP_ERR_TKT_NYV           = 33;   //Ticket not yet valid
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java
    index c18553fb85e..3e92b1cd41c 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
      */
     /*
      * Licensed to the Apache Software Foundation (ASF) under one or more
    @@ -26,2416 +26,3218 @@
      * Constants for the project, mostly defined in the JVM specification.
      *
      * @since 6.0 (intended to replace the Constants interface)
    - * @LastModified: May 2021
    + * @LastModified: May 2023
      */
     public final class Const {
     
    -  /**
    -   * Java class file format Magic number (0xCAFEBABE)
    -   *
    -   * @see 
    -   * The ClassFile Structure in The Java Virtual Machine Specification
    -   */
    -  public static final int JVM_CLASSFILE_MAGIC = 0xCAFEBABE;
    -
    -  /** Major version number of class files for Java 1.1.
    -   *  @see #MINOR_1_1
    -   *  */
    -  public static final short MAJOR_1_1 = 45;
    -
    -  /** Minor version number of class files for Java 1.1.
    -   *  @see #MAJOR_1_1
    -   *  */
    -  public static final short MINOR_1_1 = 3;
    -
    -  /** Major version number of class files for Java 1.2.
    -   *  @see #MINOR_1_2
    -   *  */
    -  public static final short MAJOR_1_2 = 46;
    -
    -  /** Minor version number of class files for Java 1.2.
    -   *  @see #MAJOR_1_2
    -   *  */
    -  public static final short MINOR_1_2 = 0;
    -
    -  /** Major version number of class files for Java 1.2.
    -   *  @see #MINOR_1_2
    -   *  */
    -  public static final short MAJOR_1_3 = 47;
    -
    -  /** Minor version number of class files for Java 1.3.
    -   *  @see #MAJOR_1_3
    -   *  */
    -  public static final short MINOR_1_3 = 0;
    -
    -  /** Major version number of class files for Java 1.3.
    -   *  @see #MINOR_1_3
    -   *  */
    -  public static final short MAJOR_1_4 = 48;
    -
    -  /** Minor version number of class files for Java 1.4.
    -   *  @see #MAJOR_1_4
    -   *  */
    -  public static final short MINOR_1_4 = 0;
    -
    -  /** Major version number of class files for Java 1.4.
    -   *  @see #MINOR_1_4
    -   *  */
    -  public static final short MAJOR_1_5 = 49;
    -
    -  /** Minor version number of class files for Java 1.5.
    -   *  @see #MAJOR_1_5
    -   *  */
    -  public static final short MINOR_1_5 = 0;
    -
    -  /** Major version number of class files for Java 1.6.
    -   *  @see #MINOR_1_6
    -   *  */
    -  public static final short MAJOR_1_6 = 50;
    -
    -  /** Minor version number of class files for Java 1.6.
    -   *  @see #MAJOR_1_6
    -   *  */
    -  public static final short MINOR_1_6 = 0;
    -
    -  /** Major version number of class files for Java 1.7.
    -   *  @see #MINOR_1_7
    -   *  */
    -  public static final short MAJOR_1_7 = 51;
    -
    -  /** Minor version number of class files for Java 1.7.
    -   *  @see #MAJOR_1_7
    -   *  */
    -  public static final short MINOR_1_7 = 0;
    -
    -  /** Major version number of class files for Java 1.8.
    -   *  @see #MINOR_1_8
    -   *  */
    -  public static final short MAJOR_1_8 = 52;
    -
    -  /** Minor version number of class files for Java 1.8.
    -   *  @see #MAJOR_1_8
    -   *  */
    -  public static final short MINOR_1_8 = 0;
    -
    -  /** Major version number of class files for Java 9.
    -   *  @see #MINOR_9
    -   *  */
    -  public static final short MAJOR_9 = 53;
    -
    -  /** Minor version number of class files for Java 9.
    -   *  @see #MAJOR_9
    -   *  */
    -  public static final short MINOR_9 = 0;
    -
    -  /**
    -   * @deprecated Use {@link #MAJOR_9} instead
    -   */
    -  @Deprecated
    -  public static final short MAJOR_1_9 = MAJOR_9;
    -
    -  /**
    -   * @deprecated Use {@link #MINOR_9} instead
    -   */
    -  @Deprecated
    -  public static final short MINOR_1_9 = MINOR_9;
    -
    -  /** Major version number of class files for Java 10.
    -   *  @see #MINOR_10
    -   *  */
    -  public static final short MAJOR_10 = 54;
    -
    -  /** Minor version number of class files for Java 10.
    -   *  @see #MAJOR_10
    -   *  */
    -  public static final short MINOR_10 = 0;
    -
    -  /** Major version number of class files for Java 11.
    -   *  @see #MINOR_11
    -   *  */
    -  public static final short MAJOR_11 = 55;
    -
    -  /** Minor version number of class files for Java 11.
    -   *  @see #MAJOR_11
    -   *  */
    -  public static final short MINOR_11 = 0;
    -
    -  /** Major version number of class files for Java 12.
    -   *  @see #MINOR_12
    -   *  */
    -  public static final short MAJOR_12 = 56;
    -
    -  /** Minor version number of class files for Java 12.
    -   *  @see #MAJOR_12
    -   *  */
    -  public static final short MINOR_12 = 0;
    -
    -  /** Major version number of class files for Java 13.
    -   *  @see #MINOR_13
    -   *  */
    -  public static final short MAJOR_13 = 57;
    -
    -  /** Minor version number of class files for Java 13.
    -   *  @see #MAJOR_13
    -   *  */
    -  public static final short MINOR_13 = 0;
    -
    -  /** Major version number of class files for Java 14.
    -   *  @see #MINOR_14
    -   *  @since 6.4.0
    -   *  */
    -  public static final short MAJOR_14 = 58;
    -
    -  /** Minor version number of class files for Java 14.
    -   *  @see #MAJOR_14
    -   *  @since 6.4.0
    -   *  */
    -  public static final short MINOR_14 = 0;
    -
    -  /** Default major version number.  Class file is for Java 1.1.
    -   *  @see #MAJOR_1_1
    -   *  */
    -  public static final short MAJOR = MAJOR_1_1;
    -
    -  /** Default major version number.  Class file is for Java 1.1.
    -   *  @see #MAJOR_1_1
    -   *  */
    -  public static final short MINOR     = MINOR_1_1;
    -
    -  /** Maximum value for an unsigned short.
    -   */
    -  public static final int MAX_SHORT = 65535; // 2^16 - 1
    -
    -  /** Maximum value for an unsigned byte.
    -   */
    -  public static final int MAX_BYTE  = 255; // 2^8 - 1
    -
    -  /** One of the access flags for fields, methods, or classes.
    -   *
    -   *  @see 
    -   *  Flag definitions for Classes in the Java Virtual Machine Specification (Java SE 9 Edition).
    -   *  @see 
    -   *  Flag definitions for Fields in the Java Virtual Machine Specification (Java SE 9 Edition).
    -   *  @see 
    -   *  Flag definitions for Methods in the Java Virtual Machine Specification (Java SE 9 Edition).
    -   *  @see 
    -   *  Flag definitions for Inner Classes in the Java Virtual Machine Specification (Java SE 9 Edition).
    -   */
    -  public static final short ACC_PUBLIC       = 0x0001;
    -
    -  /** One of the access flags for fields, methods, or classes.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_PRIVATE      = 0x0002;
    -
    -  /** One of the access flags for fields, methods, or classes.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_PROTECTED    = 0x0004;
    -
    -  /** One of the access flags for fields, methods, or classes.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_STATIC       = 0x0008;
    -
    -  /** One of the access flags for fields, methods, or classes.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_FINAL        = 0x0010;
    -
    -  /** One of the access flags for the Module attribute.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_OPEN         = 0x0020;
    -
    -  /** One of the access flags for classes.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_SUPER        = 0x0020;
    -
    -  /** One of the access flags for methods.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_SYNCHRONIZED = 0x0020;
    -
    -  /** One of the access flags for the Module attribute.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_TRANSITIVE   = 0x0020;
    -
    -  /** One of the access flags for methods.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_BRIDGE       = 0x0040;
    -
    -  /** One of the access flags for the Module attribute.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_STATIC_PHASE = 0x0040;
    -
    -  /** One of the access flags for fields.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_VOLATILE     = 0x0040;
    -
    -  /** One of the access flags for fields.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_TRANSIENT    = 0x0080;
    -
    -  /** One of the access flags for methods.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_VARARGS      = 0x0080;
    -
    -  /** One of the access flags for methods.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_NATIVE       = 0x0100;
    -
    -  /** One of the access flags for classes.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_INTERFACE    = 0x0200;
    -
    -  /** One of the access flags for methods or classes.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_ABSTRACT     = 0x0400;
    -
    -  /** One of the access flags for methods.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_STRICT       = 0x0800;
    -
    -  /** One of the access flags for fields, methods, classes, MethodParameter attribute, or Module attribute.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_SYNTHETIC    = 0x1000;
    -
    -  /** One of the access flags for classes.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_ANNOTATION   = 0x2000;
    -
    -  /** One of the access flags for fields or classes.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_ENUM         = 0x4000;
    -
    -  // Applies to classes compiled by new compilers only
    -  /** One of the access flags for MethodParameter or Module attributes.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_MANDATED     = (short) 0x8000;
    -
    -  /** One of the access flags for classes.
    -   *  @see #ACC_PUBLIC
    -   */
    -  public static final short ACC_MODULE       = (short) 0x8000;
    -
    -  /** One of the access flags for fields, methods, or classes.
    -   *  @see #ACC_PUBLIC
    -   *  @deprecated Use {@link #MAX_ACC_FLAG_I}
    -   */
    -  @Deprecated
    -  public static final short MAX_ACC_FLAG     = ACC_ENUM;
    -
    -  /** One of the access flags for fields, methods, or classes.
    -   * ACC_MODULE is negative as a short.
    -   * @see #ACC_PUBLIC
    -   * @since 6.4.0
    -   */
    -  public static final int MAX_ACC_FLAG_I = 0x8000; // ACC_MODULE is negative as a short
    -
    -  // Note that do to overloading:
    -  // 'synchronized' is for methods, might be 'open' (if Module), 'super' (if class), or 'transitive' (if Module).
    -  // 'volatile'     is for fields,  might be 'bridge' (if method) or 'static_phase' (if Module)
    -  // 'transient'    is for fields,  might be 'varargs' (if method)
    -  // 'module'       is for classes, might be 'mandated' (if Module or MethodParameters)
    -  /**
    -   * The names of the access flags.
    -   */
    -  private static final String[] ACCESS_NAMES = {
    -    "public", "private", "protected", "static", "final", "synchronized",
    -    "volatile", "transient", "native", "interface", "abstract", "strictfp",
    -    "synthetic", "annotation", "enum", "module"
    -  };
    -
    -  /** @since 6.0 */
    -  public static final int ACCESS_NAMES_LENGTH = ACCESS_NAMES.length;
    -
    -  /**
    -   * @param index
    -   * @return the ACCESS_NAMES entry at the given index
    -   * @since 6.0
    -   */
    -  public static String getAccessName(final int index) {
    -      return ACCESS_NAMES[index];
    -  }
    -
    -  /*
    -   * The description of the constant pool is at:
    -   * http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4
    -   * References below are to the individual sections
    -   */
    -
    -  /**
    -   * Marks a constant pool entry as type UTF-8.
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   */
    -  public static final byte CONSTANT_Utf8               = 1;
    -
    -  /**
    -   * Marks a constant pool entry as type Integer.
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   */
    -  public static final byte CONSTANT_Integer            = 3;
    -
    -  /**
    -   * Marks a constant pool entry as type Float.
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   */
    -  public static final byte CONSTANT_Float              = 4;
    -
    -  /**
    -   * Marks a constant pool entry as type Long.
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   */
    -  public static final byte CONSTANT_Long               = 5;
    -
    -  /**
    -   * Marks a constant pool entry as type Double.
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   */
    -  public static final byte CONSTANT_Double             = 6;
    -
    -  /**
    -   * Marks a constant pool entry as a Class
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   */
    -  public static final byte CONSTANT_Class              = 7;
    -
    -  /**
    -   * Marks a constant pool entry as a Field Reference.
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   */
    -  public static final byte CONSTANT_Fieldref           = 9;
    -
    -  /**
    -   * Marks a constant pool entry as type String
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   */
    -  public static final byte CONSTANT_String             = 8;
    -
    -  /** Marks a constant pool entry as a Method Reference.
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification */
    -  public static final byte CONSTANT_Methodref          = 10;
    -
    -  /**
    -   * Marks a constant pool entry as an Interface Method Reference.
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   */
    -  public static final byte CONSTANT_InterfaceMethodref = 11;
    -
    -  /** Marks a constant pool entry as a name and type.
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification */
    -  public static final byte CONSTANT_NameAndType        = 12;
    -
    -  /**
    -   * Marks a constant pool entry as a Method Handle.
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   */
    -  public static final byte CONSTANT_MethodHandle       = 15;
    -
    -  /**
    -   * Marks a constant pool entry as a Method Type.
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   */
    -  public static final byte CONSTANT_MethodType         = 16;
    -
    -  /**
    -   * Marks a constant pool entry as dynamically computed.
    -   * @see  
    -   * Change request for JEP 309
    -   * @since 6.3
    -   */
    -  public static final byte CONSTANT_Dynamic            = 17;
    -
    -  /**
    -   * Marks a constant pool entry as an Invoke Dynamic
    -   * @see  
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   */
    -  public static final byte CONSTANT_InvokeDynamic      = 18;
    -
    -  /**
    -   * Marks a constant pool entry as a Module Reference.
    -   * @see 
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   * @since 6.1
    -   */
    -  public static final byte CONSTANT_Module             = 19;
    -
    -  /**
    -   * Marks a constant pool entry as a Package Reference.
    -   * @see 
    -   * The Constant Pool in The Java Virtual Machine Specification
    -   * @since 6.1
    -   */
    -  public static final byte CONSTANT_Package            = 20;
    -
    -  /**
    -   * The names of the types of entries in a constant pool.
    -   * Use getConstantName instead
    -   */
    -  private static final String[] CONSTANT_NAMES = {
    -    "", "CONSTANT_Utf8", "", "CONSTANT_Integer",
    -    "CONSTANT_Float", "CONSTANT_Long", "CONSTANT_Double",
    -    "CONSTANT_Class", "CONSTANT_String", "CONSTANT_Fieldref",
    -    "CONSTANT_Methodref", "CONSTANT_InterfaceMethodref",
    -    "CONSTANT_NameAndType", "", "", "CONSTANT_MethodHandle",
    -    "CONSTANT_MethodType", "CONSTANT_Dynamic", "CONSTANT_InvokeDynamic",
    -    "CONSTANT_Module", "CONSTANT_Package"};
    -
    -  /**
    -   *
    -   * @param index
    -   * @return the CONSTANT_NAMES entry at the given index
    -   * @since 6.0
    -   */
    -  public static String getConstantName(final int index) {
    -      return CONSTANT_NAMES[index];
    -  }
    -
    -  /** The name of the static initializer, also called "class
    -   *  initialization method" or "interface initialization
    -   *   method". This is "<clinit>".
    -   */
    -  public static final String STATIC_INITIALIZER_NAME = "";
    -
    -  /** The name of every constructor method in a class, also called
    -   * "instance initialization method". This is "<init>".
    -   */
    -  public static final String CONSTRUCTOR_NAME = "";
    -
    -  /**
    -   * The names of the interfaces implemented by arrays
    -   */
    -  private static final String[] INTERFACES_IMPLEMENTED_BY_ARRAYS = {"java.lang.Cloneable", "java.io.Serializable"};
    -
    -  /**
    -   * @since 6.0
    -   */
    -  public static Iterable getInterfacesImplementedByArrays() {
    -      return Collections.unmodifiableList(Arrays.asList(INTERFACES_IMPLEMENTED_BY_ARRAYS));
    -  }
    -
    -  /**
    -   * Maximum Constant Pool entries.
    -   * One of the limitations of the Java Virtual Machine.
    -   * @see 
    -   * The Java Virtual Machine Specification, Java SE 8 Edition, page 330, chapter 4.11.
    -   */
    -  public static final int MAX_CP_ENTRIES     = 65535;
    -
    -  /**
    -   * Maximum code size (plus one; the code size must be LESS than this)
    -   * One of the limitations of the Java Virtual Machine.
    -   * Note vmspec2 page 152 ("Limitations") says:
    -   * "The amount of code per non-native, non-abstract method is limited to 65536 bytes by
    -   * the sizes of the indices in the exception_table of the Code attribute (4.7.3),
    -   * in the LineNumberTable attribute (4.7.8), and in the LocalVariableTable attribute (4.7.9)."
    -   * However this should be taken as an upper limit rather than the defined maximum.
    -   * On page 134 (4.8.1 Static Constants) of the same spec, it says:
    -   * "The value of the code_length item must be less than 65536."
    -   * The entry in the Limitations section has been removed from later versions of the spec;
    -   * it is not present in the Java SE 8 edition.
    -   *
    -   * @see 
    -   * The Java Virtual Machine Specification, Java SE 8 Edition, page 104, chapter 4.7.
    -   */
    -  public static final int MAX_CODE_SIZE      = 65536; //bytes
    -
    -  /**
    -   * The maximum number of dimensions in an array ({@value}).
    -   * One of the limitations of the Java Virtual Machine.
    -   *
    -   * @see 
    -   * Field Descriptors in The Java Virtual Machine Specification
    -   */
    -  public static final int MAX_ARRAY_DIMENSIONS = 255;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short NOP              = 0;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ACONST_NULL      = 1;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ICONST_M1        = 2;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ICONST_0         = 3;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ICONST_1         = 4;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ICONST_2         = 5;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ICONST_3         = 6;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ICONST_4         = 7;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ICONST_5         = 8;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LCONST_0         = 9;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LCONST_1         = 10;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FCONST_0         = 11;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FCONST_1         = 12;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FCONST_2         = 13;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DCONST_0         = 14;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DCONST_1         = 15;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short BIPUSH           = 16;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short SIPUSH           = 17;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LDC              = 18;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LDC_W            = 19;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LDC2_W           = 20;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ILOAD            = 21;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LLOAD            = 22;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FLOAD            = 23;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DLOAD            = 24;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ALOAD            = 25;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ILOAD_0          = 26;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ILOAD_1          = 27;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ILOAD_2          = 28;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ILOAD_3          = 29;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LLOAD_0          = 30;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LLOAD_1          = 31;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LLOAD_2          = 32;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LLOAD_3          = 33;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FLOAD_0          = 34;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FLOAD_1          = 35;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FLOAD_2          = 36;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FLOAD_3          = 37;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DLOAD_0          = 38;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DLOAD_1          = 39;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DLOAD_2          = 40;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DLOAD_3          = 41;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ALOAD_0          = 42;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ALOAD_1          = 43;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ALOAD_2          = 44;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ALOAD_3          = 45;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IALOAD           = 46;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LALOAD           = 47;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FALOAD           = 48;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DALOAD           = 49;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short AALOAD           = 50;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short BALOAD           = 51;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short CALOAD           = 52;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short SALOAD           = 53;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ISTORE           = 54;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LSTORE           = 55;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FSTORE           = 56;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DSTORE           = 57;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ASTORE           = 58;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ISTORE_0         = 59;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ISTORE_1         = 60;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ISTORE_2         = 61;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ISTORE_3         = 62;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LSTORE_0         = 63;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LSTORE_1         = 64;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LSTORE_2         = 65;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LSTORE_3         = 66;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FSTORE_0         = 67;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FSTORE_1         = 68;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FSTORE_2         = 69;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FSTORE_3         = 70;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DSTORE_0         = 71;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DSTORE_1         = 72;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DSTORE_2         = 73;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DSTORE_3         = 74;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ASTORE_0         = 75;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ASTORE_1         = 76;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ASTORE_2         = 77;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ASTORE_3         = 78;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IASTORE          = 79;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LASTORE          = 80;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FASTORE          = 81;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DASTORE          = 82;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short AASTORE          = 83;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short BASTORE          = 84;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short CASTORE          = 85;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short SASTORE          = 86;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short POP              = 87;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short POP2             = 88;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DUP              = 89;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DUP_X1           = 90;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DUP_X2           = 91;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DUP2             = 92;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DUP2_X1          = 93;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DUP2_X2          = 94;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short SWAP             = 95;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IADD             = 96;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LADD             = 97;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FADD             = 98;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DADD             = 99;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ISUB             = 100;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LSUB             = 101;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FSUB             = 102;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DSUB             = 103;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IMUL             = 104;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LMUL             = 105;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FMUL             = 106;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DMUL             = 107;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IDIV             = 108;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LDIV             = 109;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FDIV             = 110;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DDIV             = 111;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IREM             = 112;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LREM             = 113;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FREM             = 114;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DREM             = 115;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short INEG             = 116;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LNEG             = 117;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FNEG             = 118;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DNEG             = 119;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ISHL             = 120;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LSHL             = 121;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ISHR             = 122;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LSHR             = 123;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IUSHR            = 124;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LUSHR            = 125;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IAND             = 126;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LAND             = 127;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IOR              = 128;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LOR              = 129;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IXOR             = 130;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LXOR             = 131;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IINC             = 132;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short I2L              = 133;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short I2F              = 134;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short I2D              = 135;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short L2I              = 136;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short L2F              = 137;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short L2D              = 138;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short F2I              = 139;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short F2L              = 140;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short F2D              = 141;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short D2I              = 142;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short D2L              = 143;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short D2F              = 144;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short I2B              = 145;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short INT2BYTE         = 145; // Old notation
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short I2C              = 146;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short INT2CHAR         = 146; // Old notation
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short I2S              = 147;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short INT2SHORT        = 147; // Old notation
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LCMP             = 148;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FCMPL            = 149;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FCMPG            = 150;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DCMPL            = 151;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DCMPG            = 152;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IFEQ             = 153;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IFNE             = 154;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IFLT             = 155;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IFGE             = 156;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IFGT             = 157;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IFLE             = 158;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IF_ICMPEQ        = 159;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IF_ICMPNE        = 160;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IF_ICMPLT        = 161;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IF_ICMPGE        = 162;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IF_ICMPGT        = 163;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IF_ICMPLE        = 164;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IF_ACMPEQ        = 165;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IF_ACMPNE        = 166;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short GOTO             = 167;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short JSR              = 168;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short RET              = 169;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short TABLESWITCH      = 170;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LOOKUPSWITCH     = 171;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IRETURN          = 172;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short LRETURN          = 173;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short FRETURN          = 174;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short DRETURN          = 175;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ARETURN          = 176;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short RETURN           = 177;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short GETSTATIC        = 178;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short PUTSTATIC        = 179;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short GETFIELD         = 180;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short PUTFIELD         = 181;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short INVOKEVIRTUAL    = 182;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short INVOKESPECIAL    = 183;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short INVOKENONVIRTUAL = 183; // Old name in JDK 1.0
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short INVOKESTATIC     = 184;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short INVOKEINTERFACE  = 185;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short INVOKEDYNAMIC    = 186;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short NEW              = 187;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short NEWARRAY         = 188;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ANEWARRAY        = 189;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ARRAYLENGTH      = 190;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short ATHROW           = 191;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short CHECKCAST        = 192;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short INSTANCEOF       = 193;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short MONITORENTER     = 194;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short MONITOREXIT      = 195;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short WIDE             = 196;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short MULTIANEWARRAY   = 197;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IFNULL           = 198;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short IFNONNULL        = 199;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short GOTO_W           = 200;
    -
    -  /** Java VM opcode.
    -   * @see 
    -   * Opcode definitions in The Java Virtual Machine Specification */
    -  public static final short JSR_W            = 201;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Reserved opcodes in the Java Virtual Machine Specification */
    -  public static final short BREAKPOINT                = 202;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short LDC_QUICK                 = 203;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short LDC_W_QUICK               = 204;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short LDC2_W_QUICK              = 205;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short GETFIELD_QUICK            = 206;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short PUTFIELD_QUICK            = 207;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short GETFIELD2_QUICK           = 208;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short PUTFIELD2_QUICK           = 209;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short GETSTATIC_QUICK           = 210;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short PUTSTATIC_QUICK           = 211;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short GETSTATIC2_QUICK          = 212;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short PUTSTATIC2_QUICK          = 213;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short INVOKEVIRTUAL_QUICK       = 214;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short INVOKENONVIRTUAL_QUICK    = 215;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short INVOKESUPER_QUICK         = 216;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short INVOKESTATIC_QUICK        = 217;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short INVOKEINTERFACE_QUICK     = 218;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short INVOKEVIRTUALOBJECT_QUICK = 219;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short NEW_QUICK                 = 221;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short ANEWARRAY_QUICK           = 222;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short MULTIANEWARRAY_QUICK      = 223;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short CHECKCAST_QUICK           = 224;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short INSTANCEOF_QUICK          = 225;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short INVOKEVIRTUAL_QUICK_W     = 226;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short GETFIELD_QUICK_W          = 227;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    -   * @see 
    -   * Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */
    -  public static final short PUTFIELD_QUICK_W          = 228;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Reserved opcodes in the Java Virtual Machine Specification */
    -  public static final short IMPDEP1                   = 254;
    -
    -  /** JVM internal opcode.
    -   * @see 
    -   * Reserved opcodes in the Java Virtual Machine Specification */
    -  public static final short IMPDEP2                   = 255;
    -
    -  /**
    -   * BCEL virtual instruction for pushing an arbitrary data type onto the stack.  Will be converted to the appropriate JVM
    -   * opcode when the class is dumped.
    -   */
    -  public static final short PUSH             = 4711;
    -
    -  /**
    -   * BCEL virtual instruction for either LOOKUPSWITCH or TABLESWITCH.  Will be converted to the appropriate JVM
    -   * opcode when the class is dumped.
    -   */
    -  public static final short SWITCH           = 4712;
    -
    -  /** Illegal opcode. */
    -  public static final short  UNDEFINED      = -1;
    -
    -  /** Illegal opcode. */
    -  public static final short  UNPREDICTABLE  = -2;
    -
    -  /** Illegal opcode. */
    -  public static final short  RESERVED       = -3;
    -
    -  /** Mnemonic for an illegal opcode. */
    -  public static final String ILLEGAL_OPCODE = "";
    -
    -  /** Mnemonic for an illegal type. */
    -  public static final String ILLEGAL_TYPE   = "";
    -
    -  /** Boolean data type.
    -   * @see 
    -   * Static Constraints in the Java Virtual Machine Specification */
    -  public static final byte T_BOOLEAN = 4;
    -
    -  /** Char data type.
    -   * @see 
    -   * Static Constraints in the Java Virtual Machine Specification */
    -  public static final byte T_CHAR    = 5;
    -
    -  /** Float data type.
    -   * @see 
    -   * Static Constraints in the Java Virtual Machine Specification */
    -  public static final byte T_FLOAT   = 6;
    -
    -  /** Double data type.
    -   * @see 
    -   * Static Constraints in the Java Virtual Machine Specification */
    -  public static final byte T_DOUBLE  = 7;
    -
    -  /** Byte data type.
    -   * @see 
    -   * Static Constraints in the Java Virtual Machine Specification */
    -  public static final byte T_BYTE    = 8;
    -
    -  /** Short data type.
    -   * @see 
    -   * Static Constraints in the Java Virtual Machine Specification */
    -  public static final byte T_SHORT   = 9;
    -
    -  /** Int data type.
    -   * @see 
    -   * Static Constraints in the Java Virtual Machine Specification */
    -  public static final byte T_INT     = 10;
    -
    -  /** Long data type.
    -   * @see 
    -   * Static Constraints in the Java Virtual Machine Specification */
    -  public static final byte T_LONG    = 11;
    -
    -  /** Void data type (non-standard). */
    -  public static final byte T_VOID      = 12; // Non-standard
    -
    -  /** Array data type. */
    -  public static final byte T_ARRAY     = 13;
    -
    -  /** Object data type. */
    -  public static final byte T_OBJECT    = 14;
    -
    -  /** Reference data type (deprecated). */
    -  public static final byte T_REFERENCE = 14; // Deprecated
    -
    -  /** Unknown data type. */
    -  public static final byte T_UNKNOWN   = 15;
    -
    -  /** Address data type. */
    -  public static final byte T_ADDRESS   = 16;
    -
    -  /** The primitive type names corresponding to the T_XX constants,
    -   * e.g., TYPE_NAMES[T_INT] = "int"
    -   */
    -  private static final String[] TYPE_NAMES = {
    -    ILLEGAL_TYPE, ILLEGAL_TYPE,  ILLEGAL_TYPE, ILLEGAL_TYPE,
    -    "boolean", "char", "float", "double", "byte", "short", "int", "long",
    -    "void", "array", "object", "unknown", "address"
    -  };
    -
    -  /**
    -   * The primitive type names corresponding to the T_XX constants,
    -   * e.g., TYPE_NAMES[T_INT] = "int"
    -   * @param index
    -   * @return the type name
    -   * @since 6.0
    -   */
    -  public static String getTypeName(final int index) {
    -      return TYPE_NAMES[index];
    -  }
    -
    -  /** The primitive class names corresponding to the T_XX constants,
    -   * e.g., CLASS_TYPE_NAMES[T_INT] = "java.lang.Integer"
    -   */
    -  private static final String[] CLASS_TYPE_NAMES = {
    -    ILLEGAL_TYPE, ILLEGAL_TYPE,  ILLEGAL_TYPE, ILLEGAL_TYPE,
    -    "java.lang.Boolean", "java.lang.Character", "java.lang.Float",
    -    "java.lang.Double", "java.lang.Byte", "java.lang.Short",
    -    "java.lang.Integer", "java.lang.Long", "java.lang.Void",
    -    ILLEGAL_TYPE, ILLEGAL_TYPE,  ILLEGAL_TYPE,  ILLEGAL_TYPE
    -  };
    -
    -  /**
    -   * The primitive class names corresponding to the T_XX constants,
    -   * e.g., CLASS_TYPE_NAMES[T_INT] = "java.lang.Integer"
    -   * @param index
    -   * @return the class name
    -   * @since 6.0
    -   */
    -  public static String getClassTypeName(final int index) {
    -      return CLASS_TYPE_NAMES[index];
    -  }
    -
    -  /** The signature characters corresponding to primitive types,
    -   * e.g., SHORT_TYPE_NAMES[T_INT] = "I"
    -   */
    -  private static final String[] SHORT_TYPE_NAMES = {
    -    ILLEGAL_TYPE, ILLEGAL_TYPE,  ILLEGAL_TYPE, ILLEGAL_TYPE,
    -    "Z", "C", "F", "D", "B", "S", "I", "J",
    -    "V", ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE
    -  };
    -
    -  /**
    -   *
    -   * @param index
    -   * @return the short type name
    -   * @since 6.0
    -   */
    -  public static String getShortTypeName(final int index) {
    -      return SHORT_TYPE_NAMES[index];
    -  }
    -
    -
    -  /**
    -   * Number of byte code operands for each opcode, i.e., number of bytes after the tag byte
    -   * itself.  Indexed by opcode, so NO_OF_OPERANDS[BIPUSH] = the number of operands for a bipush
    -   * instruction.
    -   */
    -  private static final short[] NO_OF_OPERANDS = {
    -    0/*nop*/, 0/*aconst_null*/, 0/*iconst_m1*/, 0/*iconst_0*/,
    -    0/*iconst_1*/, 0/*iconst_2*/, 0/*iconst_3*/, 0/*iconst_4*/,
    -    0/*iconst_5*/, 0/*lconst_0*/, 0/*lconst_1*/, 0/*fconst_0*/,
    -    0/*fconst_1*/, 0/*fconst_2*/, 0/*dconst_0*/, 0/*dconst_1*/,
    -    1/*bipush*/, 2/*sipush*/, 1/*ldc*/, 2/*ldc_w*/, 2/*ldc2_w*/,
    -    1/*iload*/, 1/*lload*/, 1/*fload*/, 1/*dload*/, 1/*aload*/,
    -    0/*iload_0*/, 0/*iload_1*/, 0/*iload_2*/, 0/*iload_3*/,
    -    0/*lload_0*/, 0/*lload_1*/, 0/*lload_2*/, 0/*lload_3*/,
    -    0/*fload_0*/, 0/*fload_1*/, 0/*fload_2*/, 0/*fload_3*/,
    -    0/*dload_0*/, 0/*dload_1*/, 0/*dload_2*/, 0/*dload_3*/,
    -    0/*aload_0*/, 0/*aload_1*/, 0/*aload_2*/, 0/*aload_3*/,
    -    0/*iaload*/, 0/*laload*/, 0/*faload*/, 0/*daload*/,
    -    0/*aaload*/, 0/*baload*/, 0/*caload*/, 0/*saload*/,
    -    1/*istore*/, 1/*lstore*/, 1/*fstore*/, 1/*dstore*/,
    -    1/*astore*/, 0/*istore_0*/, 0/*istore_1*/, 0/*istore_2*/,
    -    0/*istore_3*/, 0/*lstore_0*/, 0/*lstore_1*/, 0/*lstore_2*/,
    -    0/*lstore_3*/, 0/*fstore_0*/, 0/*fstore_1*/, 0/*fstore_2*/,
    -    0/*fstore_3*/, 0/*dstore_0*/, 0/*dstore_1*/, 0/*dstore_2*/,
    -    0/*dstore_3*/, 0/*astore_0*/, 0/*astore_1*/, 0/*astore_2*/,
    -    0/*astore_3*/, 0/*iastore*/, 0/*lastore*/, 0/*fastore*/,
    -    0/*dastore*/, 0/*aastore*/, 0/*bastore*/, 0/*castore*/,
    -    0/*sastore*/, 0/*pop*/, 0/*pop2*/, 0/*dup*/, 0/*dup_x1*/,
    -    0/*dup_x2*/, 0/*dup2*/, 0/*dup2_x1*/, 0/*dup2_x2*/, 0/*swap*/,
    -    0/*iadd*/, 0/*ladd*/, 0/*fadd*/, 0/*dadd*/, 0/*isub*/,
    -    0/*lsub*/, 0/*fsub*/, 0/*dsub*/, 0/*imul*/, 0/*lmul*/,
    -    0/*fmul*/, 0/*dmul*/, 0/*idiv*/, 0/*ldiv*/, 0/*fdiv*/,
    -    0/*ddiv*/, 0/*irem*/, 0/*lrem*/, 0/*frem*/, 0/*drem*/,
    -    0/*ineg*/, 0/*lneg*/, 0/*fneg*/, 0/*dneg*/, 0/*ishl*/,
    -    0/*lshl*/, 0/*ishr*/, 0/*lshr*/, 0/*iushr*/, 0/*lushr*/,
    -    0/*iand*/, 0/*land*/, 0/*ior*/, 0/*lor*/, 0/*ixor*/, 0/*lxor*/,
    -    2/*iinc*/, 0/*i2l*/, 0/*i2f*/, 0/*i2d*/, 0/*l2i*/, 0/*l2f*/,
    -    0/*l2d*/, 0/*f2i*/, 0/*f2l*/, 0/*f2d*/, 0/*d2i*/, 0/*d2l*/,
    -    0/*d2f*/, 0/*i2b*/, 0/*i2c*/, 0/*i2s*/, 0/*lcmp*/, 0/*fcmpl*/,
    -    0/*fcmpg*/, 0/*dcmpl*/, 0/*dcmpg*/, 2/*ifeq*/, 2/*ifne*/,
    -    2/*iflt*/, 2/*ifge*/, 2/*ifgt*/, 2/*ifle*/, 2/*if_icmpeq*/,
    -    2/*if_icmpne*/, 2/*if_icmplt*/, 2/*if_icmpge*/, 2/*if_icmpgt*/,
    -    2/*if_icmple*/, 2/*if_acmpeq*/, 2/*if_acmpne*/, 2/*goto*/,
    -    2/*jsr*/, 1/*ret*/, UNPREDICTABLE/*tableswitch*/, UNPREDICTABLE/*lookupswitch*/,
    -    0/*ireturn*/, 0/*lreturn*/, 0/*freturn*/,
    -    0/*dreturn*/, 0/*areturn*/, 0/*return*/,
    -    2/*getstatic*/, 2/*putstatic*/, 2/*getfield*/,
    -    2/*putfield*/, 2/*invokevirtual*/, 2/*invokespecial*/, 2/*invokestatic*/,
    -    4/*invokeinterface*/, 4/*invokedynamic*/, 2/*new*/,
    -    1/*newarray*/, 2/*anewarray*/,
    -    0/*arraylength*/, 0/*athrow*/, 2/*checkcast*/,
    -    2/*instanceof*/, 0/*monitorenter*/,
    -    0/*monitorexit*/, UNPREDICTABLE/*wide*/, 3/*multianewarray*/,
    -    2/*ifnull*/, 2/*ifnonnull*/, 4/*goto_w*/,
    -    4/*jsr_w*/, 0/*breakpoint*/, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, RESERVED/*impdep1*/, RESERVED/*impdep2*/
    -  };
    -
    -  /**
    -   *
    -   * @param index
    -   * @return Number of byte code operands
    -   * @since 6.0
    -   */
    -  public static short getNoOfOperands(final int index) {
    -      return NO_OF_OPERANDS[index];
    -  }
    -
    -  /**
    -   * How the byte code operands are to be interpreted for each opcode.
    -   * Indexed by opcode.  TYPE_OF_OPERANDS[ILOAD] = an array of shorts
    -   * describing the data types for the instruction.
    -   */
    -  private static final short[][] TYPE_OF_OPERANDS = {
    -    {}/*nop*/, {}/*aconst_null*/, {}/*iconst_m1*/, {}/*iconst_0*/,
    -    {}/*iconst_1*/, {}/*iconst_2*/, {}/*iconst_3*/, {}/*iconst_4*/,
    -    {}/*iconst_5*/, {}/*lconst_0*/, {}/*lconst_1*/, {}/*fconst_0*/,
    -    {}/*fconst_1*/, {}/*fconst_2*/, {}/*dconst_0*/, {}/*dconst_1*/,
    -    {T_BYTE}/*bipush*/, {T_SHORT}/*sipush*/, {T_BYTE}/*ldc*/,
    -    {T_SHORT}/*ldc_w*/, {T_SHORT}/*ldc2_w*/,
    -    {T_BYTE}/*iload*/, {T_BYTE}/*lload*/, {T_BYTE}/*fload*/,
    -    {T_BYTE}/*dload*/, {T_BYTE}/*aload*/, {}/*iload_0*/,
    -    {}/*iload_1*/, {}/*iload_2*/, {}/*iload_3*/, {}/*lload_0*/,
    -    {}/*lload_1*/, {}/*lload_2*/, {}/*lload_3*/, {}/*fload_0*/,
    -    {}/*fload_1*/, {}/*fload_2*/, {}/*fload_3*/, {}/*dload_0*/,
    -    {}/*dload_1*/, {}/*dload_2*/, {}/*dload_3*/, {}/*aload_0*/,
    -    {}/*aload_1*/, {}/*aload_2*/, {}/*aload_3*/, {}/*iaload*/,
    -    {}/*laload*/, {}/*faload*/, {}/*daload*/, {}/*aaload*/,
    -    {}/*baload*/, {}/*caload*/, {}/*saload*/, {T_BYTE}/*istore*/,
    -    {T_BYTE}/*lstore*/, {T_BYTE}/*fstore*/, {T_BYTE}/*dstore*/,
    -    {T_BYTE}/*astore*/, {}/*istore_0*/, {}/*istore_1*/,
    -    {}/*istore_2*/, {}/*istore_3*/, {}/*lstore_0*/, {}/*lstore_1*/,
    -    {}/*lstore_2*/, {}/*lstore_3*/, {}/*fstore_0*/, {}/*fstore_1*/,
    -    {}/*fstore_2*/, {}/*fstore_3*/, {}/*dstore_0*/, {}/*dstore_1*/,
    -    {}/*dstore_2*/, {}/*dstore_3*/, {}/*astore_0*/, {}/*astore_1*/,
    -    {}/*astore_2*/, {}/*astore_3*/, {}/*iastore*/, {}/*lastore*/,
    -    {}/*fastore*/, {}/*dastore*/, {}/*aastore*/, {}/*bastore*/,
    -    {}/*castore*/, {}/*sastore*/, {}/*pop*/, {}/*pop2*/, {}/*dup*/,
    -    {}/*dup_x1*/, {}/*dup_x2*/, {}/*dup2*/, {}/*dup2_x1*/,
    -    {}/*dup2_x2*/, {}/*swap*/, {}/*iadd*/, {}/*ladd*/, {}/*fadd*/,
    -    {}/*dadd*/, {}/*isub*/, {}/*lsub*/, {}/*fsub*/, {}/*dsub*/,
    -    {}/*imul*/, {}/*lmul*/, {}/*fmul*/, {}/*dmul*/, {}/*idiv*/,
    -    {}/*ldiv*/, {}/*fdiv*/, {}/*ddiv*/, {}/*irem*/, {}/*lrem*/,
    -    {}/*frem*/, {}/*drem*/, {}/*ineg*/, {}/*lneg*/, {}/*fneg*/,
    -    {}/*dneg*/, {}/*ishl*/, {}/*lshl*/, {}/*ishr*/, {}/*lshr*/,
    -    {}/*iushr*/, {}/*lushr*/, {}/*iand*/, {}/*land*/, {}/*ior*/,
    -    {}/*lor*/, {}/*ixor*/, {}/*lxor*/, {T_BYTE, T_BYTE}/*iinc*/,
    -    {}/*i2l*/, {}/*i2f*/, {}/*i2d*/, {}/*l2i*/, {}/*l2f*/, {}/*l2d*/,
    -    {}/*f2i*/, {}/*f2l*/, {}/*f2d*/, {}/*d2i*/, {}/*d2l*/, {}/*d2f*/,
    -    {}/*i2b*/, {}/*i2c*/, {}/*i2s*/, {}/*lcmp*/, {}/*fcmpl*/,
    -    {}/*fcmpg*/, {}/*dcmpl*/, {}/*dcmpg*/, {T_SHORT}/*ifeq*/,
    -    {T_SHORT}/*ifne*/, {T_SHORT}/*iflt*/, {T_SHORT}/*ifge*/,
    -    {T_SHORT}/*ifgt*/, {T_SHORT}/*ifle*/, {T_SHORT}/*if_icmpeq*/,
    -    {T_SHORT}/*if_icmpne*/, {T_SHORT}/*if_icmplt*/,
    -    {T_SHORT}/*if_icmpge*/, {T_SHORT}/*if_icmpgt*/,
    -    {T_SHORT}/*if_icmple*/, {T_SHORT}/*if_acmpeq*/,
    -    {T_SHORT}/*if_acmpne*/, {T_SHORT}/*goto*/, {T_SHORT}/*jsr*/,
    -    {T_BYTE}/*ret*/, {}/*tableswitch*/, {}/*lookupswitch*/,
    -    {}/*ireturn*/, {}/*lreturn*/, {}/*freturn*/, {}/*dreturn*/,
    -    {}/*areturn*/, {}/*return*/, {T_SHORT}/*getstatic*/,
    -    {T_SHORT}/*putstatic*/, {T_SHORT}/*getfield*/,
    -    {T_SHORT}/*putfield*/, {T_SHORT}/*invokevirtual*/,
    -    {T_SHORT}/*invokespecial*/, {T_SHORT}/*invokestatic*/,
    -    {T_SHORT, T_BYTE, T_BYTE}/*invokeinterface*/, {T_SHORT, T_BYTE, T_BYTE}/*invokedynamic*/,
    -    {T_SHORT}/*new*/, {T_BYTE}/*newarray*/,
    -    {T_SHORT}/*anewarray*/, {}/*arraylength*/, {}/*athrow*/,
    -    {T_SHORT}/*checkcast*/, {T_SHORT}/*instanceof*/,
    -    {}/*monitorenter*/, {}/*monitorexit*/, {T_BYTE}/*wide*/,
    -    {T_SHORT, T_BYTE}/*multianewarray*/, {T_SHORT}/*ifnull*/,
    -    {T_SHORT}/*ifnonnull*/, {T_INT}/*goto_w*/, {T_INT}/*jsr_w*/,
    -    {}/*breakpoint*/, {}, {}, {}, {}, {}, {}, {},
    -    {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
    -    {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
    -    {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
    -    {}/*impdep1*/, {}/*impdep2*/
    -  };
    -
    -  /**
    -   * @since 6.0
    -   */
    -  public static short getOperandType(final int opcode, final int index) {
    -      return TYPE_OF_OPERANDS[opcode][index];
    -  }
    -
    -  /**
    -   * @since 6.0
    -   */
    -  public static long getOperandTypeCount(final int opcode) {
    -      return TYPE_OF_OPERANDS[opcode].length;
    -  }
    -
    -  /**
    -   * Names of opcodes.  Indexed by opcode.  OPCODE_NAMES[ALOAD] = "aload".
    -   */
    -  private static final String[] OPCODE_NAMES = {
    -    "nop", "aconst_null", "iconst_m1", "iconst_0", "iconst_1",
    -    "iconst_2", "iconst_3", "iconst_4", "iconst_5", "lconst_0",
    -    "lconst_1", "fconst_0", "fconst_1", "fconst_2", "dconst_0",
    -    "dconst_1", "bipush", "sipush", "ldc", "ldc_w", "ldc2_w", "iload",
    -    "lload", "fload", "dload", "aload", "iload_0", "iload_1", "iload_2",
    -    "iload_3", "lload_0", "lload_1", "lload_2", "lload_3", "fload_0",
    -    "fload_1", "fload_2", "fload_3", "dload_0", "dload_1", "dload_2",
    -    "dload_3", "aload_0", "aload_1", "aload_2", "aload_3", "iaload",
    -    "laload", "faload", "daload", "aaload", "baload", "caload", "saload",
    -    "istore", "lstore", "fstore", "dstore", "astore", "istore_0",
    -    "istore_1", "istore_2", "istore_3", "lstore_0", "lstore_1",
    -    "lstore_2", "lstore_3", "fstore_0", "fstore_1", "fstore_2",
    -    "fstore_3", "dstore_0", "dstore_1", "dstore_2", "dstore_3",
    -    "astore_0", "astore_1", "astore_2", "astore_3", "iastore", "lastore",
    -    "fastore", "dastore", "aastore", "bastore", "castore", "sastore",
    -    "pop", "pop2", "dup", "dup_x1", "dup_x2", "dup2", "dup2_x1",
    -    "dup2_x2", "swap", "iadd", "ladd", "fadd", "dadd", "isub", "lsub",
    -    "fsub", "dsub", "imul", "lmul", "fmul", "dmul", "idiv", "ldiv",
    -    "fdiv", "ddiv", "irem", "lrem", "frem", "drem", "ineg", "lneg",
    -    "fneg", "dneg", "ishl", "lshl", "ishr", "lshr", "iushr", "lushr",
    -    "iand", "land", "ior", "lor", "ixor", "lxor", "iinc", "i2l", "i2f",
    -    "i2d", "l2i", "l2f", "l2d", "f2i", "f2l", "f2d", "d2i", "d2l", "d2f",
    -    "i2b", "i2c", "i2s", "lcmp", "fcmpl", "fcmpg",
    -    "dcmpl", "dcmpg", "ifeq", "ifne", "iflt", "ifge", "ifgt", "ifle",
    -    "if_icmpeq", "if_icmpne", "if_icmplt", "if_icmpge", "if_icmpgt",
    -    "if_icmple", "if_acmpeq", "if_acmpne", "goto", "jsr", "ret",
    -    "tableswitch", "lookupswitch", "ireturn", "lreturn", "freturn",
    -    "dreturn", "areturn", "return", "getstatic", "putstatic", "getfield",
    -    "putfield", "invokevirtual", "invokespecial", "invokestatic",
    -    "invokeinterface", "invokedynamic", "new", "newarray", "anewarray",
    -    "arraylength", "athrow", "checkcast", "instanceof", "monitorenter",
    -    "monitorexit", "wide", "multianewarray", "ifnull", "ifnonnull",
    -    "goto_w", "jsr_w", "breakpoint", ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    -    ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    -    ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    -    ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    -    ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    -    ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    -    ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    -    ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    -    ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    -    ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    -    ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    -    ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    -    ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    -    ILLEGAL_OPCODE, "impdep1", "impdep2"
    -  };
    -
    -  /**
    -   * @since 6.0
    -   */
    -  public static final int OPCODE_NAMES_LENGTH = OPCODE_NAMES.length;
    -
    -
    -  /**
    -   * @since 6.0
    -   */
    -  public static String getOpcodeName(final int index) {
    -      return OPCODE_NAMES[index];
    -  }
    -
    -  /**
    -   * Number of words consumed on operand stack by instructions.
    -   * Indexed by opcode.  CONSUME_STACK[FALOAD] = number of words
    -   * consumed from the stack by a faload instruction.
    -   */
    -  private static final int[] CONSUME_STACK = {
    -    0/*nop*/, 0/*aconst_null*/, 0/*iconst_m1*/, 0/*iconst_0*/, 0/*iconst_1*/,
    -    0/*iconst_2*/, 0/*iconst_3*/, 0/*iconst_4*/, 0/*iconst_5*/, 0/*lconst_0*/,
    -    0/*lconst_1*/, 0/*fconst_0*/, 0/*fconst_1*/, 0/*fconst_2*/, 0/*dconst_0*/,
    -    0/*dconst_1*/, 0/*bipush*/, 0/*sipush*/, 0/*ldc*/, 0/*ldc_w*/, 0/*ldc2_w*/, 0/*iload*/,
    -    0/*lload*/, 0/*fload*/, 0/*dload*/, 0/*aload*/, 0/*iload_0*/, 0/*iload_1*/, 0/*iload_2*/,
    -    0/*iload_3*/, 0/*lload_0*/, 0/*lload_1*/, 0/*lload_2*/, 0/*lload_3*/, 0/*fload_0*/,
    -    0/*fload_1*/, 0/*fload_2*/, 0/*fload_3*/, 0/*dload_0*/, 0/*dload_1*/, 0/*dload_2*/,
    -    0/*dload_3*/, 0/*aload_0*/, 0/*aload_1*/, 0/*aload_2*/, 0/*aload_3*/, 2/*iaload*/,
    -    2/*laload*/, 2/*faload*/, 2/*daload*/, 2/*aaload*/, 2/*baload*/, 2/*caload*/, 2/*saload*/,
    -    1/*istore*/, 2/*lstore*/, 1/*fstore*/, 2/*dstore*/, 1/*astore*/, 1/*istore_0*/,
    -    1/*istore_1*/, 1/*istore_2*/, 1/*istore_3*/, 2/*lstore_0*/, 2/*lstore_1*/,
    -    2/*lstore_2*/, 2/*lstore_3*/, 1/*fstore_0*/, 1/*fstore_1*/, 1/*fstore_2*/,
    -    1/*fstore_3*/, 2/*dstore_0*/, 2/*dstore_1*/, 2/*dstore_2*/, 2/*dstore_3*/,
    -    1/*astore_0*/, 1/*astore_1*/, 1/*astore_2*/, 1/*astore_3*/, 3/*iastore*/, 4/*lastore*/,
    -    3/*fastore*/, 4/*dastore*/, 3/*aastore*/, 3/*bastore*/, 3/*castore*/, 3/*sastore*/,
    -    1/*pop*/, 2/*pop2*/, 1/*dup*/, 2/*dup_x1*/, 3/*dup_x2*/, 2/*dup2*/, 3/*dup2_x1*/,
    -    4/*dup2_x2*/, 2/*swap*/, 2/*iadd*/, 4/*ladd*/, 2/*fadd*/, 4/*dadd*/, 2/*isub*/, 4/*lsub*/,
    -    2/*fsub*/, 4/*dsub*/, 2/*imul*/, 4/*lmul*/, 2/*fmul*/, 4/*dmul*/, 2/*idiv*/, 4/*ldiv*/,
    -    2/*fdiv*/, 4/*ddiv*/, 2/*irem*/, 4/*lrem*/, 2/*frem*/, 4/*drem*/, 1/*ineg*/, 2/*lneg*/,
    -    1/*fneg*/, 2/*dneg*/, 2/*ishl*/, 3/*lshl*/, 2/*ishr*/, 3/*lshr*/, 2/*iushr*/, 3/*lushr*/,
    -    2/*iand*/, 4/*land*/, 2/*ior*/, 4/*lor*/, 2/*ixor*/, 4/*lxor*/, 0/*iinc*/,
    -    1/*i2l*/, 1/*i2f*/, 1/*i2d*/, 2/*l2i*/, 2/*l2f*/, 2/*l2d*/, 1/*f2i*/, 1/*f2l*/,
    -    1/*f2d*/, 2/*d2i*/, 2/*d2l*/, 2/*d2f*/, 1/*i2b*/, 1/*i2c*/, 1/*i2s*/,
    -    4/*lcmp*/, 2/*fcmpl*/, 2/*fcmpg*/, 4/*dcmpl*/, 4/*dcmpg*/, 1/*ifeq*/, 1/*ifne*/,
    -    1/*iflt*/, 1/*ifge*/, 1/*ifgt*/, 1/*ifle*/, 2/*if_icmpeq*/, 2/*if_icmpne*/, 2/*if_icmplt*/,
    -    2 /*if_icmpge*/, 2/*if_icmpgt*/, 2/*if_icmple*/, 2/*if_acmpeq*/, 2/*if_acmpne*/,
    -    0/*goto*/, 0/*jsr*/, 0/*ret*/, 1/*tableswitch*/, 1/*lookupswitch*/, 1/*ireturn*/,
    -    2/*lreturn*/, 1/*freturn*/, 2/*dreturn*/, 1/*areturn*/, 0/*return*/, 0/*getstatic*/,
    -    UNPREDICTABLE/*putstatic*/, 1/*getfield*/, UNPREDICTABLE/*putfield*/,
    -    UNPREDICTABLE/*invokevirtual*/, UNPREDICTABLE/*invokespecial*/,
    -    UNPREDICTABLE/*invokestatic*/,
    -    UNPREDICTABLE/*invokeinterface*/, UNPREDICTABLE/*invokedynamic*/, 0/*new*/, 1/*newarray*/, 1/*anewarray*/,
    -    1/*arraylength*/, 1/*athrow*/, 1/*checkcast*/, 1/*instanceof*/, 1/*monitorenter*/,
    -    1/*monitorexit*/, 0/*wide*/, UNPREDICTABLE/*multianewarray*/, 1/*ifnull*/, 1/*ifnonnull*/,
    -    0/*goto_w*/, 0/*jsr_w*/, 0/*breakpoint*/, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNPREDICTABLE/*impdep1*/, UNPREDICTABLE/*impdep2*/
    -  };
    -
    -  /**
    -   *
    -   * @param index
    -   * @return Number of words consumed on operand stack
    -   * @since 6.0
    -   */
    -  public static int getConsumeStack(final int index) {
    -      return CONSUME_STACK[index];
    -  }
    -
    -
    -  /**
    -   * Number of words produced onto operand stack by instructions.
    -   * Indexed by opcode.  CONSUME_STACK[DALOAD] = number of words
    -   * consumed from the stack by a daload instruction.
    -   */
    -  private static final int[] PRODUCE_STACK = {
    -    0/*nop*/, 1/*aconst_null*/, 1/*iconst_m1*/, 1/*iconst_0*/, 1/*iconst_1*/,
    -    1/*iconst_2*/, 1/*iconst_3*/, 1/*iconst_4*/, 1/*iconst_5*/, 2/*lconst_0*/,
    -    2/*lconst_1*/, 1/*fconst_0*/, 1/*fconst_1*/, 1/*fconst_2*/, 2/*dconst_0*/,
    -    2/*dconst_1*/, 1/*bipush*/, 1/*sipush*/, 1/*ldc*/, 1/*ldc_w*/, 2/*ldc2_w*/, 1/*iload*/,
    -    2/*lload*/, 1/*fload*/, 2/*dload*/, 1/*aload*/, 1/*iload_0*/, 1/*iload_1*/, 1/*iload_2*/,
    -    1/*iload_3*/, 2/*lload_0*/, 2/*lload_1*/, 2/*lload_2*/, 2/*lload_3*/, 1/*fload_0*/,
    -    1/*fload_1*/, 1/*fload_2*/, 1/*fload_3*/, 2/*dload_0*/, 2/*dload_1*/, 2/*dload_2*/,
    -    2/*dload_3*/, 1/*aload_0*/, 1/*aload_1*/, 1/*aload_2*/, 1/*aload_3*/, 1/*iaload*/,
    -    2/*laload*/, 1/*faload*/, 2/*daload*/, 1/*aaload*/, 1/*baload*/, 1/*caload*/, 1/*saload*/,
    -    0/*istore*/, 0/*lstore*/, 0/*fstore*/, 0/*dstore*/, 0/*astore*/, 0/*istore_0*/,
    -    0/*istore_1*/, 0/*istore_2*/, 0/*istore_3*/, 0/*lstore_0*/, 0/*lstore_1*/,
    -    0/*lstore_2*/, 0/*lstore_3*/, 0/*fstore_0*/, 0/*fstore_1*/, 0/*fstore_2*/,
    -    0/*fstore_3*/, 0/*dstore_0*/, 0/*dstore_1*/, 0/*dstore_2*/, 0/*dstore_3*/,
    -    0/*astore_0*/, 0/*astore_1*/, 0/*astore_2*/, 0/*astore_3*/, 0/*iastore*/, 0/*lastore*/,
    -    0/*fastore*/, 0/*dastore*/, 0/*aastore*/, 0/*bastore*/, 0/*castore*/, 0/*sastore*/,
    -    0/*pop*/, 0/*pop2*/, 2/*dup*/, 3/*dup_x1*/, 4/*dup_x2*/, 4/*dup2*/, 5/*dup2_x1*/,
    -    6/*dup2_x2*/, 2/*swap*/, 1/*iadd*/, 2/*ladd*/, 1/*fadd*/, 2/*dadd*/, 1/*isub*/, 2/*lsub*/,
    -    1/*fsub*/, 2/*dsub*/, 1/*imul*/, 2/*lmul*/, 1/*fmul*/, 2/*dmul*/, 1/*idiv*/, 2/*ldiv*/,
    -    1/*fdiv*/, 2/*ddiv*/, 1/*irem*/, 2/*lrem*/, 1/*frem*/, 2/*drem*/, 1/*ineg*/, 2/*lneg*/,
    -    1/*fneg*/, 2/*dneg*/, 1/*ishl*/, 2/*lshl*/, 1/*ishr*/, 2/*lshr*/, 1/*iushr*/, 2/*lushr*/,
    -    1/*iand*/, 2/*land*/, 1/*ior*/, 2/*lor*/, 1/*ixor*/, 2/*lxor*/,
    -    0/*iinc*/, 2/*i2l*/, 1/*i2f*/, 2/*i2d*/, 1/*l2i*/, 1/*l2f*/, 2/*l2d*/, 1/*f2i*/,
    -    2/*f2l*/, 2/*f2d*/, 1/*d2i*/, 2/*d2l*/, 1/*d2f*/,
    -    1/*i2b*/, 1/*i2c*/, 1/*i2s*/, 1/*lcmp*/, 1/*fcmpl*/, 1/*fcmpg*/,
    -    1/*dcmpl*/, 1/*dcmpg*/, 0/*ifeq*/, 0/*ifne*/, 0/*iflt*/, 0/*ifge*/, 0/*ifgt*/, 0/*ifle*/,
    -    0/*if_icmpeq*/, 0/*if_icmpne*/, 0/*if_icmplt*/, 0/*if_icmpge*/, 0/*if_icmpgt*/,
    -    0/*if_icmple*/, 0/*if_acmpeq*/, 0/*if_acmpne*/, 0/*goto*/, 1/*jsr*/, 0/*ret*/,
    -    0/*tableswitch*/, 0/*lookupswitch*/, 0/*ireturn*/, 0/*lreturn*/, 0/*freturn*/,
    -    0/*dreturn*/, 0/*areturn*/, 0/*return*/, UNPREDICTABLE/*getstatic*/, 0/*putstatic*/,
    -    UNPREDICTABLE/*getfield*/, 0/*putfield*/, UNPREDICTABLE/*invokevirtual*/,
    -    UNPREDICTABLE/*invokespecial*/, UNPREDICTABLE/*invokestatic*/,
    -    UNPREDICTABLE/*invokeinterface*/, UNPREDICTABLE/*invokedynamic*/, 1/*new*/, 1/*newarray*/, 1/*anewarray*/,
    -    1/*arraylength*/, 1/*athrow*/, 1/*checkcast*/, 1/*instanceof*/, 0/*monitorenter*/,
    -    0/*monitorexit*/, 0/*wide*/, 1/*multianewarray*/, 0/*ifnull*/, 0/*ifnonnull*/,
    -    0/*goto_w*/, 1/*jsr_w*/, 0/*breakpoint*/, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    -    UNDEFINED, UNPREDICTABLE/*impdep1*/, UNPREDICTABLE/*impdep2*/
    -  };
    -
    -  /**
    -   *
    -   * @param index
    -   * @return Number of words produced onto operand stack
    -   * @since 6.0
    -   */
    -  public static int getProduceStack(final int index) {
    -      return PRODUCE_STACK[index];
    -  }
    -
    -  /** Attributes and their corresponding names.
    -   */
    -  public static final byte ATTR_UNKNOWN                                 = -1;
    -  public static final byte ATTR_SOURCE_FILE                             = 0;
    -  public static final byte ATTR_CONSTANT_VALUE                          = 1;
    -  public static final byte ATTR_CODE                                    = 2;
    -  public static final byte ATTR_EXCEPTIONS                              = 3;
    -  public static final byte ATTR_LINE_NUMBER_TABLE                       = 4;
    -  public static final byte ATTR_LOCAL_VARIABLE_TABLE                    = 5;
    -  public static final byte ATTR_INNER_CLASSES                           = 6;
    -  public static final byte ATTR_SYNTHETIC                               = 7;
    -  public static final byte ATTR_DEPRECATED                              = 8;
    -  public static final byte ATTR_PMG                                     = 9;
    -  public static final byte ATTR_SIGNATURE                               = 10;
    -  public static final byte ATTR_STACK_MAP                               = 11;
    -  public static final byte ATTR_RUNTIME_VISIBLE_ANNOTATIONS             = 12;
    -  public static final byte ATTR_RUNTIME_INVISIBLE_ANNOTATIONS           = 13;
    -  public static final byte ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS   = 14;
    -  public static final byte ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = 15;
    -  public static final byte ATTR_ANNOTATION_DEFAULT                      = 16;
    -  public static final byte ATTR_LOCAL_VARIABLE_TYPE_TABLE               = 17;
    -  public static final byte ATTR_ENCLOSING_METHOD                        = 18;
    -  public static final byte ATTR_STACK_MAP_TABLE                         = 19;
    -  public static final byte ATTR_BOOTSTRAP_METHODS                       = 20;
    -  public static final byte ATTR_METHOD_PARAMETERS                       = 21;
    -  public static final byte ATTR_MODULE                                  = 22;
    -  public static final byte ATTR_MODULE_PACKAGES                         = 23;
    -  public static final byte ATTR_MODULE_MAIN_CLASS                       = 24;
    -  public static final byte ATTR_NEST_HOST                               = 25;
    -  public static final byte ATTR_NEST_MEMBERS                            = 26;
    -
    -  public static final short KNOWN_ATTRIBUTES = 27; // count of attributes
    -
    -  private static final String[] ATTRIBUTE_NAMES = {
    -    "SourceFile", "ConstantValue", "Code", "Exceptions",
    -    "LineNumberTable", "LocalVariableTable",
    -    "InnerClasses", "Synthetic", "Deprecated",
    -    "PMGClass", "Signature", "StackMap",
    -    "RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations",
    -    "RuntimeVisibleParameterAnnotations", "RuntimeInvisibleParameterAnnotations",
    -    "AnnotationDefault", "LocalVariableTypeTable", "EnclosingMethod", "StackMapTable",
    -    "BootstrapMethods", "MethodParameters", "Module", "ModulePackages",
    -    "ModuleMainClass", "NestHost", "NestMembers"
    -  };
    -
    -  /**
    -   *
    -   * @param index
    -   * @return the attribute name
    -   * @since 6.0
    -   */
    -  public static String getAttributeName(final int index) {
    -      return ATTRIBUTE_NAMES[index];
    -  }
    -
    -  /** Constants used in the StackMap attribute.
    -   */
    -  public static final byte ITEM_Bogus      = 0;
    -  public static final byte ITEM_Integer    = 1;
    -  public static final byte ITEM_Float      = 2;
    -  public static final byte ITEM_Double     = 3;
    -  public static final byte ITEM_Long       = 4;
    -  public static final byte ITEM_Null       = 5;
    -  public static final byte ITEM_InitObject = 6;
    -  public static final byte ITEM_Object     = 7;
    -  public static final byte ITEM_NewObject  = 8;
    -
    -  private static final String[] ITEM_NAMES = {
    -    "Bogus", "Integer", "Float", "Double", "Long",
    -    "Null", "InitObject", "Object", "NewObject"
    -  };
    -
    -  /**
    -   *
    -   * @param index
    -   * @return the item name
    -   * @since 6.0
    -   */
    -  public static String getItemName(final int index) {
    -      return ITEM_NAMES[index];
    -  }
    -
    -  /** Constants used to identify StackMapEntry types.
    -   *
    -   * For those types which can specify a range, the
    -   * constant names the lowest value.
    -   */
    -  public static final int SAME_FRAME = 0;
    -  public static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64;
    -  public static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247;
    -  public static final int CHOP_FRAME = 248;
    -  public static final int SAME_FRAME_EXTENDED = 251;
    -  public static final int APPEND_FRAME = 252;
    -  public static final int FULL_FRAME = 255;
    -
    -  /** Constants that define the maximum value of
    -   * those constants which store ranges. */
    -
    -  public static final int SAME_FRAME_MAX = 63;
    -  public static final int SAME_LOCALS_1_STACK_ITEM_FRAME_MAX = 127;
    -  public static final int CHOP_FRAME_MAX = 250;
    -  public static final int APPEND_FRAME_MAX = 254;
    -
    -
    -  // Constants defining the behavior of the Method Handles (JVMS 5.4.3.5)
    -
    -  public static final byte REF_getField         = 1;
    -  public static final byte REF_getStatic        = 2;
    -  public static final byte REF_putField         = 3;
    -  public static final byte REF_putStatic        = 4;
    -  public static final byte REF_invokeVirtual    = 5;
    -  public static final byte REF_invokeStatic     = 6;
    -  public static final byte REF_invokeSpecial    = 7;
    -  public static final byte REF_newInvokeSpecial = 8;
    -  public static final byte REF_invokeInterface  = 9;
    -
    -  /**
    -   * The names of the reference_kinds of a CONSTANT_MethodHandle_info.
    -   */
    -  private static final String[] METHODHANDLE_NAMES = {
    -      "", "getField", "getStatic", "putField", "putStatic", "invokeVirtual",
    -      "invokeStatic", "invokeSpecial", "newInvokeSpecial", "invokeInterface" };
    -
    -  /**
    -   *
    -   * @param index
    -   * @return the method handle name
    -   * @since 6.0
    -   */
    -  public static String getMethodHandleName(final int index) {
    -      return METHODHANDLE_NAMES[index];
    -  }
    -
    -  private Const() { } // not instantiable
    +    /**
    +     * Java class file format Magic number (0xCAFEBABE)
    +     *
    +     * @see  The ClassFile Structure
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final int JVM_CLASSFILE_MAGIC = 0xCAFEBABE;
    +
    +    /**
    +     * Major version number of class files for Java 1.1.
    +     *
    +     * @see #MINOR_1_1
    +     */
    +    public static final short MAJOR_1_1 = 45;
    +
    +    /**
    +     * Minor version number of class files for Java 1.1.
    +     *
    +     * @see #MAJOR_1_1
    +     */
    +    public static final short MINOR_1_1 = 3;
    +
    +    /**
    +     * Major version number of class files for Java 1.2.
    +     *
    +     * @see #MINOR_1_2
    +     */
    +    public static final short MAJOR_1_2 = 46;
    +
    +    /**
    +     * Minor version number of class files for Java 1.2.
    +     *
    +     * @see #MAJOR_1_2
    +     */
    +    public static final short MINOR_1_2 = 0;
    +
    +    /**
    +     * Major version number of class files for Java 1.2.
    +     *
    +     * @see #MINOR_1_2
    +     */
    +    public static final short MAJOR_1_3 = 47;
    +
    +    /**
    +     * Minor version number of class files for Java 1.3.
    +     *
    +     * @see #MAJOR_1_3
    +     */
    +    public static final short MINOR_1_3 = 0;
    +
    +    /**
    +     * Major version number of class files for Java 1.3.
    +     *
    +     * @see #MINOR_1_3
    +     */
    +    public static final short MAJOR_1_4 = 48;
    +
    +    /**
    +     * Minor version number of class files for Java 1.4.
    +     *
    +     * @see #MAJOR_1_4
    +     */
    +    public static final short MINOR_1_4 = 0;
    +
    +    /**
    +     * Major version number of class files for Java 1.4.
    +     *
    +     * @see #MINOR_1_4
    +     */
    +    public static final short MAJOR_1_5 = 49;
    +
    +    /**
    +     * Minor version number of class files for Java 1.5.
    +     *
    +     * @see #MAJOR_1_5
    +     */
    +    public static final short MINOR_1_5 = 0;
    +
    +    /**
    +     * Major version number of class files for Java 1.6.
    +     *
    +     * @see #MINOR_1_6
    +     */
    +    public static final short MAJOR_1_6 = 50;
    +
    +    /**
    +     * Minor version number of class files for Java 1.6.
    +     *
    +     * @see #MAJOR_1_6
    +     */
    +    public static final short MINOR_1_6 = 0;
    +
    +    /**
    +     * Major version number of class files for Java 1.7.
    +     *
    +     * @see #MINOR_1_7
    +     */
    +    public static final short MAJOR_1_7 = 51;
    +
    +    /**
    +     * Minor version number of class files for Java 1.7.
    +     *
    +     * @see #MAJOR_1_7
    +     */
    +    public static final short MINOR_1_7 = 0;
    +
    +    /**
    +     * Major version number of class files for Java 1.8.
    +     *
    +     * @see #MINOR_1_8
    +     */
    +    public static final short MAJOR_1_8 = 52;
    +
    +    /**
    +     * Minor version number of class files for Java 1.8.
    +     *
    +     * @see #MAJOR_1_8
    +     */
    +    public static final short MINOR_1_8 = 0;
    +
    +    /**
    +     * Major version number of class files for Java 9.
    +     *
    +     * @see #MINOR_9
    +     */
    +    public static final short MAJOR_9 = 53;
    +
    +    /**
    +     * Minor version number of class files for Java 9.
    +     *
    +     * @see #MAJOR_9
    +     */
    +    public static final short MINOR_9 = 0;
    +
    +    /**
    +     * @deprecated Use {@link #MAJOR_9} instead
    +     */
    +    @Deprecated
    +    public static final short MAJOR_1_9 = MAJOR_9;
    +
    +    /**
    +     * @deprecated Use {@link #MINOR_9} instead
    +     */
    +    @Deprecated
    +    public static final short MINOR_1_9 = MINOR_9;
    +
    +    /**
    +     * Major version number of class files for Java 10.
    +     *
    +     * @see #MINOR_10
    +     */
    +    public static final short MAJOR_10 = 54;
    +
    +    /**
    +     * Minor version number of class files for Java 10.
    +     *
    +     * @see #MAJOR_10
    +     */
    +    public static final short MINOR_10 = 0;
    +
    +    /**
    +     * Major version number of class files for Java 11.
    +     *
    +     * @see #MINOR_11
    +     */
    +    public static final short MAJOR_11 = 55;
    +
    +    /**
    +     * Minor version number of class files for Java 11.
    +     *
    +     * @see #MAJOR_11
    +     */
    +    public static final short MINOR_11 = 0;
    +
    +    /**
    +     * Major version number of class files for Java 12.
    +     *
    +     * @see #MINOR_12
    +     */
    +    public static final short MAJOR_12 = 56;
    +
    +    /**
    +     * Minor version number of class files for Java 12.
    +     *
    +     * @see #MAJOR_12
    +     */
    +    public static final short MINOR_12 = 0;
    +
    +    /**
    +     * Major version number of class files for Java 13.
    +     *
    +     * @see #MINOR_13
    +     */
    +    public static final short MAJOR_13 = 57;
    +
    +    /**
    +     * Minor version number of class files for Java 13.
    +     *
    +     * @see #MAJOR_13
    +     */
    +    public static final short MINOR_13 = 0;
    +
    +    /**
    +     * Minor version number of class files for Java 14.
    +     *
    +     * @see #MAJOR_14
    +     * @since 6.4.0
    +     */
    +    public static final short MINOR_14 = 0;
    +
    +    /**
    +     * Minor version number of class files for Java 15.
    +     *
    +     * @see #MAJOR_15
    +     * @since 6.6.0
    +     */
    +    public static final short MINOR_15 = 0;
    +
    +    /**
    +     * Minor version number of class files for Java 16.
    +     *
    +     * @see #MAJOR_16
    +     * @since 6.6.0
    +     */
    +    public static final short MINOR_16 = 0;
    +
    +    /**
    +     * Minor version number of class files for Java 17.
    +     *
    +     * @see #MAJOR_17
    +     * @since 6.6.0
    +     */
    +    public static final short MINOR_17 = 0;
    +
    +    /**
    +     * Minor version number of class files for Java 18.
    +     *
    +     * @see #MAJOR_18
    +     * @since 6.6.0
    +     */
    +    public static final short MINOR_18 = 0;
    +
    +    /**
    +     * Minor version number of class files for Java 19.
    +     *
    +     * @see #MAJOR_19
    +     * @since 6.6.0
    +     */
    +    public static final short MINOR_19 = 0;
    +
    +    /**
    +     * Major version number of class files for Java 14.
    +     *
    +     * @see #MINOR_14
    +     * @since 6.4.0
    +     */
    +    public static final short MAJOR_14 = 58;
    +
    +    /**
    +     * Major version number of class files for Java 15.
    +     *
    +     * @see #MINOR_15
    +     * @since 6.6.0
    +     */
    +    public static final short MAJOR_15 = 59;
    +
    +    /**
    +     * Major version number of class files for Java 16.
    +     *
    +     * @see #MINOR_16
    +     * @since 6.6.0
    +     */
    +    public static final short MAJOR_16 = 60;
    +
    +    /**
    +     * Major version number of class files for Java 17.
    +     *
    +     * @see #MINOR_17
    +     * @since 6.6.0
    +     */
    +    public static final short MAJOR_17 = 61;
    +
    +    /**
    +     * Major version number of class files for Java 18.
    +     *
    +     * @see #MINOR_18
    +     * @since 6.6.0
    +     */
    +    public static final short MAJOR_18 = 62;
    +
    +    /**
    +     * Major version number of class files for Java 19.
    +     *
    +     * @see #MINOR_19
    +     * @since 6.6.0
    +     */
    +    public static final short MAJOR_19 = 63;
    +
    +    /**
    +     * Default major version number. Class file is for Java 1.1.
    +     *
    +     * @see #MAJOR_1_1
    +     */
    +    public static final short MAJOR = MAJOR_1_1;
    +
    +    /**
    +     * Default major version number. Class file is for Java 1.1.
    +     *
    +     * @see #MAJOR_1_1
    +     */
    +    public static final short MINOR = MINOR_1_1;
    +
    +    /**
    +     * Maximum value for an unsigned short.
    +     */
    +    public static final int MAX_SHORT = 65535; // 2^16 - 1
    +
    +    /**
    +     * Maximum value for an unsigned byte.
    +     */
    +    public static final int MAX_BYTE = 255; // 2^8 - 1
    +
    +    /**
    +     * One of the access flags for fields, methods, or classes.
    +     *
    +     * @see  Flag definitions for
    +     *      Classes in the Java Virtual Machine Specification (Java SE 9 Edition).
    +     * @see  Flag definitions for Fields
    +     *      in the Java Virtual Machine Specification (Java SE 9 Edition).
    +     * @see  Flag definitions for Methods
    +     *      in the Java Virtual Machine Specification (Java SE 9 Edition).
    +     * @see  Flag
    +     *      definitions for Inner Classes in the Java Virtual Machine Specification (Java SE 9 Edition).
    +     */
    +    public static final short ACC_PUBLIC = 0x0001;
    +
    +    /**
    +     * One of the access flags for fields, methods, or classes.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_PRIVATE = 0x0002;
    +
    +    /**
    +     * One of the access flags for fields, methods, or classes.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_PROTECTED = 0x0004;
    +
    +    /**
    +     * One of the access flags for fields, methods, or classes.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_STATIC = 0x0008;
    +
    +    /**
    +     * One of the access flags for fields, methods, or classes.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_FINAL = 0x0010;
    +
    +    /**
    +     * One of the access flags for the Module attribute.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_OPEN = 0x0020;
    +
    +    /**
    +     * One of the access flags for classes.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_SUPER = 0x0020;
    +
    +    /**
    +     * One of the access flags for methods.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_SYNCHRONIZED = 0x0020;
    +
    +    /**
    +     * One of the access flags for the Module attribute.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_TRANSITIVE = 0x0020;
    +
    +    /**
    +     * One of the access flags for methods.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_BRIDGE = 0x0040;
    +
    +    /**
    +     * One of the access flags for the Module attribute.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_STATIC_PHASE = 0x0040;
    +
    +    /**
    +     * One of the access flags for fields.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_VOLATILE = 0x0040;
    +
    +    /**
    +     * One of the access flags for fields.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_TRANSIENT = 0x0080;
    +
    +    /**
    +     * One of the access flags for methods.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_VARARGS = 0x0080;
    +
    +    /**
    +     * One of the access flags for methods.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_NATIVE = 0x0100;
    +
    +    /**
    +     * One of the access flags for classes.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_INTERFACE = 0x0200;
    +
    +    /**
    +     * One of the access flags for methods or classes.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_ABSTRACT = 0x0400;
    +
    +    /**
    +     * One of the access flags for methods.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_STRICT = 0x0800;
    +
    +    /**
    +     * One of the access flags for fields, methods, classes, MethodParameter attribute, or Module attribute.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_SYNTHETIC = 0x1000;
    +
    +    /**
    +     * One of the access flags for classes.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_ANNOTATION = 0x2000;
    +
    +    /**
    +     * One of the access flags for fields or classes.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_ENUM = 0x4000;
    +
    +    // Applies to classes compiled by new compilers only
    +    /**
    +     * One of the access flags for MethodParameter or Module attributes.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_MANDATED = (short) 0x8000;
    +
    +    /**
    +     * One of the access flags for classes.
    +     *
    +     * @see #ACC_PUBLIC
    +     */
    +    public static final short ACC_MODULE = (short) 0x8000;
    +
    +    /**
    +     * One of the access flags for fields, methods, or classes.
    +     *
    +     * @see #ACC_PUBLIC
    +     * @deprecated Use {@link #MAX_ACC_FLAG_I}
    +     */
    +    @Deprecated
    +    public static final short MAX_ACC_FLAG = ACC_ENUM;
    +
    +    /**
    +     * One of the access flags for fields, methods, or classes. ACC_MODULE is negative as a short.
    +     *
    +     * @see #ACC_PUBLIC
    +     * @since 6.4.0
    +     */
    +    public static final int MAX_ACC_FLAG_I = 0x8000; // ACC_MODULE is negative as a short
    +
    +    // Note that do to overloading:
    +    // 'synchronized' is for methods, might be 'open' (if Module), 'super' (if class), or 'transitive' (if Module).
    +    // 'volatile' is for fields, might be 'bridge' (if method) or 'static_phase' (if Module)
    +    // 'transient' is for fields, might be 'varargs' (if method)
    +    // 'module' is for classes, might be 'mandated' (if Module or MethodParameters)
    +    /**
    +     * The names of the access flags.
    +     */
    +    private static final String[] ACCESS_NAMES = {"public", "private", "protected", "static", "final", "synchronized", "volatile", "transient", "native",
    +        "interface", "abstract", "strictfp", "synthetic", "annotation", "enum", "module"};
    +
    +    /** @since 6.0 */
    +    public static final int ACCESS_NAMES_LENGTH = ACCESS_NAMES.length;
    +
    +    /**
    +     * Marks a constant pool entry as type UTF-8.
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_Utf8 = 1;
    +
    +    /*
    +     * The description of the constant pool is at: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4
    +     * References below are to the individual sections
    +     */
    +
    +    /**
    +     * Marks a constant pool entry as type Integer.
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_Integer = 3;
    +
    +    /**
    +     * Marks a constant pool entry as type Float.
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_Float = 4;
    +
    +    /**
    +     * Marks a constant pool entry as type Long.
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_Long = 5;
    +
    +    /**
    +     * Marks a constant pool entry as type Double.
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_Double = 6;
    +
    +    /**
    +     * Marks a constant pool entry as a Class
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_Class = 7;
    +
    +    /**
    +     * Marks a constant pool entry as a Field Reference.
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_Fieldref = 9;
    +
    +    /**
    +     * Marks a constant pool entry as type String
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_String = 8;
    +
    +    /**
    +     * Marks a constant pool entry as a Method Reference.
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_Methodref = 10;
    +
    +    /**
    +     * Marks a constant pool entry as an Interface Method Reference.
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_InterfaceMethodref = 11;
    +
    +    /**
    +     * Marks a constant pool entry as a name and type.
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_NameAndType = 12;
    +
    +    /**
    +     * Marks a constant pool entry as a Method Handle.
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_MethodHandle = 15;
    +
    +    /**
    +     * Marks a constant pool entry as a Method Type.
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_MethodType = 16;
    +
    +    /**
    +     * Marks a constant pool entry as dynamically computed.
    +     *
    +     * @see  Change request for JEP
    +     *      309
    +     * @since 6.3
    +     */
    +    public static final byte CONSTANT_Dynamic = 17;
    +
    +    /**
    +     * Marks a constant pool entry as an Invoke Dynamic
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final byte CONSTANT_InvokeDynamic = 18;
    +
    +    /**
    +     * Marks a constant pool entry as a Module Reference.
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     * @since 6.1
    +     */
    +    public static final byte CONSTANT_Module = 19;
    +
    +    /**
    +     * Marks a constant pool entry as a Package Reference.
    +     *
    +     * @see  The Constant Pool in The
    +     *      Java Virtual Machine Specification
    +     * @since 6.1
    +     */
    +    public static final byte CONSTANT_Package = 20;
    +
    +    /**
    +     * The names of the types of entries in a constant pool. Use getConstantName instead
    +     */
    +    private static final String[] CONSTANT_NAMES = {"", "CONSTANT_Utf8", "", "CONSTANT_Integer", "CONSTANT_Float", "CONSTANT_Long", "CONSTANT_Double",
    +        "CONSTANT_Class", "CONSTANT_String", "CONSTANT_Fieldref", "CONSTANT_Methodref", "CONSTANT_InterfaceMethodref", "CONSTANT_NameAndType", "", "",
    +        "CONSTANT_MethodHandle", "CONSTANT_MethodType", "CONSTANT_Dynamic", "CONSTANT_InvokeDynamic", "CONSTANT_Module", "CONSTANT_Package"};
    +
    +    /**
    +     * The name of the static initializer, also called "class initialization method" or "interface
    +     * initialization method". This is "<clinit>".
    +     */
    +    public static final String STATIC_INITIALIZER_NAME = "";
    +
    +    /**
    +     * The name of every constructor method in a class, also called "instance initialization method". This is
    +     * "<init>".
    +     */
    +    public static final String CONSTRUCTOR_NAME = "";
    +
    +    /**
    +     * The names of the interfaces implemented by arrays
    +     */
    +    private static final String[] INTERFACES_IMPLEMENTED_BY_ARRAYS = {"java.lang.Cloneable", "java.io.Serializable"};
    +
    +    /**
    +     * Maximum Constant Pool entries. One of the limitations of the Java Virtual Machine.
    +     *
    +     * @see  The Java Virtual
    +     *      Machine Specification, Java SE 8 Edition, page 330, chapter 4.11.
    +     */
    +    public static final int MAX_CP_ENTRIES = 65535;
    +
    +    /**
    +     * Maximum code size (plus one; the code size must be LESS than this) One of the limitations of the Java Virtual
    +     * Machine. Note vmspec2 page 152 ("Limitations") says: "The amount of code per non-native, non-abstract method is
    +     * limited to 65536 bytes by the sizes of the indices in the exception_table of the Code attribute (4.7.3), in the
    +     * LineNumberTable attribute (4.7.8), and in the LocalVariableTable attribute (4.7.9)." However this should be taken
    +     * as an upper limit rather than the defined maximum. On page 134 (4.8.1 Static Constants) of the same spec, it says:
    +     * "The value of the code_length item must be less than 65536." The entry in the Limitations section has been removed
    +     * from later versions of the spec; it is not present in the Java SE 8 edition.
    +     *
    +     * @see  The Java Virtual
    +     *      Machine Specification, Java SE 8 Edition, page 104, chapter 4.7.
    +     */
    +    public static final int MAX_CODE_SIZE = 65536; // bytes
    +
    +    /**
    +     * The maximum number of dimensions in an array ({@value}). One of the limitations of the Java Virtual Machine.
    +     *
    +     * @see  Field Descriptors in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final int MAX_ARRAY_DIMENSIONS = 255;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short NOP = 0;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short ACONST_NULL = 1;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ICONST_M1 = 2;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ICONST_0 = 3;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ICONST_1 = 4;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ICONST_2 = 5;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ICONST_3 = 6;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ICONST_4 = 7;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ICONST_5 = 8;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short LCONST_0 = 9;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short LCONST_1 = 10;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short FCONST_0 = 11;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short FCONST_1 = 12;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short FCONST_2 = 13;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short DCONST_0 = 14;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short DCONST_1 = 15;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short BIPUSH = 16;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short SIPUSH = 17;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short LDC = 18;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LDC_W = 19;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LDC2_W = 20;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ILOAD = 21;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LLOAD = 22;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FLOAD = 23;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DLOAD = 24;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ALOAD = 25;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ILOAD_0 = 26;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ILOAD_1 = 27;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ILOAD_2 = 28;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ILOAD_3 = 29;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LLOAD_0 = 30;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LLOAD_1 = 31;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LLOAD_2 = 32;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LLOAD_3 = 33;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FLOAD_0 = 34;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FLOAD_1 = 35;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FLOAD_2 = 36;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FLOAD_3 = 37;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DLOAD_0 = 38;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DLOAD_1 = 39;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DLOAD_2 = 40;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DLOAD_3 = 41;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ALOAD_0 = 42;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ALOAD_1 = 43;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ALOAD_2 = 44;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ALOAD_3 = 45;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IALOAD = 46;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LALOAD = 47;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FALOAD = 48;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DALOAD = 49;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short AALOAD = 50;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short BALOAD = 51;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short CALOAD = 52;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short SALOAD = 53;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ISTORE = 54;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LSTORE = 55;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FSTORE = 56;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DSTORE = 57;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ASTORE = 58;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ISTORE_0 = 59;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ISTORE_1 = 60;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ISTORE_2 = 61;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ISTORE_3 = 62;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short LSTORE_0 = 63;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short LSTORE_1 = 64;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short LSTORE_2 = 65;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short LSTORE_3 = 66;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short FSTORE_0 = 67;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short FSTORE_1 = 68;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short FSTORE_2 = 69;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short FSTORE_3 = 70;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short DSTORE_0 = 71;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short DSTORE_1 = 72;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short DSTORE_2 = 73;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short DSTORE_3 = 74;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ASTORE_0 = 75;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ASTORE_1 = 76;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ASTORE_2 = 77;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ASTORE_3 = 78;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IASTORE = 79;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LASTORE = 80;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FASTORE = 81;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DASTORE = 82;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short AASTORE = 83;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short BASTORE = 84;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short CASTORE = 85;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short SASTORE = 86;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short POP = 87;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short POP2 = 88;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short DUP = 89;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DUP_X1 = 90;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DUP_X2 = 91;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DUP2 = 92;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DUP2_X1 = 93;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DUP2_X2 = 94;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short SWAP = 95;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IADD = 96;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LADD = 97;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FADD = 98;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DADD = 99;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ISUB = 100;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LSUB = 101;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FSUB = 102;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DSUB = 103;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IMUL = 104;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LMUL = 105;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FMUL = 106;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DMUL = 107;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IDIV = 108;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LDIV = 109;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FDIV = 110;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DDIV = 111;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IREM = 112;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LREM = 113;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FREM = 114;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DREM = 115;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short INEG = 116;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LNEG = 117;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FNEG = 118;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DNEG = 119;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ISHL = 120;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LSHL = 121;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ISHR = 122;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LSHR = 123;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IUSHR = 124;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LUSHR = 125;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IAND = 126;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LAND = 127;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short IOR = 128;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short LOR = 129;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IXOR = 130;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LXOR = 131;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IINC = 132;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short I2L = 133;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short I2F = 134;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short I2D = 135;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short L2I = 136;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short L2F = 137;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short L2D = 138;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short F2I = 139;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short F2L = 140;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short F2D = 141;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short D2I = 142;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short D2L = 143;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short D2F = 144;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short I2B = 145;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short INT2BYTE = 145; // Old notation
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short I2C = 146;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short INT2CHAR = 146; // Old notation
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short I2S = 147;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short INT2SHORT = 147; // Old notation
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LCMP = 148;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FCMPL = 149;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FCMPG = 150;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DCMPL = 151;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DCMPG = 152;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IFEQ = 153;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IFNE = 154;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IFLT = 155;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IFGE = 156;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IFGT = 157;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IFLE = 158;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short IF_ICMPEQ = 159;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short IF_ICMPNE = 160;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short IF_ICMPLT = 161;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short IF_ICMPGE = 162;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short IF_ICMPGT = 163;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short IF_ICMPLE = 164;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short IF_ACMPEQ = 165;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short IF_ACMPNE = 166;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short GOTO = 167;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short JSR = 168;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short RET = 169;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short TABLESWITCH = 170;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short LOOKUPSWITCH = 171;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IRETURN = 172;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short LRETURN = 173;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short FRETURN = 174;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short DRETURN = 175;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ARETURN = 176;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short RETURN = 177;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short GETSTATIC = 178;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short PUTSTATIC = 179;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short GETFIELD = 180;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short PUTFIELD = 181;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short INVOKEVIRTUAL = 182;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short INVOKESPECIAL = 183;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short INVOKENONVIRTUAL = 183; // Old name in JDK 1.0
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short INVOKESTATIC = 184;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short INVOKEINTERFACE = 185;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short INVOKEDYNAMIC = 186;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in The
    +     *      Java Virtual Machine Specification
    +     */
    +    public static final short NEW = 187;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short NEWARRAY = 188;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short ANEWARRAY = 189;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short ARRAYLENGTH = 190;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short ATHROW = 191;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short CHECKCAST = 192;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short INSTANCEOF = 193;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short MONITORENTER = 194;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short MONITOREXIT = 195;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short WIDE = 196;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode
    +     *      definitions in The Java Virtual Machine Specification
    +     */
    +    public static final short MULTIANEWARRAY = 197;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short IFNULL = 198;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions
    +     *      in The Java Virtual Machine Specification
    +     */
    +    public static final short IFNONNULL = 199;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short GOTO_W = 200;
    +
    +    /**
    +     * Java VM opcode.
    +     *
    +     * @see  Opcode definitions in
    +     *      The Java Virtual Machine Specification
    +     */
    +    public static final short JSR_W = 201;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see  Reserved opcodes in the Java
    +     *      Virtual Machine Specification
    +     */
    +    public static final short BREAKPOINT = 202;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short LDC_QUICK = 203;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short LDC_W_QUICK = 204;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short LDC2_W_QUICK = 205;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short GETFIELD_QUICK = 206;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short PUTFIELD_QUICK = 207;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short GETFIELD2_QUICK = 208;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short PUTFIELD2_QUICK = 209;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short GETSTATIC_QUICK = 210;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short PUTSTATIC_QUICK = 211;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short GETSTATIC2_QUICK = 212;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short PUTSTATIC2_QUICK = 213;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short INVOKEVIRTUAL_QUICK = 214;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short INVOKENONVIRTUAL_QUICK = 215;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short INVOKESUPER_QUICK = 216;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short INVOKESTATIC_QUICK = 217;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short INVOKEINTERFACE_QUICK = 218;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short INVOKEVIRTUALOBJECT_QUICK = 219;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short NEW_QUICK = 221;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short ANEWARRAY_QUICK = 222;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short MULTIANEWARRAY_QUICK = 223;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short CHECKCAST_QUICK = 224;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short INSTANCEOF_QUICK = 225;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short INVOKEVIRTUAL_QUICK_W = 226;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short GETFIELD_QUICK_W = 227;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see 
    +     *      Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)
    +     * @see  Why the _quick
    +     *      opcodes were removed from the second version of the Java Virtual Machine Specification.
    +     */
    +    public static final short PUTFIELD_QUICK_W = 228;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see  Reserved opcodes in the Java
    +     *      Virtual Machine Specification
    +     */
    +    public static final short IMPDEP1 = 254;
    +
    +    /**
    +     * JVM internal opcode.
    +     *
    +     * @see  Reserved opcodes in the Java
    +     *      Virtual Machine Specification
    +     */
    +    public static final short IMPDEP2 = 255;
    +
    +    /**
    +     * BCEL virtual instruction for pushing an arbitrary data type onto the stack. Will be converted to the appropriate JVM
    +     * opcode when the class is dumped.
    +     */
    +    public static final short PUSH = 4711;
    +
    +    /**
    +     * BCEL virtual instruction for either LOOKUPSWITCH or TABLESWITCH. Will be converted to the appropriate JVM opcode when
    +     * the class is dumped.
    +     */
    +    public static final short SWITCH = 4712;
    +
    +    /** Illegal opcode. */
    +    public static final short UNDEFINED = -1;
    +
    +    /** Illegal opcode. */
    +    public static final short UNPREDICTABLE = -2;
    +
    +    /** Illegal opcode. */
    +    public static final short RESERVED = -3;
    +
    +    /** Mnemonic for an illegal opcode. */
    +    public static final String ILLEGAL_OPCODE = "";
    +
    +    /** Mnemonic for an illegal type. */
    +    public static final String ILLEGAL_TYPE = "";
    +
    +    /**
    +     * Boolean data type.
    +     *
    +     * @see  Static Constraints in
    +     *      the Java Virtual Machine Specification
    +     */
    +    public static final byte T_BOOLEAN = 4;
    +
    +    /**
    +     * Char data type.
    +     *
    +     * @see  Static Constraints in
    +     *      the Java Virtual Machine Specification
    +     */
    +    public static final byte T_CHAR = 5;
    +
    +    /**
    +     * Float data type.
    +     *
    +     * @see  Static Constraints in
    +     *      the Java Virtual Machine Specification
    +     */
    +    public static final byte T_FLOAT = 6;
    +
    +    /**
    +     * Double data type.
    +     *
    +     * @see  Static Constraints in
    +     *      the Java Virtual Machine Specification
    +     */
    +    public static final byte T_DOUBLE = 7;
    +
    +    /**
    +     * Byte data type.
    +     *
    +     * @see  Static Constraints in
    +     *      the Java Virtual Machine Specification
    +     */
    +    public static final byte T_BYTE = 8;
    +
    +    /**
    +     * Short data type.
    +     *
    +     * @see  Static Constraints in
    +     *      the Java Virtual Machine Specification
    +     */
    +    public static final byte T_SHORT = 9;
    +
    +    /**
    +     * Int data type.
    +     *
    +     * @see  Static Constraints in
    +     *      the Java Virtual Machine Specification
    +     */
    +    public static final byte T_INT = 10;
    +
    +    /**
    +     * Long data type.
    +     *
    +     * @see  Static Constraints in
    +     *      the Java Virtual Machine Specification
    +     */
    +    public static final byte T_LONG = 11;
    +
    +    /** Void data type (non-standard). */
    +    public static final byte T_VOID = 12; // Non-standard
    +
    +    /** Array data type. */
    +    public static final byte T_ARRAY = 13;
    +
    +    /** Object data type. */
    +    public static final byte T_OBJECT = 14;
    +
    +    /** Reference data type (deprecated). */
    +    public static final byte T_REFERENCE = 14; // Deprecated
    +
    +    /** Unknown data type. */
    +    public static final byte T_UNKNOWN = 15;
    +
    +    /** Address data type. */
    +    public static final byte T_ADDRESS = 16;
    +
    +    /** Empty arrays used to replace references to ArrayUtils */
    +    public static final byte[] EMPTY_BYTE_ARRAY = {};
    +    public static final int[] EMPTY_INT_ARRAY = {};
    +    public static final String[] EMPTY_STRING_ARRAY = {};
    +
    +    /**
    +     * The primitive type names corresponding to the T_XX constants, e.g., TYPE_NAMES[T_INT] = "int"
    +     */
    +    private static final String[] TYPE_NAMES = {ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, "boolean", "char", "float", "double", "byte", "short",
    +        "int", "long", "void", "array", "object", "unknown", "address"};
    +
    +    /**
    +     * The primitive class names corresponding to the T_XX constants, e.g., CLASS_TYPE_NAMES[T_INT] = "java.lang.Integer"
    +     */
    +    private static final String[] CLASS_TYPE_NAMES = {ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, "java.lang.Boolean", "java.lang.Character",
    +        "java.lang.Float", "java.lang.Double", "java.lang.Byte", "java.lang.Short", "java.lang.Integer", "java.lang.Long", "java.lang.Void", ILLEGAL_TYPE,
    +        ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE};
    +
    +    /**
    +     * The signature characters corresponding to primitive types, e.g., SHORT_TYPE_NAMES[T_INT] = "I"
    +     */
    +    private static final String[] SHORT_TYPE_NAMES = {ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, "Z", "C", "F", "D", "B", "S", "I", "J", "V",
    +        ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE};
    +
    +    /**
    +     * Number of byte code operands for each opcode, i.e., number of bytes after the tag byte itself. Indexed by opcode, so
    +     * NO_OF_OPERANDS[BIPUSH] = the number of operands for a bipush instruction.
    +     */
    +    static final short[] NO_OF_OPERANDS = {0/* nop */, 0/* aconst_null */, 0/* iconst_m1 */, 0/* iconst_0 */, 0/* iconst_1 */, 0/* iconst_2 */,
    +        0/* iconst_3 */, 0/* iconst_4 */, 0/* iconst_5 */, 0/* lconst_0 */, 0/* lconst_1 */, 0/* fconst_0 */, 0/* fconst_1 */, 0/* fconst_2 */, 0/* dconst_0 */,
    +        0/* dconst_1 */, 1/* bipush */, 2/* sipush */, 1/* ldc */, 2/* ldc_w */, 2/* ldc2_w */, 1/* iload */, 1/* lload */, 1/* fload */, 1/* dload */,
    +        1/* aload */, 0/* iload_0 */, 0/* iload_1 */, 0/* iload_2 */, 0/* iload_3 */, 0/* lload_0 */, 0/* lload_1 */, 0/* lload_2 */, 0/* lload_3 */,
    +        0/* fload_0 */, 0/* fload_1 */, 0/* fload_2 */, 0/* fload_3 */, 0/* dload_0 */, 0/* dload_1 */, 0/* dload_2 */, 0/* dload_3 */, 0/* aload_0 */,
    +        0/* aload_1 */, 0/* aload_2 */, 0/* aload_3 */, 0/* iaload */, 0/* laload */, 0/* faload */, 0/* daload */, 0/* aaload */, 0/* baload */, 0/* caload */,
    +        0/* saload */, 1/* istore */, 1/* lstore */, 1/* fstore */, 1/* dstore */, 1/* astore */, 0/* istore_0 */, 0/* istore_1 */, 0/* istore_2 */,
    +        0/* istore_3 */, 0/* lstore_0 */, 0/* lstore_1 */, 0/* lstore_2 */, 0/* lstore_3 */, 0/* fstore_0 */, 0/* fstore_1 */, 0/* fstore_2 */, 0/* fstore_3 */,
    +        0/* dstore_0 */, 0/* dstore_1 */, 0/* dstore_2 */, 0/* dstore_3 */, 0/* astore_0 */, 0/* astore_1 */, 0/* astore_2 */, 0/* astore_3 */, 0/* iastore */,
    +        0/* lastore */, 0/* fastore */, 0/* dastore */, 0/* aastore */, 0/* bastore */, 0/* castore */, 0/* sastore */, 0/* pop */, 0/* pop2 */, 0/* dup */,
    +        0/* dup_x1 */, 0/* dup_x2 */, 0/* dup2 */, 0/* dup2_x1 */, 0/* dup2_x2 */, 0/* swap */, 0/* iadd */, 0/* ladd */, 0/* fadd */, 0/* dadd */, 0/* isub */,
    +        0/* lsub */, 0/* fsub */, 0/* dsub */, 0/* imul */, 0/* lmul */, 0/* fmul */, 0/* dmul */, 0/* idiv */, 0/* ldiv */, 0/* fdiv */, 0/* ddiv */,
    +        0/* irem */, 0/* lrem */, 0/* frem */, 0/* drem */, 0/* ineg */, 0/* lneg */, 0/* fneg */, 0/* dneg */, 0/* ishl */, 0/* lshl */, 0/* ishr */,
    +        0/* lshr */, 0/* iushr */, 0/* lushr */, 0/* iand */, 0/* land */, 0/* ior */, 0/* lor */, 0/* ixor */, 0/* lxor */, 2/* iinc */, 0/* i2l */,
    +        0/* i2f */, 0/* i2d */, 0/* l2i */, 0/* l2f */, 0/* l2d */, 0/* f2i */, 0/* f2l */, 0/* f2d */, 0/* d2i */, 0/* d2l */, 0/* d2f */, 0/* i2b */,
    +        0/* i2c */, 0/* i2s */, 0/* lcmp */, 0/* fcmpl */, 0/* fcmpg */, 0/* dcmpl */, 0/* dcmpg */, 2/* ifeq */, 2/* ifne */, 2/* iflt */, 2/* ifge */,
    +        2/* ifgt */, 2/* ifle */, 2/* if_icmpeq */, 2/* if_icmpne */, 2/* if_icmplt */, 2/* if_icmpge */, 2/* if_icmpgt */, 2/* if_icmple */, 2/* if_acmpeq */,
    +        2/* if_acmpne */, 2/* goto */, 2/* jsr */, 1/* ret */, UNPREDICTABLE/* tableswitch */, UNPREDICTABLE/* lookupswitch */, 0/* ireturn */, 0/* lreturn */,
    +        0/* freturn */, 0/* dreturn */, 0/* areturn */, 0/* return */, 2/* getstatic */, 2/* putstatic */, 2/* getfield */, 2/* putfield */,
    +        2/* invokevirtual */, 2/* invokespecial */, 2/* invokestatic */, 4/* invokeinterface */, 4/* invokedynamic */, 2/* new */, 1/* newarray */,
    +        2/* anewarray */, 0/* arraylength */, 0/* athrow */, 2/* checkcast */, 2/* instanceof */, 0/* monitorenter */, 0/* monitorexit */,
    +        UNPREDICTABLE/* wide */, 3/* multianewarray */, 2/* ifnull */, 2/* ifnonnull */, 4/* goto_w */, 4/* jsr_w */, 0/* breakpoint */, UNDEFINED, UNDEFINED,
    +        UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    +        UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    +        UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    +        UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, RESERVED/* impdep1 */,
    +        RESERVED/* impdep2 */
    +    };
    +
    +    /**
    +     * How the byte code operands are to be interpreted for each opcode. Indexed by opcode. TYPE_OF_OPERANDS[ILOAD] = an
    +     * array of shorts describing the data types for the instruction.
    +     */
    +    static final short[][] TYPE_OF_OPERANDS = {{}/* nop */, {}/* aconst_null */, {}/* iconst_m1 */, {}/* iconst_0 */, {}/* iconst_1 */,
    +        {}/* iconst_2 */, {}/* iconst_3 */, {}/* iconst_4 */, {}/* iconst_5 */, {}/* lconst_0 */, {}/* lconst_1 */, {}/* fconst_0 */, {}/* fconst_1 */,
    +        {}/* fconst_2 */, {}/* dconst_0 */, {}/* dconst_1 */, {T_BYTE}/* bipush */, {T_SHORT}/* sipush */, {T_BYTE}/* ldc */, {T_SHORT}/* ldc_w */,
    +        {T_SHORT}/* ldc2_w */, {T_BYTE}/* iload */, {T_BYTE}/* lload */, {T_BYTE}/* fload */, {T_BYTE}/* dload */, {T_BYTE}/* aload */, {}/* iload_0 */,
    +        {}/* iload_1 */, {}/* iload_2 */, {}/* iload_3 */, {}/* lload_0 */, {}/* lload_1 */, {}/* lload_2 */, {}/* lload_3 */, {}/* fload_0 */, {}/* fload_1 */,
    +        {}/* fload_2 */, {}/* fload_3 */, {}/* dload_0 */, {}/* dload_1 */, {}/* dload_2 */, {}/* dload_3 */, {}/* aload_0 */, {}/* aload_1 */, {}/* aload_2 */,
    +        {}/* aload_3 */, {}/* iaload */, {}/* laload */, {}/* faload */, {}/* daload */, {}/* aaload */, {}/* baload */, {}/* caload */, {}/* saload */,
    +        {T_BYTE}/* istore */, {T_BYTE}/* lstore */, {T_BYTE}/* fstore */, {T_BYTE}/* dstore */, {T_BYTE}/* astore */, {}/* istore_0 */, {}/* istore_1 */,
    +        {}/* istore_2 */, {}/* istore_3 */, {}/* lstore_0 */, {}/* lstore_1 */, {}/* lstore_2 */, {}/* lstore_3 */, {}/* fstore_0 */, {}/* fstore_1 */,
    +        {}/* fstore_2 */, {}/* fstore_3 */, {}/* dstore_0 */, {}/* dstore_1 */, {}/* dstore_2 */, {}/* dstore_3 */, {}/* astore_0 */, {}/* astore_1 */,
    +        {}/* astore_2 */, {}/* astore_3 */, {}/* iastore */, {}/* lastore */, {}/* fastore */, {}/* dastore */, {}/* aastore */, {}/* bastore */,
    +        {}/* castore */, {}/* sastore */, {}/* pop */, {}/* pop2 */, {}/* dup */, {}/* dup_x1 */, {}/* dup_x2 */, {}/* dup2 */, {}/* dup2_x1 */,
    +        {}/* dup2_x2 */, {}/* swap */, {}/* iadd */, {}/* ladd */, {}/* fadd */, {}/* dadd */, {}/* isub */, {}/* lsub */, {}/* fsub */, {}/* dsub */,
    +        {}/* imul */, {}/* lmul */, {}/* fmul */, {}/* dmul */, {}/* idiv */, {}/* ldiv */, {}/* fdiv */, {}/* ddiv */, {}/* irem */, {}/* lrem */,
    +        {}/* frem */, {}/* drem */, {}/* ineg */, {}/* lneg */, {}/* fneg */, {}/* dneg */, {}/* ishl */, {}/* lshl */, {}/* ishr */, {}/* lshr */,
    +        {}/* iushr */, {}/* lushr */, {}/* iand */, {}/* land */, {}/* ior */, {}/* lor */, {}/* ixor */, {}/* lxor */, {T_BYTE, T_BYTE}/* iinc */, {}/* i2l */,
    +        {}/* i2f */, {}/* i2d */, {}/* l2i */, {}/* l2f */, {}/* l2d */, {}/* f2i */, {}/* f2l */, {}/* f2d */, {}/* d2i */, {}/* d2l */, {}/* d2f */,
    +        {}/* i2b */, {}/* i2c */, {}/* i2s */, {}/* lcmp */, {}/* fcmpl */, {}/* fcmpg */, {}/* dcmpl */, {}/* dcmpg */, {T_SHORT}/* ifeq */,
    +        {T_SHORT}/* ifne */, {T_SHORT}/* iflt */, {T_SHORT}/* ifge */, {T_SHORT}/* ifgt */, {T_SHORT}/* ifle */, {T_SHORT}/* if_icmpeq */,
    +        {T_SHORT}/* if_icmpne */, {T_SHORT}/* if_icmplt */, {T_SHORT}/* if_icmpge */, {T_SHORT}/* if_icmpgt */, {T_SHORT}/* if_icmple */,
    +        {T_SHORT}/* if_acmpeq */, {T_SHORT}/* if_acmpne */, {T_SHORT}/* goto */, {T_SHORT}/* jsr */, {T_BYTE}/* ret */, {}/* tableswitch */,
    +        {}/* lookupswitch */, {}/* ireturn */, {}/* lreturn */, {}/* freturn */, {}/* dreturn */, {}/* areturn */, {}/* return */, {T_SHORT}/* getstatic */,
    +        {T_SHORT}/* putstatic */, {T_SHORT}/* getfield */, {T_SHORT}/* putfield */, {T_SHORT}/* invokevirtual */, {T_SHORT}/* invokespecial */,
    +        {T_SHORT}/* invokestatic */, {T_SHORT, T_BYTE, T_BYTE}/* invokeinterface */, {T_SHORT, T_BYTE, T_BYTE}/* invokedynamic */, {T_SHORT}/* new */,
    +        {T_BYTE}/* newarray */, {T_SHORT}/* anewarray */, {}/* arraylength */, {}/* athrow */, {T_SHORT}/* checkcast */, {T_SHORT}/* instanceof */,
    +        {}/* monitorenter */, {}/* monitorexit */, {T_BYTE}/* wide */, {T_SHORT, T_BYTE}/* multianewarray */, {T_SHORT}/* ifnull */, {T_SHORT}/* ifnonnull */,
    +        {T_INT}/* goto_w */, {T_INT}/* jsr_w */, {}/* breakpoint */, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
    +        {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}/* impdep1 */, {}/* impdep2 */
    +    };
    +
    +    /**
    +     * Names of opcodes. Indexed by opcode. OPCODE_NAMES[ALOAD] = "aload".
    +     */
    +    static final String[] OPCODE_NAMES = {"nop", "aconst_null", "iconst_m1", "iconst_0", "iconst_1", "iconst_2", "iconst_3", "iconst_4", "iconst_5",
    +        "lconst_0", "lconst_1", "fconst_0", "fconst_1", "fconst_2", "dconst_0", "dconst_1", "bipush", "sipush", "ldc", "ldc_w", "ldc2_w", "iload", "lload",
    +        "fload", "dload", "aload", "iload_0", "iload_1", "iload_2", "iload_3", "lload_0", "lload_1", "lload_2", "lload_3", "fload_0", "fload_1", "fload_2",
    +        "fload_3", "dload_0", "dload_1", "dload_2", "dload_3", "aload_0", "aload_1", "aload_2", "aload_3", "iaload", "laload", "faload", "daload", "aaload",
    +        "baload", "caload", "saload", "istore", "lstore", "fstore", "dstore", "astore", "istore_0", "istore_1", "istore_2", "istore_3", "lstore_0", "lstore_1",
    +        "lstore_2", "lstore_3", "fstore_0", "fstore_1", "fstore_2", "fstore_3", "dstore_0", "dstore_1", "dstore_2", "dstore_3", "astore_0", "astore_1",
    +        "astore_2", "astore_3", "iastore", "lastore", "fastore", "dastore", "aastore", "bastore", "castore", "sastore", "pop", "pop2", "dup", "dup_x1",
    +        "dup_x2", "dup2", "dup2_x1", "dup2_x2", "swap", "iadd", "ladd", "fadd", "dadd", "isub", "lsub", "fsub", "dsub", "imul", "lmul", "fmul", "dmul", "idiv",
    +        "ldiv", "fdiv", "ddiv", "irem", "lrem", "frem", "drem", "ineg", "lneg", "fneg", "dneg", "ishl", "lshl", "ishr", "lshr", "iushr", "lushr", "iand",
    +        "land", "ior", "lor", "ixor", "lxor", "iinc", "i2l", "i2f", "i2d", "l2i", "l2f", "l2d", "f2i", "f2l", "f2d", "d2i", "d2l", "d2f", "i2b", "i2c", "i2s",
    +        "lcmp", "fcmpl", "fcmpg", "dcmpl", "dcmpg", "ifeq", "ifne", "iflt", "ifge", "ifgt", "ifle", "if_icmpeq", "if_icmpne", "if_icmplt", "if_icmpge",
    +        "if_icmpgt", "if_icmple", "if_acmpeq", "if_acmpne", "goto", "jsr", "ret", "tableswitch", "lookupswitch", "ireturn", "lreturn", "freturn", "dreturn",
    +        "areturn", "return", "getstatic", "putstatic", "getfield", "putfield", "invokevirtual", "invokespecial", "invokestatic", "invokeinterface",
    +        "invokedynamic", "new", "newarray", "anewarray", "arraylength", "athrow", "checkcast", "instanceof", "monitorenter", "monitorexit", "wide",
    +        "multianewarray", "ifnull", "ifnonnull", "goto_w", "jsr_w", "breakpoint", ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    +        ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    +        ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    +        ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    +        ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    +        ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
    +        ILLEGAL_OPCODE, ILLEGAL_OPCODE, "impdep1", "impdep2"};
    +
    +    /**
    +     * @since 6.0
    +     */
    +    public static final int OPCODE_NAMES_LENGTH = OPCODE_NAMES.length;
    +
    +    /**
    +     * Number of words consumed on operand stack by instructions. Indexed by opcode. CONSUME_STACK[FALOAD] = number of words
    +     * consumed from the stack by a faload instruction.
    +     */
    +    static final int[] CONSUME_STACK = {0/* nop */, 0/* aconst_null */, 0/* iconst_m1 */, 0/* iconst_0 */, 0/* iconst_1 */, 0/* iconst_2 */,
    +        0/* iconst_3 */, 0/* iconst_4 */, 0/* iconst_5 */, 0/* lconst_0 */, 0/* lconst_1 */, 0/* fconst_0 */, 0/* fconst_1 */, 0/* fconst_2 */, 0/* dconst_0 */,
    +        0/* dconst_1 */, 0/* bipush */, 0/* sipush */, 0/* ldc */, 0/* ldc_w */, 0/* ldc2_w */, 0/* iload */, 0/* lload */, 0/* fload */, 0/* dload */,
    +        0/* aload */, 0/* iload_0 */, 0/* iload_1 */, 0/* iload_2 */, 0/* iload_3 */, 0/* lload_0 */, 0/* lload_1 */, 0/* lload_2 */, 0/* lload_3 */,
    +        0/* fload_0 */, 0/* fload_1 */, 0/* fload_2 */, 0/* fload_3 */, 0/* dload_0 */, 0/* dload_1 */, 0/* dload_2 */, 0/* dload_3 */, 0/* aload_0 */,
    +        0/* aload_1 */, 0/* aload_2 */, 0/* aload_3 */, 2/* iaload */, 2/* laload */, 2/* faload */, 2/* daload */, 2/* aaload */, 2/* baload */, 2/* caload */,
    +        2/* saload */, 1/* istore */, 2/* lstore */, 1/* fstore */, 2/* dstore */, 1/* astore */, 1/* istore_0 */, 1/* istore_1 */, 1/* istore_2 */,
    +        1/* istore_3 */, 2/* lstore_0 */, 2/* lstore_1 */, 2/* lstore_2 */, 2/* lstore_3 */, 1/* fstore_0 */, 1/* fstore_1 */, 1/* fstore_2 */, 1/* fstore_3 */,
    +        2/* dstore_0 */, 2/* dstore_1 */, 2/* dstore_2 */, 2/* dstore_3 */, 1/* astore_0 */, 1/* astore_1 */, 1/* astore_2 */, 1/* astore_3 */, 3/* iastore */,
    +        4/* lastore */, 3/* fastore */, 4/* dastore */, 3/* aastore */, 3/* bastore */, 3/* castore */, 3/* sastore */, 1/* pop */, 2/* pop2 */, 1/* dup */,
    +        2/* dup_x1 */, 3/* dup_x2 */, 2/* dup2 */, 3/* dup2_x1 */, 4/* dup2_x2 */, 2/* swap */, 2/* iadd */, 4/* ladd */, 2/* fadd */, 4/* dadd */, 2/* isub */,
    +        4/* lsub */, 2/* fsub */, 4/* dsub */, 2/* imul */, 4/* lmul */, 2/* fmul */, 4/* dmul */, 2/* idiv */, 4/* ldiv */, 2/* fdiv */, 4/* ddiv */,
    +        2/* irem */, 4/* lrem */, 2/* frem */, 4/* drem */, 1/* ineg */, 2/* lneg */, 1/* fneg */, 2/* dneg */, 2/* ishl */, 3/* lshl */, 2/* ishr */,
    +        3/* lshr */, 2/* iushr */, 3/* lushr */, 2/* iand */, 4/* land */, 2/* ior */, 4/* lor */, 2/* ixor */, 4/* lxor */, 0/* iinc */, 1/* i2l */,
    +        1/* i2f */, 1/* i2d */, 2/* l2i */, 2/* l2f */, 2/* l2d */, 1/* f2i */, 1/* f2l */, 1/* f2d */, 2/* d2i */, 2/* d2l */, 2/* d2f */, 1/* i2b */,
    +        1/* i2c */, 1/* i2s */, 4/* lcmp */, 2/* fcmpl */, 2/* fcmpg */, 4/* dcmpl */, 4/* dcmpg */, 1/* ifeq */, 1/* ifne */, 1/* iflt */, 1/* ifge */,
    +        1/* ifgt */, 1/* ifle */, 2/* if_icmpeq */, 2/* if_icmpne */, 2/* if_icmplt */, 2 /* if_icmpge */, 2/* if_icmpgt */, 2/* if_icmple */, 2/* if_acmpeq */,
    +        2/* if_acmpne */, 0/* goto */, 0/* jsr */, 0/* ret */, 1/* tableswitch */, 1/* lookupswitch */, 1/* ireturn */, 2/* lreturn */, 1/* freturn */,
    +        2/* dreturn */, 1/* areturn */, 0/* return */, 0/* getstatic */, UNPREDICTABLE/* putstatic */, 1/* getfield */, UNPREDICTABLE/* putfield */,
    +        UNPREDICTABLE/* invokevirtual */, UNPREDICTABLE/* invokespecial */, UNPREDICTABLE/* invokestatic */, UNPREDICTABLE/* invokeinterface */,
    +        UNPREDICTABLE/* invokedynamic */, 0/* new */, 1/* newarray */, 1/* anewarray */, 1/* arraylength */, 1/* athrow */, 1/* checkcast */, 1/* instanceof */,
    +        1/* monitorenter */, 1/* monitorexit */, 0/* wide */, UNPREDICTABLE/* multianewarray */, 1/* ifnull */, 1/* ifnonnull */, 0/* goto_w */, 0/* jsr_w */,
    +        0/* breakpoint */, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    +        UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    +        UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    +        UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    +        UNPREDICTABLE/* impdep1 */, UNPREDICTABLE/* impdep2 */
    +    };
    +
    +    /**
    +     * Number of words produced onto operand stack by instructions. Indexed by opcode. CONSUME_STACK[DALOAD] = number of
    +     * words consumed from the stack by a daload instruction.
    +     */
    +    static final int[] PRODUCE_STACK = {0/* nop */, 1/* aconst_null */, 1/* iconst_m1 */, 1/* iconst_0 */, 1/* iconst_1 */, 1/* iconst_2 */,
    +        1/* iconst_3 */, 1/* iconst_4 */, 1/* iconst_5 */, 2/* lconst_0 */, 2/* lconst_1 */, 1/* fconst_0 */, 1/* fconst_1 */, 1/* fconst_2 */, 2/* dconst_0 */,
    +        2/* dconst_1 */, 1/* bipush */, 1/* sipush */, 1/* ldc */, 1/* ldc_w */, 2/* ldc2_w */, 1/* iload */, 2/* lload */, 1/* fload */, 2/* dload */,
    +        1/* aload */, 1/* iload_0 */, 1/* iload_1 */, 1/* iload_2 */, 1/* iload_3 */, 2/* lload_0 */, 2/* lload_1 */, 2/* lload_2 */, 2/* lload_3 */,
    +        1/* fload_0 */, 1/* fload_1 */, 1/* fload_2 */, 1/* fload_3 */, 2/* dload_0 */, 2/* dload_1 */, 2/* dload_2 */, 2/* dload_3 */, 1/* aload_0 */,
    +        1/* aload_1 */, 1/* aload_2 */, 1/* aload_3 */, 1/* iaload */, 2/* laload */, 1/* faload */, 2/* daload */, 1/* aaload */, 1/* baload */, 1/* caload */,
    +        1/* saload */, 0/* istore */, 0/* lstore */, 0/* fstore */, 0/* dstore */, 0/* astore */, 0/* istore_0 */, 0/* istore_1 */, 0/* istore_2 */,
    +        0/* istore_3 */, 0/* lstore_0 */, 0/* lstore_1 */, 0/* lstore_2 */, 0/* lstore_3 */, 0/* fstore_0 */, 0/* fstore_1 */, 0/* fstore_2 */, 0/* fstore_3 */,
    +        0/* dstore_0 */, 0/* dstore_1 */, 0/* dstore_2 */, 0/* dstore_3 */, 0/* astore_0 */, 0/* astore_1 */, 0/* astore_2 */, 0/* astore_3 */, 0/* iastore */,
    +        0/* lastore */, 0/* fastore */, 0/* dastore */, 0/* aastore */, 0/* bastore */, 0/* castore */, 0/* sastore */, 0/* pop */, 0/* pop2 */, 2/* dup */,
    +        3/* dup_x1 */, 4/* dup_x2 */, 4/* dup2 */, 5/* dup2_x1 */, 6/* dup2_x2 */, 2/* swap */, 1/* iadd */, 2/* ladd */, 1/* fadd */, 2/* dadd */, 1/* isub */,
    +        2/* lsub */, 1/* fsub */, 2/* dsub */, 1/* imul */, 2/* lmul */, 1/* fmul */, 2/* dmul */, 1/* idiv */, 2/* ldiv */, 1/* fdiv */, 2/* ddiv */,
    +        1/* irem */, 2/* lrem */, 1/* frem */, 2/* drem */, 1/* ineg */, 2/* lneg */, 1/* fneg */, 2/* dneg */, 1/* ishl */, 2/* lshl */, 1/* ishr */,
    +        2/* lshr */, 1/* iushr */, 2/* lushr */, 1/* iand */, 2/* land */, 1/* ior */, 2/* lor */, 1/* ixor */, 2/* lxor */, 0/* iinc */, 2/* i2l */,
    +        1/* i2f */, 2/* i2d */, 1/* l2i */, 1/* l2f */, 2/* l2d */, 1/* f2i */, 2/* f2l */, 2/* f2d */, 1/* d2i */, 2/* d2l */, 1/* d2f */, 1/* i2b */,
    +        1/* i2c */, 1/* i2s */, 1/* lcmp */, 1/* fcmpl */, 1/* fcmpg */, 1/* dcmpl */, 1/* dcmpg */, 0/* ifeq */, 0/* ifne */, 0/* iflt */, 0/* ifge */,
    +        0/* ifgt */, 0/* ifle */, 0/* if_icmpeq */, 0/* if_icmpne */, 0/* if_icmplt */, 0/* if_icmpge */, 0/* if_icmpgt */, 0/* if_icmple */, 0/* if_acmpeq */,
    +        0/* if_acmpne */, 0/* goto */, 1/* jsr */, 0/* ret */, 0/* tableswitch */, 0/* lookupswitch */, 0/* ireturn */, 0/* lreturn */, 0/* freturn */,
    +        0/* dreturn */, 0/* areturn */, 0/* return */, UNPREDICTABLE/* getstatic */, 0/* putstatic */, UNPREDICTABLE/* getfield */, 0/* putfield */,
    +        UNPREDICTABLE/* invokevirtual */, UNPREDICTABLE/* invokespecial */, UNPREDICTABLE/* invokestatic */, UNPREDICTABLE/* invokeinterface */,
    +        UNPREDICTABLE/* invokedynamic */, 1/* new */, 1/* newarray */, 1/* anewarray */, 1/* arraylength */, 1/* athrow */, 1/* checkcast */, 1/* instanceof */,
    +        0/* monitorenter */, 0/* monitorexit */, 0/* wide */, 1/* multianewarray */, 0/* ifnull */, 0/* ifnonnull */, 0/* goto_w */, 1/* jsr_w */,
    +        0/* breakpoint */, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    +        UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    +        UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    +        UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
    +        UNPREDICTABLE/* impdep1 */, UNPREDICTABLE/* impdep2 */
    +    };
    +
    +    /**
    +     * Attributes and their corresponding names.
    +     */
    +    public static final byte ATTR_UNKNOWN = -1;
    +
    +    public static final byte ATTR_SOURCE_FILE = 0;
    +
    +    public static final byte ATTR_CONSTANT_VALUE = 1;
    +
    +    public static final byte ATTR_CODE = 2;
    +
    +    public static final byte ATTR_EXCEPTIONS = 3;
    +
    +    public static final byte ATTR_LINE_NUMBER_TABLE = 4;
    +
    +    public static final byte ATTR_LOCAL_VARIABLE_TABLE = 5;
    +
    +    public static final byte ATTR_INNER_CLASSES = 6;
    +
    +    public static final byte ATTR_SYNTHETIC = 7;
    +
    +    public static final byte ATTR_DEPRECATED = 8;
    +
    +    public static final byte ATTR_PMG = 9;
    +
    +    public static final byte ATTR_SIGNATURE = 10;
    +
    +    public static final byte ATTR_STACK_MAP = 11;
    +    public static final byte ATTR_RUNTIME_VISIBLE_ANNOTATIONS = 12;
    +    public static final byte ATTR_RUNTIME_INVISIBLE_ANNOTATIONS = 13;
    +    public static final byte ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = 14;
    +    public static final byte ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = 15;
    +    public static final byte ATTR_ANNOTATION_DEFAULT = 16;
    +    public static final byte ATTR_LOCAL_VARIABLE_TYPE_TABLE = 17;
    +    public static final byte ATTR_ENCLOSING_METHOD = 18;
    +    public static final byte ATTR_STACK_MAP_TABLE = 19;
    +    public static final byte ATTR_BOOTSTRAP_METHODS = 20;
    +    public static final byte ATTR_METHOD_PARAMETERS = 21;
    +    public static final byte ATTR_MODULE = 22;
    +    public static final byte ATTR_MODULE_PACKAGES = 23;
    +    public static final byte ATTR_MODULE_MAIN_CLASS = 24;
    +    public static final byte ATTR_NEST_HOST = 25;
    +    public static final byte ATTR_NEST_MEMBERS = 26;
    +    public static final short KNOWN_ATTRIBUTES = 27; // count of attributes
    +    private static final String[] ATTRIBUTE_NAMES = {"SourceFile", "ConstantValue", "Code", "Exceptions", "LineNumberTable", "LocalVariableTable",
    +        "InnerClasses", "Synthetic", "Deprecated", "PMGClass", "Signature", "StackMap", "RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations",
    +        "RuntimeVisibleParameterAnnotations", "RuntimeInvisibleParameterAnnotations", "AnnotationDefault", "LocalVariableTypeTable", "EnclosingMethod",
    +        "StackMapTable", "BootstrapMethods", "MethodParameters", "Module", "ModulePackages", "ModuleMainClass", "NestHost", "NestMembers"};
    +    /**
    +     * Constants used in the StackMap attribute.
    +     */
    +    public static final byte ITEM_Bogus = 0;
    +    public static final byte ITEM_Integer = 1;
    +    public static final byte ITEM_Float = 2;
    +    public static final byte ITEM_Double = 3;
    +    public static final byte ITEM_Long = 4;
    +    public static final byte ITEM_Null = 5;
    +    public static final byte ITEM_InitObject = 6;
    +    public static final byte ITEM_Object = 7;
    +    public static final byte ITEM_NewObject = 8;
    +    private static final String[] ITEM_NAMES = {"Bogus", "Integer", "Float", "Double", "Long", "Null", "InitObject", "Object", "NewObject"};
    +
    +    /**
    +     * Constants used to identify StackMapEntry types.
    +     *
    +     * For those types which can specify a range, the constant names the lowest value.
    +     */
    +    public static final int SAME_FRAME = 0;
    +
    +    public static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64;
    +
    +    public static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247;
    +
    +    public static final int CHOP_FRAME = 248;
    +    public static final int SAME_FRAME_EXTENDED = 251;
    +    public static final int APPEND_FRAME = 252;
    +    public static final int FULL_FRAME = 255;
    +    /**
    +     * Constants that define the maximum value of those constants which store ranges.
    +     */
    +
    +    public static final int SAME_FRAME_MAX = 63;
    +    public static final int SAME_LOCALS_1_STACK_ITEM_FRAME_MAX = 127;
    +    public static final int CHOP_FRAME_MAX = 250;
    +    public static final int APPEND_FRAME_MAX = 254;
    +    public static final byte REF_getField = 1;
    +
    +    public static final byte REF_getStatic = 2;
    +
    +    public static final byte REF_putField = 3;
    +
    +    public static final byte REF_putStatic = 4;
    +    public static final byte REF_invokeVirtual = 5;
    +    public static final byte REF_invokeStatic = 6;
    +    public static final byte REF_invokeSpecial = 7;
    +    public static final byte REF_newInvokeSpecial = 8;
    +    public static final byte REF_invokeInterface = 9;
    +    /**
    +     * The names of the reference_kinds of a CONSTANT_MethodHandle_info.
    +     */
    +    private static final String[] METHODHANDLE_NAMES = {"", "getField", "getStatic", "putField", "putStatic", "invokeVirtual", "invokeStatic", "invokeSpecial",
    +        "newInvokeSpecial", "invokeInterface"};
    +
    +    /**
    +     * @param index
    +     * @return the ACCESS_NAMES entry at the given index
    +     * @since 6.0
    +     */
    +    public static String getAccessName(final int index) {
    +        return ACCESS_NAMES[index];
    +    }
    +
    +    /**
    +     *
    +     * @param index
    +     * @return the attribute name
    +     * @since 6.0
    +     */
    +    public static String getAttributeName(final int index) {
    +        return ATTRIBUTE_NAMES[index];
    +    }
    +
    +    /**
    +     * The primitive class names corresponding to the T_XX constants, e.g., CLASS_TYPE_NAMES[T_INT] = "java.lang.Integer"
    +     *
    +     * @param index
    +     * @return the class name
    +     * @since 6.0
    +     */
    +    public static String getClassTypeName(final int index) {
    +        return CLASS_TYPE_NAMES[index];
    +    }
    +
    +    /**
    +     *
    +     * @param index
    +     * @return the CONSTANT_NAMES entry at the given index
    +     * @since 6.0
    +     */
    +    public static String getConstantName(final int index) {
    +        return CONSTANT_NAMES[index];
    +    }
    +
    +    // Constants defining the behavior of the Method Handles (JVMS 5.4.3.5)
    +
    +    /**
    +     *
    +     * @param index
    +     * @return Number of words consumed on operand stack
    +     * @since 6.0
    +     */
    +    public static int getConsumeStack(final int index) {
    +        return CONSUME_STACK[index];
    +    }
    +
    +    /**
    +     * @since 6.0
    +     */
    +    public static Iterable getInterfacesImplementedByArrays() {
    +        return Collections.unmodifiableList(Arrays.asList(INTERFACES_IMPLEMENTED_BY_ARRAYS));
    +    }
    +
    +    /**
    +     *
    +     * @param index
    +     * @return the item name
    +     * @since 6.0
    +     */
    +    public static String getItemName(final int index) {
    +        return ITEM_NAMES[index];
    +    }
    +
    +    /**
    +     *
    +     * @param index
    +     * @return the method handle name
    +     * @since 6.0
    +     */
    +    public static String getMethodHandleName(final int index) {
    +        return METHODHANDLE_NAMES[index];
    +    }
    +
    +    /**
    +     *
    +     * @param index
    +     * @return Number of byte code operands
    +     * @since 6.0
    +     */
    +    public static short getNoOfOperands(final int index) {
    +        return NO_OF_OPERANDS[index];
    +    }
    +
    +    /**
    +     * @since 6.0
    +     */
    +    public static String getOpcodeName(final int index) {
    +        return OPCODE_NAMES[index];
    +    }
    +
    +    /**
    +     * @since 6.0
    +     */
    +    public static short getOperandType(final int opcode, final int index) {
    +        return TYPE_OF_OPERANDS[opcode][index];
    +    }
    +
    +    /**
    +     * @since 6.0
    +     */
    +    public static long getOperandTypeCount(final int opcode) {
    +        return TYPE_OF_OPERANDS[opcode].length;
    +    }
    +
    +    /**
    +     *
    +     * @param index
    +     * @return Number of words produced onto operand stack
    +     * @since 6.0
    +     */
    +    public static int getProduceStack(final int index) {
    +        return PRODUCE_STACK[index];
    +    }
    +
    +    /**
    +     *
    +     * @param index
    +     * @return the short type name
    +     * @since 6.0
    +     */
    +    public static String getShortTypeName(final int index) {
    +        return SHORT_TYPE_NAMES[index];
    +    }
    +
    +    /**
    +     * The primitive type names corresponding to the T_XX constants, e.g., TYPE_NAMES[T_INT] = "int"
    +     *
    +     * @param index
    +     * @return the type name
    +     * @since 6.0
    +     */
    +    public static String getTypeName(final int index) {
    +        return TYPE_NAMES[index];
    +    }
    +
    +    private Const() {
    +    } // not instantiable
     
     }
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/ExceptionConst.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/ExceptionConst.java
    index 14be14ee3b0..d45c5794b7b 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/ExceptionConst.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/ExceptionConst.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
      */
     /*
      * Licensed to the Apache Software Foundation (ASF) under one or more
    @@ -20,13 +20,24 @@
     
     package com.sun.org.apache.bcel.internal;
     
    +import jdk.xml.internal.Utils;
    +
     /**
      * Exception constants.
    + *
      * @since 6.0 (intended to replace the InstructionConstant interface)
    - * @LastModified: May 2021
    + * @LastModified: Feb 2023
      */
     public final class ExceptionConst {
     
    +    /**
    +     * Enum corresponding to the various Exception Class arrays, used by
    +     * {@link ExceptionConst#createExceptions(EXCS, Class...)}
    +     */
    +    public enum EXCS {
    +        EXCS_CLASS_AND_INTERFACE_RESOLUTION, EXCS_FIELD_AND_METHOD_RESOLUTION, EXCS_INTERFACE_METHOD_RESOLUTION, EXCS_STRING_RESOLUTION, EXCS_ARRAY_EXCEPTION,
    +    }
    +
         /**
          * The mother of all exceptions
          */
    @@ -64,61 +75,41 @@ public final class ExceptionConst {
          * Run-Time Exceptions
          */
         public static final Class NULL_POINTER_EXCEPTION = NullPointerException.class;
    -    public static final Class ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION
    -                                                            = ArrayIndexOutOfBoundsException.class;
    +    public static final Class ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION = ArrayIndexOutOfBoundsException.class;
         public static final Class ARITHMETIC_EXCEPTION = ArithmeticException.class;
         public static final Class NEGATIVE_ARRAY_SIZE_EXCEPTION = NegativeArraySizeException.class;
         public static final Class CLASS_CAST_EXCEPTION = ClassCastException.class;
    +
         public static final Class ILLEGAL_MONITOR_STATE = IllegalMonitorStateException.class;
    +    /**
    +     * Pre-defined exception arrays according to chapters 5.1-5.4 of the Java Virtual Machine Specification
    +     */
    +    private static final Class[] EXCS_CLASS_AND_INTERFACE_RESOLUTION = {NO_CLASS_DEF_FOUND_ERROR, CLASS_FORMAT_ERROR, VERIFY_ERROR, ABSTRACT_METHOD_ERROR,
    +        EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR}; // Chapter 5.1
    +
    +    private static final Class[] EXCS_FIELD_AND_METHOD_RESOLUTION = {NO_SUCH_FIELD_ERROR, ILLEGAL_ACCESS_ERROR, NO_SUCH_METHOD_ERROR}; // Chapter 5.2
     
         /**
    -     * Pre-defined exception arrays according to chapters 5.1-5.4 of the Java Virtual
    -     * Machine Specification
    +     * Empty array.
          */
    -    private static final Class[] EXCS_CLASS_AND_INTERFACE_RESOLUTION = {
    -            NO_CLASS_DEF_FOUND_ERROR, CLASS_FORMAT_ERROR, VERIFY_ERROR, ABSTRACT_METHOD_ERROR,
    -            EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR
    -    }; // Chapter 5.1
    -    private static final Class[] EXCS_FIELD_AND_METHOD_RESOLUTION = {
    -            NO_SUCH_FIELD_ERROR, ILLEGAL_ACCESS_ERROR, NO_SUCH_METHOD_ERROR
    -    }; // Chapter 5.2
         private static final Class[] EXCS_INTERFACE_METHOD_RESOLUTION = new Class[0]; // Chapter 5.3 (as below)
    -    private static final Class[] EXCS_STRING_RESOLUTION = new Class[0];
    -    // Chapter 5.4 (no errors but the ones that _always_ could happen! How stupid.)
    -    private static final Class[] EXCS_ARRAY_EXCEPTION = {
    -            NULL_POINTER_EXCEPTION, ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION
    -    };
     
         /**
    -     * Enum corresponding to the various Exception Class arrays,
    -     * used by {@link ExceptionConst#createExceptions(EXCS, Class...)}
    +     * Empty array.
          */
    -    public enum EXCS {
    -        EXCS_CLASS_AND_INTERFACE_RESOLUTION,
    -        EXCS_FIELD_AND_METHOD_RESOLUTION,
    -        EXCS_INTERFACE_METHOD_RESOLUTION,
    -        EXCS_STRING_RESOLUTION,
    -        EXCS_ARRAY_EXCEPTION,
    -    }
    +    private static final Class[] EXCS_STRING_RESOLUTION = new Class[0];
     
    -    // helper method to merge exception class arrays
    -    private static Class[] mergeExceptions(final Class[] input, final Class ... extraClasses) {
    -        final int extraLen = extraClasses == null ? 0 : extraClasses.length;
    -        final Class[] excs = new Class[input.length + extraLen];
    -        System.arraycopy(input, 0, excs, 0, input.length);
    -        if (extraLen > 0) {
    -            System.arraycopy(extraClasses, 0, excs, input.length, extraLen);
    -        }
    -        return excs;
    -    }
    +    // Chapter 5.4 (no errors but the ones that _always_ could happen! How stupid.)
    +    private static final Class[] EXCS_ARRAY_EXCEPTION = {NULL_POINTER_EXCEPTION, ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION};
     
         /**
          * Creates a copy of the specified Exception Class array combined with any additional Exception classes.
    +     *
          * @param type the basic array type
          * @param extraClasses additional classes, if any
          * @return the merged array
          */
    -    public static Class[] createExceptions(final EXCS type, final Class ... extraClasses) {
    +    public static Class[] createExceptions(final EXCS type, final Class... extraClasses) {
             switch (type) {
             case EXCS_CLASS_AND_INTERFACE_RESOLUTION:
                 return mergeExceptions(EXCS_CLASS_AND_INTERFACE_RESOLUTION, extraClasses);
    @@ -135,5 +126,8 @@ public static Class[] createExceptions(final EXCS type, final Class ... ex
             }
         }
     
    -
    +    // helper method to merge exception class arrays
    +    private static Class[] mergeExceptions(final Class[] input, final Class... extraClasses) {
    +        return Utils.arraysAppend(input, extraClasses);
    +    }
     }
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Repository.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Repository.java
    index 4b419f399a6..d36260cc23a 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Repository.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Repository.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
      */
     /*
      * Licensed to the Apache Software Foundation (ASF) under one or more
    @@ -24,227 +24,183 @@
     import com.sun.org.apache.bcel.internal.util.SyntheticRepository;
     
     /**
    - * The repository maintains informations about class interdependencies, e.g.,
    - * whether a class is a sub-class of another. Delegates actual class loading
    - * to SyntheticRepository with current class path by default.
    + * The repository maintains informations about class interdependencies, e.g., whether a class is a sub-class of another.
    + * Delegates actual class loading to SyntheticRepository with current class path by default.
      *
      * @see com.sun.org.apache.bcel.internal.util.Repository
      * @see SyntheticRepository
      *
    - * @LastModified: Jan 2020
    + * @LastModified: Feb 2023
      */
     public abstract class Repository {
     
    -    private static com.sun.org.apache.bcel.internal.util.Repository repository
    -            = SyntheticRepository.getInstance();
    -
    +    private static com.sun.org.apache.bcel.internal.util.Repository repository = SyntheticRepository.getInstance();
     
         /**
    -     * @return currently used repository instance
    +     * Adds clazz to repository if there isn't an equally named class already in there.
    +     *
    +     * @return old entry in repository
          */
    -    public static com.sun.org.apache.bcel.internal.util.Repository getRepository() {
    -        return repository;
    +    public static JavaClass addClass(final JavaClass clazz) {
    +        final JavaClass old = repository.findClass(clazz.getClassName());
    +        repository.storeClass(clazz);
    +        return old;
         }
     
    -
         /**
    -     * Sets repository instance to be used for class loading
    +     * Clears the repository.
          */
    -    public static void setRepository( final com.sun.org.apache.bcel.internal.util.Repository rep ) {
    -        repository = rep;
    +    public static void clearCache() {
    +        repository.clear();
         }
     
    -
         /**
    -     * Lookups class somewhere found on your CLASSPATH, or whereever the
    -     * repository instance looks for it.
    -     *
    -     * @return class object for given fully qualified class name
    -     * @throws ClassNotFoundException if the class could not be found or
    -     * parsed correctly
    +     * @return all interfaces implemented by class and its super classes and the interfaces that those interfaces extend,
    +     *         and so on. (Some people call this a transitive hull).
    +     * @throws ClassNotFoundException if any of the class's superclasses or superinterfaces can't be found
          */
    -    public static JavaClass lookupClass( final String class_name ) throws ClassNotFoundException {
    -        return repository.loadClass(class_name);
    +    public static JavaClass[] getInterfaces(final JavaClass clazz) throws ClassNotFoundException {
    +        return clazz.getAllInterfaces();
         }
     
    -
         /**
    -     * Tries to find class source using the internal repository instance.
    -     *
    -     * @see Class
    -     * @return JavaClass object for given runtime class
    -     * @throws ClassNotFoundException if the class could not be found or
    -     * parsed correctly
    +     * @return all interfaces implemented by class and its super classes and the interfaces that extend those interfaces,
    +     *         and so on
    +     * @throws ClassNotFoundException if the named class can't be found, or if any of its superclasses or superinterfaces
    +     *         can't be found
          */
    -    public static JavaClass lookupClass( final Class clazz ) throws ClassNotFoundException {
    -        return repository.loadClass(clazz);
    +    public static JavaClass[] getInterfaces(final String className) throws ClassNotFoundException {
    +        return getInterfaces(lookupClass(className));
         }
     
    -
         /**
    -     * Clear the repository.
    +     * @return currently used repository instance
          */
    -    public static void clearCache() {
    -        repository.clear();
    +    public static com.sun.org.apache.bcel.internal.util.Repository getRepository() {
    +        return repository;
         }
     
    -
         /**
    -     * Adds clazz to repository if there isn't an equally named class already in there.
    -     *
    -     * @return old entry in repository
    +     * @return list of super classes of clazz in ascending order, i.e., Object is always the last element
    +     * @throws ClassNotFoundException if any of the superclasses can't be found
          */
    -    public static JavaClass addClass( final JavaClass clazz ) {
    -        final JavaClass old = repository.findClass(clazz.getClassName());
    -        repository.storeClass(clazz);
    -        return old;
    +    public static JavaClass[] getSuperClasses(final JavaClass clazz) throws ClassNotFoundException {
    +        return clazz.getSuperClasses();
         }
     
    -
         /**
    -     * Removes class with given (fully qualified) name from repository.
    +     * @return list of super classes of clazz in ascending order, i.e., Object is always the last element.
    +     * @throws ClassNotFoundException if the named class or any of its superclasses can't be found
          */
    -    public static void removeClass( final String clazz ) {
    -        repository.removeClass(repository.findClass(clazz));
    +    public static JavaClass[] getSuperClasses(final String className) throws ClassNotFoundException {
    +        return getSuperClasses(lookupClass(className));
         }
     
    -
         /**
    -     * Removes given class from repository.
    +     * @return true, if clazz is an implementation of interface inter
    +     * @throws ClassNotFoundException if any superclasses or superinterfaces of clazz can't be found
          */
    -    public static void removeClass( final JavaClass clazz ) {
    -        repository.removeClass(clazz);
    +    public static boolean implementationOf(final JavaClass clazz, final JavaClass inter) throws ClassNotFoundException {
    +        return clazz.implementationOf(inter);
         }
     
    -
         /**
    -     * @return list of super classes of clazz in ascending order, i.e.,
    -     * Object is always the last element
    -     * @throws ClassNotFoundException if any of the superclasses can't be found
    +     * @return true, if clazz is an implementation of interface inter
    +     * @throws ClassNotFoundException if inter or any superclasses or superinterfaces of clazz can't be found
          */
    -    public static JavaClass[] getSuperClasses( final JavaClass clazz ) throws ClassNotFoundException {
    -        return clazz.getSuperClasses();
    +    public static boolean implementationOf(final JavaClass clazz, final String inter) throws ClassNotFoundException {
    +        return implementationOf(clazz, lookupClass(inter));
         }
     
    -
         /**
    -     * @return list of super classes of clazz in ascending order, i.e.,
    -     * Object is always the last element.
    -     * @throws ClassNotFoundException if the named class or any of its
    -     *  superclasses can't be found
    +     * @return true, if clazz is an implementation of interface inter
    +     * @throws ClassNotFoundException if clazz or any superclasses or superinterfaces of clazz can't be found
          */
    -    public static JavaClass[] getSuperClasses( final String class_name ) throws ClassNotFoundException {
    -        final JavaClass jc = lookupClass(class_name);
    -        return getSuperClasses(jc);
    +    public static boolean implementationOf(final String clazz, final JavaClass inter) throws ClassNotFoundException {
    +        return implementationOf(lookupClass(clazz), inter);
         }
     
    -
         /**
    -     * @return all interfaces implemented by class and its super
    -     * classes and the interfaces that those interfaces extend, and so on.
    -     * (Some people call this a transitive hull).
    -     * @throws ClassNotFoundException if any of the class's
    -     *  superclasses or superinterfaces can't be found
    +     * @return true, if clazz is an implementation of interface inter
    +     * @throws ClassNotFoundException if clazz, inter, or any superclasses or superinterfaces of clazz can't be found
          */
    -    public static JavaClass[] getInterfaces( final JavaClass clazz ) throws ClassNotFoundException {
    -        return clazz.getAllInterfaces();
    +    public static boolean implementationOf(final String clazz, final String inter) throws ClassNotFoundException {
    +        return implementationOf(lookupClass(clazz), lookupClass(inter));
         }
     
    -
         /**
    -     * @return all interfaces implemented by class and its super
    -     * classes and the interfaces that extend those interfaces, and so on
    -     * @throws ClassNotFoundException if the named class can't be found,
    -     *   or if any of its superclasses or superinterfaces can't be found
    +     * Equivalent to runtime "instanceof" operator.
    +     *
    +     * @return true, if clazz is an instance of superclass
    +     * @throws ClassNotFoundException if any superclasses or superinterfaces of clazz can't be found
          */
    -    public static JavaClass[] getInterfaces( final String class_name ) throws ClassNotFoundException {
    -        return getInterfaces(lookupClass(class_name));
    +    public static boolean instanceOf(final JavaClass clazz, final JavaClass superclass) throws ClassNotFoundException {
    +        return clazz.instanceOf(superclass);
         }
     
    -
         /**
    -     * Equivalent to runtime "instanceof" operator.
    -     * @return true, if clazz is an instance of super_class
    -     * @throws ClassNotFoundException if any superclasses or superinterfaces
    -     *   of clazz can't be found
    +     * @return true, if clazz is an instance of superclass
    +     * @throws ClassNotFoundException if superclass can't be found
          */
    -    public static boolean instanceOf( final JavaClass clazz, final JavaClass super_class )
    -            throws ClassNotFoundException {
    -        return clazz.instanceOf(super_class);
    +    public static boolean instanceOf(final JavaClass clazz, final String superclass) throws ClassNotFoundException {
    +        return instanceOf(clazz, lookupClass(superclass));
         }
     
    -
         /**
    -     * @return true, if clazz is an instance of super_class
    -     * @throws ClassNotFoundException if either clazz or super_class
    -     *   can't be found
    +     * @return true, if clazz is an instance of superclass
    +     * @throws ClassNotFoundException if clazz can't be found
          */
    -    public static boolean instanceOf( final String clazz, final String super_class )
    -            throws ClassNotFoundException {
    -        return instanceOf(lookupClass(clazz), lookupClass(super_class));
    +    public static boolean instanceOf(final String clazz, final JavaClass superclass) throws ClassNotFoundException {
    +        return instanceOf(lookupClass(clazz), superclass);
         }
     
    -
         /**
    -     * @return true, if clazz is an instance of super_class
    -     * @throws ClassNotFoundException if super_class can't be found
    +     * @return true, if clazz is an instance of superclass
    +     * @throws ClassNotFoundException if either clazz or superclass can't be found
          */
    -    public static boolean instanceOf( final JavaClass clazz, final String super_class )
    -            throws ClassNotFoundException {
    -        return instanceOf(clazz, lookupClass(super_class));
    +    public static boolean instanceOf(final String clazz, final String superclass) throws ClassNotFoundException {
    +        return instanceOf(lookupClass(clazz), lookupClass(superclass));
         }
     
    -
         /**
    -     * @return true, if clazz is an instance of super_class
    -     * @throws ClassNotFoundException if clazz can't be found
    +     * Tries to find class source using the internal repository instance.
    +     *
    +     * @see Class
    +     * @return JavaClass object for given runtime class
    +     * @throws ClassNotFoundException if the class could not be found or parsed correctly
          */
    -    public static boolean instanceOf( final String clazz, final JavaClass super_class )
    -            throws ClassNotFoundException {
    -        return instanceOf(lookupClass(clazz), super_class);
    +    public static JavaClass lookupClass(final Class clazz) throws ClassNotFoundException {
    +        return repository.loadClass(clazz);
         }
     
    -
         /**
    -     * @return true, if clazz is an implementation of interface inter
    -     * @throws ClassNotFoundException if any superclasses or superinterfaces
    -     *   of clazz can't be found
    +     * Lookups class somewhere found on your CLASSPATH, or wherever the repository instance looks for it.
    +     *
    +     * @return class object for given fully qualified class name
    +     * @throws ClassNotFoundException if the class could not be found or parsed correctly
          */
    -    public static boolean implementationOf( final JavaClass clazz, final JavaClass inter )
    -            throws ClassNotFoundException {
    -        return clazz.implementationOf(inter);
    +    public static JavaClass lookupClass(final String className) throws ClassNotFoundException {
    +        return repository.loadClass(className);
         }
     
    -
         /**
    -     * @return true, if clazz is an implementation of interface inter
    -     * @throws ClassNotFoundException if clazz, inter, or any superclasses
    -     *   or superinterfaces of clazz can't be found
    +     * Removes given class from repository.
          */
    -    public static boolean implementationOf( final String clazz, final String inter )
    -            throws ClassNotFoundException {
    -        return implementationOf(lookupClass(clazz), lookupClass(inter));
    +    public static void removeClass(final JavaClass clazz) {
    +        repository.removeClass(clazz);
         }
     
    -
         /**
    -     * @return true, if clazz is an implementation of interface inter
    -     * @throws ClassNotFoundException if inter or any superclasses
    -     *   or superinterfaces of clazz can't be found
    +     * Removes class with given (fully qualified) name from repository.
          */
    -    public static boolean implementationOf( final JavaClass clazz, final String inter )
    -            throws ClassNotFoundException {
    -        return implementationOf(clazz, lookupClass(inter));
    +    public static void removeClass(final String clazz) {
    +        repository.removeClass(repository.findClass(clazz));
         }
     
    -
         /**
    -     * @return true, if clazz is an implementation of interface inter
    -     * @throws ClassNotFoundException if clazz or any superclasses or
    -     *   superinterfaces of clazz can't be found
    +     * Sets repository instance to be used for class loading
          */
    -    public static boolean implementationOf( final String clazz, final JavaClass inter )
    -            throws ClassNotFoundException {
    -        return implementationOf(lookupClass(clazz), inter);
    +    public static void setRepository(final com.sun.org.apache.bcel.internal.util.Repository rep) {
    +        repository = rep;
         }
     }
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AccessFlags.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AccessFlags.java
    index a6e086a97a9..61ec9c4d690 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AccessFlags.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AccessFlags.java
    @@ -29,14 +29,17 @@
      */
     public abstract class AccessFlags {
     
    -    private int access_flags;
    +    /**
    +     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
    +     */
    +    @java.lang.Deprecated
    +    protected int access_flags; // TODO not used externally at present
     
         public AccessFlags() {
         }
     
         /**
    -     * @param a
    -     *            inital access flags
    +     * @param a initial access flags
          */
         public AccessFlags(final int a) {
             access_flags = a;
    @@ -56,163 +59,159 @@ public final int getModifiers() {
             return access_flags;
         }
     
    -    /**
    -     * Set access flags aka "modifiers".
    -     *
    -     * @param access_flags
    -     *            Access flags of the object.
    -     */
    -    public final void setAccessFlags(final int access_flags) {
    -        this.access_flags = access_flags;
    -    }
    -
    -    /**
    -     * Set access flags aka "modifiers".
    -     *
    -     * @param access_flags
    -     *            Access flags of the object.
    -     */
    -    public final void setModifiers(final int access_flags) {
    -        setAccessFlags(access_flags);
    -    }
    -
    -    private void setFlag(final int flag, final boolean set) {
    -        if ((access_flags & flag) != 0) { // Flag is set already
    -            if (!set) {
    -                access_flags ^= flag;
    -            }
    -        } else { // Flag not set
    -            if (set) {
    -                access_flags |= flag;
    -            }
    -        }
    -    }
    -
    -    public final void isPublic(final boolean flag) {
    -        setFlag(Const.ACC_PUBLIC, flag);
    -    }
    -
    -    public final boolean isPublic() {
    -        return (access_flags & Const.ACC_PUBLIC) != 0;
    +    public final boolean isAbstract() {
    +        return (access_flags & Const.ACC_ABSTRACT) != 0;
         }
     
    -    public final void isPrivate(final boolean flag) {
    -        setFlag(Const.ACC_PRIVATE, flag);
    +    public final void isAbstract(final boolean flag) {
    +        setFlag(Const.ACC_ABSTRACT, flag);
         }
     
    -    public final boolean isPrivate() {
    -        return (access_flags & Const.ACC_PRIVATE) != 0;
    +    public final boolean isAnnotation() {
    +        return (access_flags & Const.ACC_ANNOTATION) != 0;
         }
     
    -    public final void isProtected(final boolean flag) {
    -        setFlag(Const.ACC_PROTECTED, flag);
    +    public final void isAnnotation(final boolean flag) {
    +        setFlag(Const.ACC_ANNOTATION, flag);
         }
     
    -    public final boolean isProtected() {
    -        return (access_flags & Const.ACC_PROTECTED) != 0;
    +    public final boolean isEnum() {
    +        return (access_flags & Const.ACC_ENUM) != 0;
         }
     
    -    public final void isStatic(final boolean flag) {
    -        setFlag(Const.ACC_STATIC, flag);
    +    public final void isEnum(final boolean flag) {
    +        setFlag(Const.ACC_ENUM, flag);
         }
     
    -    public final boolean isStatic() {
    -        return (access_flags & Const.ACC_STATIC) != 0;
    +    public final boolean isFinal() {
    +        return (access_flags & Const.ACC_FINAL) != 0;
         }
     
         public final void isFinal(final boolean flag) {
             setFlag(Const.ACC_FINAL, flag);
         }
     
    -    public final boolean isFinal() {
    -        return (access_flags & Const.ACC_FINAL) != 0;
    +    public final boolean isInterface() {
    +        return (access_flags & Const.ACC_INTERFACE) != 0;
         }
     
    -    public final void isSynchronized(final boolean flag) {
    -        setFlag(Const.ACC_SYNCHRONIZED, flag);
    +    public final void isInterface(final boolean flag) {
    +        setFlag(Const.ACC_INTERFACE, flag);
         }
     
    -    public final boolean isSynchronized() {
    -        return (access_flags & Const.ACC_SYNCHRONIZED) != 0;
    +    public final boolean isNative() {
    +        return (access_flags & Const.ACC_NATIVE) != 0;
         }
     
    -    public final void isVolatile(final boolean flag) {
    -        setFlag(Const.ACC_VOLATILE, flag);
    +    public final void isNative(final boolean flag) {
    +        setFlag(Const.ACC_NATIVE, flag);
         }
     
    -    public final boolean isVolatile() {
    -        return (access_flags & Const.ACC_VOLATILE) != 0;
    +    public final boolean isPrivate() {
    +        return (access_flags & Const.ACC_PRIVATE) != 0;
         }
     
    -    public final void isTransient(final boolean flag) {
    -        setFlag(Const.ACC_TRANSIENT, flag);
    +    public final void isPrivate(final boolean flag) {
    +        setFlag(Const.ACC_PRIVATE, flag);
         }
     
    -    public final boolean isTransient() {
    -        return (access_flags & Const.ACC_TRANSIENT) != 0;
    +    public final boolean isProtected() {
    +        return (access_flags & Const.ACC_PROTECTED) != 0;
         }
     
    -    public final void isNative(final boolean flag) {
    -        setFlag(Const.ACC_NATIVE, flag);
    +    public final void isProtected(final boolean flag) {
    +        setFlag(Const.ACC_PROTECTED, flag);
         }
     
    -    public final boolean isNative() {
    -        return (access_flags & Const.ACC_NATIVE) != 0;
    +    public final boolean isPublic() {
    +        return (access_flags & Const.ACC_PUBLIC) != 0;
         }
     
    -    public final void isInterface(final boolean flag) {
    -        setFlag(Const.ACC_INTERFACE, flag);
    +    public final void isPublic(final boolean flag) {
    +        setFlag(Const.ACC_PUBLIC, flag);
         }
     
    -    public final boolean isInterface() {
    -        return (access_flags & Const.ACC_INTERFACE) != 0;
    +    public final boolean isStatic() {
    +        return (access_flags & Const.ACC_STATIC) != 0;
         }
     
    -    public final void isAbstract(final boolean flag) {
    -        setFlag(Const.ACC_ABSTRACT, flag);
    +    public final void isStatic(final boolean flag) {
    +        setFlag(Const.ACC_STATIC, flag);
         }
     
    -    public final boolean isAbstract() {
    -        return (access_flags & Const.ACC_ABSTRACT) != 0;
    +    public final boolean isStrictfp() {
    +        return (access_flags & Const.ACC_STRICT) != 0;
         }
     
         public final void isStrictfp(final boolean flag) {
             setFlag(Const.ACC_STRICT, flag);
         }
     
    -    public final boolean isStrictfp() {
    -        return (access_flags & Const.ACC_STRICT) != 0;
    +    public final boolean isSynchronized() {
    +        return (access_flags & Const.ACC_SYNCHRONIZED) != 0;
         }
     
    -    public final void isSynthetic(final boolean flag) {
    -        setFlag(Const.ACC_SYNTHETIC, flag);
    +    public final void isSynchronized(final boolean flag) {
    +        setFlag(Const.ACC_SYNCHRONIZED, flag);
         }
     
         public final boolean isSynthetic() {
             return (access_flags & Const.ACC_SYNTHETIC) != 0;
         }
     
    -    public final void isAnnotation(final boolean flag) {
    -        setFlag(Const.ACC_ANNOTATION, flag);
    +    public final void isSynthetic(final boolean flag) {
    +        setFlag(Const.ACC_SYNTHETIC, flag);
         }
     
    -    public final boolean isAnnotation() {
    -        return (access_flags & Const.ACC_ANNOTATION) != 0;
    +    public final boolean isTransient() {
    +        return (access_flags & Const.ACC_TRANSIENT) != 0;
         }
     
    -    public final void isEnum(final boolean flag) {
    -        setFlag(Const.ACC_ENUM, flag);
    +    public final void isTransient(final boolean flag) {
    +        setFlag(Const.ACC_TRANSIENT, flag);
         }
     
    -    public final boolean isEnum() {
    -        return (access_flags & Const.ACC_ENUM) != 0;
    +    public final boolean isVarArgs() {
    +        return (access_flags & Const.ACC_VARARGS) != 0;
         }
     
         public final void isVarArgs(final boolean flag) {
             setFlag(Const.ACC_VARARGS, flag);
         }
     
    -    public final boolean isVarArgs() {
    -        return (access_flags & Const.ACC_VARARGS) != 0;
    +    public final boolean isVolatile() {
    +        return (access_flags & Const.ACC_VOLATILE) != 0;
    +    }
    +
    +    public final void isVolatile(final boolean flag) {
    +        setFlag(Const.ACC_VOLATILE, flag);
    +    }
    +
    +    /**
    +     * Set access flags aka "modifiers".
    +     *
    +     * @param accessFlags Access flags of the object.
    +     */
    +    public final void setAccessFlags(final int accessFlags) {
    +        this.access_flags = accessFlags;
    +    }
    +
    +    private void setFlag(final int flag, final boolean set) {
    +        if ((access_flags & flag) != 0) { // Flag is set already
    +            if (!set) {
    +                access_flags ^= flag;
    +            }
    +        } else if (set) {
    +            access_flags |= flag;
    +        }
    +    }
    +
    +    /**
    +     * Set access flags aka "modifiers".
    +     *
    +     * @param accessFlags Access flags of the object.
    +     */
    +    public final void setModifiers(final int accessFlags) {
    +        setAccessFlags(accessFlags);
         }
     }
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationDefault.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationDefault.java
    index dc9c8ca47ba..40bbfb6eae0 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationDefault.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationDefault.java
    @@ -28,7 +28,7 @@
     import com.sun.org.apache.bcel.internal.Const;
     
     /**
    - * Represents the default value of a annotation for a method info
    + * Represents the default value of a annotation for a method info.
      *
      * @since 6.0
      */
    @@ -37,31 +37,30 @@ public class AnnotationDefault extends Attribute {
         private ElementValue defaultValue;
     
         /**
    -     * @param name_index    Index pointing to the name Code
    -     * @param length        Content length in bytes
    -     * @param input         Input stream
    -     * @param constant_pool Array of constants
    +     * @param nameIndex Index pointing to the name Code
    +     * @param length Content length in bytes
    +     * @param input Input stream
    +     * @param constantPool Array of constants
          */
    -    AnnotationDefault(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
    -        this(name_index, length, (ElementValue) null, constant_pool);
    -        defaultValue = ElementValue.readElementValue(input, constant_pool);
    +    AnnotationDefault(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
    +        this(nameIndex, length, (ElementValue) null, constantPool);
    +        defaultValue = ElementValue.readElementValue(input, constantPool);
         }
     
         /**
    -     * @param name_index    Index pointing to the name Code
    -     * @param length        Content length in bytes
    -     * @param defaultValue  the annotation's default value
    -     * @param constant_pool Array of constants
    +     * @param nameIndex Index pointing to the name Code
    +     * @param length Content length in bytes
    +     * @param defaultValue the annotation's default value
    +     * @param constantPool Array of constants
          */
    -    public AnnotationDefault(final int name_index, final int length, final ElementValue defaultValue, final ConstantPool constant_pool) {
    -        super(Const.ATTR_ANNOTATION_DEFAULT, name_index, length, constant_pool);
    +    public AnnotationDefault(final int nameIndex, final int length, final ElementValue defaultValue, final ConstantPool constantPool) {
    +        super(Const.ATTR_ANNOTATION_DEFAULT, nameIndex, length, constantPool);
             this.defaultValue = defaultValue;
         }
     
         /**
    -     * Called by objects that are traversing the nodes of the tree implicitely
    -     * defined by the contents of a Java class. I.e., the hierarchy of methods,
    -     * fields, attributes, etc. spawns a tree of objects.
    +     * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
    +     * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
          *
          * @param v Visitor object
          */
    @@ -70,11 +69,15 @@ public void accept(final Visitor v) {
             v.visitAnnotationDefault(this);
         }
     
    -    /**
    -     * @param defaultValue the default value of this methodinfo's annotation
    -     */
    -    public final void setDefaultValue(final ElementValue defaultValue) {
    -        this.defaultValue = defaultValue;
    +    @Override
    +    public Attribute copy(final ConstantPool constantPool) {
    +        return (Attribute) clone();
    +    }
    +
    +    @Override
    +    public final void dump(final DataOutputStream dos) throws IOException {
    +        super.dump(dos);
    +        defaultValue.dump(dos);
         }
     
         /**
    @@ -84,14 +87,10 @@ public final ElementValue getDefaultValue() {
             return defaultValue;
         }
     
    -    @Override
    -    public Attribute copy(final ConstantPool _constant_pool) {
    -        return (Attribute) clone();
    -    }
    -
    -    @Override
    -    public final void dump(final DataOutputStream dos) throws IOException {
    -        super.dump(dos);
    -        defaultValue.dump(dos);
    +    /**
    +     * @param defaultValue the default value of this methodinfo's annotation
    +     */
    +    public final void setDefaultValue(final ElementValue defaultValue) {
    +        this.defaultValue = defaultValue;
         }
     }
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationElementValue.java
    index 79c7b25a266..8d618258d53 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationElementValue.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationElementValue.java
    @@ -27,43 +27,35 @@
     /**
      * @since 6.0
      */
    -public class AnnotationElementValue extends ElementValue
    -{
    -        // For annotation element values, this is the annotation
    -        private final AnnotationEntry annotationEntry;
    -
    -        public AnnotationElementValue(final int type, final AnnotationEntry annotationEntry,
    -                        final ConstantPool cpool)
    -        {
    -                super(type, cpool);
    -                if (type != ANNOTATION) {
    -                    throw new IllegalArgumentException(
    -                                    "Only element values of type annotation can be built with this ctor - type specified: " + type);
    -                }
    -                this.annotationEntry = annotationEntry;
    -        }
    -
    -        @Override
    -        public void dump(final DataOutputStream dos) throws IOException
    -        {
    -                dos.writeByte(super.getType()); // u1 type of value (ANNOTATION == '@')
    -                annotationEntry.dump(dos);
    -        }
    -
    -        @Override
    -        public String stringifyValue()
    -        {
    -                return annotationEntry.toString();
    -        }
    -
    -        @Override
    -        public String toString()
    -        {
    -                return stringifyValue();
    -        }
    -
    -        public AnnotationEntry getAnnotationEntry()
    -        {
    -                return annotationEntry;
    +public class AnnotationElementValue extends ElementValue {
    +    // For annotation element values, this is the annotation
    +    private final AnnotationEntry annotationEntry;
    +
    +    public AnnotationElementValue(final int type, final AnnotationEntry annotationEntry, final ConstantPool cpool) {
    +        super(type, cpool);
    +        if (type != ANNOTATION) {
    +            throw new ClassFormatException("Only element values of type annotation can be built with this ctor - type specified: " + type);
             }
    +        this.annotationEntry = annotationEntry;
    +    }
    +
    +    @Override
    +    public void dump(final DataOutputStream dos) throws IOException {
    +        dos.writeByte(super.getType()); // u1 type of value (ANNOTATION == '@')
    +        annotationEntry.dump(dos);
    +    }
    +
    +    public AnnotationEntry getAnnotationEntry() {
    +        return annotationEntry;
    +    }
    +
    +    @Override
    +    public String stringifyValue() {
    +        return annotationEntry.toString();
    +    }
    +
    +    @Override
    +    public String toString() {
    +        return stringifyValue();
    +    }
     }
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationEntry.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationEntry.java
    index 8344048ab93..466e9bf3404 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationEntry.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationEntry.java
    @@ -25,66 +25,60 @@
     import java.io.DataOutputStream;
     import java.io.IOException;
     import java.util.ArrayList;
    -import java.util.Collections;
     import java.util.List;
    -
    -import com.sun.org.apache.bcel.internal.Const;
    +import java.util.stream.Stream;
     
     /**
    - * represents one annotation in the annotation table
    + * Represents one annotation in the annotation table
      *
      * @since 6.0
      */
     public class AnnotationEntry implements Node {
     
    -    private final int typeIndex;
    -    private final ConstantPool constantPool;
    -    private final boolean isRuntimeVisible;
    +    public static final AnnotationEntry[] EMPTY_ARRAY = {};
     
    -    private List elementValuePairs;
    +    public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attrs) {
    +        // Find attributes that contain annotation data
    +        return Stream.of(attrs).filter(Annotations.class::isInstance).flatMap(e -> Stream.of(((Annotations) e).getAnnotationEntries()))
    +            .toArray(AnnotationEntry[]::new);
    +    }
     
    -    /*
    +    /**
          * Factory method to create an AnnotionEntry from a DataInput
          *
          * @param input
          * @param constantPool
          * @param isRuntimeVisible
          * @return the entry
    -     * @throws IOException
    +     * @throws IOException if an I/O error occurs.
          */
    -    public static AnnotationEntry read(final DataInput input, final ConstantPool constant_pool, final boolean isRuntimeVisible) throws IOException {
    -
    -        final AnnotationEntry annotationEntry = new AnnotationEntry(input.readUnsignedShort(), constant_pool, isRuntimeVisible);
    -        final int num_element_value_pairs = input.readUnsignedShort();
    +    public static AnnotationEntry read(final DataInput input, final ConstantPool constantPool, final boolean isRuntimeVisible) throws IOException {
    +        final AnnotationEntry annotationEntry = new AnnotationEntry(input.readUnsignedShort(), constantPool, isRuntimeVisible);
    +        final int numElementValuePairs = input.readUnsignedShort();
             annotationEntry.elementValuePairs = new ArrayList<>();
    -        for (int i = 0; i < num_element_value_pairs; i++) {
    -            annotationEntry.elementValuePairs.add(
    -                    new ElementValuePair(input.readUnsignedShort(), ElementValue.readElementValue(input, constant_pool),
    -                    constant_pool));
    +        for (int i = 0; i < numElementValuePairs; i++) {
    +            annotationEntry.elementValuePairs
    +                .add(new ElementValuePair(input.readUnsignedShort(), ElementValue.readElementValue(input, constantPool), constantPool));
             }
             return annotationEntry;
         }
     
    -    public AnnotationEntry(final int type_index, final ConstantPool constant_pool, final boolean isRuntimeVisible) {
    -        this.typeIndex = type_index;
    -        this.constantPool = constant_pool;
    -        this.isRuntimeVisible = isRuntimeVisible;
    -    }
    +    private final int typeIndex;
     
    -    public int getTypeIndex() {
    -        return typeIndex;
    -    }
    +    private final ConstantPool constantPool;
     
    -    public ConstantPool getConstantPool() {
    -        return constantPool;
    -    }
    +    private final boolean isRuntimeVisible;
     
    -    public boolean isRuntimeVisible() {
    -        return isRuntimeVisible;
    +    private List elementValuePairs;
    +
    +    public AnnotationEntry(final int typeIndex, final ConstantPool constantPool, final boolean isRuntimeVisible) {
    +        this.typeIndex = typeIndex;
    +        this.constantPool = constantPool;
    +        this.isRuntimeVisible = isRuntimeVisible;
         }
     
         /**
    -     * Called by objects that are traversing the nodes of the tree implicitely defined by the contents of a Java class.
    +     * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
          * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
          *
          * @param v Visitor object
    @@ -94,12 +88,24 @@ public void accept(final Visitor v) {
             v.visitAnnotationEntry(this);
         }
     
    +    public void addElementNameValuePair(final ElementValuePair elementNameValuePair) {
    +        elementValuePairs.add(elementNameValuePair);
    +    }
    +
    +    public void dump(final DataOutputStream dos) throws IOException {
    +        dos.writeShort(typeIndex); // u2 index of type name in cpool
    +        dos.writeShort(elementValuePairs.size()); // u2 element_value pair
    +        // count
    +        for (final ElementValuePair envp : elementValuePairs) {
    +            envp.dump(dos);
    +        }
    +    }
    +
         /**
          * @return the annotation type name
          */
         public String getAnnotationType() {
    -        final ConstantUtf8 c = (ConstantUtf8) constantPool.getConstant(typeIndex, Const.CONSTANT_Utf8);
    -        return c.getBytes();
    +        return constantPool.getConstantUtf8(typeIndex).getBytes();
         }
     
         /**
    @@ -109,11 +115,8 @@ public int getAnnotationTypeIndex() {
             return typeIndex;
         }
     
    -    /**
    -     * @return the number of element value pairs in this annotation entry
    -     */
    -    public final int getNumElementValuePairs() {
    -        return elementValuePairs.size();
    +    public ConstantPool getConstantPool() {
    +        return constantPool;
         }
     
         /**
    @@ -121,20 +124,22 @@ public final int getNumElementValuePairs() {
          */
         public ElementValuePair[] getElementValuePairs() {
             // TODO return List
    -        return elementValuePairs.toArray(new ElementValuePair[elementValuePairs.size()]);
    +        return elementValuePairs.toArray(ElementValuePair.EMPTY_ARRAY);
         }
     
    -    public void dump(final DataOutputStream dos) throws IOException {
    -        dos.writeShort(typeIndex); // u2 index of type name in cpool
    -        dos.writeShort(elementValuePairs.size()); // u2 element_value pair
    -        // count
    -        for (final ElementValuePair envp : elementValuePairs) {
    -            envp.dump(dos);
    -        }
    +    /**
    +     * @return the number of element value pairs in this annotation entry
    +     */
    +    public final int getNumElementValuePairs() {
    +        return elementValuePairs.size();
         }
     
    -    public void addElementNameValuePair(final ElementValuePair elementNameValuePair) {
    -        elementValuePairs.add(elementNameValuePair);
    +    public int getTypeIndex() {
    +        return typeIndex;
    +    }
    +
    +    public boolean isRuntimeVisible() {
    +        return isRuntimeVisible;
         }
     
         public String toShortString() {
    @@ -146,7 +151,10 @@ public String toShortString() {
                 result.append("(");
                 for (final ElementValuePair element : evPairs) {
                     result.append(element.toShortString());
    +                result.append(", ");
                 }
    +            // remove last ", "
    +            result.setLength(result.length() - 2);
                 result.append(")");
             }
             return result.toString();
    @@ -156,16 +164,4 @@ public String toShortString() {
         public String toString() {
             return toShortString();
         }
    -
    -    public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attrs) {
    -        // Find attributes that contain annotation data
    -        final List accumulatedAnnotations = new ArrayList<>(attrs.length);
    -        for (final Attribute attribute : attrs) {
    -            if (attribute instanceof Annotations) {
    -                final Annotations runtimeAnnotations = (Annotations) attribute;
    -                Collections.addAll(accumulatedAnnotations, runtimeAnnotations.getAnnotationEntries());
    -            }
    -        }
    -        return accumulatedAnnotations.toArray(new AnnotationEntry[accumulatedAnnotations.size()]);
    -    }
     }
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Annotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Annotations.java
    index 5dc5f5cae77..52ac9d0dd98 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Annotations.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Annotations.java
    @@ -24,40 +24,30 @@
     import java.io.DataInput;
     import java.io.DataOutputStream;
     import java.io.IOException;
    +import java.util.Iterator;
    +import java.util.stream.Stream;
    +
    +import com.sun.org.apache.bcel.internal.Const;
     
     /**
      * base class for annotations
      *
      * @since 6.0
      */
    -public abstract class Annotations extends Attribute {
    +public abstract class Annotations extends Attribute implements Iterable {
     
         private AnnotationEntry[] annotationTable;
         private final boolean isRuntimeVisible;
     
         /**
    -     * @param annotation_type the subclass type of the annotation
    -     * @param name_index Index pointing to the name Code
    -     * @param length Content length in bytes
    -     * @param input Input stream
    -     * @param constant_pool Array of constants
    -     */
    -    Annotations(final byte annotation_type, final int name_index, final int length, final DataInput input,
    -            final ConstantPool constant_pool, final boolean isRuntimeVisible) throws IOException {
    -        this(annotation_type, name_index, length, (AnnotationEntry[]) null, constant_pool, isRuntimeVisible);
    -        final int annotation_table_length = input.readUnsignedShort();
    -        annotationTable = new AnnotationEntry[annotation_table_length];
    -        for (int i = 0; i < annotation_table_length; i++) {
    -            annotationTable[i] = AnnotationEntry.read(input, constant_pool, isRuntimeVisible);
    -        }
    -    }
    -
    -    /**
    -     * @param annotationType the subclass type of the annotation
    -     * @param nameIndex Index pointing to the name Code
    -     * @param length Content length in bytes
    -     * @param annotationTable the actual annotations
    -     * @param constantPool Array of constants
    +     * Constructs an instance.
    +     *
    +     * @param annotationType   the subclass type of the annotation
    +     * @param nameIndex        Index pointing to the name Code
    +     * @param length           Content length in bytes
    +     * @param annotationTable  the actual annotations
    +     * @param constantPool     Array of constants
    +     * @param isRuntimeVisible whether this Annotation visible at runtime
          */
         public Annotations(final byte annotationType, final int nameIndex, final int length, final AnnotationEntry[] annotationTable,
                 final ConstantPool constantPool, final boolean isRuntimeVisible) {
    @@ -67,8 +57,30 @@ public Annotations(final byte annotationType, final int nameIndex, final int len
         }
     
         /**
    -     * Called by objects that are traversing the nodes of the tree implicitely defined by the contents of a Java class.
    -     * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
    +     * Constructs an instance.
    +     *
    +     * @param annotationType   the subclass type of the annotation
    +     * @param nameIndex        Index pointing to the name Code
    +     * @param length           Content length in bytes
    +     * @param input            Input stream
    +     * @param constantPool     Array of constants
    +     * @param isRuntimeVisible whether this Annotation visible at runtime
    +     * @throws IOException if an I/O error occurs.
    +     */
    +    Annotations(final byte annotationType, final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool,
    +            final boolean isRuntimeVisible) throws IOException {
    +        this(annotationType, nameIndex, length, (AnnotationEntry[]) null, constantPool, isRuntimeVisible);
    +        final int annotationTableLength = input.readUnsignedShort();
    +        annotationTable = new AnnotationEntry[annotationTableLength];
    +        for (int i = 0; i < annotationTableLength; i++) {
    +            annotationTable[i] = AnnotationEntry.read(input, constantPool, isRuntimeVisible);
    +        }
    +    }
    +
    +    /**
    +     * Called by objects that are traversing the nodes of the tree implicitly
    +     * defined by the contents of a Java class. I.e., the hierarchy of methods,
    +     * fields, attributes, etc. spawns a tree of objects.
          *
          * @param v Visitor object
          */
    @@ -77,21 +89,22 @@ public void accept(final Visitor v) {
             v.visitAnnotation(this);
         }
     
    -    /**
    -     * @param annotationTable the entries to set in this annotation
    -     */
    -    public final void setAnnotationTable(final AnnotationEntry[] annotationTable) {
    -        this.annotationTable = annotationTable;
    +    @Override
    +    public Attribute copy(final ConstantPool constantPool) {
    +        // TODO Auto-generated method stub
    +        return null;
         }
     
         /**
    -     * returns the array of annotation entries in this annotation
    +     * Gets the array of annotation entries in this annotation
          */
         public AnnotationEntry[] getAnnotationEntries() {
             return annotationTable;
         }
     
         /**
    +     * Gets the number of annotation entries in this annotation.
    +     *
          * @return the number of annotation entries in this annotation
          */
         public final int getNumAnnotations() {
    @@ -105,6 +118,38 @@ public boolean isRuntimeVisible() {
             return isRuntimeVisible;
         }
     
    +    @Override
    +    public Iterator iterator() {
    +        return Stream.of(annotationTable).iterator();
    +    }
    +
    +    /**
    +     * Sets the entries to set in this annotation.
    +     *
    +     * @param annotationTable the entries to set in this annotation
    +     */
    +    public final void setAnnotationTable(final AnnotationEntry[] annotationTable) {
    +        this.annotationTable = annotationTable;
    +    }
    +
    +    /**
    +     * Converts to a String representation.
    +     *
    +     * @return String representation
    +     */
    +    @Override
    +    public final String toString() {
    +        final StringBuilder buf = new StringBuilder(Const.getAttributeName(getTag()));
    +        buf.append(":\n");
    +        for (int i = 0; i < annotationTable.length; i++) {
    +            buf.append("  ").append(annotationTable[i]);
    +            if (i < annotationTable.length - 1) {
    +                buf.append('\n');
    +            }
    +        }
    +        return buf.toString();
    +    }
    +
         protected void writeAnnotations(final DataOutputStream dos) throws IOException {
             if (annotationTable == null) {
                 return;
    @@ -114,4 +159,5 @@ protected void writeAnnotations(final DataOutputStream dos) throws IOException {
                 element.dump(dos);
             }
         }
    +
     }
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ArrayElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ArrayElementValue.java
    index 1e15d77049c..e8768886de5 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ArrayElementValue.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ArrayElementValue.java
    @@ -27,40 +27,20 @@
     /**
      * @since 6.0
      */
    -public class ArrayElementValue extends ElementValue
    -{
    +public class ArrayElementValue extends ElementValue {
         // For array types, this is the array
         private final ElementValue[] elementValues;
     
    -    @Override
    -    public String toString()
    -    {
    -        final StringBuilder sb = new StringBuilder();
    -        sb.append("{");
    -        for (int i = 0; i < elementValues.length; i++)
    -        {
    -            sb.append(elementValues[i]);
    -            if ((i + 1) < elementValues.length) {
    -                sb.append(",");
    -            }
    -        }
    -        sb.append("}");
    -        return sb.toString();
    -    }
    -
    -    public ArrayElementValue(final int type, final ElementValue[] datums, final ConstantPool cpool)
    -    {
    +    public ArrayElementValue(final int type, final ElementValue[] datums, final ConstantPool cpool) {
             super(type, cpool);
             if (type != ARRAY) {
    -            throw new IllegalArgumentException(
    -                    "Only element values of type array can be built with this ctor - type specified: " + type);
    +            throw new ClassFormatException("Only element values of type array can be built with this ctor - type specified: " + type);
             }
             this.elementValues = datums;
         }
     
         @Override
    -    public void dump(final DataOutputStream dos) throws IOException
    -    {
    +    public void dump(final DataOutputStream dos) throws IOException {
             dos.writeByte(super.getType()); // u1 type of value (ARRAY == '[')
             dos.writeShort(elementValues.length);
             for (final ElementValue evalue : elementValues) {
    @@ -68,15 +48,21 @@ public void dump(final DataOutputStream dos) throws IOException
             }
         }
     
    +    public ElementValue[] getElementValuesArray() {
    +        return elementValues;
    +    }
    +
    +    public int getElementValuesArraySize() {
    +        return elementValues.length;
    +    }
    +
         @Override
    -    public String stringifyValue()
    -    {
    +    public String stringifyValue() {
             final StringBuilder sb = new StringBuilder();
             sb.append("[");
    -        for (int i = 0; i < elementValues.length; i++)
    -        {
    +        for (int i = 0; i < elementValues.length; i++) {
                 sb.append(elementValues[i].stringifyValue());
    -            if ((i + 1) < elementValues.length) {
    +            if (i + 1 < elementValues.length) {
                     sb.append(",");
                 }
             }
    @@ -84,13 +70,17 @@ public String stringifyValue()
             return sb.toString();
         }
     
    -    public ElementValue[] getElementValuesArray()
    -    {
    -        return elementValues;
    -    }
    -
    -    public int getElementValuesArraySize()
    -    {
    -        return elementValues.length;
    +    @Override
    +    public String toString() {
    +        final StringBuilder sb = new StringBuilder();
    +        sb.append("{");
    +        for (int i = 0; i < elementValues.length; i++) {
    +            sb.append(elementValues[i]);
    +            if (i + 1 < elementValues.length) {
    +                sb.append(",");
    +            }
    +        }
    +        sb.append("}");
    +        return sb.toString();
         }
     }
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Attribute.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Attribute.java
    index 4b21e9cdcc2..bf72fee4e00 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Attribute.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Attribute.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
      */
     /*
      * Licensed to the Apache Software Foundation (ASF) under one or more
    @@ -27,14 +27,20 @@
     import java.util.Map;
     
     import com.sun.org.apache.bcel.internal.Const;
    +import com.sun.org.apache.bcel.internal.util.Args;
     
     /**
    - * Abstract super class for Attribute objects. Currently the
    - * ConstantValue, SourceFile, Code,
    - * Exceptiontable, LineNumberTable,
    - * LocalVariableTable, InnerClasses and
    - * Synthetic attributes are supported. The Unknown
    - * attribute stands for non-standard-attributes.
    + * Abstract super class for Attribute objects. Currently the ConstantValue, SourceFile, Code, Exceptiontable,
    + * LineNumberTable, LocalVariableTable, InnerClasses and Synthetic attributes are supported. The Unknown attribute
    + * stands for non-standard-attributes.
    + *
    + * 
    + * attribute_info {
    + *   u2 attribute_name_index;
    + *   u4 attribute_length;
    + *   u1 info[attribute_length];
    + * }
    + * 
    * * @see ConstantValue * @see SourceFile @@ -47,28 +53,29 @@ * @see Synthetic * @see Deprecated * @see Signature - * @LastModified: May 2021 + * @LastModified: Feb 2023 */ public abstract class Attribute implements Cloneable, Node { private static final boolean debug = false; - private int name_index; // Points to attribute name in constant pool - private int length; // Content length of attribute field - private final byte tag; // Tag to distinguish subclasses - private ConstantPool constant_pool; - private static final Map readers = new HashMap<>(); + private static final Map READERS = new HashMap<>(); + + /** + * Empty array. + * + * @since 6.6.0 + */ + public static final Attribute[] EMPTY_ARRAY = {}; /** - * Add an Attribute reader capable of parsing (user-defined) attributes - * named "name". You should not add readers for the standard attributes such - * as "LineNumberTable", because those are handled internally. + * Add an Attribute reader capable of parsing (user-defined) attributes named "name". You should not add readers for the + * standard attributes such as "LineNumberTable", because those are handled internally. * * @param name the name of the attribute as stored in the class file - * @param r the reader object + * @param unknownAttributeReader the reader object */ - public static void addAttributeReader(final String name, final UnknownAttributeReader r) - { - readers.put(name, r); + public static void addAttributeReader(final String name, final UnknownAttributeReader unknownAttributeReader) { + READERS.put(name, unknownAttributeReader); } protected static void println(final String msg) { @@ -78,135 +85,122 @@ protected static void println(final String msg) { } /** - * Class method reads one attribute from the input data stream. This method - * must not be accessible from the outside. It is called by the Field and - * Method constructor methods. + * Class method reads one attribute from the input data stream. This method must not be accessible from the outside. It + * is called by the Field and Method constructor methods. * * @see Field * @see Method * - * @param file Input stream - * @param constant_pool Array of constants + * @param dataInput Input stream + * @param constantPool Array of constants * @return Attribute - * @throws IOException - * @throws ClassFormatException + * @throws IOException if an I/O error occurs. * @since 6.0 */ - public static Attribute readAttribute(final DataInput file, final ConstantPool constant_pool) - throws IOException, ClassFormatException - { + public static Attribute readAttribute(final DataInput dataInput, final ConstantPool constantPool) throws IOException { byte tag = Const.ATTR_UNKNOWN; // Unknown attribute - // Get class name from constant pool via `name_index' indirection - final int name_index = file.readUnsignedShort(); - final ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8); - final String name = c.getBytes(); + // Get class name from constant pool via 'name_index' indirection + final int nameIndex = dataInput.readUnsignedShort(); + final String name = constantPool.getConstantUtf8(nameIndex).getBytes(); // Length of data in bytes - final int length = file.readInt(); + final int length = dataInput.readInt(); // Compare strings to find known attribute - for (byte i = 0; i < Const.KNOWN_ATTRIBUTES; i++) - { - if (name.equals(Const.getAttributeName(i))) - { + for (byte i = 0; i < Const.KNOWN_ATTRIBUTES; i++) { + if (name.equals(Const.getAttributeName(i))) { tag = i; // found! break; } } - // Call proper constructor, depending on `tag' - switch (tag) - { - case Const.ATTR_UNKNOWN: - final Object r = readers.get(name); - if (r instanceof UnknownAttributeReader) - { - return ((UnknownAttributeReader) r).createAttribute(name_index, length, file, constant_pool); - } - return new Unknown(name_index, length, file, constant_pool); - case Const.ATTR_CONSTANT_VALUE: - return new ConstantValue(name_index, length, file, constant_pool); - case Const.ATTR_SOURCE_FILE: - return new SourceFile(name_index, length, file, constant_pool); - case Const.ATTR_CODE: - return new Code(name_index, length, file, constant_pool); - case Const.ATTR_EXCEPTIONS: - return new ExceptionTable(name_index, length, file, constant_pool); - case Const.ATTR_LINE_NUMBER_TABLE: - return new LineNumberTable(name_index, length, file, constant_pool); - case Const.ATTR_LOCAL_VARIABLE_TABLE: - return new LocalVariableTable(name_index, length, file, constant_pool); - case Const.ATTR_INNER_CLASSES: - return new InnerClasses(name_index, length, file, constant_pool); - case Const.ATTR_SYNTHETIC: - return new Synthetic(name_index, length, file, constant_pool); - case Const.ATTR_DEPRECATED: - return new Deprecated(name_index, length, file, constant_pool); - case Const.ATTR_PMG: - return new PMGClass(name_index, length, file, constant_pool); - case Const.ATTR_SIGNATURE: - return new Signature(name_index, length, file, constant_pool); - case Const.ATTR_STACK_MAP: - // old style stack map: unneeded for JDK5 and below; - // illegal(?) for JDK6 and above. So just delete with a warning. - println("Warning: Obsolete StackMap attribute ignored."); - return new Unknown(name_index, length, file, constant_pool); - case Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS: - return new RuntimeVisibleAnnotations(name_index, length, file, constant_pool); - case Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS: - return new RuntimeInvisibleAnnotations(name_index, length, file, constant_pool); - case Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS: - return new RuntimeVisibleParameterAnnotations(name_index, length, file, constant_pool); - case Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS: - return new RuntimeInvisibleParameterAnnotations(name_index, length, file, constant_pool); - case Const.ATTR_ANNOTATION_DEFAULT: - return new AnnotationDefault(name_index, length, file, constant_pool); - case Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE: - return new LocalVariableTypeTable(name_index, length, file, constant_pool); - case Const.ATTR_ENCLOSING_METHOD: - return new EnclosingMethod(name_index, length, file, constant_pool); - case Const.ATTR_STACK_MAP_TABLE: - // read new style stack map: StackMapTable. The rest of the code - // calls this a StackMap for historical reasons. - return new StackMap(name_index, length, file, constant_pool); - case Const.ATTR_BOOTSTRAP_METHODS: - return new BootstrapMethods(name_index, length, file, constant_pool); - case Const.ATTR_METHOD_PARAMETERS: - return new MethodParameters(name_index, length, file, constant_pool); - case Const.ATTR_MODULE: - return new Module(name_index, length, file, constant_pool); - case Const.ATTR_MODULE_PACKAGES: - return new ModulePackages(name_index, length, file, constant_pool); - case Const.ATTR_MODULE_MAIN_CLASS: - return new ModuleMainClass(name_index, length, file, constant_pool); - case Const.ATTR_NEST_HOST: - return new NestHost(name_index, length, file, constant_pool); - case Const.ATTR_NEST_MEMBERS: - return new NestMembers(name_index, length, file, constant_pool); - default: - // Never reached - throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag); + // Call proper constructor, depending on 'tag' + switch (tag) { + case Const.ATTR_UNKNOWN: + final Object r = READERS.get(name); + if (r instanceof UnknownAttributeReader) { + return ((UnknownAttributeReader) r).createAttribute(nameIndex, length, dataInput, constantPool); + } + return new Unknown(nameIndex, length, dataInput, constantPool); + case Const.ATTR_CONSTANT_VALUE: + return new ConstantValue(nameIndex, length, dataInput, constantPool); + case Const.ATTR_SOURCE_FILE: + return new SourceFile(nameIndex, length, dataInput, constantPool); + case Const.ATTR_CODE: + return new Code(nameIndex, length, dataInput, constantPool); + case Const.ATTR_EXCEPTIONS: + return new ExceptionTable(nameIndex, length, dataInput, constantPool); + case Const.ATTR_LINE_NUMBER_TABLE: + return new LineNumberTable(nameIndex, length, dataInput, constantPool); + case Const.ATTR_LOCAL_VARIABLE_TABLE: + return new LocalVariableTable(nameIndex, length, dataInput, constantPool); + case Const.ATTR_INNER_CLASSES: + return new InnerClasses(nameIndex, length, dataInput, constantPool); + case Const.ATTR_SYNTHETIC: + return new Synthetic(nameIndex, length, dataInput, constantPool); + case Const.ATTR_DEPRECATED: + return new Deprecated(nameIndex, length, dataInput, constantPool); + case Const.ATTR_PMG: + return new PMGClass(nameIndex, length, dataInput, constantPool); + case Const.ATTR_SIGNATURE: + return new Signature(nameIndex, length, dataInput, constantPool); + case Const.ATTR_STACK_MAP: + // old style stack map: unneeded for JDK5 and below; + // illegal(?) for JDK6 and above. So just delete with a warning. + println("Warning: Obsolete StackMap attribute ignored."); + return new Unknown(nameIndex, length, dataInput, constantPool); + case Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS: + return new RuntimeVisibleAnnotations(nameIndex, length, dataInput, constantPool); + case Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS: + return new RuntimeInvisibleAnnotations(nameIndex, length, dataInput, constantPool); + case Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS: + return new RuntimeVisibleParameterAnnotations(nameIndex, length, dataInput, constantPool); + case Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS: + return new RuntimeInvisibleParameterAnnotations(nameIndex, length, dataInput, constantPool); + case Const.ATTR_ANNOTATION_DEFAULT: + return new AnnotationDefault(nameIndex, length, dataInput, constantPool); + case Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE: + return new LocalVariableTypeTable(nameIndex, length, dataInput, constantPool); + case Const.ATTR_ENCLOSING_METHOD: + return new EnclosingMethod(nameIndex, length, dataInput, constantPool); + case Const.ATTR_STACK_MAP_TABLE: + // read new style stack map: StackMapTable. The rest of the code + // calls this a StackMap for historical reasons. + return new StackMap(nameIndex, length, dataInput, constantPool); + case Const.ATTR_BOOTSTRAP_METHODS: + return new BootstrapMethods(nameIndex, length, dataInput, constantPool); + case Const.ATTR_METHOD_PARAMETERS: + return new MethodParameters(nameIndex, length, dataInput, constantPool); + case Const.ATTR_MODULE: + return new Module(nameIndex, length, dataInput, constantPool); + case Const.ATTR_MODULE_PACKAGES: + return new ModulePackages(nameIndex, length, dataInput, constantPool); + case Const.ATTR_MODULE_MAIN_CLASS: + return new ModuleMainClass(nameIndex, length, dataInput, constantPool); + case Const.ATTR_NEST_HOST: + return new NestHost(nameIndex, length, dataInput, constantPool); + case Const.ATTR_NEST_MEMBERS: + return new NestMembers(nameIndex, length, dataInput, constantPool); + default: + // Never reached + throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag); } } /** - * Class method reads one attribute from the input data stream. This method - * must not be accessible from the outside. It is called by the Field and - * Method constructor methods. + * Class method reads one attribute from the input data stream. This method must not be accessible from the outside. It + * is called by the Field and Method constructor methods. * * @see Field * @see Method * - * @param file Input stream - * @param constant_pool Array of constants + * @param dataInputStream Input stream + * @param constantPool Array of constants * @return Attribute - * @throws IOException - * @throws ClassFormatException + * @throws IOException if an I/O error occurs. */ - public static Attribute readAttribute(final DataInputStream file, final ConstantPool constant_pool) - throws IOException, ClassFormatException - { - return readAttribute((DataInput) file, constant_pool); + public static Attribute readAttribute(final DataInputStream dataInputStream, final ConstantPool constantPool) throws IOException { + return readAttribute((DataInput) dataInputStream, constantPool); } /** @@ -214,65 +208,95 @@ public static Attribute readAttribute(final DataInputStream file, final Constant * * @param name the name of the attribute as stored in the class file */ - public static void removeAttributeReader(final String name) - { - readers.remove(name); + public static void removeAttributeReader(final String name) { + READERS.remove(name); } - protected Attribute(final byte tag, final int name_index, final int length, final ConstantPool constant_pool) - { + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @java.lang.Deprecated + protected int name_index; // Points to attribute name in constant pool TODO make private (has getter & setter) + + /** + * @deprecated (since 6.0) (since 6.0) will be made private; do not access directly, use getter/setter + */ + @java.lang.Deprecated + protected int length; // Content length of attribute field TODO make private (has getter & setter) + + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @java.lang.Deprecated + protected byte tag; // Tag to distinguish subclasses TODO make private & final; supposed to be immutable + + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @java.lang.Deprecated + protected ConstantPool constant_pool; // TODO make private (has getter & setter) + + /** + * Constructs an instance. + * + *
    +     * attribute_info {
    +     *   u2 attribute_name_index;
    +     *   u4 attribute_length;
    +     *   u1 info[attribute_length];
    +     * }
    +     * 
    + * + * @param tag tag. + * @param nameIndex u2 name index. + * @param length u4 length. + * @param constantPool constant pool. + */ + protected Attribute(final byte tag, final int nameIndex, final int length, final ConstantPool constantPool) { this.tag = tag; - this.name_index = name_index; - this.length = length; - this.constant_pool = constant_pool; + this.name_index = Args.requireU2(nameIndex, 0, constantPool.getLength(), getClass().getSimpleName() + " name index"); + this.length = Args.requireU4(length, getClass().getSimpleName() + " attribute length"); + this.constant_pool = constantPool; } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * - * @param v - * Visitor object + * @param v Visitor object */ @Override public abstract void accept(Visitor v); /** - * Use copy() if you want to have a deep copy(), i.e., with all references - * copied correctly. + * Use copy() if you want to have a deep copy(), i.e., with all references copied correctly. * * @return shallow copy of this attribute */ @Override - public Object clone() - { + public Object clone() { Attribute attr = null; - try - { + try { attr = (Attribute) super.clone(); - } - catch (final CloneNotSupportedException e) - { + } catch (final CloneNotSupportedException e) { throw new Error("Clone Not Supported"); // never happens } return attr; } /** - * @return deep copy of this attribute + * @param constantPool constant pool to save. + * @return deep copy of this attribute. */ - public abstract Attribute copy(ConstantPool _constant_pool); + public abstract Attribute copy(ConstantPool constantPool); /** - * Dump attribute to file stream in binary format. + * Dumps attribute to file stream in binary format. * - * @param file - * Output file stream - * @throws IOException + * @param file Output file stream + * @throws IOException if an I/O error occurs. */ - public void dump(final DataOutputStream file) throws IOException - { + public void dump(final DataOutputStream file) throws IOException { file.writeShort(name_index); file.writeInt(length); } @@ -281,16 +305,14 @@ public void dump(final DataOutputStream file) throws IOException * @return Constant pool used by this object. * @see ConstantPool */ - public final ConstantPool getConstantPool() - { + public final ConstantPool getConstantPool() { return constant_pool; } /** * @return Length of attribute field in bytes. */ - public final int getLength() - { + public final int getLength() { return length; } @@ -298,59 +320,51 @@ public final int getLength() * @return Name of attribute * @since 6.0 */ - public String getName() - { - final ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8); - return c.getBytes(); + public String getName() { + return constant_pool.getConstantUtf8(name_index).getBytes(); } /** * @return Name index in constant pool of attribute name. */ - public final int getNameIndex() - { + public final int getNameIndex() { return name_index; } /** * @return Tag of attribute, i.e., its type. Value may not be altered, thus there is no setTag() method. */ - public final byte getTag() - { + public final byte getTag() { return tag; } /** - * @param constant_pool Constant pool to be used for this object. + * @param constantPool Constant pool to be used for this object. * @see ConstantPool */ - public final void setConstantPool(final ConstantPool constant_pool) - { - this.constant_pool = constant_pool; + public final void setConstantPool(final ConstantPool constantPool) { + this.constant_pool = constantPool; } /** * @param length length in bytes. */ - public final void setLength(final int length) - { + public final void setLength(final int length) { this.length = length; } /** - * @param name_index of attribute. + * @param nameIndex of attribute. */ - public final void setNameIndex(final int name_index) - { - this.name_index = name_index; + public final void setNameIndex(final int nameIndex) { + this.name_index = nameIndex; } /** * @return attribute name. */ @Override - public String toString() - { + public String toString() { return Const.getAttributeName(tag); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AttributeReader.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AttributeReader.java index 33dcd33cec4..6d4891f953f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AttributeReader.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AttributeReader.java @@ -22,10 +22,9 @@ package com.sun.org.apache.bcel.internal.classfile; /** - * Unknown (non-standard) attributes may be read via user-defined factory - * objects that can be registered with the Attribute.addAttributeReader - * method. These factory objects should implement this interface. - + * Unknown (non-standard) attributes may be read via user-defined factory objects that can be registered with the + * Attribute.addAttributeReader method. These factory objects should implement this interface. + * * @see Attribute * * @deprecated Use UnknownAttributeReader instead @@ -34,30 +33,23 @@ public interface AttributeReader { /** - When this attribute reader is added via the static method - Attribute.addAttributeReader, an attribute name is associated with it. - As the class file parser parses attributes, it will call various - AttributeReaders based on the name of the attributes it is - constructing. - - @param name_index An index into the constant pool, indexing a - ConstantUtf8 that represents the name of the attribute. - - @param length The length of the data contained in the attribute. This - is written into the constant pool and should agree with what the - factory expects the length to be. - - @param file This is the data input stream that the factory needs to read - its data from. - - @param constant_pool This is the constant pool associated with the - Attribute that we are constructing. - - @return The user-defined AttributeReader should take this data and use - it to construct an attribute. In the case of errors, a null can be - returned which will cause the parsing of the class file to fail. - - @see Attribute#addAttributeReader( String, AttributeReader ) + * When this attribute reader is added via the static method Attribute.addAttributeReader, an attribute name is + * associated with it. As the class file parser parses attributes, it will call various AttributeReaders based on the + * name of the attributes it is constructing. + * + * @param nameIndex An index into the constant pool, indexing a ConstantUtf8 that represents the name of the attribute. + * + * @param length The length of the data contained in the attribute. This is written into the constant pool and should + * agree with what the factory expects the length to be. + * + * @param file This is the data input stream that the factory needs to read its data from. + * + * @param constantPool This is the constant pool associated with the Attribute that we are constructing. + * + * @return The user-defined AttributeReader should take this data and use it to construct an attribute. In the case of + * errors, a null can be returned which will cause the parsing of the class file to fail. + * + * @see Attribute#addAttributeReader( String, AttributeReader ) */ - Attribute createAttribute( int name_index, int length, java.io.DataInputStream file, ConstantPool constant_pool ); + Attribute createAttribute(int nameIndex, int length, java.io.DataInputStream file, ConstantPool constantPool); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethod.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethod.java index 47e655e13c5..61b818ec4f0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethod.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethod.java @@ -29,12 +29,11 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class represents a bootstrap method attribute, i.e., the bootstrap - * method ref, the number of bootstrap arguments and an array of the - * bootstrap arguments. + * This class represents a bootstrap method attribute, i.e., the bootstrap method ref, the number of bootstrap arguments + * and an array of the bootstrap arguments. * - * @see - * The class File Format : The BootstrapMethods Attribute + * @see The class File Format : + * The BootstrapMethods Attribute * @since 6.0 */ public class BootstrapMethod implements Cloneable { @@ -45,9 +44,10 @@ public class BootstrapMethod implements Cloneable { /** Array of references to the constant_pool table */ private int[] bootstrapArguments; - /** * Initialize from another object. + * + * @param c Source to copy. */ public BootstrapMethod(final BootstrapMethod c) { this(c.getBootstrapMethodRef(), c.getBootstrapArguments()); @@ -57,7 +57,7 @@ public BootstrapMethod(final BootstrapMethod c) { * Construct object from input stream. * * @param input Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ BootstrapMethod(final DataInput input) throws IOException { this(input.readUnsignedShort(), input.readUnsignedShort()); @@ -68,8 +68,8 @@ public BootstrapMethod(final BootstrapMethod c) { } // helper method - private BootstrapMethod(final int bootstrap_method_ref, final int num_bootstrap_arguments) { - this(bootstrap_method_ref, new int[num_bootstrap_arguments]); + private BootstrapMethod(final int bootstrapMethodRef, final int numBootstrapArguments) { + this(bootstrapMethodRef, new int[numBootstrapArguments]); } /** @@ -82,17 +82,29 @@ public BootstrapMethod(final int bootstrapMethodRef, final int[] bootstrapArgume } /** - * @return index into constant_pool of bootstrap_method + * @return deep copy of this object */ - public int getBootstrapMethodRef() { - return bootstrapMethodRef; + public BootstrapMethod copy() { + try { + return (BootstrapMethod) clone(); + } catch (final CloneNotSupportedException e) { + // TODO should this throw? + } + return null; } /** - * @param bootstrapMethodRef int index into constant_pool of CONSTANT_MethodHandle + * Dump object to file stream in binary format. + * + * @param file Output file stream + * @throws IOException if an I/O error occurs. */ - public void setBootstrapMethodRef(final int bootstrapMethodRef) { - this.bootstrapMethodRef = bootstrapMethodRef; + public final void dump(final DataOutputStream file) throws IOException { + file.writeShort(bootstrapMethodRef); + file.writeShort(bootstrapArguments.length); + for (final int bootstrapArgument : bootstrapArguments) { + file.writeShort(bootstrapArgument); + } } /** @@ -102,6 +114,13 @@ public int[] getBootstrapArguments() { return bootstrapArguments; } + /** + * @return index into constant_pool of bootstrap_method + */ + public int getBootstrapMethodRef() { + return bootstrapMethodRef; + } + /** * @return count of number of boostrap arguments */ @@ -116,58 +135,36 @@ public void setBootstrapArguments(final int[] bootstrapArguments) { this.bootstrapArguments = bootstrapArguments; } + /** + * @param bootstrapMethodRef int index into constant_pool of CONSTANT_MethodHandle + */ + public void setBootstrapMethodRef(final int bootstrapMethodRef) { + this.bootstrapMethodRef = bootstrapMethodRef; + } + /** * @return String representation. */ @Override public final String toString() { - return "BootstrapMethod(" + bootstrapMethodRef + ", " + bootstrapArguments.length + ", " - + Arrays.toString(bootstrapArguments) + ")"; + return "BootstrapMethod(" + bootstrapMethodRef + ", " + bootstrapArguments.length + ", " + Arrays.toString(bootstrapArguments) + ")"; } /** * @return Resolved string representation */ - public final String toString( final ConstantPool constantPool ) { + public final String toString(final ConstantPool constantPool) { final StringBuilder buf = new StringBuilder(); - String bootstrap_method_name; - bootstrap_method_name = constantPool.constantToString(bootstrapMethodRef, - Const.CONSTANT_MethodHandle); - buf.append(Utility.compactClassName(bootstrap_method_name, false)); - final int num_bootstrap_arguments = bootstrapArguments.length; - if (num_bootstrap_arguments > 0) { + final String bootstrapMethodName = constantPool.constantToString(bootstrapMethodRef, Const.CONSTANT_MethodHandle); + buf.append(Utility.compactClassName(bootstrapMethodName, false)); + final int bootstrapArgumentsLen = bootstrapArguments.length; + if (bootstrapArgumentsLen > 0) { buf.append("\nMethod Arguments:"); - for (int i = 0; i < num_bootstrap_arguments; i++) { + for (int i = 0; i < bootstrapArgumentsLen; i++) { buf.append("\n ").append(i).append(": "); buf.append(constantPool.constantToString(constantPool.getConstant(bootstrapArguments[i]))); } } return buf.toString(); } - - /** - * Dump object to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(final DataOutputStream file) throws IOException { - file.writeShort(bootstrapMethodRef); - file.writeShort(bootstrapArguments.length); - for (final int bootstrap_argument : bootstrapArguments) { - file.writeShort(bootstrap_argument); - } - } - - /** - * @return deep copy of this object - */ - public BootstrapMethod copy() { - try { - return (BootstrapMethod) clone(); - } catch (final CloneNotSupportedException e) { - // TODO should this throw? - } - return null; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethods.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethods.java index 1a55a725c9f..6f9930f1b16 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethods.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethods.java @@ -24,73 +24,62 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Iterator; +import java.util.stream.Stream; import com.sun.org.apache.bcel.internal.Const; /** * This class represents a BootstrapMethods attribute. * - * @see - * The class File Format : The BootstrapMethods Attribute + * @see The class File Format : + * The BootstrapMethods Attribute * @since 6.0 */ -public class BootstrapMethods extends Attribute { +public class BootstrapMethods extends Attribute implements Iterable { - private BootstrapMethod[] bootstrapMethods; // TODO this could be made final (setter is not used) + private BootstrapMethod[] bootstrapMethods; // TODO this could be made final (setter is not used) /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. + * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a + * physical copy. + * + * @param c Source to copy. */ public BootstrapMethods(final BootstrapMethods c) { this(c.getNameIndex(), c.getLength(), c.getBootstrapMethods(), c.getConstantPool()); } - /** - * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes * @param bootstrapMethods array of bootstrap methods - * @param constant_pool Array of constants + * @param constantPool Array of constants */ - public BootstrapMethods(final int name_index, final int length, final BootstrapMethod[] bootstrapMethods, final ConstantPool constant_pool) { - super(Const.ATTR_BOOTSTRAP_METHODS, name_index, length, constant_pool); + public BootstrapMethods(final int nameIndex, final int length, final BootstrapMethod[] bootstrapMethods, final ConstantPool constantPool) { + super(Const.ATTR_BOOTSTRAP_METHODS, nameIndex, length, constantPool); this.bootstrapMethods = bootstrapMethods; } /** * Construct object from Input stream. * - * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - BootstrapMethods(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException { - this(name_index, length, (BootstrapMethod[]) null, constant_pool); + BootstrapMethods(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, (BootstrapMethod[]) null, constantPool); - final int num_bootstrap_methods = input.readUnsignedShort(); - bootstrapMethods = new BootstrapMethod[num_bootstrap_methods]; - for (int i = 0; i < num_bootstrap_methods; i++) { + final int numBootstrapMethods = input.readUnsignedShort(); + bootstrapMethods = new BootstrapMethod[numBootstrapMethods]; + for (int i = 0; i < numBootstrapMethods; i++) { bootstrapMethods[i] = new BootstrapMethod(input); } } - /** - * @return array of bootstrap method "records" - */ - public final BootstrapMethod[] getBootstrapMethods() { - return bootstrapMethods; - } - - /** - * @param bootstrapMethods the array of bootstrap methods - */ - public final void setBootstrapMethods(final BootstrapMethod[] bootstrapMethods) { - this.bootstrapMethods = bootstrapMethods; - } - /** * @param v Visitor object */ @@ -103,14 +92,14 @@ public void accept(final Visitor v) { * @return deep copy of this attribute */ @Override - public BootstrapMethods copy(final ConstantPool _constant_pool) { + public BootstrapMethods copy(final ConstantPool constantPool) { final BootstrapMethods c = (BootstrapMethods) clone(); c.bootstrapMethods = new BootstrapMethod[bootstrapMethods.length]; for (int i = 0; i < bootstrapMethods.length; i++) { c.bootstrapMethods[i] = bootstrapMethods[i].copy(); } - c.setConstantPool(_constant_pool); + c.setConstantPool(constantPool); return c; } @@ -118,18 +107,37 @@ public BootstrapMethods copy(final ConstantPool _constant_pool) { * Dump bootstrap methods attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override public final void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(bootstrapMethods.length); - for (final BootstrapMethod bootstrap_method : bootstrapMethods) { - bootstrap_method.dump(file); + for (final BootstrapMethod bootstrapMethod : bootstrapMethods) { + bootstrapMethod.dump(file); } } + /** + * @return array of bootstrap method "records" + */ + public final BootstrapMethod[] getBootstrapMethods() { + return bootstrapMethods; + } + + @Override + public Iterator iterator() { + return Stream.of(bootstrapMethods).iterator(); + } + + /** + * @param bootstrapMethods the array of bootstrap methods + */ + public final void setBootstrapMethods(final BootstrapMethod[] bootstrapMethods) { + this.bootstrapMethods = bootstrapMethods; + } + /** * @return String representation. */ @@ -143,11 +151,11 @@ public final String toString() { buf.append("\n"); final int start = buf.length(); buf.append(" ").append(i).append(": "); - final int indent_count = buf.length() - start; - final String[] lines = (bootstrapMethods[i].toString(super.getConstantPool())).split("\\r?\\n"); + final int indentCount = buf.length() - start; + final String[] lines = bootstrapMethods[i].toString(super.getConstantPool()).split("\\r?\\n"); buf.append(lines[0]); for (int j = 1; j < lines.length; j++) { - buf.append("\n").append(" ".substring(0,indent_count)).append(lines[j]); + buf.append("\n").append(" ", 0, indentCount).append(lines[j]); } } return buf.toString(); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassElementValue.java index 1a9939c656b..3df0eb98653 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassElementValue.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassElementValue.java @@ -24,48 +24,36 @@ import java.io.DataOutputStream; import java.io.IOException; -import com.sun.org.apache.bcel.internal.Const; - /** * @since 6.0 */ -public class ClassElementValue extends ElementValue -{ +public class ClassElementValue extends ElementValue { // For primitive types and string type, this points to the value entry in // the cpool // For 'class' this points to the class entry in the cpool private final int idx; - public ClassElementValue(final int type, final int idx, final ConstantPool cpool) - { + public ClassElementValue(final int type, final int idx, final ConstantPool cpool) { super(type, cpool); this.idx = idx; } - public int getIndex() - { - return idx; + @Override + public void dump(final DataOutputStream dos) throws IOException { + dos.writeByte(super.getType()); // u1 kind of value + dos.writeShort(idx); } - public String getClassString() - { - final ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(idx, - Const.CONSTANT_Utf8); - return c.getBytes(); + public String getClassString() { + return super.getConstantPool().getConstantUtf8(idx).getBytes(); } - @Override - public String stringifyValue() - { - final ConstantUtf8 cu8 = (ConstantUtf8) super.getConstantPool().getConstant(idx, - Const.CONSTANT_Utf8); - return cu8.getBytes(); + public int getIndex() { + return idx; } @Override - public void dump(final DataOutputStream dos) throws IOException - { - dos.writeByte(super.getType()); // u1 kind of value - dos.writeShort(idx); + public String stringifyValue() { + return super.getConstantPool().getConstantUtf8(idx).getBytes(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassFormatException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassFormatException.java index 02f8142c58b..a61e1d75390 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassFormatException.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassFormatException.java @@ -22,28 +22,52 @@ package com.sun.org.apache.bcel.internal.classfile; /** - * Thrown when the BCEL attempts to read a class file and determines - * that the file is malformed or otherwise cannot be interpreted as a - * class file. - * + * Thrown when the BCEL attempts to read a class file and determines that a class is malformed or otherwise cannot be interpreted as a class file. */ public class ClassFormatException extends RuntimeException { private static final long serialVersionUID = -3569097343160139969L; + /** + * Constructs a new instance with {@code null} as its detail message. The cause is not initialized, and may subsequently be initialized by a call to + * {@link #initCause}. + */ public ClassFormatException() { - super(); } - - public ClassFormatException(final String s) { - super(s); + /** + * Constructs a new instance with the specified detail message. The cause is not initialized, and may subsequently be initialized by a call to + * {@link #initCause}. + * + * @param message the detail message. The detail message is saved for later retrieval by the {@link #getMessage()} method. + */ + public ClassFormatException(final String message) { + super(message); } /** + * Constructs a new instance with the specified detail message and cause. + *

    + * Note that the detail message associated with {@code cause} is not automatically incorporated in this runtime exception's detail message. + * + * @param message the detail message (which is saved for later retrieval by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). (A {@code null} value is permitted, and indicates that + * the cause is nonexistent or unknown.) * @since 6.0 */ public ClassFormatException(final String message, final Throwable cause) { super(message, cause); } + + /** + * Constructs a new instance with the specified cause and a detail message of {@code (cause==null ? null : cause.toString())} (which typically contains the + * class and detail message of {@code cause}). This constructor is useful for runtime exceptions that are little more than wrappers for other throwables. + * + * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). (A {@code null} value is permitted, and indicates that the + * cause is nonexistent or unknown.) + * @since 6.7.0 + */ + public ClassFormatException(final Throwable cause) { + super(cause); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java index 0ad2b781629..c9daaeabf9b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java @@ -32,20 +32,17 @@ import com.sun.org.apache.bcel.internal.Const; /** - * Wrapper class that parses a given Java .class file. The method parse returns a - * JavaClass object on success. When an I/O error or an - * inconsistency occurs an appropiate exception is propagated back to - * the caller. - * - * The structure and the names comply, except for a few conveniences, - * exactly with the - * JVM specification 1.0. See this paper for - * further details about the structure of a bytecode file. + * Wrapper class that parses a given Java .class file. The method parse returns a + * JavaClass object on success. When an I/O error or an inconsistency occurs an + * appropriate exception is propagated back to the caller. * + * The structure and the names comply, except for a few conveniences, exactly with the + * JVM specification 1.0. See this paper for further details about + * the structure of a bytecode file. */ public final class ClassParser { + private static final int BUFSIZE = 8192; private DataInputStream dataInputStream; private final boolean fileOwned; private final String fileName; @@ -61,8 +58,6 @@ public final class ClassParser { private Method[] methods; // methods defined in the class private Attribute[] attributes; // attributes defined in the class private final boolean isZip; // Loaded from zip file - private static final int BUFSIZE = 8192; - /** * Parses class from the given stream. @@ -72,9 +67,9 @@ public final class ClassParser { */ public ClassParser(final InputStream inputStream, final String fileName) { this.fileName = fileName; - fileOwned = false; + this.fileOwned = false; final String clazz = inputStream.getClass().getName(); // Not a very clean solution ... - isZip = clazz.startsWith("java.util.zip.") || clazz.startsWith("java.util.jar."); + this.isZip = clazz.startsWith("java.util.zip.") || clazz.startsWith("java.util.jar."); if (inputStream instanceof DataInputStream) { this.dataInputStream = (DataInputStream) inputStream; } else { @@ -82,41 +77,38 @@ public ClassParser(final InputStream inputStream, final String fileName) { } } - - /** Parses class from given .class file. + /** + * Parses class from given .class file. * * @param fileName file name */ public ClassParser(final String fileName) { - isZip = false; + this.isZip = false; this.fileName = fileName; - fileOwned = true; + this.fileOwned = true; } - - /** Parses class from given .class file in a ZIP-archive + /** + * Parses class from given .class file in a ZIP-archive * * @param zipFile zip file name * @param fileName file name */ public ClassParser(final String zipFile, final String fileName) { - isZip = true; - fileOwned = true; + this.isZip = true; + this.fileOwned = true; this.zipFile = zipFile; this.fileName = fileName; } - /** - * Parses the given Java class file and return an object that represents - * the contained data, i.e., constants, methods, fields and commands. - * A ClassFormatException is raised, if the file is not a valid - * .class file. (This does not include verification of the byte code as it - * is performed by the java interpreter). + * Parses the given Java class file and return an object that represents the contained data, i.e., constants, methods, + * fields and commands. A ClassFormatException is raised, if the file is not a valid .class file. (This does + * not include verification of the byte code as it is performed by the java interpreter). * * @return Class object representing the parsed class file - * @throws IOException - * @throws ClassFormatException + * @throws IOException if an I/O error occurs. + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ public JavaClass parse() throws IOException, ClassFormatException { ZipFile zip = null; @@ -130,11 +122,9 @@ public JavaClass parse() throws IOException, ClassFormatException { throw new IOException("File " + fileName + " not found"); } - dataInputStream = new DataInputStream(new BufferedInputStream(zip.getInputStream(entry), - BUFSIZE)); + dataInputStream = new DataInputStream(new BufferedInputStream(zip.getInputStream(entry), BUFSIZE)); } else { - dataInputStream = new DataInputStream(new BufferedInputStream(new FileInputStream( - fileName), BUFSIZE)); + dataInputStream = new DataInputStream(new BufferedInputStream(new FileInputStream(fileName), BUFSIZE)); } } /****************** Read headers ********************************/ @@ -157,19 +147,19 @@ public JavaClass parse() throws IOException, ClassFormatException { // Read class attributes readAttributes(); // Check for unknown variables - //Unknown[] u = Unknown.getUnknownAttributes(); - //for (int i=0; i < u.length; i++) - // System.err.println("WARNING: " + u[i]); + // Unknown[] u = Unknown.getUnknownAttributes(); + // for (int i=0; i < u.length; i++) + // System.err.println("WARNING: " + u[i]); // Everything should have been read now - // if(file.available() > 0) { - // int bytes = file.available(); - // byte[] buf = new byte[bytes]; - // file.read(buf); - // if(!(isZip && (buf.length == 1))) { - // System.err.println("WARNING: Trailing garbage at end of " + fileName); - // System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf)); - // } - // } + // if(file.available() > 0) { + // int bytes = file.available(); + // byte[] buf = new byte[bytes]; + // file.read(buf); + // if(!(isZip && (buf.length == 1))) { + // System.err.println("WARNING: Trailing garbage at end of " + fileName); + // System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf)); + // } + // } } finally { // Read everything of interest, so close the file if (fileOwned) { @@ -177,92 +167,88 @@ public JavaClass parse() throws IOException, ClassFormatException { if (dataInputStream != null) { dataInputStream.close(); } - } catch (final IOException ioe) { - //ignore close exceptions + } catch (final IOException ignored) { + // ignore close exceptions } } try { if (zip != null) { zip.close(); } - } catch (final IOException ioe) { - //ignore close exceptions + } catch (final IOException ignored) { + // ignore close exceptions } } // Return the information we have gathered in a new object - return new JavaClass(classNameIndex, superclassNameIndex, fileName, major, minor, - accessFlags, constantPool, interfaces, fields, methods, attributes, isZip - ? JavaClass.ZIP - : JavaClass.FILE); + return new JavaClass(classNameIndex, superclassNameIndex, fileName, major, minor, accessFlags, constantPool, interfaces, fields, methods, attributes, + isZip ? JavaClass.ZIP : JavaClass.FILE); } - /** * Reads information about the attributes of the class. - * @throws IOException - * @throws ClassFormatException + * + * @throws IOException if an I/O error occurs. + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ private void readAttributes() throws IOException, ClassFormatException { - final int attributes_count = dataInputStream.readUnsignedShort(); - attributes = new Attribute[attributes_count]; - for (int i = 0; i < attributes_count; i++) { + final int attributesCount = dataInputStream.readUnsignedShort(); + attributes = new Attribute[attributesCount]; + for (int i = 0; i < attributesCount; i++) { attributes[i] = Attribute.readAttribute(dataInputStream, constantPool); } } - /** * Reads information about the class and its super class. - * @throws IOException - * @throws ClassFormatException + * + * @throws IOException if an I/O error occurs. + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ private void readClassInfo() throws IOException, ClassFormatException { accessFlags = dataInputStream.readUnsignedShort(); - /* Interfaces are implicitely abstract, the flag should be set - * according to the JVM specification. + /* + * Interfaces are implicitly abstract, the flag should be set according to the JVM specification. */ if ((accessFlags & Const.ACC_INTERFACE) != 0) { accessFlags |= Const.ACC_ABSTRACT; } - if (((accessFlags & Const.ACC_ABSTRACT) != 0) - && ((accessFlags & Const.ACC_FINAL) != 0)) { + if ((accessFlags & Const.ACC_ABSTRACT) != 0 && (accessFlags & Const.ACC_FINAL) != 0) { throw new ClassFormatException("Class " + fileName + " can't be both final and abstract"); } classNameIndex = dataInputStream.readUnsignedShort(); superclassNameIndex = dataInputStream.readUnsignedShort(); } - /** * Reads constant pool entries. - * @throws IOException - * @throws ClassFormatException + * + * @throws IOException if an I/O error occurs. + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ private void readConstantPool() throws IOException, ClassFormatException { constantPool = new ConstantPool(dataInputStream); } - /** * Reads information about the fields of the class, i.e., its variables. - * @throws IOException - * @throws ClassFormatException + * + * @throws IOException if an I/O error occurs. + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ private void readFields() throws IOException, ClassFormatException { - final int fields_count = dataInputStream.readUnsignedShort(); - fields = new Field[fields_count]; - for (int i = 0; i < fields_count; i++) { + final int fieldsCount = dataInputStream.readUnsignedShort(); + fields = new Field[fieldsCount]; + for (int i = 0; i < fieldsCount; i++) { fields[i] = new Field(dataInputStream, constantPool); } } - /******************** Private utility methods **********************/ /** - * Checks whether the header of the file is ok. - * Of course, this has to be the first action on successive file reads. - * @throws IOException - * @throws ClassFormatException + * Checks whether the header of the file is ok. Of course, this has to be the first action on successive file reads. + * + * @throws IOException if an I/O error occurs. + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ private void readID() throws IOException, ClassFormatException { if (dataInputStream.readInt() != Const.JVM_CLASSFILE_MAGIC) { @@ -270,39 +256,39 @@ private void readID() throws IOException, ClassFormatException { } } - /** * Reads information about the interfaces implemented by this class. - * @throws IOException - * @throws ClassFormatException + * + * @throws IOException if an I/O error occurs. + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ private void readInterfaces() throws IOException, ClassFormatException { - final int interfaces_count = dataInputStream.readUnsignedShort(); - interfaces = new int[interfaces_count]; - for (int i = 0; i < interfaces_count; i++) { + final int interfacesCount = dataInputStream.readUnsignedShort(); + interfaces = new int[interfacesCount]; + for (int i = 0; i < interfacesCount; i++) { interfaces[i] = dataInputStream.readUnsignedShort(); } } - /** * Reads information about the methods of the class. - * @throws IOException - * @throws ClassFormatException + * + * @throws IOException if an I/O error occurs. + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ - private void readMethods() throws IOException, ClassFormatException { - final int methods_count = dataInputStream.readUnsignedShort(); - methods = new Method[methods_count]; - for (int i = 0; i < methods_count; i++) { + private void readMethods() throws IOException { + final int methodsCount = dataInputStream.readUnsignedShort(); + methods = new Method[methodsCount]; + for (int i = 0; i < methodsCount; i++) { methods[i] = new Method(dataInputStream, constantPool); } } - /** * Reads major and minor version of compiler which created the file. - * @throws IOException - * @throws ClassFormatException + * + * @throws IOException if an I/O error occurs. + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ private void readVersion() throws IOException, ClassFormatException { minor = dataInputStream.readUnsignedShort(); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java index c486f2bb273..498a8c71b18 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -24,126 +23,173 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class represents a chunk of Java byte code contained in a - * method. It is instantiated by the - * Attribute.readAttribute() method. A Code - * attribute contains informations about operand stack, local - * variables, byte code and the exceptions handled within this - * method. + * This class represents a chunk of Java byte code contained in a method. It is instantiated by the + * Attribute.readAttribute() method. A Code attribute contains informations about operand stack, local + * variables, byte code and the exceptions handled within this method. * - * This attribute has attributes itself, namely LineNumberTable which - * is used for debugging purposes and LocalVariableTable which - * contains information about the local variables. + * This attribute has attributes itself, namely LineNumberTable which is used for debugging purposes and + * LocalVariableTable which contains information about the local variables. * - * @see Attribute - * @see CodeException - * @see LineNumberTable + *

    + * Code_attribute {
    + *   u2 attribute_name_index;
    + *   u4 attribute_length;
    + *   u2 max_stack;
    + *   u2 max_locals;
    + *   u4 code_length;
    + *   u1 code[code_length];
    + *   u2 exception_table_length;
    + *   {
    + *     u2 start_pc;
    + *     u2 end_pc;
    + *     u2 handler_pc;
    + *     u2 catch_type;
    + *   } exception_table[exception_table_length];
    + *   u2 attributes_count;
    + *   attribute_info attributes[attributes_count];
    + * }
    + * 
    + * @see Attribute + * @see CodeException + * @see LineNumberTable * @see LocalVariableTable + * @LastModified: Feb 2023 */ public final class Code extends Attribute { - private int maxStack; // Maximum size of stack used by this method // TODO this could be made final (setter is not used) - private int maxLocals; // Number of local variables // TODO this could be made final (setter is not used) + private int maxStack; // Maximum size of stack used by this method // TODO this could be made final (setter is not used) + private int maxLocals; // Number of local variables // TODO this could be made final (setter is not used) private byte[] code; // Actual byte code private CodeException[] exceptionTable; // Table of handled exceptions private Attribute[] attributes; // or LocalVariable - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. + * Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a + * physical copy. + * + * @param code The source Code. */ - public Code(final Code c) { - this(c.getNameIndex(), c.getLength(), c.getMaxStack(), c.getMaxLocals(), c.getCode(), c - .getExceptionTable(), c.getAttributes(), c.getConstantPool()); + public Code(final Code code) { + this(code.getNameIndex(), code.getLength(), code.getMaxStack(), code.getMaxLocals(), code.getCode(), code.getExceptionTable(), code.getAttributes(), + code.getConstantPool()); } - /** - * @param name_index Index pointing to the name Code + * @param nameIndex Index pointing to the name Code * @param length Content length in bytes * @param file Input stream - * @param constant_pool Array of constants + * @param constantPool Array of constants */ - Code(final int name_index, final int length, final DataInput file, final ConstantPool constant_pool) - throws IOException { + Code(final int nameIndex, final int length, final DataInput file, final ConstantPool constantPool) throws IOException { // Initialize with some default values which will be overwritten later - this(name_index, length, file.readUnsignedShort(), file.readUnsignedShort(), (byte[]) null, - (CodeException[]) null, (Attribute[]) null, constant_pool); - final int code_length = file.readInt(); - code = new byte[code_length]; // Read byte code + this(nameIndex, length, file.readUnsignedShort(), file.readUnsignedShort(), (byte[]) null, (CodeException[]) null, (Attribute[]) null, constantPool); + final int codeLength = Args.requireU4(file.readInt(), 1, "Code length attribute"); + code = new byte[codeLength]; // Read byte code file.readFully(code); - /* Read exception table that contains all regions where an exception - * handler is active, i.e., a try { ... } catch() block. + /* + * Read exception table that contains all regions where an exception handler is active, i.e., a try { ... } catch() + * block. */ - final int exception_table_length = file.readUnsignedShort(); - exceptionTable = new CodeException[exception_table_length]; - for (int i = 0; i < exception_table_length; i++) { + final int exceptionTableLength = file.readUnsignedShort(); + exceptionTable = new CodeException[exceptionTableLength]; + for (int i = 0; i < exceptionTableLength; i++) { exceptionTable[i] = new CodeException(file); } - /* Read all attributes, currently `LineNumberTable' and - * `LocalVariableTable' + /* + * Read all attributes, currently 'LineNumberTable' and 'LocalVariableTable' */ - final int attributes_count = file.readUnsignedShort(); - attributes = new Attribute[attributes_count]; - for (int i = 0; i < attributes_count; i++) { - attributes[i] = Attribute.readAttribute(file, constant_pool); + final int attributesCount = file.readUnsignedShort(); + attributes = new Attribute[attributesCount]; + for (int i = 0; i < attributesCount; i++) { + attributes[i] = Attribute.readAttribute(file, constantPool); } - /* Adjust length, because of setAttributes in this(), s.b. length - * is incorrect, because it didn't take the internal attributes - * into account yet! Very subtle bug, fixed in 3.1.1. + /* + * Adjust length, because of setAttributes in this(), s.b. length is incorrect, because it didn't take the internal + * attributes into account yet! Very subtle bug, fixed in 3.1.1. */ super.setLength(length); } - /** - * @param name_index Index pointing to the name Code + * @param nameIndex Index pointing to the name Code * @param length Content length in bytes * @param maxStack Maximum size of stack * @param maxLocals Number of local variables * @param code Actual byte code * @param exceptionTable of handled exceptions * @param attributes Attributes of code: LineNumber or LocalVariable - * @param constant_pool Array of constants + * @param constantPool Array of constants */ - public Code(final int name_index, final int length, final int maxStack, final int maxLocals, final byte[] code, - final CodeException[] exceptionTable, final Attribute[] attributes, final ConstantPool constant_pool) { - super(Const.ATTR_CODE, name_index, length, constant_pool); - this.maxStack = maxStack; - this.maxLocals = maxLocals; - this.code = code != null ? code : new byte[0]; - this.exceptionTable = exceptionTable != null ? exceptionTable : new CodeException[0]; - this.attributes = attributes != null ? attributes : new Attribute[0]; + public Code(final int nameIndex, final int length, final int maxStack, final int maxLocals, final byte[] code, final CodeException[] exceptionTable, + final Attribute[] attributes, final ConstantPool constantPool) { + super(Const.ATTR_CODE, nameIndex, length, constantPool); + this.maxStack = Args.requireU2(maxStack, "maxStack"); + this.maxLocals = Args.requireU2(maxLocals, "maxLocals"); + this.code = code != null ? code : Const.EMPTY_BYTE_ARRAY; + this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY; + Args.requireU2(this.exceptionTable.length, "exceptionTable.length"); + this.attributes = attributes != null ? attributes : EMPTY_ARRAY; super.setLength(calculateLength()); // Adjust length } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitCode(this); } + /** + * @return the full size of this code attribute, minus its first 6 bytes, including the size of all its contained + * attributes + */ + private int calculateLength() { + int len = 0; + if (attributes != null) { + for (final Attribute attribute : attributes) { + len += attribute.getLength() + 6 /* attribute header size */; + } + } + return len + getInternalLength(); + } + + /** + * @return deep copy of this attribute + * + * @param constantPool the constant pool to duplicate + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final Code c = (Code) clone(); + if (code != null) { + c.code = code.clone(); + } + c.setConstantPool(constantPool); + c.exceptionTable = new CodeException[exceptionTable.length]; + Arrays.setAll(c.exceptionTable, i -> exceptionTable[i].copy()); + c.attributes = new Attribute[attributes.length]; + Arrays.setAll(c.attributes, i -> attributes[i].copy(constantPool)); + return c; + } /** * Dump code attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(maxStack); file.writeShort(maxLocals); @@ -159,7 +205,6 @@ public void dump( final DataOutputStream file ) throws IOException { } } - /** * @return Collection of code attributes. * @see Attribute @@ -168,6 +213,31 @@ public Attribute[] getAttributes() { return attributes; } + /** + * @return Actual byte code of the method. + */ + public byte[] getCode() { + return code; + } + + /** + * @return Table of handled exceptions. + * @see CodeException + */ + public CodeException[] getExceptionTable() { + return exceptionTable; + } + + /** + * @return the internal length of this code attribute (minus the first 6 bytes) and excluding all its attributes + */ + private int getInternalLength() { + return 2 /* maxStack */ + 2 /* maxLocals */ + 4 /* code length */ + + code.length /* byte-code */ + + 2 /* exception-table length */ + + 8 * (exceptionTable == null ? 0 : exceptionTable.length) /* exception table */ + + 2 /* attributes count */; + } /** * @return LineNumberTable of Code, if it has one @@ -181,7 +251,6 @@ public LineNumberTable getLineNumberTable() { return null; } - /** * @return LocalVariableTable of Code, if it has one */ @@ -194,24 +263,6 @@ public LocalVariableTable getLocalVariableTable() { return null; } - - /** - * @return Actual byte code of the method. - */ - public byte[] getCode() { - return code; - } - - - /** - * @return Table of handled exceptions. - * @see CodeException - */ - public CodeException[] getExceptionTable() { - return exceptionTable; - } - - /** * @return Number of local variables. */ @@ -219,7 +270,6 @@ public int getMaxLocals() { return maxLocals; } - /** * @return Maximum size of stack used by this method. */ @@ -227,86 +277,62 @@ public int getMaxStack() { return maxStack; } - - /** - * @return the internal length of this code attribute (minus the first 6 bytes) - * and excluding all its attributes - */ - private int getInternalLength() { - return 2 /*maxStack*/+ 2 /*maxLocals*/+ 4 /*code length*/ - + code.length /*byte-code*/ - + 2 /*exception-table length*/ - + 8 * (exceptionTable == null ? 0 : exceptionTable.length) /* exception table */ - + 2 /* attributes count */; - } - - - /** - * @return the full size of this code attribute, minus its first 6 bytes, - * including the size of all its contained attributes - */ - private int calculateLength() { - int len = 0; - if (attributes != null) { - for (final Attribute attribute : attributes) { - len += attribute.getLength() + 6 /*attribute header size*/; - } - } - return len + getInternalLength(); - } - - /** * @param attributes the attributes to set for this Code */ - public void setAttributes( final Attribute[] attributes ) { - this.attributes = attributes != null ? attributes : new Attribute[0]; + public void setAttributes(final Attribute[] attributes) { + this.attributes = attributes != null ? attributes : EMPTY_ARRAY; super.setLength(calculateLength()); // Adjust length } - /** * @param code byte code */ - public void setCode( final byte[] code ) { - this.code = code != null ? code : new byte[0]; + public void setCode(final byte[] code) { + this.code = code != null ? code : Const.EMPTY_BYTE_ARRAY; super.setLength(calculateLength()); // Adjust length } - /** * @param exceptionTable exception table */ - public void setExceptionTable( final CodeException[] exceptionTable ) { - this.exceptionTable = exceptionTable != null ? exceptionTable : new CodeException[0]; + public void setExceptionTable(final CodeException[] exceptionTable) { + this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY; super.setLength(calculateLength()); // Adjust length } - /** * @param maxLocals maximum number of local variables */ - public void setMaxLocals( final int maxLocals ) { + public void setMaxLocals(final int maxLocals) { this.maxLocals = maxLocals; } - /** * @param maxStack maximum stack size */ - public void setMaxStack( final int maxStack ) { + public void setMaxStack(final int maxStack) { this.maxStack = maxStack; } + /** + * @return String representation of code chunk. + */ + @Override + public String toString() { + return toString(true); + } /** + * Converts this object to a String. + * + * @param verbose Provides verbose output when true. * @return String representation of code chunk. */ - public String toString( final boolean verbose ) { + public String toString(final boolean verbose) { final StringBuilder buf = new StringBuilder(100); // CHECKSTYLE IGNORE MagicNumber - buf.append("Code(maxStack = ").append(maxStack).append(", maxLocals = ").append( - maxLocals).append(", code_length = ").append(code.length).append(")\n").append( - Utility.codeToString(code, super.getConstantPool(), 0, -1, verbose)); + buf.append("Code(maxStack = ").append(maxStack).append(", maxLocals = ").append(maxLocals).append(", code_length = ").append(code.length).append(")\n") + .append(Utility.codeToString(code, super.getConstantPool(), 0, -1, verbose)); if (exceptionTable.length > 0) { buf.append("\nException handler(s) = \n").append("From\tTo\tHandler\tType\n"); for (final CodeException exception : exceptionTable) { @@ -322,38 +348,4 @@ public String toString( final boolean verbose ) { } return buf.toString(); } - - - /** - * @return String representation of code chunk. - */ - @Override - public String toString() { - return toString(true); - } - - - /** - * @return deep copy of this attribute - * - * @param _constant_pool the constant pool to duplicate - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - final Code c = (Code) clone(); - if (code != null) { - c.code = new byte[code.length]; - System.arraycopy(code, 0, c.code, 0, code.length); - } - c.setConstantPool(_constant_pool); - c.exceptionTable = new CodeException[exceptionTable.length]; - for (int i = 0; i < exceptionTable.length; i++) { - c.exceptionTable[i] = exceptionTable[i].copy(); - } - c.attributes = new Attribute[attributes.length]; - for (int i = 0; i < attributes.length; i++) { - c.attributes[i] = attributes[i].copy(_constant_pool); - } - return c; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java index a1b8e46c825..ee224e6b348 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -25,101 +25,136 @@ import java.io.IOException; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class represents an entry in the exception table of the Code - * attribute and is used only there. It contains a range in which a - * particular exception handler is active. + * This class represents an entry in the exception table of the Code attribute and is used only there. It + * contains a range in which a particular exception handler is active. * - * @see Code - * @LastModified: May 2021 + *
    + * Code_attribute {
    + *   u2 attribute_name_index;
    + *   u4 attribute_length;
    + *   u2 max_stack;
    + *   u2 max_locals;
    + *   u4 code_length;
    + *   u1 code[code_length];
    + *   u2 exception_table_length;
    + *   {
    + *     u2 start_pc;
    + *     u2 end_pc;
    + *     u2 handler_pc;
    + *     u2 catch_type;
    + *   } exception_table[exception_table_length];
    + *   u2 attributes_count;
    + *   attribute_info attributes[attributes_count];
    + * }
    + * 
    + * + * @see Code + * @LastModified: Feb 2023 */ public final class CodeException implements Cloneable, Node { - private int startPc; // Range in the code the exception handler is - private int endPc; // active. startPc is inclusive, endPc exclusive - private int handlerPc; /* Starting address of exception handler, i.e., - * an offset from start of code. + /** + * Empty array. */ - private int catchType; /* If this is zero the handler catches any - * exception, otherwise it points to the - * exception class which is to be caught. + static final CodeException[] EMPTY_CODE_EXCEPTION_ARRAY = {}; + + /** Range in the code the exception handler. */ + private int startPc; + + /** active. startPc is inclusive, endPc exclusive. */ + private int endPc; + + /** + * Starting address of exception handler, i.e., an offset from start of code. */ + private int handlerPc; + /* + * If this is zero the handler catches any exception, otherwise it points to the exception class which is to be caught. + */ + private int catchType; /** - * Initialize from another object. + * Constructs a new instance from another instance. + * + * @param c Source for copying. */ public CodeException(final CodeException c) { this(c.getStartPC(), c.getEndPC(), c.getHandlerPC(), c.getCatchType()); } - /** - * Construct object from file stream. + * Constructs a new instance from a DataInput. + * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ CodeException(final DataInput file) throws IOException { - this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file - .readUnsignedShort()); + this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort()); } - /** - * @param startPc Range in the code the exception handler is active, - * startPc is inclusive while + * Constructs a new instance. + * + * @param startPc Range in the code the exception handler is active, startPc is inclusive while * @param endPc is exclusive - * @param handlerPc Starting address of exception handler, i.e., - * an offset from start of code. - * @param catchType If zero the handler catches any - * exception, otherwise it points to the exception class which is - * to be caught. + * @param handlerPc Starting address of exception handler, i.e., an offset from start of code. + * @param catchType If zero the handler catches any exception, otherwise it points to the exception class which is to be + * caught. */ public CodeException(final int startPc, final int endPc, final int handlerPc, final int catchType) { - this.startPc = startPc; - this.endPc = endPc; - this.handlerPc = handlerPc; - this.catchType = catchType; + this.startPc = Args.requireU2(startPc, "startPc"); + this.endPc = Args.requireU2(endPc, "endPc"); + this.handlerPc = Args.requireU2(handlerPc, "handlerPc"); + this.catchType = Args.requireU2(catchType, "catchType"); } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitCodeException(this); } + /** + * @return deep copy of this object + */ + public CodeException copy() { + try { + return (CodeException) clone(); + } catch (final CloneNotSupportedException e) { + // TODO should this throw? + } + return null; + } /** - * Dump code exception to file stream in binary format. + * Dumps code exception to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeShort(startPc); file.writeShort(endPc); file.writeShort(handlerPc); file.writeShort(catchType); } - /** - * @return 0, if the handler catches any exception, otherwise it points to - * the exception class which is to be caught. + * @return 0, if the handler catches any exception, otherwise it points to the exception class which is to be caught. */ public int getCatchType() { return catchType; } - /** * @return Exclusive end index of the region where the handler is active. */ @@ -127,7 +162,6 @@ public int getEndPC() { return endPc; } - /** * @return Starting address of exception handler, relative to the code. */ @@ -135,7 +169,6 @@ public int getHandlerPC() { return handlerPc; } - /** * @return Inclusive start index of the region where the handler is active. */ @@ -143,78 +176,58 @@ public int getStartPC() { return startPc; } - /** * @param catchType the type of exception that is caught */ - public void setCatchType( final int catchType ) { + public void setCatchType(final int catchType) { this.catchType = catchType; } - /** * @param endPc end of handled block */ - public void setEndPC( final int endPc ) { + public void setEndPC(final int endPc) { this.endPc = endPc; } - /** * @param handlerPc where the actual code is */ - public void setHandlerPC( final int handlerPc ) { // TODO unused + public void setHandlerPC(final int handlerPc) { // TODO unused this.handlerPc = handlerPc; } - /** * @param startPc start of handled block */ - public void setStartPC( final int startPc ) { // TODO unused + public void setStartPC(final int startPc) { // TODO unused this.startPc = startPc; } - /** * @return String representation. */ @Override public String toString() { - return "CodeException(startPc = " + startPc + ", endPc = " + endPc + ", handlerPc = " - + handlerPc + ", catchType = " + catchType + ")"; + return "CodeException(startPc = " + startPc + ", endPc = " + endPc + ", handlerPc = " + handlerPc + ", catchType = " + catchType + ")"; } + public String toString(final ConstantPool cp) { + return toString(cp, true); + } /** + * @param cp constant pool source. + * @param verbose Output more if true. * @return String representation. */ - public String toString( final ConstantPool cp, final boolean verbose ) { + public String toString(final ConstantPool cp, final boolean verbose) { String str; if (catchType == 0) { str = "(0)"; } else { - str = Utility.compactClassName(cp.getConstantString(catchType, Const.CONSTANT_Class), false) - + (verbose ? "(" + catchType + ")" : ""); + str = Utility.compactClassName(cp.getConstantString(catchType, Const.CONSTANT_Class), false) + (verbose ? "(" + catchType + ")" : ""); } return startPc + "\t" + endPc + "\t" + handlerPc + "\t" + str; } - - - public String toString( final ConstantPool cp ) { - return toString(cp, true); - } - - - /** - * @return deep copy of this object - */ - public CodeException copy() { - try { - return (CodeException) clone(); - } catch (final CloneNotSupportedException e) { - // TODO should this throw? - } - return null; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java index 56ffb23cc83..885e1b599eb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java @@ -39,81 +39,24 @@ public abstract class Constant implements Cloneable, Node { private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals( final Object o1, final Object o2 ) { + public boolean equals(final Object o1, final Object o2) { final Constant THIS = (Constant) o1; final Constant THAT = (Constant) o2; return Objects.equals(THIS.toString(), THAT.toString()); } - @Override - public int hashCode( final Object o ) { + public int hashCode(final Object o) { final Constant THIS = (Constant) o; return THIS.toString().hashCode(); } }; - /* In fact this tag is redundant since we can distinguish different - * `Constant' objects by their type, i.e., via `instanceof'. In some - * places we will use the tag for switch()es anyway. - * - * First, we want match the specification as closely as possible. Second we - * need the tag as an index to select the corresponding class name from the - * `CONSTANT_NAMES' array. - */ - private byte tag; - - Constant(final byte tag) { - this.tag = tag; - } - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - @Override - public abstract void accept( Visitor v ); - - public abstract void dump( DataOutputStream file ) throws IOException; - - /** - * @return Tag of constant, i.e., its type. No setTag() method to avoid - * confusion. - */ - public final byte getTag() { - return tag; - } - - /** - * @return String representation. - */ - @Override - public String toString() { - return Const.getConstantName(tag) + "[" + tag + "]"; - } - /** - * @return deep copy of this constant + * @return Comparison strategy object */ - public Constant copy() { - try { - return (Constant) super.clone(); - } catch (final CloneNotSupportedException e) { - // TODO should this throw? - } - return null; - } - - @Override - public Object clone() { - try { - return super.clone(); - } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens - } + public static BCELComparator getComparator() { + return bcelComparator; } /** @@ -168,39 +111,95 @@ public static Constant readConstant(final DataInput dataInput) throws IOExceptio } /** - * @return Comparison strategy object + * @param comparator Comparison strategy object */ - public static BCELComparator getComparator() { - return bcelComparator; + public static void setComparator(final BCELComparator comparator) { + bcelComparator = comparator; } + /* + * In fact this tag is redundant since we can distinguish different 'Constant' objects by their type, i.e., via + * 'instanceof'. In some places we will use the tag for switch()es anyway. + * + * First, we want match the specification as closely as possible. Second we need the tag as an index to select the + * corresponding class name from the 'CONSTANT_NAMES' array. + */ /** - * @param comparator Comparison strategy object + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter */ - public static void setComparator( final BCELComparator comparator ) { - bcelComparator = comparator; + @java.lang.Deprecated + protected byte tag; // TODO should be private & final + + Constant(final byte tag) { + this.tag = tag; + } + + /** + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + @Override + public abstract void accept(Visitor v); + + @Override + public Object clone() { + try { + return super.clone(); + } catch (final CloneNotSupportedException e) { + throw new Error("Clone Not Supported"); // never happens + } } /** - * Returns value as defined by given BCELComparator strategy. - * By default two Constant objects are said to be equal when + * @return deep copy of this constant + */ + public Constant copy() { + try { + return (Constant) super.clone(); + } catch (final CloneNotSupportedException e) { + // TODO should this throw? + } + return null; + } + + public abstract void dump(DataOutputStream file) throws IOException; + + /** + * Returns value as defined by given BCELComparator strategy. By default two Constant objects are said to be equal when * the result of toString() is equal. * - * @see java.lang.Object#equals(java.lang.Object) + * @see Object#equals(Object) */ @Override - public boolean equals( final Object obj ) { + public boolean equals(final Object obj) { return bcelComparator.equals(this, obj); } /** - * Returns value as defined by given BCELComparator strategy. - * By default return the hashcode of the result of toString(). + * @return Tag of constant, i.e., its type. No setTag() method to avoid confusion. + */ + public final byte getTag() { + return tag; + } + + /** + * Returns value as defined by given BCELComparator strategy. By default return the hashcode of the result of + * toString(). * - * @see java.lang.Object#hashCode() + * @see Object#hashCode() */ @Override public int hashCode() { return bcelComparator.hashCode(this); } + + /** + * @return String representation. + */ + @Override + public String toString() { + return Const.getConstantName(tag) + "[" + tag + "]"; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java index 1573bd2172f..71fd91b249a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java @@ -26,8 +26,7 @@ import com.sun.org.apache.bcel.internal.Const; /** - * Abstract super class for Fieldref, Methodref, InterfaceMethodref and - * InvokeDynamic constants. + * Abstract super class for Fieldref, Methodref, InterfaceMethodref and InvokeDynamic constants. * * @see ConstantFieldref * @see ConstantMethodref @@ -42,71 +41,76 @@ public abstract class ConstantCP extends Constant { */ // Note that this field is used to store the // bootstrap_method_attr_index of a ConstantInvokeDynamic. - private int class_index; + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @java.lang.Deprecated + protected int class_index; // TODO make private (has getter & setter) // This field has the same meaning for all subclasses. - private int name_and_type_index; /** - * Initialize from another object. + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter */ - public ConstantCP(final ConstantCP c) { - this(c.getTag(), c.getClassIndex(), c.getNameAndTypeIndex()); - } - + @java.lang.Deprecated + protected int name_and_type_index; // TODO make private (has getter & setter) /** * Initialize instance from file data. * - * @param tag Constant type tag + * @param tag Constant type tag * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantCP(final byte tag, final DataInput file) throws IOException { this(tag, file.readUnsignedShort(), file.readUnsignedShort()); } - /** - * @param class_index Reference to the class containing the field - * @param name_and_type_index and the field signature + * @param classIndex Reference to the class containing the field + * @param nameAndTypeIndex and the field signature */ - protected ConstantCP(final byte tag, final int class_index, final int name_and_type_index) { + protected ConstantCP(final byte tag, final int classIndex, final int nameAndTypeIndex) { super(tag); - this.class_index = class_index; - this.name_and_type_index = name_and_type_index; + this.class_index = classIndex; + this.name_and_type_index = nameAndTypeIndex; } + /** + * Initialize from another object. + * + * @param c Source to copy. + */ + public ConstantCP(final ConstantCP c) { + this(c.getTag(), c.getClassIndex(), c.getNameAndTypeIndex()); + } /** * Dump constant field reference to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public final void dump( final DataOutputStream file ) throws IOException { + public final void dump(final DataOutputStream file) throws IOException { file.writeByte(super.getTag()); file.writeShort(class_index); file.writeShort(name_and_type_index); } - /** - * @return Reference (index) to class this constant refers to. + * @return Class this field belongs to. */ - public final int getClassIndex() { - return class_index; + public String getClass(final ConstantPool cp) { + return cp.constantToString(class_index, Const.CONSTANT_Class); } - /** - * @param class_index points to Constant_class + * @return Reference (index) to class this constant refers to. */ - public final void setClassIndex( final int class_index ) { - this.class_index = class_index; + public final int getClassIndex() { + return class_index; } - /** * @return Reference (index) to signature of the field. */ @@ -114,31 +118,27 @@ public final int getNameAndTypeIndex() { return name_and_type_index; } - /** - * @param name_and_type_index points to Constant_NameAndType + * @param classIndex points to Constant_class */ - public final void setNameAndTypeIndex( final int name_and_type_index ) { - this.name_and_type_index = name_and_type_index; + public final void setClassIndex(final int classIndex) { + this.class_index = classIndex; } - /** - * @return Class this field belongs to. + * @param nameAndTypeIndex points to Constant_NameAndType */ - public String getClass( final ConstantPool cp ) { - return cp.constantToString(class_index, Const.CONSTANT_Class); + public final void setNameAndTypeIndex(final int nameAndTypeIndex) { + this.name_and_type_index = nameAndTypeIndex; } - /** * @return String representation. * - * not final as ConstantInvokeDynamic needs to modify + * not final as ConstantInvokeDynamic needs to modify */ @Override public String toString() { - return super.toString() + "(class_index = " + class_index + ", name_and_type_index = " - + name_and_type_index + ")"; + return super.toString() + "(class_index = " + class_index + ", name_and_type_index = " + name_and_type_index + ")"; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantClass.java index ed64179834a..9361a5d572f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantClass.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantClass.java @@ -28,24 +28,23 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from the abstract {@link Constant} - * and represents a reference to a (external) class. + * This class is derived from the abstract {@link Constant} and represents a reference to a (external) class. * - * @see Constant + * @see Constant */ public final class ConstantClass extends Constant implements ConstantObject { private int nameIndex; // Identical to ConstantString except for the name - /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantClass(final ConstantClass c) { this(c.getNameIndex()); } - /** * Constructs an instance from file data. * @@ -56,30 +55,25 @@ public ConstantClass(final ConstantClass c) { this(dataInput.readUnsignedShort()); } - /** - * @param nameIndex Name index in constant pool. Should refer to a - * ConstantUtf8. + * @param nameIndex Name index in constant pool. Should refer to a ConstantUtf8. */ public ConstantClass(final int nameIndex) { super(Const.CONSTANT_Class); this.nameIndex = nameIndex; } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantClass(this); } - /** * Dumps constant class to file stream in binary format. * @@ -87,44 +81,40 @@ public void accept( final Visitor v ) { * @throws IOException if an I/O error occurs writing to the DataOutputStream. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeByte(super.getTag()); file.writeShort(nameIndex); } - /** - * @return Name index in constant pool of class name. + * @return dereferenced string */ - public int getNameIndex() { - return nameIndex; + public String getBytes(final ConstantPool cp) { + return (String) getConstantValue(cp); } - /** - * @param nameIndex the name index in the constant pool of this Constant Class + * @return String object */ - public void setNameIndex( final int nameIndex ) { - this.nameIndex = nameIndex; + @Override + public Object getConstantValue(final ConstantPool cp) { + return cp.getConstantUtf8(nameIndex).getBytes(); } - - /** @return String object + /** + * @return Name index in constant pool of class name. */ - @Override - public Object getConstantValue( final ConstantPool cp ) { - final Constant c = cp.getConstant(nameIndex, Const.CONSTANT_Utf8); - return ((ConstantUtf8) c).getBytes(); + public int getNameIndex() { + return nameIndex; } - - /** @return dereferenced string + /** + * @param nameIndex the name index in the constant pool of this Constant Class */ - public String getBytes( final ConstantPool cp ) { - return (String) getConstantValue(cp); + public void setNameIndex(final int nameIndex) { + this.nameIndex = nameIndex; } - /** * @return String representation. */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java index bdbabe63bbd..ebb3d0af46a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java @@ -27,8 +27,7 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from the abstract {@link Constant} - * and represents a reference to a Double object. + * This class is derived from the abstract {@link Constant} and represents a reference to a Double object. * * @see Constant * @LastModified: Jun 2019 @@ -37,61 +36,56 @@ public final class ConstantDouble extends Constant implements ConstantObject { private double bytes; - - /** - * @param bytes Data - */ - public ConstantDouble(final double bytes) { - super(Const.CONSTANT_Double); - this.bytes = bytes; - } - - /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantDouble(final ConstantDouble c) { this(c.getBytes()); } - /** * Initialize instance from file data. * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantDouble(final DataInput file) throws IOException { this(file.readDouble()); } + /** + * @param bytes Data + */ + public ConstantDouble(final double bytes) { + super(Const.CONSTANT_Double); + this.bytes = bytes; + } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantDouble(this); } - /** * Dump constant double to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeByte(super.getTag()); file.writeDouble(bytes); } - /** * @return data, i.e., 8 bytes. */ @@ -99,15 +93,21 @@ public double getBytes() { return bytes; } + /** + * @return Double object + */ + @Override + public Object getConstantValue(final ConstantPool cp) { + return Double.valueOf(bytes); + } /** * @param bytes the raw bytes that represent the double value */ - public void setBytes( final double bytes ) { + public void setBytes(final double bytes) { this.bytes = bytes; } - /** * @return String representation. */ @@ -115,12 +115,4 @@ public void setBytes( final double bytes ) { public String toString() { return super.toString() + "(bytes = " + bytes + ")"; } - - - /** @return Double object - */ - @Override - public Object getConstantValue( final ConstantPool cp ) { - return bytes; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDynamic.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDynamic.java index ed569151615..6313b0c85f7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDynamic.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDynamic.java @@ -27,18 +27,20 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from the abstract {@link Constant} - * and represents a reference to a dynamically computed constant. + * This class is derived from the abstract {@link Constant} and represents a reference to a dynamically computed + * constant. * - * @see Constant - * @see - * Change request for JEP 309 + * @see Constant + * @see Change request for JEP + * 309 * @since 6.3 */ public final class ConstantDynamic extends ConstantCP { /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantDynamic(final ConstantDynamic c) { this(c.getBootstrapMethodAttrIndex(), c.getNameAndTypeIndex()); @@ -49,39 +51,37 @@ public ConstantDynamic(final ConstantDynamic c) { * Initialize instance from file data. * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantDynamic(final DataInput file) throws IOException { this(file.readShort(), file.readShort()); } - public ConstantDynamic(final int bootstrap_method_attr_index, final int name_and_type_index) { - super(Const.CONSTANT_Dynamic, bootstrap_method_attr_index, name_and_type_index); + public ConstantDynamic(final int bootstrapMethodAttrIndex, final int nameAndTypeIndex) { + super(Const.CONSTANT_Dynamic, bootstrapMethodAttrIndex, nameAndTypeIndex); } /** - * Called by objects that are traversing the nodes of the tree implicitly - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e., + * the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantDynamic(this); } /** * @return Reference (index) to bootstrap method this constant refers to. * - * Note that this method is a functional duplicate of getClassIndex - * for use by ConstantInvokeDynamic. + * Note that this method is a functional duplicate of getClassIndex for use by ConstantInvokeDynamic. * @since 6.0 */ public int getBootstrapMethodAttrIndex() { - return super.getClassIndex(); // AKA bootstrap_method_attr_index + return super.getClassIndex(); // AKA bootstrap_method_attr_index } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFieldref.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFieldref.java index 23af999e469..32bd750bed4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFieldref.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFieldref.java @@ -28,47 +28,44 @@ /** * This class represents a constant pool reference to a field. - * */ public final class ConstantFieldref extends ConstantCP { /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantFieldref(final ConstantFieldref c) { super(Const.CONSTANT_Fieldref, c.getClassIndex(), c.getNameAndTypeIndex()); } - /** * Initialize instance from input data. * * @param input input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantFieldref(final DataInput input) throws IOException { super(Const.CONSTANT_Fieldref, input); } - /** - * @param class_index Reference to the class containing the Field - * @param name_and_type_index and the Field signature + * @param classIndex Reference to the class containing the Field + * @param nameAndTypeIndex and the Field signature */ - public ConstantFieldref(final int class_index, final int name_and_type_index) { - super(Const.CONSTANT_Fieldref, class_index, name_and_type_index); + public ConstantFieldref(final int classIndex, final int nameAndTypeIndex) { + super(Const.CONSTANT_Fieldref, classIndex, nameAndTypeIndex); } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of Fields, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of Fields, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantFieldref(this); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java index 24f0ac4db03..9c30c9e4fdb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java @@ -27,8 +27,7 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from the abstract {@link Constant} - * and represents a reference to a float object. + * This class is derived from the abstract {@link Constant} and represents a reference to a float object. * * @see Constant * @LastModified: Jun 2019 @@ -37,62 +36,57 @@ public final class ConstantFloat extends Constant implements ConstantObject { private float bytes; - - /** - * @param bytes Data - */ - public ConstantFloat(final float bytes) { - super(Const.CONSTANT_Float); - this.bytes = bytes; - } - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. + * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a + * physical copy. + * + * @param c Source to copy. */ public ConstantFloat(final ConstantFloat c) { this(c.getBytes()); } - /** * Initialize instance from file data. * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantFloat(final DataInput file) throws IOException { this(file.readFloat()); } + /** + * @param bytes Data + */ + public ConstantFloat(final float bytes) { + super(Const.CONSTANT_Float); + this.bytes = bytes; + } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantFloat(this); } - /** * Dump constant float to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeByte(super.getTag()); file.writeFloat(bytes); } - /** * @return data, i.e., 4 bytes. */ @@ -100,15 +94,21 @@ public float getBytes() { return bytes; } + /** + * @return Float object + */ + @Override + public Object getConstantValue(final ConstantPool cp) { + return Float.valueOf(bytes); + } /** * @param bytes the raw bytes that represent this float */ - public void setBytes( final float bytes ) { + public void setBytes(final float bytes) { this.bytes = bytes; } - /** * @return String representation. */ @@ -116,12 +116,4 @@ public void setBytes( final float bytes ) { public String toString() { return super.toString() + "(bytes = " + bytes + ")"; } - - - /** @return Float object - */ - @Override - public Object getConstantValue( final ConstantPool cp ) { - return bytes; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java index ceff5bdc41a..cabd2e15b03 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java @@ -27,8 +27,7 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from the abstract {@link Constant} - * and represents a reference to an int object. + * This class is derived from the abstract {@link Constant} and represents a reference to an int object. * * @see Constant * @LastModified: Jun 2019 @@ -37,61 +36,56 @@ public final class ConstantInteger extends Constant implements ConstantObject { private int bytes; - - /** - * @param bytes Data - */ - public ConstantInteger(final int bytes) { - super(Const.CONSTANT_Integer); - this.bytes = bytes; - } - - /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantInteger(final ConstantInteger c) { this(c.getBytes()); } - /** * Initialize instance from file data. * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantInteger(final DataInput file) throws IOException { this(file.readInt()); } + /** + * @param bytes Data + */ + public ConstantInteger(final int bytes) { + super(Const.CONSTANT_Integer); + this.bytes = bytes; + } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantInteger(this); } - /** * Dump constant integer to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeByte(super.getTag()); file.writeInt(bytes); } - /** * @return data, i.e., 4 bytes. */ @@ -99,15 +93,21 @@ public int getBytes() { return bytes; } + /** + * @return Integer object + */ + @Override + public Object getConstantValue(final ConstantPool cp) { + return Integer.valueOf(bytes); + } /** * @param bytes the raw bytes that represent this integer */ - public void setBytes( final int bytes ) { + public void setBytes(final int bytes) { this.bytes = bytes; } - /** * @return String representation. */ @@ -115,12 +115,4 @@ public void setBytes( final int bytes ) { public String toString() { return super.toString() + "(bytes = " + bytes + ")"; } - - - /** @return Integer object - */ - @Override - public Object getConstantValue( final ConstantPool cp ) { - return Integer.valueOf(bytes); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInterfaceMethodref.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInterfaceMethodref.java index 882ecaada10..14cac5b9000 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInterfaceMethodref.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInterfaceMethodref.java @@ -28,47 +28,44 @@ /** * This class represents a constant pool reference to an interface method. - * */ public final class ConstantInterfaceMethodref extends ConstantCP { /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantInterfaceMethodref(final ConstantInterfaceMethodref c) { super(Const.CONSTANT_InterfaceMethodref, c.getClassIndex(), c.getNameAndTypeIndex()); } - /** * Initialize instance from input data. * * @param input input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantInterfaceMethodref(final DataInput input) throws IOException { super(Const.CONSTANT_InterfaceMethodref, input); } - /** - * @param class_index Reference to the class containing the method - * @param name_and_type_index and the method signature + * @param classIndex Reference to the class containing the method + * @param nameAndTypeIndex and the method signature */ - public ConstantInterfaceMethodref(final int class_index, final int name_and_type_index) { - super(Const.CONSTANT_InterfaceMethodref, class_index, name_and_type_index); + public ConstantInterfaceMethodref(final int classIndex, final int nameAndTypeIndex) { + super(Const.CONSTANT_InterfaceMethodref, classIndex, nameAndTypeIndex); } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantInterfaceMethodref(this); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInvokeDynamic.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInvokeDynamic.java index 7191c7ea207..b4154edd5a4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInvokeDynamic.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInvokeDynamic.java @@ -27,61 +27,57 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from the abstract {@link Constant} - * and represents a reference to a invoke dynamic. + * This class is derived from the abstract {@link Constant} and represents a reference to a invoke dynamic. * - * @see Constant - * @see - * The CONSTANT_InvokeDynamic_info Structure in The Java Virtual Machine Specification + * @see Constant + * @see The + * CONSTANT_InvokeDynamic_info Structure in The Java Virtual Machine Specification * @since 6.0 */ public final class ConstantInvokeDynamic extends ConstantCP { /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantInvokeDynamic(final ConstantInvokeDynamic c) { this(c.getBootstrapMethodAttrIndex(), c.getNameAndTypeIndex()); } - /** * Initialize instance from file data. * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantInvokeDynamic(final DataInput file) throws IOException { - this(file.readShort(), file.readShort()); + this(file.readUnsignedShort(), file.readUnsignedShort()); } - - public ConstantInvokeDynamic(final int bootstrap_method_attr_index, final int name_and_type_index) { - super(Const.CONSTANT_InvokeDynamic, bootstrap_method_attr_index, name_and_type_index); + public ConstantInvokeDynamic(final int bootstrapMethodAttrIndex, final int nameAndTypeIndex) { + super(Const.CONSTANT_InvokeDynamic, bootstrapMethodAttrIndex, nameAndTypeIndex); } - /** - * Called by objects that are traversing the nodes of the tree implicitly - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e., + * the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantInvokeDynamic(this); } /** * @return Reference (index) to bootstrap method this constant refers to. * - * Note that this method is a functional duplicate of getClassIndex - * for use by ConstantInvokeDynamic. + * Note that this method is a functional duplicate of getClassIndex for use by ConstantInvokeDynamic. * @since 6.0 */ public int getBootstrapMethodAttrIndex() { - return super.getClassIndex(); // AKA bootstrap_method_attr_index + return super.getClassIndex(); // AKA bootstrap_method_attr_index } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java index 1177c2702d2..2b2fc39caff 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java @@ -27,8 +27,7 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from the abstract {@link Constant} - * and represents a reference to a long object. + * This class is derived from the abstract {@link Constant} and represents a reference to a long object. * * @see Constant * @LastModified: Jan 2020 @@ -37,61 +36,56 @@ public final class ConstantLong extends Constant implements ConstantObject { private long bytes; - - /** - * @param bytes Data - */ - public ConstantLong(final long bytes) { - super(Const.CONSTANT_Long); - this.bytes = bytes; - } - - /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantLong(final ConstantLong c) { this(c.getBytes()); } - /** * Initialize instance from file data. * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantLong(final DataInput file) throws IOException { this(file.readLong()); } + /** + * @param bytes Data + */ + public ConstantLong(final long bytes) { + super(Const.CONSTANT_Long); + this.bytes = bytes; + } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantLong(this); } - /** * Dump constant long to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeByte(super.getTag()); file.writeLong(bytes); } - /** * @return data, i.e., 8 bytes. */ @@ -99,15 +93,21 @@ public long getBytes() { return bytes; } + /** + * @return Long object + */ + @Override + public Object getConstantValue(final ConstantPool cp) { + return Long.valueOf(bytes); + } /** * @param bytes the raw bytes that represent this long */ - public void setBytes( final long bytes ) { + public void setBytes(final long bytes) { this.bytes = bytes; } - /** * @return String representation. */ @@ -115,12 +115,4 @@ public void setBytes( final long bytes ) { public String toString() { return super.toString() + "(bytes = " + bytes + ")"; } - - - /** @return Long object - */ - @Override - public Object getConstantValue( final ConstantPool cp ) { - return bytes; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantMethodHandle.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantMethodHandle.java index d516f1a609f..40dfc8fe64a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantMethodHandle.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantMethodHandle.java @@ -28,10 +28,9 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from the abstract {@link Constant} - * and represents a reference to a method handle. + * This class is derived from the abstract {@link Constant} and represents a reference to a method handle. * - * @see Constant + * @see Constant * @since 6.0 */ public final class ConstantMethodHandle extends Constant { @@ -39,86 +38,76 @@ public final class ConstantMethodHandle extends Constant { private int referenceKind; private int referenceIndex; - /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantMethodHandle(final ConstantMethodHandle c) { this(c.getReferenceKind(), c.getReferenceIndex()); } - /** * Initialize instance from file data. * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantMethodHandle(final DataInput file) throws IOException { this(file.readUnsignedByte(), file.readUnsignedShort()); } - - public ConstantMethodHandle(final int reference_kind, final int reference_index) { + public ConstantMethodHandle(final int referenceKind, final int referenceIndex) { super(Const.CONSTANT_MethodHandle); - this.referenceKind = reference_kind; - this.referenceIndex = reference_index; + this.referenceKind = referenceKind; + this.referenceIndex = referenceIndex; } - /** - * Called by objects that are traversing the nodes of the tree implicitly - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e., + * the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantMethodHandle(this); } - /** * Dump method kind and index to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeByte(super.getTag()); file.writeByte(referenceKind); file.writeShort(referenceIndex); } + public int getReferenceIndex() { + return referenceIndex; + } public int getReferenceKind() { return referenceKind; } - - public void setReferenceKind(final int reference_kind) { - this.referenceKind = reference_kind; - } - - - public int getReferenceIndex() { - return referenceIndex; + public void setReferenceIndex(final int referenceIndex) { + this.referenceIndex = referenceIndex; } - - public void setReferenceIndex(final int reference_index) { - this.referenceIndex = reference_index; + public void setReferenceKind(final int referenceKind) { + this.referenceKind = referenceKind; } - /** * @return String representation */ @Override public String toString() { - return super.toString() + "(referenceKind = " + referenceKind + - ", referenceIndex = " + referenceIndex + ")"; + return super.toString() + "(referenceKind = " + referenceKind + ", referenceIndex = " + referenceIndex + ")"; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantMethodType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantMethodType.java index 08f894f0d4e..654d801709c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantMethodType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantMethodType.java @@ -28,78 +28,70 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from the abstract {@link Constant} - * and represents a reference to a method type. + * This class is derived from the abstract {@link Constant} and represents a reference to a method type. * - * @see Constant + * @see Constant * @since 6.0 */ public final class ConstantMethodType extends Constant { private int descriptorIndex; - /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantMethodType(final ConstantMethodType c) { this(c.getDescriptorIndex()); } - /** * Initialize instance from file data. * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantMethodType(final DataInput file) throws IOException { this(file.readUnsignedShort()); } - - public ConstantMethodType(final int descriptor_index) { + public ConstantMethodType(final int descriptorIndex) { super(Const.CONSTANT_MethodType); - this.descriptorIndex = descriptor_index; + this.descriptorIndex = descriptorIndex; } - /** - * Called by objects that are traversing the nodes of the tree implicitly - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e., + * the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantMethodType(this); } - /** * Dump name and signature index to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeByte(super.getTag()); file.writeShort(descriptorIndex); } - public int getDescriptorIndex() { return descriptorIndex; } - - public void setDescriptorIndex(final int descriptor_index) { - this.descriptorIndex = descriptor_index; + public void setDescriptorIndex(final int descriptorIndex) { + this.descriptorIndex = descriptorIndex; } - /** * @return String representation */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantMethodref.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantMethodref.java index d8bdd7fd789..cd914092c4f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantMethodref.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantMethodref.java @@ -28,47 +28,44 @@ /** * This class represents a constant pool reference to a method. - * */ public final class ConstantMethodref extends ConstantCP { /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantMethodref(final ConstantMethodref c) { super(Const.CONSTANT_Methodref, c.getClassIndex(), c.getNameAndTypeIndex()); } - /** * Initialize instance from input data. * * @param input input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantMethodref(final DataInput input) throws IOException { super(Const.CONSTANT_Methodref, input); } - /** - * @param class_index Reference to the class containing the method - * @param name_and_type_index and the method signature + * @param classIndex Reference to the class containing the method + * @param nameAndTypeIndex and the method signature */ - public ConstantMethodref(final int class_index, final int name_and_type_index) { - super(Const.CONSTANT_Methodref, class_index, name_and_type_index); + public ConstantMethodref(final int classIndex, final int nameAndTypeIndex) { + super(Const.CONSTANT_Methodref, classIndex, nameAndTypeIndex); } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantMethodref(this); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantModule.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantModule.java index 12c37069255..06754b9676e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantModule.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantModule.java @@ -28,106 +28,98 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from the abstract {@link Constant} - * and represents a reference to a module. + * This class is derived from the abstract {@link Constant} and represents a reference to a module. * - *

    Note: Early access Java 9 support- currently subject to change

    + *

    + * Note: Early access Java 9 support- currently subject to change + *

    * - * @see Constant + * @see Constant * @since 6.1 */ public final class ConstantModule extends Constant implements ConstantObject { private int nameIndex; - /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantModule(final ConstantModule c) { this(c.getNameIndex()); } - /** * Initialize instance from file data. * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantModule(final DataInput file) throws IOException { this(file.readUnsignedShort()); } - /** - * @param nameIndex Name index in constant pool. Should refer to a - * ConstantUtf8. + * @param nameIndex Name index in constant pool. Should refer to a ConstantUtf8. */ public ConstantModule(final int nameIndex) { super(Const.CONSTANT_Module); this.nameIndex = nameIndex; } - /** - * Called by objects that are traversing the nodes of the tree implicitly - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e., + * the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantModule(this); } - /** * Dump constant module to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeByte(super.getTag()); file.writeShort(nameIndex); } - /** - * @return Name index in constant pool of module name. + * @return dereferenced string */ - public int getNameIndex() { - return nameIndex; + public String getBytes(final ConstantPool cp) { + return (String) getConstantValue(cp); } - /** - * @param nameIndex the name index in the constant pool of this Constant Module + * @return String object */ - public void setNameIndex( final int nameIndex ) { - this.nameIndex = nameIndex; + @Override + public Object getConstantValue(final ConstantPool cp) { + return cp.getConstantUtf8(nameIndex).getBytes(); } - - /** @return String object + /** + * @return Name index in constant pool of module name. */ - @Override - public Object getConstantValue( final ConstantPool cp ) { - final Constant c = cp.getConstant(nameIndex, Const.CONSTANT_Utf8); - return ((ConstantUtf8) c).getBytes(); + public int getNameIndex() { + return nameIndex; } - - /** @return dereferenced string + /** + * @param nameIndex the name index in the constant pool of this Constant Module */ - public String getBytes( final ConstantPool cp ) { - return (String) getConstantValue(cp); + public void setNameIndex(final int nameIndex) { + this.nameIndex = nameIndex; } - /** * @return String representation. */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantNameAndType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantNameAndType.java index f1ce11948aa..fbf09c9794c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantNameAndType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantNameAndType.java @@ -28,37 +28,35 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from the abstract {@link Constant} - * and represents a reference to the name and signature - * of a field or method. + * This class is derived from the abstract {@link Constant} and represents a reference to the name and signature of a + * field or method. * - * @see Constant + * @see Constant */ public final class ConstantNameAndType extends Constant { private int nameIndex; // Name of field/method private int signatureIndex; // and its signature. - /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantNameAndType(final ConstantNameAndType c) { this(c.getNameIndex(), c.getSignatureIndex()); } - /** * Initialize instance from file data. * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantNameAndType(final DataInput file) throws IOException { this(file.readUnsignedShort(), file.readUnsignedShort()); } - /** * @param nameIndex Name of field/method * @param signatureIndex and its signature @@ -69,33 +67,36 @@ public ConstantNameAndType(final int nameIndex, final int signatureIndex) { this.signatureIndex = signatureIndex; } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantNameAndType(this); } - /** * Dump name and signature index to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeByte(super.getTag()); file.writeShort(nameIndex); file.writeShort(signatureIndex); } + /** + * @return name + */ + public String getName(final ConstantPool cp) { + return cp.constantToString(getNameIndex(), Const.CONSTANT_Utf8); + } /** * @return Name index in constant pool of field/method name. @@ -104,14 +105,13 @@ public int getNameIndex() { return nameIndex; } - - /** @return name + /** + * @return signature */ - public String getName( final ConstantPool cp ) { - return cp.constantToString(getNameIndex(), Const.CONSTANT_Utf8); + public String getSignature(final ConstantPool cp) { + return cp.constantToString(getSignatureIndex(), Const.CONSTANT_Utf8); } - /** * @return Index in constant pool of field/method signature. */ @@ -119,36 +119,25 @@ public int getSignatureIndex() { return signatureIndex; } - - /** @return signature - */ - public String getSignature( final ConstantPool cp ) { - return cp.constantToString(getSignatureIndex(), Const.CONSTANT_Utf8); - } - - /** * @param nameIndex the name index of this constant */ - public void setNameIndex( final int nameIndex ) { + public void setNameIndex(final int nameIndex) { this.nameIndex = nameIndex; } - /** * @param signatureIndex the signature index in the constant pool of this type */ - public void setSignatureIndex( final int signatureIndex ) { + public void setSignatureIndex(final int signatureIndex) { this.signatureIndex = signatureIndex; } - /** * @return String representation */ @Override public String toString() { - return super.toString() + "(nameIndex = " + nameIndex + ", signatureIndex = " - + signatureIndex + ")"; + return super.toString() + "(nameIndex = " + nameIndex + ", signatureIndex = " + signatureIndex + ")"; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java index 361593e3d66..cb28f7dacb8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java @@ -22,14 +22,14 @@ package com.sun.org.apache.bcel.internal.classfile; /** - * This interface denotes those constants that have a "natural" value, - * such as ConstantLong, ConstantString, etc.. + * This interface denotes those constants that have a "natural" value, such as ConstantLong, ConstantString, etc.. * - * @see Constant + * @see Constant */ public interface ConstantObject { - /** @return object representing the constant, e.g., Long for ConstantLong + /** + * @return object representing the constant, e.g., Long for ConstantLong */ - Object getConstantValue( ConstantPool cp ); + Object getConstantValue(ConstantPool cp); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPackage.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPackage.java index 2770f95b2a2..2e8c7215016 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPackage.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPackage.java @@ -28,106 +28,98 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from the abstract {@link Constant} - * and represents a reference to a package. + * This class is derived from the abstract {@link Constant} and represents a reference to a package. * - *

    Note: Early access Java 9 support- currently subject to change

    + *

    + * Note: Early access Java 9 support- currently subject to change + *

    * - * @see Constant + * @see Constant * @since 6.1 */ public final class ConstantPackage extends Constant implements ConstantObject { private int nameIndex; - /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantPackage(final ConstantPackage c) { this(c.getNameIndex()); } - /** * Initialize instance from file data. * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantPackage(final DataInput file) throws IOException { this(file.readUnsignedShort()); } - /** - * @param nameIndex Name index in constant pool. Should refer to a - * ConstantUtf8. + * @param nameIndex Name index in constant pool. Should refer to a ConstantUtf8. */ public ConstantPackage(final int nameIndex) { super(Const.CONSTANT_Package); this.nameIndex = nameIndex; } - /** - * Called by objects that are traversing the nodes of the tree implicitly - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e., + * the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantPackage(this); } - /** * Dump constant package to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeByte(super.getTag()); file.writeShort(nameIndex); } - /** - * @return Name index in constant pool of package name. + * @return dereferenced string */ - public int getNameIndex() { - return nameIndex; + public String getBytes(final ConstantPool cp) { + return (String) getConstantValue(cp); } - /** - * @param nameIndex the name index in the constant pool of this Constant Package + * @return String object */ - public void setNameIndex( final int nameIndex ) { - this.nameIndex = nameIndex; + @Override + public Object getConstantValue(final ConstantPool cp) { + return cp.getConstantUtf8(nameIndex).getBytes(); } - - /** @return String object + /** + * @return Name index in constant pool of package name. */ - @Override - public Object getConstantValue( final ConstantPool cp ) { - final Constant c = cp.getConstant(nameIndex, Const.CONSTANT_Utf8); - return ((ConstantUtf8) c).getBytes(); + public int getNameIndex() { + return nameIndex; } - - /** @return dereferenced string + /** + * @param nameIndex the name index in the constant pool of this Constant Package */ - public String getBytes( final ConstantPool cp ) { - return (String) getConstantValue(cp); + public void setNameIndex(final int nameIndex) { + this.nameIndex = nameIndex; } - /** * @return String representation. */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java index b10c6521a38..5fb4ef1b080 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -23,23 +23,49 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; +import java.util.Iterator; import com.sun.org.apache.bcel.internal.Const; -import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; /** - * This class represents the constant pool, i.e., a table of constants, of - * a parsed classfile. It may contain null references, due to the JVM - * specification that skips an entry after an 8-byte constant (double, - * long) entry. Those interested in generating constant pools - * programatically should see - * ConstantPoolGen. - - * @see Constant - * @see com.sun.org.apache.bcel.internal.generic.ConstantPoolGen - * @LastModified: June 2022 + * This class represents the constant pool, i.e., a table of constants, of a parsed classfile. It may contain null references, due to the JVM specification that + * skips an entry after an 8-byte constant (double, long) entry. Those interested in generating constant pools programmatically should see + * ConstantPoolGen. + * + * @see Constant + * @see com.sun.org.apache.bcel.internal.generic.ConstantPoolGen + * @LastModified: Feb 2023 */ -public class ConstantPool implements Cloneable, Node { +public class ConstantPool implements Cloneable, Node, Iterable { + + private static String escape(final String str) { + final int len = str.length(); + final StringBuilder buf = new StringBuilder(len + 5); + final char[] ch = str.toCharArray(); + for (int i = 0; i < len; i++) { + switch (ch[i]) { + case '\n': + buf.append("\\n"); + break; + case '\r': + buf.append("\\r"); + break; + case '\t': + buf.append("\\t"); + break; + case '\b': + buf.append("\\b"); + break; + case '"': + buf.append("\\\""); + break; + default: + buf.append(ch[i]); + } + } + return buf.toString(); + } private Constant[] constantPool; @@ -54,182 +80,166 @@ public ConstantPool(final Constant[] constantPool) { * Reads constants from given input stream. * * @param input Input stream - * @throws IOException - * @throws ClassFormatException + * @throws IOException if problem in readUnsignedShort or readConstant */ - public ConstantPool(final DataInput input) throws IOException, ClassFormatException { + public ConstantPool(final DataInput input) throws IOException { byte tag; - final int constant_pool_count = input.readUnsignedShort(); - constantPool = new Constant[constant_pool_count]; - /* constantPool[0] is unused by the compiler and may be used freely - * by the implementation. + final int constantPoolCount = input.readUnsignedShort(); + constantPool = new Constant[constantPoolCount]; + /* + * constantPool[0] is unused by the compiler and may be used freely by the implementation. */ - for (int i = 1; i < constant_pool_count; i++) { + for (int i = 1; i < constantPoolCount; i++) { constantPool[i] = Constant.readConstant(input); - /* Quote from the JVM specification: - * "All eight byte constants take up two spots in the constant pool. - * If this is the n'th byte in the constant pool, then the next item - * will be numbered n+2" + /* + * Quote from the JVM specification: "All eight byte constants take up two spots in the constant pool. If this is the n'th byte in the constant + * pool, then the next item will be numbered n+2" * * Thus we have to increment the index counter. */ tag = constantPool[i].getTag(); - if ((tag == Const.CONSTANT_Double) || (tag == Const.CONSTANT_Long)) { + if (tag == Const.CONSTANT_Double || tag == Const.CONSTANT_Long) { i++; } } } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e., the hierarchy of methods, fields, + * attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantPool(this); } /** * Resolves constant to a string representation. * - * @param c Constant to be printed + * @param c Constant to be printed * @return String representation + * @throws IllegalArgumentException if c is unknown constant type */ - public String constantToString( Constant c ) throws ClassFormatException { + public String constantToString(Constant c) throws IllegalArgumentException { String str; int i; final byte tag = c.getTag(); switch (tag) { - case Const.CONSTANT_Class: - i = ((ConstantClass) c).getNameIndex(); - c = getConstant(i, Const.CONSTANT_Utf8); - str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false); - break; - case Const.CONSTANT_String: - i = ((ConstantString) c).getStringIndex(); - c = getConstant(i, Const.CONSTANT_Utf8); - str = "\"" + escape(((ConstantUtf8) c).getBytes()) + "\""; - break; - case Const.CONSTANT_Utf8: - str = ((ConstantUtf8) c).getBytes(); - break; - case Const.CONSTANT_Double: - str = String.valueOf(((ConstantDouble) c).getBytes()); - break; - case Const.CONSTANT_Float: - str = String.valueOf(((ConstantFloat) c).getBytes()); - break; - case Const.CONSTANT_Long: - str = String.valueOf(((ConstantLong) c).getBytes()); - break; - case Const.CONSTANT_Integer: - str = String.valueOf(((ConstantInteger) c).getBytes()); - break; - case Const.CONSTANT_NameAndType: - str = constantToString(((ConstantNameAndType) c).getNameIndex(), - Const.CONSTANT_Utf8) - + " " + constantToString(((ConstantNameAndType) c).getSignatureIndex(), - Const.CONSTANT_Utf8); - break; - case Const.CONSTANT_InterfaceMethodref: - case Const.CONSTANT_Methodref: - case Const.CONSTANT_Fieldref: - str = constantToString(((ConstantCP) c).getClassIndex(), Const.CONSTANT_Class) - + "." + constantToString(((ConstantCP) c).getNameAndTypeIndex(), - Const.CONSTANT_NameAndType); - break; - case Const.CONSTANT_MethodHandle: - // Note that the ReferenceIndex may point to a Fieldref, Methodref or - // InterfaceMethodref - so we need to peek ahead to get the actual type. - final ConstantMethodHandle cmh = (ConstantMethodHandle) c; - str = Const.getMethodHandleName(cmh.getReferenceKind()) - + " " + constantToString(cmh.getReferenceIndex(), - getConstant(cmh.getReferenceIndex()).getTag()); - break; - case Const.CONSTANT_MethodType: - final ConstantMethodType cmt = (ConstantMethodType) c; - str = constantToString(cmt.getDescriptorIndex(), Const.CONSTANT_Utf8); - break; - case Const.CONSTANT_InvokeDynamic: - final ConstantInvokeDynamic cid = (ConstantInvokeDynamic) c; - str = cid.getBootstrapMethodAttrIndex() - + ":" + constantToString(cid.getNameAndTypeIndex(), - Const.CONSTANT_NameAndType); - break; - case Const.CONSTANT_Module: - i = ((ConstantModule) c).getNameIndex(); - c = getConstant(i, Const.CONSTANT_Utf8); - str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false); - break; - case Const.CONSTANT_Package: - i = ((ConstantPackage) c).getNameIndex(); - c = getConstant(i, Const.CONSTANT_Utf8); - str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false); - break; - default: // Never reached - throw new IllegalArgumentException("Unknown constant type " + tag); + case Const.CONSTANT_Class: + i = ((ConstantClass) c).getNameIndex(); + c = getConstantUtf8(i); + str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false); + break; + case Const.CONSTANT_String: + i = ((ConstantString) c).getStringIndex(); + c = getConstantUtf8(i); + str = "\"" + escape(((ConstantUtf8) c).getBytes()) + "\""; + break; + case Const.CONSTANT_Utf8: + str = ((ConstantUtf8) c).getBytes(); + break; + case Const.CONSTANT_Double: + str = String.valueOf(((ConstantDouble) c).getBytes()); + break; + case Const.CONSTANT_Float: + str = String.valueOf(((ConstantFloat) c).getBytes()); + break; + case Const.CONSTANT_Long: + str = String.valueOf(((ConstantLong) c).getBytes()); + break; + case Const.CONSTANT_Integer: + str = String.valueOf(((ConstantInteger) c).getBytes()); + break; + case Const.CONSTANT_NameAndType: + str = constantToString(((ConstantNameAndType) c).getNameIndex(), Const.CONSTANT_Utf8) + " " + + constantToString(((ConstantNameAndType) c).getSignatureIndex(), Const.CONSTANT_Utf8); + break; + case Const.CONSTANT_InterfaceMethodref: + case Const.CONSTANT_Methodref: + case Const.CONSTANT_Fieldref: + str = constantToString(((ConstantCP) c).getClassIndex(), Const.CONSTANT_Class) + "." + + constantToString(((ConstantCP) c).getNameAndTypeIndex(), Const.CONSTANT_NameAndType); + break; + case Const.CONSTANT_MethodHandle: + // Note that the ReferenceIndex may point to a Fieldref, Methodref or + // InterfaceMethodref - so we need to peek ahead to get the actual type. + final ConstantMethodHandle cmh = (ConstantMethodHandle) c; + str = Const.getMethodHandleName(cmh.getReferenceKind()) + " " + + constantToString(cmh.getReferenceIndex(), getConstant(cmh.getReferenceIndex()).getTag()); + break; + case Const.CONSTANT_MethodType: + final ConstantMethodType cmt = (ConstantMethodType) c; + str = constantToString(cmt.getDescriptorIndex(), Const.CONSTANT_Utf8); + break; + case Const.CONSTANT_InvokeDynamic: + final ConstantInvokeDynamic cid = (ConstantInvokeDynamic) c; + str = cid.getBootstrapMethodAttrIndex() + ":" + constantToString(cid.getNameAndTypeIndex(), Const.CONSTANT_NameAndType); + break; + case Const.CONSTANT_Dynamic: + final ConstantDynamic cd = (ConstantDynamic) c; + str = cd.getBootstrapMethodAttrIndex() + ":" + constantToString(cd.getNameAndTypeIndex(), Const.CONSTANT_NameAndType); + break; + case Const.CONSTANT_Module: + i = ((ConstantModule) c).getNameIndex(); + c = getConstantUtf8(i); + str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false); + break; + case Const.CONSTANT_Package: + i = ((ConstantPackage) c).getNameIndex(); + c = getConstantUtf8(i); + str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false); + break; + default: // Never reached + throw new IllegalArgumentException("Unknown constant type " + tag); } return str; } - private static String escape( final String str ) { - final int len = str.length(); - final StringBuilder buf = new StringBuilder(len + 5); - final char[] ch = str.toCharArray(); - for (int i = 0; i < len; i++) { - switch (ch[i]) { - case '\n': - buf.append("\\n"); - break; - case '\r': - buf.append("\\r"); - break; - case '\t': - buf.append("\\t"); - break; - case '\b': - buf.append("\\b"); - break; - case '"': - buf.append("\\\""); - break; - default: - buf.append(ch[i]); - } - } - return buf.toString(); - } - /** - * Retrieves constant at `index' from constant pool and resolve it to - * a string representation. + * Retrieves constant at 'index' from constant pool and resolve it to a string representation. * - * @param index of constant in constant pool - * @param tag expected type + * @param index of constant in constant pool + * @param tag expected type * @return String representation */ - public String constantToString( final int index, final byte tag ) throws ClassFormatException { - final Constant c = getConstant(index, tag); - return constantToString(c); + public String constantToString(final int index, final byte tag) { + return constantToString(getConstant(index, tag)); + } + + /** + * @return deep copy of this constant pool + */ + public ConstantPool copy() { + ConstantPool c = null; + try { + c = (ConstantPool) clone(); + c.constantPool = new Constant[constantPool.length]; + for (int i = 1; i < constantPool.length; i++) { + if (constantPool[i] != null) { + c.constantPool[i] = constantPool[i].copy(); + } + } + } catch (final CloneNotSupportedException e) { + // TODO should this throw? + } + return c; } /** * Dump constant pool to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if problem in writeShort or dump */ - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { /* * Constants over the size of the constant pool shall not be written out. * This is a redundant measure as the ConstantPoolGen should have already * reported an error back in the situation. - */ - int size = constantPool.length < ConstantPoolGen.CONSTANT_POOL_SIZE ? - constantPool.length : ConstantPoolGen.CONSTANT_POOL_SIZE; + */ + final int size = Math.min(constantPool.length, Const.MAX_CP_ENTRIES); file.writeShort(size); for (int i = 1; i < size; i++) { @@ -242,94 +252,151 @@ public void dump( final DataOutputStream file ) throws IOException { /** * Gets constant from constant pool. * - * @param index Index in constant pool + * @param index Index in constant pool * @return Constant value - * @see Constant + * @see Constant + * @throws ClassFormatException if index is invalid */ - public Constant getConstant( final int index ) { - if (index >= constantPool.length || index < 0) { - throw new ClassFormatException("Invalid constant pool reference: " + index - + ". Constant pool size is: " + constantPool.length); + @SuppressWarnings("unchecked") + public T getConstant(final int index) throws ClassFormatException { + return (T) getConstant(index, Constant.class); + } + + /** + * Gets constant from constant pool and check whether it has the expected type. + * + * @param index Index in constant pool + * @param tag Tag of expected constant, i.e., its type + * @return Constant value + * @see Constant + * @throws ClassFormatException if constant type does not match tag + */ + @SuppressWarnings("unchecked") + public T getConstant(final int index, final byte tag) throws ClassFormatException { + return (T) getConstant(index, tag, Constant.class); + } + + /** + * Gets constant from constant pool and check whether it has the expected type. + * + * @param index Index in constant pool + * @param tag Tag of expected constant, i.e., its type + * @return Constant value + * @see Constant + * @throws ClassFormatException if constant type does not match tag + * @since 6.6.0 + */ + public T getConstant(final int index, final byte tag, final Class castTo) throws ClassFormatException { + final T c = getConstant(index); + if (c.getTag() != tag) { + throw new ClassFormatException("Expected class '" + Const.getConstantName(tag) + "' at index " + index + " and got " + c); } - return constantPool[index]; + return c; } /** - * Gets constant from constant pool and check whether it has the - * expected type. + * Gets constant from constant pool. * - * @param index Index in constant pool - * @param tag Tag of expected constant, i.e., its type + * @param A {@link Constant} subclass + * @param index Index in constant pool + * @param castTo The {@link Constant} subclass to cast to. * @return Constant value - * @see Constant - * @throws ClassFormatException + * @see Constant + * @throws ClassFormatException if index is invalid + * @since 6.6.0 */ - public Constant getConstant( final int index, final byte tag ) throws ClassFormatException { - Constant c; - c = getConstant(index); - if (c == null) { - throw new ClassFormatException("Constant pool at index " + index + " is null."); + public T getConstant(final int index, final Class castTo) throws ClassFormatException { + if (index >= constantPool.length || index < 0) { + throw new ClassFormatException("Invalid constant pool reference using index: " + index + ". Constant pool size is: " + constantPool.length); } - if (c.getTag() != tag) { - throw new ClassFormatException("Expected class `" + Const.getConstantName(tag) - + "' at index " + index + " and got " + c); + if (constantPool[index] != null && !castTo.isAssignableFrom(constantPool[index].getClass())) { + throw new ClassFormatException("Invalid constant pool reference at index: " + index + + ". Expected " + castTo + " but was " + constantPool[index].getClass()); + } + // Previous check ensures this won't throw a ClassCastException + final T c = castTo.cast(constantPool[index]); + if (c == null + // the 0th element is always null + && index != 0) { + final Constant prev = constantPool[index - 1]; + if (prev == null || prev.getTag() != Const.CONSTANT_Double && prev.getTag() != Const.CONSTANT_Long) { + throw new ClassFormatException("Constant pool at index " + index + " is null."); + } } return c; } + /** + * Gets constant from constant pool and check whether it has the expected type. + * + * @param index Index in constant pool + * @return ConstantInteger value + * @see ConstantInteger + * @throws ClassFormatException if constant type does not match tag + */ + public ConstantInteger getConstantInteger(final int index) { + return getConstant(index, Const.CONSTANT_Integer, ConstantInteger.class); + } + /** * @return Array of constants. - * @see Constant + * @see Constant */ public Constant[] getConstantPool() { return constantPool; } /** - * Gets string from constant pool and bypass the indirection of - * `ConstantClass' and `ConstantString' objects. I.e. these classes have - * an index field that points to another entry of the constant pool of - * type `ConstantUtf8' which contains the real data. + * Gets string from constant pool and bypass the indirection of 'ConstantClass' and 'ConstantString' objects. I.e. these classes have an index field that + * points to another entry of the constant pool of type 'ConstantUtf8' which contains the real data. * - * @param index Index in constant pool - * @param tag Tag of expected constant, either ConstantClass or ConstantString + * @param index Index in constant pool + * @param tag Tag of expected constant, either ConstantClass or ConstantString * @return Contents of string reference - * @see ConstantClass - * @see ConstantString - * @throws ClassFormatException + * @see ConstantClass + * @see ConstantString + * @throws IllegalArgumentException if tag is invalid */ - public String getConstantString( final int index, final byte tag ) throws ClassFormatException { - Constant c; + public String getConstantString(final int index, final byte tag) throws IllegalArgumentException { int i; - c = getConstant(index, tag); - /* This switch() is not that elegant, since the four classes have the - * same contents, they just differ in the name of the index - * field variable. - * But we want to stick to the JVM naming conventions closely though - * we could have solved these more elegantly by using the same - * variable name or by subclassing. + /* + * This switch() is not that elegant, since the four classes have the same contents, they just differ in the name of the index field variable. But we + * want to stick to the JVM naming conventions closely though we could have solved these more elegantly by using the same variable name or by + * subclassing. */ switch (tag) { - case Const.CONSTANT_Class: - i = ((ConstantClass) c).getNameIndex(); - break; - case Const.CONSTANT_String: - i = ((ConstantString) c).getStringIndex(); - break; - case Const.CONSTANT_Module: - i = ((ConstantModule) c).getNameIndex(); - break; - case Const.CONSTANT_Package: - i = ((ConstantPackage) c).getNameIndex(); - break; - default: - throw new IllegalArgumentException("getConstantString called with illegal tag " + tag); + case Const.CONSTANT_Class: + i = getConstant(index, ConstantClass.class).getNameIndex(); + break; + case Const.CONSTANT_String: + i = getConstant(index, ConstantString.class).getStringIndex(); + break; + case Const.CONSTANT_Module: + i = getConstant(index, ConstantModule.class).getNameIndex(); + break; + case Const.CONSTANT_Package: + i = getConstant(index, ConstantPackage.class).getNameIndex(); + break; + case Const.CONSTANT_Utf8: + return getConstantUtf8(index).getBytes(); + default: + throw new IllegalArgumentException("getConstantString called with illegal tag " + tag); } // Finally get the string from the constant pool - c = getConstant(i, Const.CONSTANT_Utf8); - return ((ConstantUtf8) c).getBytes(); + return getConstantUtf8(i).getBytes(); } + /** + * Gets constant from constant pool and check whether it has the expected type. + * + * @param index Index in constant pool + * @return ConstantUtf8 value + * @see ConstantUtf8 + * @throws ClassFormatException if constant type does not match tag + */ + public ConstantUtf8 getConstantUtf8(final int index) throws ClassFormatException { + return getConstant(index, Const.CONSTANT_Utf8, ConstantUtf8.class); + } /** * @return Length of constant pool. @@ -338,23 +405,25 @@ public int getLength() { return constantPool == null ? 0 : constantPool.length; } + @Override + public Iterator iterator() { + return Arrays.stream(constantPool).iterator(); + } /** * @param constant Constant to set */ - public void setConstant( final int index, final Constant constant ) { + public void setConstant(final int index, final Constant constant) { constantPool[index] = constant; } - /** * @param constantPool */ - public void setConstantPool( final Constant[] constantPool ) { + public void setConstantPool(final Constant[] constantPool) { this.constantPool = constantPool; } - /** * @return String representation. */ @@ -366,24 +435,4 @@ public String toString() { } return buf.toString(); } - - - /** - * @return deep copy of this constant pool - */ - public ConstantPool copy() { - ConstantPool c = null; - try { - c = (ConstantPool) clone(); - c.constantPool = new Constant[constantPool.length]; - for (int i = 1; i < constantPool.length; i++) { - if (constantPool[i] != null) { - c.constantPool[i] = constantPool[i].copy(); - } - } - } catch (final CloneNotSupportedException e) { - // TODO should this throw? - } - return c; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantString.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantString.java index cdc2c0c5f9f..287e092b9aa 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantString.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantString.java @@ -28,35 +28,33 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from the abstract {@link Constant} - * and represents a reference to a String object. + * This class is derived from the abstract {@link Constant} and represents a reference to a String object. * - * @see Constant + * @see Constant */ public final class ConstantString extends Constant implements ConstantObject { private int stringIndex; // Identical to ConstantClass except for this name - /** * Initialize from another object. + * + * @param c Source to copy. */ public ConstantString(final ConstantString c) { this(c.getStringIndex()); } - /** * Initialize instance from file data. * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantString(final DataInput file) throws IOException { this(file.readUnsignedShort()); } - /** * @param stringIndex Index of Constant_Utf8 in constant pool */ @@ -65,32 +63,43 @@ public ConstantString(final int stringIndex) { this.stringIndex = stringIndex; } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantString(this); } - /** * Dump constant field reference to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeByte(super.getTag()); file.writeShort(stringIndex); } + /** + * @return dereferenced string + */ + public String getBytes(final ConstantPool cp) { + return (String) getConstantValue(cp); + } + + /** + * @return String object + */ + @Override + public Object getConstantValue(final ConstantPool cp) { + return cp.getConstantUtf8(stringIndex).getBytes(); + } /** * @return Index in constant pool of the string (ConstantUtf8). @@ -99,15 +108,13 @@ public int getStringIndex() { return stringIndex; } - /** * @param stringIndex the index into the constant of the string value */ - public void setStringIndex( final int stringIndex ) { + public void setStringIndex(final int stringIndex) { this.stringIndex = stringIndex; } - /** * @return String representation. */ @@ -115,20 +122,4 @@ public void setStringIndex( final int stringIndex ) { public String toString() { return super.toString() + "(stringIndex = " + stringIndex + ")"; } - - - /** @return String object - */ - @Override - public Object getConstantValue( final ConstantPool cp ) { - final Constant c = cp.getConstant(stringIndex, Const.CONSTANT_Utf8); - return ((ConstantUtf8) c).getBytes(); - } - - - /** @return dereferenced string - */ - public String getBytes( final ConstantPool cp ) { - return (String) getConstantValue(cp); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java index dd701a72bfb..ec875554c1a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,19 +20,45 @@ package com.sun.org.apache.bcel.internal.classfile; -import com.sun.org.apache.bcel.internal.Const; import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Objects; + +import com.sun.org.apache.bcel.internal.Const; /** * Extends the abstract {@link Constant} to represent a reference to a UTF-8 encoded string. + *

    + * The following system properties govern caching this class performs. + *

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

    + * Here is a sample Maven invocation with caching disabled: + *

    + * + *
    + * mvn test -Dbcel.statistics=true -Dbcel.maxcached.size=0 -Dbcel.maxcached=0
    + * 
    + *

    + * Here is a sample Maven invocation with caching enabled: + *

    + * + *
    + * mvn test -Dbcel.statistics=true -Dbcel.maxcached.size=100000 -Dbcel.maxcached=5000000
    + * 
    * * @see Constant - * @LastModified: Jan 2020 + * @LastModified: Feb 2023 */ public final class ConstantUtf8 extends Constant { @@ -42,8 +68,7 @@ private static class Cache { private static final int MAX_ENTRIES = 20000; private static final int INITIAL_CAPACITY = (int) (MAX_ENTRIES / 0.75); - private static final HashMap CACHE = new LinkedHashMap( - INITIAL_CAPACITY, 0.75f, true) { + private static final HashMap CACHE = new LinkedHashMap(INITIAL_CAPACITY, 0.75f, true) { private static final long serialVersionUID = -8506975356158971766L; @@ -62,6 +87,22 @@ static boolean isEnabled() { } + // TODO these should perhaps be AtomicInt? + private static volatile int considered; + private static volatile int created; + private static volatile int hits; + private static volatile int skipped; + + private static final String SYS_PROP_CACHE_MAX_ENTRIES = "bcel.maxcached"; + private static final String SYS_PROP_CACHE_MAX_ENTRY_SIZE = "bcel.maxcached.size"; + private static final String SYS_PROP_STATISTICS = "bcel.statistics"; + + static { + if (Cache.BCEL_STATISTICS) { + Runtime.getRuntime().addShutdownHook(new Thread(ConstantUtf8::printStats)); + } + } + /** * Clears the cache. * @@ -71,6 +112,11 @@ public static synchronized void clearCache() { Cache.CACHE.clear(); } + // for access by test code + static synchronized void clearStats() { + hits = considered = skipped = created = 0; + } + /** * Gets a new or cached instance of the given value. *

    @@ -83,12 +129,14 @@ public static synchronized void clearCache() { */ public static ConstantUtf8 getCachedInstance(final String value) { if (value.length() > Cache.MAX_ENTRY_SIZE) { + skipped++; return new ConstantUtf8(value); } - + considered++; synchronized (ConstantUtf8.class) { // might be better with a specific lock object ConstantUtf8 result = Cache.CACHE.get(value); if (result != null) { + hits++; return result; } result = new ConstantUtf8(value); @@ -126,6 +174,15 @@ public static ConstantUtf8 getInstance(final String value) { return Cache.isEnabled() ? getCachedInstance(value) : new ConstantUtf8(value); } + // for access by test code + static void printStats() { + final String prefix = "[Apache Commons BCEL]"; + System.err.printf("%s Cache hit %,d/%,d, %d skipped.%n", prefix, hits, considered, skipped); + System.err.printf("%s Total of %,d ConstantUtf8 objects created.%n", prefix, created); + System.err.printf("%s Configuration: %s=%,d, %s=%,d.%n", prefix, SYS_PROP_CACHE_MAX_ENTRIES, Cache.MAX_ENTRIES, SYS_PROP_CACHE_MAX_ENTRY_SIZE, + Cache.MAX_ENTRY_SIZE); + } + private final String value; /** @@ -141,11 +198,12 @@ public ConstantUtf8(final ConstantUtf8 constantUtf8) { * Initializes instance from file data. * * @param dataInput Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ ConstantUtf8(final DataInput dataInput) throws IOException { super(Const.CONSTANT_Utf8); value = dataInput.readUTF(); + created++; } /** @@ -153,14 +211,12 @@ public ConstantUtf8(final ConstantUtf8 constantUtf8) { */ public ConstantUtf8(final String value) { super(Const.CONSTANT_Utf8); - if (value == null) { - throw new IllegalArgumentException("Value must not be null."); - } - this.value = value; + this.value = Objects.requireNonNull(value, "value"); + created++; } /** - * Called by objects that are traversing the nodes of the tree implicitely defined by the contents of a Java class. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object @@ -174,7 +230,7 @@ public void accept(final Visitor v) { * Dumps String in Utf8 format to file stream. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override public void dump(final DataOutputStream file) throws IOException { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java index 4b58ae8d40e..311e9a33fa3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java @@ -26,81 +26,92 @@ import java.io.IOException; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class is derived from Attribute and represents a constant - * value, i.e., a default value for initializing a class field. - * This class is instantiated by the Attribute.readAttribute() method. + * This class is derived from Attribute and represents a constant value, i.e., a default value for initializing + * a class field. This class is instantiated by the Attribute.readAttribute() method. * - * @see Attribute + *

    + * ConstantValue_attribute {
    + *   u2 attribute_name_index;
    + *   u4 attribute_length;
    + *   u2 constantvalue_index;
    + * }
    + * 
    + * @see Attribute */ public final class ConstantValue extends Attribute { private int constantValueIndex; - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. + * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a + * physical copy. + * + * @param c Source to copy. */ public ConstantValue(final ConstantValue c) { this(c.getNameIndex(), c.getLength(), c.getConstantValueIndex(), c.getConstantPool()); } - /** * Construct object from input stream. - * @param name_index Name index in constant pool + * + * @param nameIndex Name index in constant pool * @param length Content length in bytes * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - ConstantValue(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) - throws IOException { - this(name_index, length, input.readUnsignedShort(), constant_pool); + ConstantValue(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, input.readUnsignedShort(), constantPool); } - /** - * @param name_index Name index in constant pool + * @param nameIndex Name index in constant pool * @param length Content length in bytes * @param constantValueIndex Index in constant pool - * @param constant_pool Array of constants + * @param constantPool Array of constants */ - public ConstantValue(final int name_index, final int length, final int constantValueIndex, - final ConstantPool constant_pool) { - super(Const.ATTR_CONSTANT_VALUE, name_index, length, constant_pool); + public ConstantValue(final int nameIndex, final int length, final int constantValueIndex, final ConstantPool constantPool) { + super(Const.ATTR_CONSTANT_VALUE, nameIndex, Args.require(length, 2, "ConstantValue attribute length"), constantPool); this.constantValueIndex = constantValueIndex; } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitConstantValue(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final ConstantValue c = (ConstantValue) clone(); + c.setConstantPool(constantPool); + return c; + } /** * Dump constant value attribute to file stream on binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(constantValueIndex); } - /** * @return Index in constant pool of constant value. */ @@ -108,15 +119,13 @@ public int getConstantValueIndex() { return constantValueIndex; } - /** * @param constantValueIndex the index info the constant pool of this constant value */ - public void setConstantValueIndex( final int constantValueIndex ) { + public void setConstantValueIndex(final int constantValueIndex) { this.constantValueIndex = constantValueIndex; } - /** * @return String representation of constant value. */ @@ -127,37 +136,26 @@ public String toString() { int i; // Print constant to string depending on its type switch (c.getTag()) { - case Const.CONSTANT_Long: - buf = String.valueOf(((ConstantLong) c).getBytes()); - break; - case Const.CONSTANT_Float: - buf = String.valueOf(((ConstantFloat) c).getBytes()); - break; - case Const.CONSTANT_Double: - buf = String.valueOf(((ConstantDouble) c).getBytes()); - break; - case Const.CONSTANT_Integer: - buf = String.valueOf(((ConstantInteger) c).getBytes()); - break; - case Const.CONSTANT_String: - i = ((ConstantString) c).getStringIndex(); - c = super.getConstantPool().getConstant(i, Const.CONSTANT_Utf8); - buf = "\"" + Utility.convertString(((ConstantUtf8) c).getBytes()) + "\""; - break; - default: - throw new IllegalStateException("Type of ConstValue invalid: " + c); + case Const.CONSTANT_Long: + buf = String.valueOf(((ConstantLong) c).getBytes()); + break; + case Const.CONSTANT_Float: + buf = String.valueOf(((ConstantFloat) c).getBytes()); + break; + case Const.CONSTANT_Double: + buf = String.valueOf(((ConstantDouble) c).getBytes()); + break; + case Const.CONSTANT_Integer: + buf = String.valueOf(((ConstantInteger) c).getBytes()); + break; + case Const.CONSTANT_String: + i = ((ConstantString) c).getStringIndex(); + c = super.getConstantPool().getConstantUtf8(i); + buf = "\"" + Utility.convertString(((ConstantUtf8) c).getBytes()) + "\""; + break; + default: + throw new IllegalStateException("Type of ConstValue invalid: " + c); } return buf; } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - final ConstantValue c = (ConstantValue) clone(); - c.setConstantPool(_constant_pool); - return c; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java index 5b530f59b1c..90841d96081 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java @@ -25,52 +25,50 @@ import java.io.IOException; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class is derived from Attribute and denotes that this is a - * deprecated method. - * It is instantiated from the Attribute.readAttribute() method. + * This class is derived from Attribute and denotes that this is a deprecated method. It is instantiated from + * the Attribute.readAttribute() method. * - * @see Attribute + * @see Attribute */ public final class Deprecated extends Attribute { private byte[] bytes; - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. + * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a + * physical copy. + * + * @param c Source to copy. */ public Deprecated(final Deprecated c) { this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool()); } - /** - * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes * @param bytes Attribute contents - * @param constant_pool Array of constants + * @param constantPool Array of constants */ - public Deprecated(final int name_index, final int length, final byte[] bytes, final ConstantPool constant_pool) { - super(Const.ATTR_DEPRECATED, name_index, length, constant_pool); + public Deprecated(final int nameIndex, final int length, final byte[] bytes, final ConstantPool constantPool) { + super(Const.ATTR_DEPRECATED, nameIndex, Args.require0(length, "Deprecated attribute length"), constantPool); this.bytes = bytes; } - /** * Construct object from input stream. * - * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - Deprecated(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) - throws IOException { - this(name_index, length, (byte[]) null, constant_pool); + Deprecated(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, (byte[]) null, constantPool); if (length > 0) { bytes = new byte[length]; input.readFully(bytes); @@ -78,35 +76,44 @@ public Deprecated(final int name_index, final int length, final byte[] bytes, fi } } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitDeprecated(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final Deprecated c = (Deprecated) clone(); + if (bytes != null) { + c.bytes = bytes.clone(); + } + c.setConstantPool(constantPool); + return c; + } /** * Dump source file attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); if (super.getLength() > 0) { file.write(bytes, 0, super.getLength()); } } - /** * @return data bytes. */ @@ -114,35 +121,18 @@ public byte[] getBytes() { return bytes; } - /** * @param bytes the raw bytes that represents this byte array */ - public void setBytes( final byte[] bytes ) { + public void setBytes(final byte[] bytes) { this.bytes = bytes; } - /** * @return attribute name */ @Override public String toString() { - return Const.getAttributeName(Const.ATTR_DEPRECATED); - } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - final Deprecated c = (Deprecated) clone(); - if (bytes != null) { - c.bytes = new byte[bytes.length]; - System.arraycopy(bytes, 0, c.bytes, 0, bytes.length); - } - c.setConstantPool(_constant_pool); - return c; + return Const.getAttributeName(Const.ATTR_DEPRECATED) + ": true"; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java index e57eec78311..3c475891acd 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java @@ -19,7 +19,9 @@ */ package com.sun.org.apache.bcel.internal.classfile; +import java.util.Objects; import java.util.Stack; +import java.util.stream.Stream; /** * Traverses a JavaClass with another Visitor object 'piggy-backed' that is @@ -27,8 +29,7 @@ * traversal strategy, other classes can make use of it. * */ -public class DescendingVisitor implements Visitor -{ +public class DescendingVisitor implements Visitor { private final JavaClass clazz; private final Visitor visitor; @@ -36,74 +37,59 @@ public class DescendingVisitor implements Visitor private final Stack stack = new Stack<>(); /** - * @return container of current entitity, i.e., predecessor during traversal + * @param clazz Class to traverse + * @param visitor visitor object to apply to all components */ - public Object predecessor() - { - return predecessor(0); + public DescendingVisitor(final JavaClass clazz, final Visitor visitor) { + this.clazz = clazz; + this.visitor = visitor; } - /** - * @param level - * nesting level, i.e., 0 returns the direct predecessor - * @return container of current entitity, i.e., predecessor during traversal - */ - public Object predecessor(final int level) - { - final int size = stack.size(); - if ((size < 2) || (level < 0)) - { - return null; - } - return stack.elementAt(size - (level + 2)); // size - 1 == current + private void accept(final E[] node) { + Stream.of(node).forEach(e -> e.accept(this)); } /** * @return current object */ - public Object current() - { + public Object current() { return stack.peek(); } /** - * @param clazz - * Class to traverse - * @param visitor - * visitor object to apply to all components + * @return container of current entitity, i.e., predecessor during traversal */ - public DescendingVisitor(final JavaClass clazz, final Visitor visitor) - { - this.clazz = clazz; - this.visitor = visitor; + public Object predecessor() { + return predecessor(0); + } + + /** + * @param level nesting level, i.e., 0 returns the direct predecessor + * @return container of current entitity, i.e., predecessor during traversal + */ + public Object predecessor(final int level) { + final int size = stack.size(); + if (size < 2 || level < 0) { + return null; + } + return stack.elementAt(size - (level + 2)); // size - 1 == current } /** * Start traversal. */ - public void visit() - { + public void visit() { clazz.accept(this); } + /** + * @since 6.0 + */ @Override - public void visitJavaClass(final JavaClass _clazz) - { - stack.push(_clazz); - _clazz.accept(visitor); - final Field[] fields = _clazz.getFields(); - for (final Field field : fields) { - field.accept(this); - } - final Method[] methods = _clazz.getMethods(); - for (final Method method : methods) { - method.accept(this); - } - final Attribute[] attributes = _clazz.getAttributes(); - for (final Attribute attribute : attributes) { - attribute.accept(this); - } - _clazz.getConstantPool().accept(this); + public void visitAnnotation(final Annotations annotation) { + stack.push(annotation); + annotation.accept(visitor); + accept(annotation.getAnnotationEntries()); stack.pop(); } @@ -111,14 +97,9 @@ public void visitJavaClass(final JavaClass _clazz) * @since 6.0 */ @Override - public void visitAnnotation(final Annotations annotation) - { - stack.push(annotation); - annotation.accept(visitor); - final AnnotationEntry[] entries = annotation.getAnnotationEntries(); - for (final AnnotationEntry entrie : entries) { - entrie.accept(this); - } + public void visitAnnotationDefault(final AnnotationDefault obj) { + stack.push(obj); + obj.accept(visitor); stack.pop(); } @@ -126,327 +107,270 @@ public void visitAnnotation(final Annotations annotation) * @since 6.0 */ @Override - public void visitAnnotationEntry(final AnnotationEntry annotationEntry) - { + public void visitAnnotationEntry(final AnnotationEntry annotationEntry) { stack.push(annotationEntry); annotationEntry.accept(visitor); stack.pop(); } + /** + * @since 6.0 + */ @Override - public void visitField(final Field field) - { - stack.push(field); - field.accept(visitor); - final Attribute[] attributes = field.getAttributes(); - for (final Attribute attribute : attributes) { - attribute.accept(this); - } + public void visitBootstrapMethods(final BootstrapMethods bm) { + stack.push(bm); + bm.accept(visitor); + // BootstrapMethod[] bms = bm.getBootstrapMethods(); + // for (int i = 0; i < bms.length; i++) + // { + // bms[i].accept(this); + // } stack.pop(); } @Override - public void visitConstantValue(final ConstantValue cv) - { - stack.push(cv); - cv.accept(visitor); + public void visitCode(final Code code) { + stack.push(code); + code.accept(visitor); + accept(code.getExceptionTable()); + accept(code.getAttributes()); stack.pop(); } @Override - public void visitMethod(final Method method) - { - stack.push(method); - method.accept(visitor); - final Attribute[] attributes = method.getAttributes(); - for (final Attribute attribute : attributes) { - attribute.accept(this); - } + public void visitCodeException(final CodeException ce) { + stack.push(ce); + ce.accept(visitor); stack.pop(); } @Override - public void visitExceptionTable(final ExceptionTable table) - { - stack.push(table); - table.accept(visitor); + public void visitConstantClass(final ConstantClass constant) { + stack.push(constant); + constant.accept(visitor); stack.pop(); } @Override - public void visitCode(final Code code) - { - stack.push(code); - code.accept(visitor); - final CodeException[] table = code.getExceptionTable(); - for (final CodeException element : table) { - element.accept(this); - } - final Attribute[] attributes = code.getAttributes(); - for (final Attribute attribute : attributes) { - attribute.accept(this); - } + public void visitConstantDouble(final ConstantDouble constant) { + stack.push(constant); + constant.accept(visitor); stack.pop(); } + /** @since 6.3 */ @Override - public void visitCodeException(final CodeException ce) - { - stack.push(ce); - ce.accept(visitor); + public void visitConstantDynamic(final ConstantDynamic obj) { + stack.push(obj); + obj.accept(visitor); stack.pop(); } @Override - public void visitLineNumberTable(final LineNumberTable table) - { - stack.push(table); - table.accept(visitor); - final LineNumber[] numbers = table.getLineNumberTable(); - for (final LineNumber number : numbers) { - number.accept(this); - } + public void visitConstantFieldref(final ConstantFieldref constant) { + stack.push(constant); + constant.accept(visitor); stack.pop(); } @Override - public void visitLineNumber(final LineNumber number) - { - stack.push(number); - number.accept(visitor); + public void visitConstantFloat(final ConstantFloat constant) { + stack.push(constant); + constant.accept(visitor); stack.pop(); } @Override - public void visitLocalVariableTable(final LocalVariableTable table) - { - stack.push(table); - table.accept(visitor); - final LocalVariable[] vars = table.getLocalVariableTable(); - for (final LocalVariable var : vars) { - var.accept(this); - } + public void visitConstantInteger(final ConstantInteger constant) { + stack.push(constant); + constant.accept(visitor); stack.pop(); } @Override - public void visitStackMap(final StackMap table) - { - stack.push(table); - table.accept(visitor); - final StackMapEntry[] vars = table.getStackMap(); - for (final StackMapEntry var : vars) { - var.accept(this); - } + public void visitConstantInterfaceMethodref(final ConstantInterfaceMethodref constant) { + stack.push(constant); + constant.accept(visitor); stack.pop(); } + /** + * @since 6.0 + */ @Override - public void visitStackMapEntry(final StackMapEntry var) - { - stack.push(var); - var.accept(visitor); + public void visitConstantInvokeDynamic(final ConstantInvokeDynamic constant) { + stack.push(constant); + constant.accept(visitor); stack.pop(); } @Override - public void visitLocalVariable(final LocalVariable var) - { - stack.push(var); - var.accept(visitor); + public void visitConstantLong(final ConstantLong constant) { + stack.push(constant); + constant.accept(visitor); stack.pop(); } + /** @since 6.0 */ @Override - public void visitConstantPool(final ConstantPool cp) - { - stack.push(cp); - cp.accept(visitor); - final Constant[] constants = cp.getConstantPool(); - for (int i = 1; i < constants.length; i++) - { - if (constants[i] != null) - { - constants[i].accept(this); - } - } + public void visitConstantMethodHandle(final ConstantMethodHandle obj) { + stack.push(obj); + obj.accept(visitor); stack.pop(); } @Override - public void visitConstantClass(final ConstantClass constant) - { + public void visitConstantMethodref(final ConstantMethodref constant) { stack.push(constant); constant.accept(visitor); stack.pop(); } + /** @since 6.0 */ @Override - public void visitConstantDouble(final ConstantDouble constant) - { - stack.push(constant); - constant.accept(visitor); + public void visitConstantMethodType(final ConstantMethodType obj) { + stack.push(obj); + obj.accept(visitor); stack.pop(); } + /** @since 6.1 */ @Override - public void visitConstantFieldref(final ConstantFieldref constant) - { - stack.push(constant); - constant.accept(visitor); + public void visitConstantModule(final ConstantModule obj) { + stack.push(obj); + obj.accept(visitor); stack.pop(); } @Override - public void visitConstantFloat(final ConstantFloat constant) - { + public void visitConstantNameAndType(final ConstantNameAndType constant) { stack.push(constant); constant.accept(visitor); stack.pop(); } + /** @since 6.1 */ @Override - public void visitConstantInteger(final ConstantInteger constant) - { - stack.push(constant); - constant.accept(visitor); + public void visitConstantPackage(final ConstantPackage obj) { + stack.push(obj); + obj.accept(visitor); stack.pop(); } @Override - public void visitConstantInterfaceMethodref( - final ConstantInterfaceMethodref constant) - { - stack.push(constant); - constant.accept(visitor); + public void visitConstantPool(final ConstantPool cp) { + stack.push(cp); + cp.accept(visitor); + Stream.of(cp.getConstantPool()).filter(Objects::nonNull).forEach(e -> e.accept(this)); stack.pop(); } - /** - * @since 6.0 - */ @Override - public void visitConstantInvokeDynamic( - final ConstantInvokeDynamic constant) - { + public void visitConstantString(final ConstantString constant) { stack.push(constant); constant.accept(visitor); stack.pop(); } @Override - public void visitConstantLong(final ConstantLong constant) - { + public void visitConstantUtf8(final ConstantUtf8 constant) { stack.push(constant); constant.accept(visitor); stack.pop(); } @Override - public void visitConstantMethodref(final ConstantMethodref constant) - { - stack.push(constant); - constant.accept(visitor); + public void visitConstantValue(final ConstantValue cv) { + stack.push(cv); + cv.accept(visitor); stack.pop(); } @Override - public void visitConstantNameAndType(final ConstantNameAndType constant) - { - stack.push(constant); - constant.accept(visitor); + public void visitDeprecated(final Deprecated attribute) { + stack.push(attribute); + attribute.accept(visitor); stack.pop(); } + /** + * @since 6.0 + */ @Override - public void visitConstantString(final ConstantString constant) - { - stack.push(constant); - constant.accept(visitor); + public void visitEnclosingMethod(final EnclosingMethod obj) { + stack.push(obj); + obj.accept(visitor); stack.pop(); } @Override - public void visitConstantUtf8(final ConstantUtf8 constant) - { - stack.push(constant); - constant.accept(visitor); + public void visitExceptionTable(final ExceptionTable table) { + stack.push(table); + table.accept(visitor); stack.pop(); } @Override - public void visitInnerClasses(final InnerClasses ic) - { - stack.push(ic); - ic.accept(visitor); - final InnerClass[] ics = ic.getInnerClasses(); - for (final InnerClass ic2 : ics) { - ic2.accept(this); - } + public void visitField(final Field field) { + stack.push(field); + field.accept(visitor); + accept(field.getAttributes()); stack.pop(); } @Override - public void visitInnerClass(final InnerClass inner) - { + public void visitInnerClass(final InnerClass inner) { stack.push(inner); inner.accept(visitor); stack.pop(); } - /** - * @since 6.0 - */ @Override - public void visitBootstrapMethods(final BootstrapMethods bm) - { - stack.push(bm); - bm.accept(visitor); - // BootstrapMethod[] bms = bm.getBootstrapMethods(); - // for (int i = 0; i < bms.length; i++) - // { - // bms[i].accept(this); - // } + public void visitInnerClasses(final InnerClasses ic) { + stack.push(ic); + ic.accept(visitor); + accept(ic.getInnerClasses()); stack.pop(); } @Override - public void visitDeprecated(final Deprecated attribute) - { - stack.push(attribute); - attribute.accept(visitor); + public void visitJavaClass(final JavaClass clazz) { + stack.push(clazz); + clazz.accept(visitor); + accept(clazz.getFields()); + accept(clazz.getMethods()); + accept(clazz.getAttributes()); + clazz.getConstantPool().accept(this); stack.pop(); } @Override - public void visitSignature(final Signature attribute) - { - stack.push(attribute); - attribute.accept(visitor); + public void visitLineNumber(final LineNumber number) { + stack.push(number); + number.accept(visitor); stack.pop(); } @Override - public void visitSourceFile(final SourceFile attribute) - { - stack.push(attribute); - attribute.accept(visitor); + public void visitLineNumberTable(final LineNumberTable table) { + stack.push(table); + table.accept(visitor); + accept(table.getLineNumberTable()); stack.pop(); } @Override - public void visitSynthetic(final Synthetic attribute) - { - stack.push(attribute); - attribute.accept(visitor); + public void visitLocalVariable(final LocalVariable var) { + stack.push(var); + var.accept(visitor); stack.pop(); } @Override - public void visitUnknown(final Unknown attribute) - { - stack.push(attribute); - attribute.accept(visitor); + public void visitLocalVariableTable(final LocalVariableTable table) { + stack.push(table); + table.accept(visitor); + accept(table.getLocalVariableTable()); stack.pop(); } @@ -454,30 +378,25 @@ public void visitUnknown(final Unknown attribute) * @since 6.0 */ @Override - public void visitAnnotationDefault(final AnnotationDefault obj) - { + public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj) { stack.push(obj); obj.accept(visitor); stack.pop(); } - /** - * @since 6.0 - */ @Override - public void visitEnclosingMethod(final EnclosingMethod obj) - { - stack.push(obj); - obj.accept(visitor); + public void visitMethod(final Method method) { + stack.push(method); + method.accept(visitor); + accept(method.getAttributes()); stack.pop(); } /** - * @since 6.0 + * @since 6.4.0 */ @Override - public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj) - { + public void visitMethodParameter(final MethodParameter obj) { stack.push(obj); obj.accept(visitor); stack.pop(); @@ -487,82 +406,76 @@ public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj) * @since 6.0 */ @Override - public void visitParameterAnnotation(final ParameterAnnotations obj) - { + public void visitMethodParameters(final MethodParameters obj) { stack.push(obj); obj.accept(visitor); + Stream.of(obj.getParameters()).forEach(e -> e.accept(this)); stack.pop(); } - /** - * @since 6.0 - */ + /** @since 6.4.0 */ @Override - public void visitMethodParameters(final MethodParameters obj) - { + public void visitModule(final Module obj) { stack.push(obj); obj.accept(visitor); - final MethodParameter[] table = obj.getParameters(); - for (final MethodParameter element : table) { - element.accept(this); - } + accept(obj.getRequiresTable()); + accept(obj.getExportsTable()); + accept(obj.getOpensTable()); + accept(obj.getProvidesTable()); stack.pop(); } - /** - * @since 6.4.0 - */ + /** @since 6.4.0 */ @Override - public void visitMethodParameter(final MethodParameter obj) - { + public void visitModuleExports(final ModuleExports obj) { stack.push(obj); obj.accept(visitor); stack.pop(); } - /** @since 6.0 */ + /** @since 6.4.0 */ @Override - public void visitConstantMethodType(final ConstantMethodType obj) { + public void visitModuleMainClass(final ModuleMainClass obj) { stack.push(obj); obj.accept(visitor); stack.pop(); } - /** @since 6.0 */ + /** @since 6.4.0 */ @Override - public void visitConstantMethodHandle(final ConstantMethodHandle obj) { + public void visitModuleOpens(final ModuleOpens obj) { stack.push(obj); obj.accept(visitor); stack.pop(); } - /** @since 6.0 */ + /** @since 6.4.0 */ @Override - public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) { + public void visitModulePackages(final ModulePackages obj) { stack.push(obj); obj.accept(visitor); stack.pop(); } - /** @since 6.1 */ + /** @since 6.4.0 */ @Override - public void visitConstantPackage(final ConstantPackage obj) { + public void visitModuleProvides(final ModuleProvides obj) { stack.push(obj); obj.accept(visitor); stack.pop(); } - /** @since 6.1 */ + /** @since 6.4.0 */ @Override - public void visitConstantModule(final ConstantModule obj) { + public void visitModuleRequires(final ModuleRequires obj) { stack.push(obj); obj.accept(visitor); stack.pop(); } - /** @since 6.3 */ + /** @since 6.4.0 */ @Override - public void visitConstantDynamic(final ConstantDynamic obj) { + public void visitNestHost(final NestHost obj) { stack.push(obj); obj.accept(visitor); stack.pop(); @@ -570,89 +483,70 @@ public void visitConstantDynamic(final ConstantDynamic obj) { /** @since 6.4.0 */ @Override - public void visitModule(final Module obj) { + public void visitNestMembers(final NestMembers obj) { stack.push(obj); obj.accept(visitor); - final ModuleRequires[] rtable = obj.getRequiresTable(); - for (final ModuleRequires element : rtable) { - element.accept(this); - } - final ModuleExports[] etable = obj.getExportsTable(); - for (final ModuleExports element : etable) { - element.accept(this); - } - final ModuleOpens[] otable = obj.getOpensTable(); - for (final ModuleOpens element : otable) { - element.accept(this); - } - final ModuleProvides[] ptable = obj.getProvidesTable(); - for (final ModuleProvides element : ptable) { - element.accept(this); - } stack.pop(); } - /** @since 6.4.0 */ + /** + * @since 6.0 + */ @Override - public void visitModuleRequires(final ModuleRequires obj) { + public void visitParameterAnnotation(final ParameterAnnotations obj) { stack.push(obj); obj.accept(visitor); stack.pop(); } - /** @since 6.4.0 */ + /** @since 6.0 */ @Override - public void visitModuleExports(final ModuleExports obj) { + public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) { stack.push(obj); obj.accept(visitor); stack.pop(); } - /** @since 6.4.0 */ @Override - public void visitModuleOpens(final ModuleOpens obj) { - stack.push(obj); - obj.accept(visitor); + public void visitSignature(final Signature attribute) { + stack.push(attribute); + attribute.accept(visitor); stack.pop(); } - /** @since 6.4.0 */ @Override - public void visitModuleProvides(final ModuleProvides obj) { - stack.push(obj); - obj.accept(visitor); + public void visitSourceFile(final SourceFile attribute) { + stack.push(attribute); + attribute.accept(visitor); stack.pop(); } - /** @since 6.4.0 */ @Override - public void visitModulePackages(final ModulePackages obj) { - stack.push(obj); - obj.accept(visitor); + public void visitStackMap(final StackMap table) { + stack.push(table); + table.accept(visitor); + accept(table.getStackMap()); stack.pop(); } - /** @since 6.4.0 */ @Override - public void visitModuleMainClass(final ModuleMainClass obj) { - stack.push(obj); - obj.accept(visitor); + public void visitStackMapEntry(final StackMapEntry var) { + stack.push(var); + var.accept(visitor); stack.pop(); } - /** @since 6.4.0 */ @Override - public void visitNestHost(final NestHost obj) { - stack.push(obj); - obj.accept(visitor); + public void visitSynthetic(final Synthetic attribute) { + stack.push(attribute); + attribute.accept(visitor); stack.pop(); } - /** @since 6.4.0 */ @Override - public void visitNestMembers(final NestMembers obj) { - stack.push(obj); - obj.accept(visitor); + public void visitUnknown(final Unknown attribute) { + stack.push(attribute); + attribute.accept(visitor); stack.pop(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java index d5967ffd531..5c3d9b3172b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java @@ -24,103 +24,155 @@ import java.io.DataOutputStream; import java.io.IOException; +import com.sun.org.apache.bcel.internal.Const; + /** + * The element_value structure is documented at https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7.16.1 + * + *
    + * element_value {
    + *    u1 tag;
    + *    union {
    + *        u2 const_value_index;
    + *
    + *        {   u2 type_name_index;
    + *            u2 const_name_index;
    + *        } enum_const_value;
    + *
    + *        u2 class_info_index;
    + *
    + *        annotation annotation_value;
    + *
    + *        {   u2            num_values;
    + *            element_value values[num_values];
    + *        } array_value;
    + *    } value;
    + *}
    + *
    * @since 6.0 * @LastModified: May 2021 */ -public abstract class ElementValue -{ - private final int type; +public abstract class ElementValue { + + public static final byte STRING = 's'; + public static final byte ENUM_CONSTANT = 'e'; + public static final byte CLASS = 'c'; + public static final byte ANNOTATION = '@'; + public static final byte ARRAY = '['; + public static final byte PRIMITIVE_INT = 'I'; + public static final byte PRIMITIVE_BYTE = 'B'; + public static final byte PRIMITIVE_CHAR = 'C'; + public static final byte PRIMITIVE_DOUBLE = 'D'; + public static final byte PRIMITIVE_FLOAT = 'F'; + public static final byte PRIMITIVE_LONG = 'J'; + public static final byte PRIMITIVE_SHORT = 'S'; + public static final byte PRIMITIVE_BOOLEAN = 'Z'; - private final ConstantPool cpool; + /** + * Reads an {@code element_value} as an {@code ElementValue}. + * + * @param input Raw data input. + * @param cpool Constant pool. + * @return a new ElementValue. + * @throws IOException if an I/O error occurs. + */ + public static ElementValue readElementValue(final DataInput input, final ConstantPool cpool) throws IOException { + return readElementValue(input, cpool, 0); + } - @Override - public String toString() - { - return stringifyValue(); + /** + * Reads an {@code element_value} as an {@code ElementValue}. + * + * @param input Raw data input. + * @param cpool Constant pool. + * @param arrayNesting level of current array nesting. + * @return a new ElementValue. + * @throws IOException if an I/O error occurs. + * @since 6.7.0 + */ + public static ElementValue readElementValue(final DataInput input, final ConstantPool cpool, int arrayNesting) + throws IOException { + final byte tag = input.readByte(); + switch (tag) { + case PRIMITIVE_BYTE: + case PRIMITIVE_CHAR: + case PRIMITIVE_DOUBLE: + case PRIMITIVE_FLOAT: + case PRIMITIVE_INT: + case PRIMITIVE_LONG: + case PRIMITIVE_SHORT: + case PRIMITIVE_BOOLEAN: + case STRING: + return new SimpleElementValue(tag, input.readUnsignedShort(), cpool); + + case ENUM_CONSTANT: + return new EnumElementValue(ENUM_CONSTANT, input.readUnsignedShort(), input.readUnsignedShort(), cpool); + + case CLASS: + return new ClassElementValue(CLASS, input.readUnsignedShort(), cpool); + + case ANNOTATION: + // TODO isRuntimeVisible + return new AnnotationElementValue(ANNOTATION, AnnotationEntry.read(input, cpool, false), cpool); + + case ARRAY: + arrayNesting++; + if (arrayNesting > Const.MAX_ARRAY_DIMENSIONS) { + // JVM spec 4.4.1 + throw new ClassFormatException(String.format("Arrays are only valid if they represent %,d or fewer dimensions.", Const.MAX_ARRAY_DIMENSIONS)); + } + final int numArrayVals = input.readUnsignedShort(); + final ElementValue[] evalues = new ElementValue[numArrayVals]; + for (int j = 0; j < numArrayVals; j++) { + evalues[j] = ElementValue.readElementValue(input, cpool, arrayNesting); + } + return new ArrayElementValue(ARRAY, evalues, cpool); + + default: + throw new ClassFormatException("Unexpected element value tag in annotation: " + tag); + } } - protected ElementValue(final int type, final ConstantPool cpool) - { + /** + * @deprecated (since 6.0) will be made private and final; do not access directly, use getter + */ + @java.lang.Deprecated + protected int type; // TODO should be final + /** + * @deprecated (since 6.0) will be made private and final; do not access directly, use getter + */ + @java.lang.Deprecated + protected ConstantPool cpool; // TODO should be final + + protected ElementValue(final int type, final ConstantPool cpool) { this.type = type; this.cpool = cpool; } - public int getElementValueType() - { - return type; - } - - public abstract String stringifyValue(); - public abstract void dump(DataOutputStream dos) throws IOException; - public static final byte STRING = 's'; - public static final byte ENUM_CONSTANT = 'e'; - public static final byte CLASS = 'c'; - public static final byte ANNOTATION = '@'; - public static final byte ARRAY = '['; - public static final byte PRIMITIVE_INT = 'I'; - public static final byte PRIMITIVE_BYTE = 'B'; - public static final byte PRIMITIVE_CHAR = 'C'; - public static final byte PRIMITIVE_DOUBLE = 'D'; - public static final byte PRIMITIVE_FLOAT = 'F'; - public static final byte PRIMITIVE_LONG = 'J'; - public static final byte PRIMITIVE_SHORT = 'S'; - public static final byte PRIMITIVE_BOOLEAN = 'Z'; - - public static ElementValue readElementValue(final DataInput input, final ConstantPool cpool) throws IOException - { - final byte type = input.readByte(); - switch (type) - { - case PRIMITIVE_BYTE: - case PRIMITIVE_CHAR: - case PRIMITIVE_DOUBLE: - case PRIMITIVE_FLOAT: - case PRIMITIVE_INT: - case PRIMITIVE_LONG: - case PRIMITIVE_SHORT: - case PRIMITIVE_BOOLEAN: - case STRING: - return new SimpleElementValue(type, input.readUnsignedShort(), cpool); - - case ENUM_CONSTANT: - return new EnumElementValue(ENUM_CONSTANT, input.readUnsignedShort(), input.readUnsignedShort(), cpool); - - case CLASS: - return new ClassElementValue(CLASS, input.readUnsignedShort(), cpool); - - case ANNOTATION: - // TODO isRuntimeVisible - return new AnnotationElementValue(ANNOTATION, AnnotationEntry.read(input, cpool, false), cpool); - - case ARRAY: - final int numArrayVals = input.readUnsignedShort(); - final ElementValue[] evalues = new ElementValue[numArrayVals]; - for (int j = 0; j < numArrayVals; j++) - { - evalues[j] = ElementValue.readElementValue(input, cpool); - } - return new ArrayElementValue(ARRAY, evalues, cpool); - - default: - throw new IllegalArgumentException("Unexpected element value kind in annotation: " + type); - } - } - /** @since 6.0 */ final ConstantPool getConstantPool() { return cpool; } + public int getElementValueType() { + return type; + } + /** @since 6.0 */ final int getType() { return type; } - public String toShortString() - { + public abstract String stringifyValue(); + + public String toShortString() { + return stringifyValue(); + } + + @Override + public String toString() { return stringifyValue(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValuePair.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValuePair.java index a1fa26593d6..8a2e6706034 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValuePair.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValuePair.java @@ -24,56 +24,47 @@ import java.io.DataOutputStream; import java.io.IOException; -import com.sun.org.apache.bcel.internal.Const; - /** - * an annotation's element value pair + * An annotation's element value pair. * * @since 6.0 */ -public class ElementValuePair -{ +public class ElementValuePair { + + static final ElementValuePair[] EMPTY_ARRAY = {}; + private final ElementValue elementValue; private final ConstantPool constantPool; private final int elementNameIndex; - public ElementValuePair(final int elementNameIndex, final ElementValue elementValue, - final ConstantPool constantPool) - { + public ElementValuePair(final int elementNameIndex, final ElementValue elementValue, final ConstantPool constantPool) { this.elementValue = elementValue; this.elementNameIndex = elementNameIndex; this.constantPool = constantPool; } - public String getNameString() - { - final ConstantUtf8 c = (ConstantUtf8) constantPool.getConstant( - elementNameIndex, Const.CONSTANT_Utf8); - return c.getBytes(); + protected void dump(final DataOutputStream dos) throws IOException { + dos.writeShort(elementNameIndex); // u2 name of the element + elementValue.dump(dos); } - public final ElementValue getValue() - { - return elementValue; + public int getNameIndex() { + return elementNameIndex; } - public int getNameIndex() - { - return elementNameIndex; + public String getNameString() { + return constantPool.getConstantUtf8(elementNameIndex).getBytes(); } - public String toShortString() - { - final StringBuilder result = new StringBuilder(); - result.append(getNameString()).append("=").append( - getValue().toShortString()); - return result.toString(); + public final ElementValue getValue() { + return elementValue; } - protected void dump(final DataOutputStream dos) throws IOException { - dos.writeShort(elementNameIndex); // u2 name of the element - elementValue.dump(dos); + public String toShortString() { + final StringBuilder result = new StringBuilder(); + result.append(getNameString()).append("=").append(getValue().toShortString()); + return result.toString(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java index 231e4e64c1a..826ba41af70 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java @@ -22,355 +22,304 @@ package com.sun.org.apache.bcel.internal.classfile; /** - * Visitor with empty method bodies, can be extended and used in conjunction - * with the DescendingVisitor class, e.g. By courtesy of David Spencer. + * Visitor with empty method bodies, can be extended and used in conjunction with the DescendingVisitor class, e.g. By + * courtesy of David Spencer. * * @see DescendingVisitor */ -public class EmptyVisitor implements Visitor -{ - protected EmptyVisitor() - { +public class EmptyVisitor implements Visitor { + protected EmptyVisitor() { } /** * @since 6.0 */ @Override - public void visitAnnotation(final Annotations obj) - { + public void visitAnnotation(final Annotations obj) { } /** * @since 6.0 */ @Override - public void visitParameterAnnotation(final ParameterAnnotations obj) - { + public void visitAnnotationDefault(final AnnotationDefault obj) { } /** * @since 6.0 */ @Override - public void visitAnnotationEntry(final AnnotationEntry obj) - { + public void visitAnnotationEntry(final AnnotationEntry obj) { } /** * @since 6.0 */ @Override - public void visitAnnotationDefault(final AnnotationDefault obj) - { + public void visitBootstrapMethods(final BootstrapMethods obj) { } @Override - public void visitCode(final Code obj) - { + public void visitCode(final Code obj) { } @Override - public void visitCodeException(final CodeException obj) - { + public void visitCodeException(final CodeException obj) { } @Override - public void visitConstantClass(final ConstantClass obj) - { + public void visitConstantClass(final ConstantClass obj) { } @Override - public void visitConstantDouble(final ConstantDouble obj) - { + public void visitConstantDouble(final ConstantDouble obj) { } + /** + * @since 6.3 + */ @Override - public void visitConstantFieldref(final ConstantFieldref obj) - { + public void visitConstantDynamic(final ConstantDynamic obj) { } @Override - public void visitConstantFloat(final ConstantFloat obj) - { + public void visitConstantFieldref(final ConstantFieldref obj) { } @Override - public void visitConstantInteger(final ConstantInteger obj) - { + public void visitConstantFloat(final ConstantFloat obj) { } @Override - public void visitConstantInterfaceMethodref(final ConstantInterfaceMethodref obj) - { + public void visitConstantInteger(final ConstantInteger obj) { } @Override - public void visitConstantInvokeDynamic(final ConstantInvokeDynamic obj) - { + public void visitConstantInterfaceMethodref(final ConstantInterfaceMethodref obj) { } @Override - public void visitConstantLong(final ConstantLong obj) - { + public void visitConstantInvokeDynamic(final ConstantInvokeDynamic obj) { } @Override - public void visitConstantMethodref(final ConstantMethodref obj) - { + public void visitConstantLong(final ConstantLong obj) { } + /** + * @since 6.0 + */ @Override - public void visitConstantNameAndType(final ConstantNameAndType obj) - { + public void visitConstantMethodHandle(final ConstantMethodHandle constantMethodHandle) { + } + + @Override + public void visitConstantMethodref(final ConstantMethodref obj) { } + /** + * @since 6.0 + */ @Override - public void visitConstantPool(final ConstantPool obj) - { + public void visitConstantMethodType(final ConstantMethodType obj) { } + /** + * @since 6.1 + */ @Override - public void visitConstantString(final ConstantString obj) - { + public void visitConstantModule(final ConstantModule constantModule) { } @Override - public void visitConstantUtf8(final ConstantUtf8 obj) - { + public void visitConstantNameAndType(final ConstantNameAndType obj) { } + /** + * @since 6.1 + */ @Override - public void visitConstantValue(final ConstantValue obj) - { + public void visitConstantPackage(final ConstantPackage constantPackage) { } @Override - public void visitDeprecated(final Deprecated obj) - { + public void visitConstantPool(final ConstantPool obj) { } @Override - public void visitExceptionTable(final ExceptionTable obj) - { + public void visitConstantString(final ConstantString obj) { } @Override - public void visitField(final Field obj) - { + public void visitConstantUtf8(final ConstantUtf8 obj) { } @Override - public void visitInnerClass(final InnerClass obj) - { + public void visitConstantValue(final ConstantValue obj) { } @Override - public void visitInnerClasses(final InnerClasses obj) - { + public void visitDeprecated(final Deprecated obj) { } /** * @since 6.0 */ @Override - public void visitBootstrapMethods(final BootstrapMethods obj) - { - } - - @Override - public void visitJavaClass(final JavaClass obj) - { + public void visitEnclosingMethod(final EnclosingMethod obj) { } @Override - public void visitLineNumber(final LineNumber obj) - { + public void visitExceptionTable(final ExceptionTable obj) { } @Override - public void visitLineNumberTable(final LineNumberTable obj) - { + public void visitField(final Field obj) { } @Override - public void visitLocalVariable(final LocalVariable obj) - { + public void visitInnerClass(final InnerClass obj) { } @Override - public void visitLocalVariableTable(final LocalVariableTable obj) - { + public void visitInnerClasses(final InnerClasses obj) { } @Override - public void visitMethod(final Method obj) - { + public void visitJavaClass(final JavaClass obj) { } @Override - public void visitSignature(final Signature obj) - { + public void visitLineNumber(final LineNumber obj) { } @Override - public void visitSourceFile(final SourceFile obj) - { + public void visitLineNumberTable(final LineNumberTable obj) { } @Override - public void visitSynthetic(final Synthetic obj) - { + public void visitLocalVariable(final LocalVariable obj) { } @Override - public void visitUnknown(final Unknown obj) - { + public void visitLocalVariableTable(final LocalVariableTable obj) { } + /** + * @since 6.0 + */ @Override - public void visitStackMap(final StackMap obj) - { + public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj) { } @Override - public void visitStackMapEntry(final StackMapEntry obj) - { + public void visitMethod(final Method obj) { } /** * @since 6.0 - @Override - public void visitStackMapTable(StackMapTable obj) - { - } + * @Override public void visitStackMapTable(StackMapTable obj) { } */ /** * @since 6.0 - @Override - public void visitStackMapTableEntry(StackMapTableEntry obj) - { - } + * @Override public void visitStackMapTableEntry(StackMapTableEntry obj) { } */ /** - * @since 6.0 + * @since 6.4.0 */ @Override - public void visitEnclosingMethod(final EnclosingMethod obj) - { + public void visitMethodParameter(final MethodParameter obj) { } /** * @since 6.0 */ @Override - public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj) - { + public void visitMethodParameters(final MethodParameters obj) { } - /** - * @since 6.0 - */ + /** @since 6.4.0 */ @Override - public void visitMethodParameters(final MethodParameters obj) - { + public void visitModule(final Module obj) { } - /** - * @since 6.4.0 - */ + /** @since 6.4.0 */ @Override - public void visitMethodParameter(final MethodParameter obj) - { + public void visitModuleExports(final ModuleExports obj) { } - /** - * @since 6.0 - */ + /** @since 6.4.0 */ @Override - public void visitConstantMethodType(final ConstantMethodType obj) - { + public void visitModuleMainClass(final ModuleMainClass obj) { } - /** - * @since 6.0 - */ + /** @since 6.4.0 */ @Override - public void visitConstantMethodHandle(final ConstantMethodHandle constantMethodHandle) { + public void visitModuleOpens(final ModuleOpens obj) { } - /** - * @since 6.0 - */ + /** @since 6.4.0 */ @Override - public void visitParameterAnnotationEntry(final ParameterAnnotationEntry parameterAnnotationEntry) { + public void visitModulePackages(final ModulePackages obj) { } - /** - * @since 6.1 - */ + /** @since 6.4.0 */ @Override - public void visitConstantPackage(final ConstantPackage constantPackage) { + public void visitModuleProvides(final ModuleProvides obj) { } - /** - * @since 6.1 - */ + /** @since 6.4.0 */ @Override - public void visitConstantModule(final ConstantModule constantModule) { + public void visitModuleRequires(final ModuleRequires obj) { } - /** - * @since 6.3 - */ + /** @since 6.4.0 */ @Override - public void visitConstantDynamic(final ConstantDynamic obj) { + public void visitNestHost(final NestHost obj) { } /** @since 6.4.0 */ @Override - public void visitModule(final Module obj) { + public void visitNestMembers(final NestMembers obj) { } - /** @since 6.4.0 */ + /** + * @since 6.0 + */ @Override - public void visitModuleRequires(final ModuleRequires obj) { + public void visitParameterAnnotation(final ParameterAnnotations obj) { } - /** @since 6.4.0 */ + /** + * @since 6.0 + */ @Override - public void visitModuleExports(final ModuleExports obj) { + public void visitParameterAnnotationEntry(final ParameterAnnotationEntry parameterAnnotationEntry) { } - /** @since 6.4.0 */ @Override - public void visitModuleOpens(final ModuleOpens obj) { + public void visitSignature(final Signature obj) { } - /** @since 6.4.0 */ @Override - public void visitModuleProvides(final ModuleProvides obj) { + public void visitSourceFile(final SourceFile obj) { } - /** @since 6.4.0 */ @Override - public void visitModulePackages(final ModulePackages obj) { + public void visitStackMap(final StackMap obj) { } - /** @since 6.4.0 */ @Override - public void visitModuleMainClass(final ModuleMainClass obj) { + public void visitStackMapEntry(final StackMapEntry obj) { } - /** @since 6.4.0 */ @Override - public void visitNestHost(final NestHost obj) { + public void visitSynthetic(final Synthetic obj) { } - /** @since 6.4.0 */ @Override - public void visitNestMembers(final NestMembers obj) { + public void visitUnknown(final Unknown obj) { } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EnclosingMethod.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EnclosingMethod.java index 431cabd8771..326e77738b0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EnclosingMethod.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EnclosingMethod.java @@ -26,10 +26,10 @@ import java.io.IOException; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This attribute exists for local or - * anonymous classes and ... there can be only one. + * This attribute exists for local or anonymous classes and ... there can be only one. * * @since 6.0 */ @@ -41,10 +41,10 @@ public class EnclosingMethod extends Attribute { // If the current class is not immediately enclosed by a method or // constructor, then the value of the method_index item must be zero. - // Otherwise, the value of the method_index item must point to a + // Otherwise, the value of the method_index item must point to a // CONSTANT_NameAndType_info structure representing the name and the // type of a method in the class referenced by the class we point - // to in the class_index. *It is the compiler responsibility* to + // to in the class_index. *It is the compiler responsibility* to // ensure that the method identified by this index is the closest // lexically enclosing method that includes the local/anonymous class. private int methodIndex; @@ -54,27 +54,45 @@ public class EnclosingMethod extends Attribute { this(nameIndex, len, input.readUnsignedShort(), input.readUnsignedShort(), cpool); } - private EnclosingMethod(final int nameIndex, final int len, final int classIdx,final int methodIdx, final ConstantPool cpool) { - super(Const.ATTR_ENCLOSING_METHOD, nameIndex, len, cpool); - classIndex = classIdx; - methodIndex = methodIdx; + private EnclosingMethod(final int nameIndex, final int len, final int classIndex, final int methodIndex, final ConstantPool cpool) { + super(Const.ATTR_ENCLOSING_METHOD, nameIndex, Args.require(len, 4, "EnclosingMethod attribute length"), cpool); + this.classIndex = Args.requireU2(classIndex, 0, cpool.getLength(), "EnclosingMethod class index"); + this.methodIndex = Args.requireU2(methodIndex, "EnclosingMethod method index"); } @Override public void accept(final Visitor v) { - v.visitEnclosingMethod(this); + v.visitEnclosingMethod(this); } @Override - public Attribute copy(final ConstantPool constant_pool) { + public Attribute copy(final ConstantPool constantPool) { return (Attribute) clone(); } + @Override + public final void dump(final DataOutputStream file) throws IOException { + super.dump(file); + file.writeShort(classIndex); + file.writeShort(methodIndex); + } + + public final ConstantClass getEnclosingClass() { + return super.getConstantPool().getConstant(classIndex, Const.CONSTANT_Class, ConstantClass.class); + } + // Accessors public final int getEnclosingClassIndex() { return classIndex; } + public final ConstantNameAndType getEnclosingMethod() { + if (methodIndex == 0) { + return null; + } + return super.getConstantPool().getConstant(methodIndex, Const.CONSTANT_NameAndType, ConstantNameAndType.class); + } + public final int getEnclosingMethodIndex() { return methodIndex; } @@ -86,26 +104,4 @@ public final void setEnclosingClassIndex(final int idx) { public final void setEnclosingMethodIndex(final int idx) { methodIndex = idx; } - - public final ConstantClass getEnclosingClass() { - final ConstantClass c = - (ConstantClass)super.getConstantPool().getConstant(classIndex,Const.CONSTANT_Class); - return c; - } - - public final ConstantNameAndType getEnclosingMethod() { - if (methodIndex == 0) { - return null; - } - final ConstantNameAndType nat = - (ConstantNameAndType)super.getConstantPool().getConstant(methodIndex,Const.CONSTANT_NameAndType); - return nat; - } - - @Override - public final void dump(final DataOutputStream file) throws IOException { - super.dump(file); - file.writeShort(classIndex); - file.writeShort(methodIndex); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EnumElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EnumElementValue.java index ac8632ee223..0a8163ededa 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EnumElementValue.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EnumElementValue.java @@ -24,67 +24,49 @@ import java.io.DataOutputStream; import java.io.IOException; -import com.sun.org.apache.bcel.internal.Const; - /** * @since 6.0 */ -public class EnumElementValue extends ElementValue -{ +public class EnumElementValue extends ElementValue { // For enum types, these two indices point to the type and value private final int typeIdx; private final int valueIdx; - public EnumElementValue(final int type, final int typeIdx, final int valueIdx, - final ConstantPool cpool) - { + public EnumElementValue(final int type, final int typeIdx, final int valueIdx, final ConstantPool cpool) { super(type, cpool); if (type != ENUM_CONSTANT) { - throw new IllegalArgumentException( - "Only element values of type enum can be built with this ctor - type specified: " + type); + throw new ClassFormatException("Only element values of type enum can be built with this ctor - type specified: " + type); } this.typeIdx = typeIdx; this.valueIdx = valueIdx; } @Override - public void dump(final DataOutputStream dos) throws IOException - { + public void dump(final DataOutputStream dos) throws IOException { dos.writeByte(super.getType()); // u1 type of value (ENUM_CONSTANT == 'e') dos.writeShort(typeIdx); // u2 dos.writeShort(valueIdx); // u2 } - @Override - public String stringifyValue() - { - final ConstantUtf8 cu8 = (ConstantUtf8) super.getConstantPool().getConstant(valueIdx, - Const.CONSTANT_Utf8); - return cu8.getBytes(); + public String getEnumTypeString() { + return super.getConstantPool().getConstantUtf8(typeIdx).getBytes(); } - public String getEnumTypeString() - { - final ConstantUtf8 cu8 = (ConstantUtf8) super.getConstantPool().getConstant(typeIdx, - Const.CONSTANT_Utf8); - return cu8.getBytes();// Utility.signatureToString(cu8.getBytes()); + public String getEnumValueString() { + return super.getConstantPool().getConstantUtf8(valueIdx).getBytes(); } - public String getEnumValueString() - { - final ConstantUtf8 cu8 = (ConstantUtf8) super.getConstantPool().getConstant(valueIdx, - Const.CONSTANT_Utf8); - return cu8.getBytes(); + public int getTypeIndex() { + return typeIdx; } - public int getValueIndex() - { + public int getValueIndex() { return valueIdx; } - public int getTypeIndex() - { - return typeIdx; + @Override + public String stringifyValue() { + return super.getConstantPool().getConstantUtf8(valueIdx).getBytes(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java index cddae111923..90eaa3eb062 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -24,85 +23,104 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class represents the table of exceptions that are thrown by a - * method. This attribute may be used once per method. The name of - * this class is ExceptionTable for historical reasons; The - * Java Virtual Machine Specification, Second Edition defines this - * attribute using the name Exceptions (which is inconsistent - * with the other classes). + * This class represents the table of exceptions that are thrown by a method. This attribute may be used once per + * method. The name of this class is ExceptionTable for historical reasons; The Java Virtual Machine + * Specification, Second Edition defines this attribute using the name Exceptions (which is inconsistent with + * the other classes). * - * @see Code + *
    + * Exceptions_attribute {
    + *   u2 attribute_name_index;
    + *   u4 attribute_length;
    + *   u2 number_of_exceptions;
    + *   u2 exception_index_table[number_of_exceptions];
    + * }
    + * 
    + * @see Code + * @LastModified: Feb 2023 */ public final class ExceptionTable extends Attribute { private int[] exceptionIndexTable; // constant pool - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. + * Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a + * physical copy. + * + * @param c Source to copy. */ public ExceptionTable(final ExceptionTable c) { this(c.getNameIndex(), c.getLength(), c.getExceptionIndexTable(), c.getConstantPool()); } - - /** - * @param name_index Index in constant pool - * @param length Content length in bytes - * @param exceptionIndexTable Table of indices in constant pool - * @param constant_pool Array of constants - */ - public ExceptionTable(final int name_index, final int length, final int[] exceptionIndexTable, - final ConstantPool constant_pool) { - super(Const.ATTR_EXCEPTIONS, name_index, length, constant_pool); - this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : new int[0]; - } - - /** * Construct object from input stream. + * * @param nameIndex Index in constant pool * @param length Content length in bytes * @param input Input stream * @param constantPool Array of constants - * @throws IOException + * @throws IOException if an I/O error occurs. */ ExceptionTable(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { this(nameIndex, length, (int[]) null, constantPool); - final int number_of_exceptions = input.readUnsignedShort(); - exceptionIndexTable = new int[number_of_exceptions]; - for (int i = 0; i < number_of_exceptions; i++) { + final int exceptionCount = input.readUnsignedShort(); + exceptionIndexTable = new int[exceptionCount]; + for (int i = 0; i < exceptionCount; i++) { exceptionIndexTable[i] = input.readUnsignedShort(); } } + /** + * @param nameIndex Index in constant pool + * @param length Content length in bytes + * @param exceptionIndexTable Table of indices in constant pool + * @param constantPool Array of constants + */ + public ExceptionTable(final int nameIndex, final int length, final int[] exceptionIndexTable, final ConstantPool constantPool) { + super(Const.ATTR_EXCEPTIONS, nameIndex, length, constantPool); + this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : Const.EMPTY_INT_ARRAY; + Args.requireU2(this.exceptionIndexTable.length, "exceptionIndexTable.length"); + } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionTable(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final ExceptionTable c = (ExceptionTable) clone(); + if (exceptionIndexTable != null) { + c.exceptionIndexTable = exceptionIndexTable.clone(); + } + c.setConstantPool(constantPool); + return c; + } /** * Dump exceptions attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(exceptionIndexTable.length); for (final int index : exceptionIndexTable) { @@ -110,7 +128,6 @@ public void dump( final DataOutputStream file ) throws IOException { } } - /** * @return Array of indices into constant pool of thrown exceptions. */ @@ -118,36 +135,29 @@ public int[] getExceptionIndexTable() { return exceptionIndexTable; } - - /** - * @return Length of exception table. - */ - public int getNumberOfExceptions() { - return exceptionIndexTable == null ? 0 : exceptionIndexTable.length; - } - - /** * @return class names of thrown exceptions */ public String[] getExceptionNames() { final String[] names = new String[exceptionIndexTable.length]; - for (int i = 0; i < exceptionIndexTable.length; i++) { - names[i] = super.getConstantPool().getConstantString(exceptionIndexTable[i], - Const.CONSTANT_Class).replace('/', '.'); - } + Arrays.setAll(names, i -> Utility.pathToPackage(super.getConstantPool().getConstantString(exceptionIndexTable[i], Const.CONSTANT_Class))); return names; } - /** - * @param exceptionIndexTable the list of exception indexes - * Also redefines number_of_exceptions according to table length. + * @return Length of exception table. */ - public void setExceptionIndexTable( final int[] exceptionIndexTable ) { - this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : new int[0]; + public int getNumberOfExceptions() { + return exceptionIndexTable == null ? 0 : exceptionIndexTable.length; } + /** + * @param exceptionIndexTable the list of exception indexes Also redefines number_of_exceptions according to table + * length. + */ + public void setExceptionIndexTable(final int[] exceptionIndexTable) { + this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : Const.EMPTY_INT_ARRAY; + } /** * @return String representation, i.e., a list of thrown exceptions. @@ -166,20 +176,4 @@ public String toString() { } return buf.toString(); } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - final ExceptionTable c = (ExceptionTable) clone(); - if (exceptionIndexTable != null) { - c.exceptionIndexTable = new int[exceptionIndexTable.length]; - System.arraycopy(exceptionIndexTable, 0, c.exceptionIndexTable, 0, - exceptionIndexTable.length); - } - c.setConstantPool(_constant_pool); - return c; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java index f3ad1c45f94..7e6ccb2ecb5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java @@ -30,75 +30,111 @@ import com.sun.org.apache.bcel.internal.util.BCELComparator; /** - * This class represents the field info structure, i.e., the representation - * for a variable in the class. See JVM specification for details. - * + * This class represents the field info structure, i.e., the representation for a variable in the class. See JVM + * specification for details. */ public final class Field extends FieldOrMethod { + /** + * Empty array constant. + * + * @since 6.6.0 + */ + public static final Field[] EMPTY_ARRAY = {}; + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals( final Object o1, final Object o2 ) { + public boolean equals(final Object o1, final Object o2) { final Field THIS = (Field) o1; final Field THAT = (Field) o2; - return Objects.equals(THIS.getName(), THAT.getName()) - && Objects.equals(THIS.getSignature(), THAT.getSignature()); + return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature()); } - @Override - public int hashCode( final Object o ) { + public int hashCode(final Object o) { final Field THIS = (Field) o; return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); } }; + /** + * Empty array. + */ + static final Field[] EMPTY_FIELD_ARRAY = {}; /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. + * @return Comparison strategy object */ - public Field(final Field c) { - super(c); + public static BCELComparator getComparator() { + return bcelComparator; } + /** + * @param comparator Comparison strategy object + */ + public static void setComparator(final BCELComparator comparator) { + bcelComparator = comparator; + } /** * Construct object from file stream. + * * @param file Input stream */ - Field(final DataInput file, final ConstantPool constant_pool) throws IOException, - ClassFormatException { - super(file, constant_pool); + Field(final DataInput file, final ConstantPool constantPool) throws IOException, ClassFormatException { + super(file, constantPool); } + /** + * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a + * physical copy. + * + * @param c Source to copy. + */ + public Field(final Field c) { + super(c); + } /** - * @param access_flags Access rights of field - * @param name_index Points to field name in constant pool - * @param signature_index Points to encoded signature + * @param accessFlags Access rights of field + * @param nameIndex Points to field name in constant pool + * @param signatureIndex Points to encoded signature * @param attributes Collection of attributes - * @param constant_pool Array of constants + * @param constantPool Array of constants */ - public Field(final int access_flags, final int name_index, final int signature_index, final Attribute[] attributes, - final ConstantPool constant_pool) { - super(access_flags, name_index, signature_index, attributes, constant_pool); + public Field(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, final ConstantPool constantPool) { + super(accessFlags, nameIndex, signatureIndex, attributes, constantPool); } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitField(this); } + /** + * @return deep copy of this field + */ + public Field copy(final ConstantPool constantPool) { + return (Field) copy_(constantPool); + } + + /** + * Return value as defined by given BCELComparator strategy. By default two Field objects are said to be equal when + * their names and signatures are equal. + * + * @see Object#equals(Object) + */ + @Override + public boolean equals(final Object obj) { + return bcelComparator.equals(this, obj); + } /** * @return constant value associated with this field (may be null) @@ -112,10 +148,26 @@ public ConstantValue getConstantValue() { return null; } + /** + * @return type of field + */ + public Type getType() { + return Type.getReturnType(getSignature()); + } /** - * Return string representation close to declaration format, - * `public static final short MAX = 100', e.g.. + * Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR + * signature. + * + * @see Object#hashCode() + */ + @Override + public int hashCode() { + return bcelComparator.hashCode(this); + } + + /** + * Return string representation close to declaration format, 'public static final short MAX = 100', e.g.. * * @return String representation of field, including the signature. */ @@ -127,7 +179,7 @@ public String toString() { // Get names from constant pool access = Utility.accessToString(super.getAccessFlags()); - access = access.isEmpty() ? "" : (access + " "); + access = access.isEmpty() ? "" : access + " "; signature = Utility.signatureToString(getSignature()); name = getName(); final StringBuilder buf = new StringBuilder(64); // CHECKSTYLE IGNORE MagicNumber @@ -143,61 +195,4 @@ public String toString() { } return buf.toString(); } - - - /** - * @return deep copy of this field - */ - public Field copy( final ConstantPool _constant_pool ) { - return (Field) copy_(_constant_pool); - } - - - /** - * @return type of field - */ - public Type getType() { - return Type.getReturnType(getSignature()); - } - - - /** - * @return Comparison strategy object - */ - public static BCELComparator getComparator() { - return bcelComparator; - } - - - /** - * @param comparator Comparison strategy object - */ - public static void setComparator( final BCELComparator comparator ) { - bcelComparator = comparator; - } - - - /** - * Return value as defined by given BCELComparator strategy. - * By default two Field objects are said to be equal when - * their names and signatures are equal. - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals( final Object obj ) { - return bcelComparator.equals(this, obj); - } - - - /** - * Return value as defined by given BCELComparator strategy. - * By default return the hashcode of the field's name XOR signature. - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - return bcelComparator.hashCode(this); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java index 40e3ad4675a..1daa6a62fd5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java @@ -23,8 +23,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; - -import com.sun.org.apache.bcel.internal.Const; +import java.util.Arrays; /** * Abstract super class for fields and methods. @@ -32,89 +31,121 @@ * @LastModified: Jan 2020 */ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node { - private int name_index; // Points to field name in constant pool - private int signature_index; // Points to encoded signature - private Attribute[] attributes; // Collection of attributes - private int attributes_count; // No. of attributes + + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @java.lang.Deprecated + protected int name_index; // Points to field name in constant pool + + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @java.lang.Deprecated + protected int signature_index; // Points to encoded signature + + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @java.lang.Deprecated + protected Attribute[] attributes; // Collection of attributes + + /** + * @deprecated (since 6.0) will be removed (not needed) + */ + @java.lang.Deprecated + protected int attributes_count; // No. of attributes // @since 6.0 private AnnotationEntry[] annotationEntries; // annotations defined on the field or method - private ConstantPool constant_pool; + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @java.lang.Deprecated + protected ConstantPool constant_pool; - private String signatureAttributeString = null; - private boolean searchedForSignatureAttribute = false; + private String signatureAttributeString; + private boolean searchedForSignatureAttribute; FieldOrMethod() { } - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. + * Construct object from file stream. + * + * @param file Input stream + * @throws IOException if an I/O error occurs. */ - protected FieldOrMethod(final FieldOrMethod c) { - this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), - c.getAttributes(), c.getConstantPool()); + protected FieldOrMethod(final DataInput file, final ConstantPool constantPool) throws IOException { + this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null, constantPool); + final int attributesCount = file.readUnsignedShort(); + attributes = new Attribute[attributesCount]; + for (int i = 0; i < attributesCount; i++) { + attributes[i] = Attribute.readAttribute(file, constantPool); + } + this.attributes_count = attributesCount; // init deprecated field } - /** * Construct object from file stream. * * @param file Input stream - * @throws IOException - * @throws ClassFormatException + * @throws IOException if an I/O error occurs. * @deprecated (6.0) Use {@link #FieldOrMethod(java.io.DataInput, ConstantPool)} instead. */ @java.lang.Deprecated - protected FieldOrMethod(final DataInputStream file, final ConstantPool constant_pool) - throws IOException, - ClassFormatException { - this((DataInput) file, constant_pool); + protected FieldOrMethod(final DataInputStream file, final ConstantPool constantPool) throws IOException { + this((DataInput) file, constantPool); } /** - * Construct object from file stream. - * @param file Input stream - * @throws IOException - * @throws ClassFormatException + * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a + * physical copy. + * + * @param c Source to copy. */ - protected FieldOrMethod(final DataInput file, final ConstantPool constant_pool) - throws IOException, ClassFormatException { - this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null, - constant_pool); - final int attributes_count = file.readUnsignedShort(); - attributes = new Attribute[attributes_count]; - for (int i = 0; i < attributes_count; i++) { - attributes[i] = Attribute.readAttribute(file, constant_pool); - } - this.attributes_count = attributes_count; // init deprecated field + protected FieldOrMethod(final FieldOrMethod c) { + this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), c.getAttributes(), c.getConstantPool()); } - /** - * @param access_flags Access rights of method - * @param name_index Points to field name in constant pool - * @param signature_index Points to encoded signature + * @param accessFlags Access rights of method + * @param nameIndex Points to field name in constant pool + * @param signatureIndex Points to encoded signature * @param attributes Collection of attributes - * @param constant_pool Array of constants + * @param constantPool Array of constants */ - protected FieldOrMethod(final int access_flags, final int name_index, final int signature_index, - final Attribute[] attributes, final ConstantPool constant_pool) { - super(access_flags); - this.name_index = name_index; - this.signature_index = signature_index; - this.constant_pool = constant_pool; + protected FieldOrMethod(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, + final ConstantPool constantPool) { + super(accessFlags); + this.name_index = nameIndex; + this.signature_index = signatureIndex; + this.constant_pool = constantPool; setAttributes(attributes); } + /** + * @return deep copy of this field + */ + protected FieldOrMethod copy_(final ConstantPool constantPool) { + try { + final FieldOrMethod c = (FieldOrMethod) clone(); + c.constant_pool = constantPool; + c.attributes = new Attribute[attributes.length]; + c.attributes_count = attributes_count; // init deprecated field + Arrays.setAll(c.attributes, i -> attributes[i].copy(constantPool)); + return c; + } catch (final CloneNotSupportedException e) { + throw new IllegalStateException(e); + } + } /** * Dump object to file stream on binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ public final void dump(final DataOutputStream file) throws IOException { file.writeShort(super.getAccessFlags()); @@ -128,24 +159,25 @@ public final void dump(final DataOutputStream file) throws IOException { } } - /** - * @return Collection of object attributes. + * @return Annotations on the field or method + * @since 6.0 */ - public final Attribute[] getAttributes() { - return attributes; - } + public AnnotationEntry[] getAnnotationEntries() { + if (annotationEntries == null) { + annotationEntries = AnnotationEntry.createAnnotationEntries(getAttributes()); + } + return annotationEntries; + } /** - * @param attributes Collection of object attributes. + * @return Collection of object attributes. */ - public final void setAttributes( final Attribute[] attributes ) { - this.attributes = attributes; - this.attributes_count = attributes != null ? attributes.length : 0; // init deprecated field + public final Attribute[] getAttributes() { + return attributes; } - /** * @return Constant pool used by this object. */ @@ -153,14 +185,33 @@ public final ConstantPool getConstantPool() { return constant_pool; } - /** - * @param constant_pool Constant pool to be used for this object. + * Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature may be + * (Ljava/util/Vector;)V the signature attribute may in fact say 'Ljava/lang/Vector<Ljava/lang/String>;' Coded for + * performance - searches for the attribute only when requested - only searches for it once. + * + * @since 6.0 */ - public final void setConstantPool( final ConstantPool constant_pool ) { - this.constant_pool = constant_pool; + public final String getGenericSignature() { + if (!searchedForSignatureAttribute) { + boolean found = false; + for (int i = 0; !found && i < attributes.length; i++) { + if (attributes[i] instanceof Signature) { + signatureAttributeString = ((Signature) attributes[i]).getSignature(); + found = true; + } + } + searchedForSignatureAttribute = true; + } + return signatureAttributeString; } + /** + * @return Name of object, i.e., method name or field name + */ + public final String getName() { + return constant_pool.getConstantUtf8(name_index).getBytes(); + } /** * @return Index in constant pool of object's name. @@ -169,15 +220,13 @@ public final int getNameIndex() { return name_index; } - /** - * @param name_index Index in constant pool of object's name. + * @return String representation of object's type signature (java style) */ - public final void setNameIndex( final int name_index ) { - this.name_index = name_index; + public final String getSignature() { + return constant_pool.getConstantUtf8(signature_index).getBytes(); } - /** * @return Index in constant pool of field signature. */ @@ -185,96 +234,32 @@ public final int getSignatureIndex() { return signature_index; } - - /** - * @param signature_index Index in constant pool of field signature. - */ - public final void setSignatureIndex( final int signature_index ) { - this.signature_index = signature_index; - } - - /** - * @return Name of object, i.e., method name or field name - */ - public final String getName() { - ConstantUtf8 c; - c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8); - return c.getBytes(); - } - - - /** - * @return String representation of object's type signature (java style) + * @param attributes Collection of object attributes. */ - public final String getSignature() { - ConstantUtf8 c; - c = (ConstantUtf8) constant_pool.getConstant(signature_index, Const.CONSTANT_Utf8); - return c.getBytes(); + public final void setAttributes(final Attribute[] attributes) { + this.attributes = attributes; + this.attributes_count = attributes != null ? attributes.length : 0; // init deprecated field } - /** - * @return deep copy of this field + * @param constantPool Constant pool to be used for this object. */ - protected FieldOrMethod copy_( final ConstantPool _constant_pool ) { - FieldOrMethod c = null; - - try { - c = (FieldOrMethod)clone(); - } catch(final CloneNotSupportedException e) { - // ignored, but will cause NPE ... - } - - c.constant_pool = constant_pool; - c.attributes = new Attribute[attributes.length]; - c.attributes_count = attributes_count; // init deprecated field - - for (int i = 0; i < attributes.length; i++) { - c.attributes[i] = attributes[i].copy(constant_pool); - } - - return c; + public final void setConstantPool(final ConstantPool constantPool) { + this.constant_pool = constantPool; } /** - * @return Annotations on the field or method - * @since 6.0 + * @param nameIndex Index in constant pool of object's name. */ - public AnnotationEntry[] getAnnotationEntries() { - if (annotationEntries == null) { - annotationEntries = AnnotationEntry.createAnnotationEntries(getAttributes()); - } - - return annotationEntries; + public final void setNameIndex(final int nameIndex) { + this.name_index = nameIndex; } /** - * Hunts for a signature attribute on the member and returns its contents. - * So where the 'regular' signature may be (Ljava/util/Vector;)V the - * signature attribute may in fact say - * 'Ljava/lang/Vector<Ljava/lang/String>;' Coded for performance - - * searches for the attribute only when requested - only searches for it - * once. - * - * @since 6.0 + * @param signatureIndex Index in constant pool of field signature. */ - public final String getGenericSignature() - { - if (!searchedForSignatureAttribute) - { - boolean found = false; - for (int i = 0; !found && i < attributes.length; i++) - { - if (attributes[i] instanceof Signature) - { - signatureAttributeString = ((Signature) attributes[i]) - .getSignature(); - found = true; - } - } - searchedForSignatureAttribute = true; - } - return signatureAttributeString; + public final void setSignatureIndex(final int signatureIndex) { + this.signature_index = signatureIndex; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java index e7fbbe02b0f..d77582815b7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java @@ -28,9 +28,8 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class represents a inner class attribute, i.e., the class - * indices of the inner and outer classes, the name and the attributes - * of the inner class. + * This class represents a inner class attribute, i.e., the class indices of the inner and outer classes, the name and + * the attributes of the inner class. * * @see InnerClasses */ @@ -41,69 +40,74 @@ public final class InnerClass implements Cloneable, Node { private int innerNameIndex; private int innerAccessFlags; - - /** - * Initialize from another object. - */ - public InnerClass(final InnerClass c) { - this(c.getInnerClassIndex(), c.getOuterClassIndex(), c.getInnerNameIndex(), c - .getInnerAccessFlags()); - } - - /** * Construct object from file stream. + * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ InnerClass(final DataInput file) throws IOException { - this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file - .readUnsignedShort()); + this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort()); } + /** + * Initialize from another object. + * + * @param c Source to copy. + */ + public InnerClass(final InnerClass c) { + this(c.getInnerClassIndex(), c.getOuterClassIndex(), c.getInnerNameIndex(), c.getInnerAccessFlags()); + } /** * @param innerClassIndex Class index in constant pool of inner class * @param outerClassIndex Class index in constant pool of outer class - * @param innerNameIndex Name index in constant pool of inner class + * @param innerNameIndex Name index in constant pool of inner class * @param innerAccessFlags Access flags of inner class */ - public InnerClass(final int innerClassIndex, final int outerClassIndex, final int innerNameIndex, - final int innerAccessFlags) { + public InnerClass(final int innerClassIndex, final int outerClassIndex, final int innerNameIndex, final int innerAccessFlags) { this.innerClassIndex = innerClassIndex; this.outerClassIndex = outerClassIndex; this.innerNameIndex = innerNameIndex; this.innerAccessFlags = innerAccessFlags; } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitInnerClass(this); } + /** + * @return deep copy of this object + */ + public InnerClass copy() { + try { + return (InnerClass) clone(); + } catch (final CloneNotSupportedException e) { + // TODO should this throw? + } + return null; + } /** * Dump inner class attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeShort(innerClassIndex); file.writeShort(outerClassIndex); file.writeShort(innerNameIndex); file.writeShort(innerAccessFlags); } - /** * @return access flags of inner class. */ @@ -111,7 +115,6 @@ public int getInnerAccessFlags() { return innerAccessFlags; } - /** * @return class index of inner class. */ @@ -119,7 +122,6 @@ public int getInnerClassIndex() { return innerClassIndex; } - /** * @return name index of inner class. */ @@ -127,7 +129,6 @@ public int getInnerNameIndex() { return innerNameIndex; } - /** * @return class index of outer class. */ @@ -135,86 +136,63 @@ public int getOuterClassIndex() { return outerClassIndex; } - /** * @param innerAccessFlags access flags for this inner class */ - public void setInnerAccessFlags( final int innerAccessFlags ) { + public void setInnerAccessFlags(final int innerAccessFlags) { this.innerAccessFlags = innerAccessFlags; } - /** * @param innerClassIndex index into the constant pool for this class */ - public void setInnerClassIndex( final int innerClassIndex ) { + public void setInnerClassIndex(final int innerClassIndex) { this.innerClassIndex = innerClassIndex; } - /** * @param innerNameIndex index into the constant pool for this class's name */ - public void setInnerNameIndex( final int innerNameIndex ) { // TODO unused + public void setInnerNameIndex(final int innerNameIndex) { // TODO unused this.innerNameIndex = innerNameIndex; } - /** * @param outerClassIndex index into the constant pool for the owning class */ - public void setOuterClassIndex( final int outerClassIndex ) { // TODO unused + public void setOuterClassIndex(final int outerClassIndex) { // TODO unused this.outerClassIndex = outerClassIndex; } - /** * @return String representation. */ @Override public String toString() { - return "InnerClass(" + innerClassIndex + ", " + outerClassIndex + ", " - + innerNameIndex + ", " + innerAccessFlags + ")"; + return "InnerClass(" + innerClassIndex + ", " + outerClassIndex + ", " + innerNameIndex + ", " + innerAccessFlags + ")"; } - /** * @return Resolved string representation */ - public String toString( final ConstantPool constantPool ) { - String outer_class_name; - String inner_name; - String inner_class_name = constantPool.getConstantString(innerClassIndex, - Const.CONSTANT_Class); - inner_class_name = Utility.compactClassName(inner_class_name, false); + public String toString(final ConstantPool constantPool) { + String outerClassName; + String innerName; + String innerClassName = constantPool.getConstantString(innerClassIndex, Const.CONSTANT_Class); + innerClassName = Utility.compactClassName(innerClassName, false); if (outerClassIndex != 0) { - outer_class_name = constantPool.getConstantString(outerClassIndex, - Const.CONSTANT_Class); - outer_class_name = " of class " + Utility.compactClassName(outer_class_name, false); + outerClassName = constantPool.getConstantString(outerClassIndex, Const.CONSTANT_Class); + outerClassName = " of class " + Utility.compactClassName(outerClassName, false); } else { - outer_class_name = ""; + outerClassName = ""; } if (innerNameIndex != 0) { - inner_name = ((ConstantUtf8) constantPool.getConstant(innerNameIndex, - Const.CONSTANT_Utf8)).getBytes(); + innerName = constantPool.getConstantUtf8(innerNameIndex).getBytes(); } else { - inner_name = "(anonymous)"; + innerName = "(anonymous)"; } String access = Utility.accessToString(innerAccessFlags, true); - access = access.isEmpty() ? "" : (access + " "); - return " " + access + inner_name + "=class " + inner_class_name + outer_class_name; - } - - - /** - * @return deep copy of this object - */ - public InnerClass copy() { - try { - return (InnerClass) clone(); - } catch (final CloneNotSupportedException e) { - // TODO should this throw? - } - return null; + access = access.isEmpty() ? "" : access + " "; + return " " + access + innerName + "=class " + innerClassName + outerClassName; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java index 567972f0242..2295ca5c625 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java @@ -24,93 +24,107 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.stream.Stream; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class is derived from Attribute and denotes that this class - * is an Inner class of another. - * to the source file of this class. - * It is instantiated from the Attribute.readAttribute() method. + * This class is derived from Attribute and denotes that this class is an Inner class of another. to the source + * file of this class. It is instantiated from the Attribute.readAttribute() method. * - * @see Attribute + * @see Attribute */ -public final class InnerClasses extends Attribute { - - private InnerClass[] innerClasses; - +public final class InnerClasses extends Attribute implements Iterable { /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. + * Empty array. */ - public InnerClasses(final InnerClasses c) { - this(c.getNameIndex(), c.getLength(), c.getInnerClasses(), c.getConstantPool()); - } + private static final InnerClass[] EMPTY_INNER_CLASSE_ARRAY = {}; + private InnerClass[] innerClasses; /** - * @param name_index Index in constant pool to CONSTANT_Utf8 - * @param length Content length in bytes - * @param innerClasses array of inner classes attributes - * @param constant_pool Array of constants + * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a + * physical copy. + * + * @param c Source to copy. */ - public InnerClasses(final int name_index, final int length, final InnerClass[] innerClasses, - final ConstantPool constant_pool) { - super(Const.ATTR_INNER_CLASSES, name_index, length, constant_pool); - this.innerClasses = innerClasses != null ? innerClasses : new InnerClass[0]; + public InnerClasses(final InnerClasses c) { + this(c.getNameIndex(), c.getLength(), c.getInnerClasses(), c.getConstantPool()); } - /** * Construct object from input stream. * - * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - InnerClasses(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) - throws IOException { - this(name_index, length, (InnerClass[]) null, constant_pool); - final int number_of_classes = input.readUnsignedShort(); - innerClasses = new InnerClass[number_of_classes]; - for (int i = 0; i < number_of_classes; i++) { + InnerClasses(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, (InnerClass[]) null, constantPool); + final int classCount = input.readUnsignedShort(); + innerClasses = new InnerClass[classCount]; + for (int i = 0; i < classCount; i++) { innerClasses[i] = new InnerClass(input); } } + /** + * @param nameIndex Index in constant pool to CONSTANT_Utf8 + * @param length Content length in bytes + * @param innerClasses array of inner classes attributes + * @param constantPool Array of constants + */ + public InnerClasses(final int nameIndex, final int length, final InnerClass[] innerClasses, final ConstantPool constantPool) { + super(Const.ATTR_INNER_CLASSES, nameIndex, length, constantPool); + this.innerClasses = innerClasses != null ? innerClasses : EMPTY_INNER_CLASSE_ARRAY; + Args.requireU2(this.innerClasses.length, "innerClasses.length"); + } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitInnerClasses(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + // TODO this could be recoded to use a lower level constructor after creating a copy of the inner classes + final InnerClasses c = (InnerClasses) clone(); + c.innerClasses = new InnerClass[innerClasses.length]; + Arrays.setAll(c.innerClasses, i -> innerClasses[i].copy()); + c.setConstantPool(constantPool); + return c; + } /** * Dump source file attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(innerClasses.length); - for (final InnerClass inner_class : innerClasses) { - inner_class.dump(file); + for (final InnerClass innerClass : innerClasses) { + innerClass.dump(file); } } - /** * @return array of inner class "records" */ @@ -118,15 +132,18 @@ public InnerClass[] getInnerClasses() { return innerClasses; } + @Override + public Iterator iterator() { + return Stream.of(innerClasses).iterator(); + } /** * @param innerClasses the array of inner classes */ - public void setInnerClasses( final InnerClass[] innerClasses ) { - this.innerClasses = innerClasses != null ? innerClasses : new InnerClass[0]; + public void setInnerClasses(final InnerClass[] innerClasses) { + this.innerClasses = innerClasses != null ? innerClasses : EMPTY_INNER_CLASSE_ARRAY; } - /** * @return String representation. */ @@ -136,25 +153,9 @@ public String toString() { buf.append("InnerClasses("); buf.append(innerClasses.length); buf.append("):\n"); - for (final InnerClass inner_class : innerClasses) { - buf.append(inner_class.toString(super.getConstantPool())).append("\n"); + for (final InnerClass innerClass : innerClasses) { + buf.append(innerClass.toString(super.getConstantPool())).append("\n"); } - return buf.substring(0, buf.length()-1); // remove the last newline - } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - // TODO this could be recoded to use a lower level constructor after creating a copy of the inner classes - final InnerClasses c = (InnerClasses) clone(); - c.innerClasses = new InnerClass[innerClasses.length]; - for (int i = 0; i < innerClasses.length; i++) { - c.innerClasses[i] = innerClasses[i].copy(); - } - c.setConstantPool(_constant_pool); - return c; + return buf.substring(0, buf.length() - 1); // remove the last newline } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java index 052059fba0b..d6c4cfa6a07 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -26,10 +26,11 @@ import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; -import java.util.Objects; -import java.util.StringTokenizer; +import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.Set; +import java.util.StringTokenizer; import java.util.TreeSet; import com.sun.org.apache.bcel.internal.Const; @@ -39,20 +40,74 @@ import com.sun.org.apache.bcel.internal.util.SyntheticRepository; /** - * Represents a Java class, i.e., the data structures, constant pool, - * fields, methods and commands contained in a Java .class file. - * See JVM specification for details. - * The intent of this class is to represent a parsed or otherwise existing - * class file. Those interested in programatically generating classes - * should see the ClassGen class. - + * Represents a Java class, i.e., the data structures, constant pool, fields, methods and commands contained in a Java + * .class file. See JVM specification for details. The intent of + * this class is to represent a parsed or otherwise existing class file. Those interested in programmatically generating + * classes should see the ClassGen class. + * * @see com.sun.org.apache.bcel.internal.generic.ClassGen - * @LastModified: May 2021 + * @LastModified: Feb 2023 */ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparable { + /** + * The standard class file extension. + * + * @since 6.7.0 + */ + public static final String EXTENSION = ".class"; + + /** + * Empty array. + * + * @since 6.6.0 + */ + public static final JavaClass[] EMPTY_ARRAY = {}; + + public static final byte HEAP = 1; + public static final byte FILE = 2; + public static final byte ZIP = 3; + private static BCELComparator bcelComparator = new BCELComparator() { + + @Override + public boolean equals(final Object o1, final Object o2) { + final JavaClass THIS = (JavaClass) o1; + final JavaClass THAT = (JavaClass) o2; + return Objects.equals(THIS.getClassName(), THAT.getClassName()); + } + + @Override + public int hashCode(final Object o) { + final JavaClass THIS = (JavaClass) o; + return THIS.getClassName().hashCode(); + } + }; + + /** + * @return Comparison strategy object + */ + public static BCELComparator getComparator() { + return bcelComparator; + } + + private static String indent(final Object obj) { + final StringTokenizer tokenizer = new StringTokenizer(obj.toString(), "\n"); + final StringBuilder buf = new StringBuilder(); + while (tokenizer.hasMoreTokens()) { + buf.append("\t").append(tokenizer.nextToken()).append("\n"); + } + return buf.toString(); + } + + /** + * @param comparator Comparison strategy object + */ + public static void setComparator(final BCELComparator comparator) { + bcelComparator = comparator; + } + private String fileName; - private String packageName; + private final String packageName; private String sourceFileName = ""; private int classNameIndex; private int superclassNameIndex; @@ -66,52 +121,52 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl private Field[] fields; // Fields, i.e., variables of class private Method[] methods; // methods defined in the class private Attribute[] attributes; // attributes defined in the class - private AnnotationEntry[] annotations; // annotations defined on the class + + private AnnotationEntry[] annotations; // annotations defined on the class private byte source = HEAP; // Generated in memory - private boolean isAnonymous = false; - private boolean isNested = false; - private boolean computedNestedTypeStatus = false; - public static final byte HEAP = 1; - public static final byte FILE = 2; - public static final byte ZIP = 3; - private static final boolean debug = false; - private static BCELComparator bcelComparator = new BCELComparator() { + private boolean isAnonymous; - @Override - public boolean equals( final Object o1, final Object o2 ) { - final JavaClass THIS = (JavaClass) o1; - final JavaClass THAT = (JavaClass) o2; - return Objects.equals(THIS.getClassName(), THAT.getClassName()); - } + private boolean isNested; + private boolean computedNestedTypeStatus; - @Override - public int hashCode( final Object o ) { - final JavaClass THIS = (JavaClass) o; - return THIS.getClassName().hashCode(); - } - }; /** - * In cases where we go ahead and create something, - * use the default SyntheticRepository, because we - * don't know any better. + * In cases where we go ahead and create something, use the default SyntheticRepository, because we don't know any + * better. */ - private transient com.sun.org.apache.bcel.internal.util.Repository repository - = SyntheticRepository.getInstance(); + private transient com.sun.org.apache.bcel.internal.util.Repository repository = SyntheticRepository.getInstance(); + /** + * Constructor gets all contents as arguments. + * + * @param classNameIndex Class name + * @param superclassNameIndex Superclass name + * @param fileName File name + * @param major Major compiler version + * @param minor Minor compiler version + * @param accessFlags Access rights defined by bit flags + * @param constantPool Array of constants + * @param interfaces Implemented interfaces + * @param fields Class fields + * @param methods Class methods + * @param attributes Class attributes + */ + public JavaClass(final int classNameIndex, final int superclassNameIndex, final String fileName, final int major, final int minor, final int accessFlags, + final ConstantPool constantPool, final int[] interfaces, final Field[] fields, final Method[] methods, final Attribute[] attributes) { + this(classNameIndex, superclassNameIndex, fileName, major, minor, accessFlags, constantPool, interfaces, fields, methods, attributes, HEAP); + } /** * Constructor gets all contents as arguments. * - * @param classNameIndex Index into constant pool referencing a - * ConstantClass that represents this class. - * @param superclassNameIndex Index into constant pool referencing a - * ConstantClass that represents this class's superclass. + * @param classNameIndex Index into constant pool referencing a ConstantClass that represents this class. + * @param superclassNameIndex Index into constant pool referencing a ConstantClass that represents this class's + * superclass. * @param fileName File name * @param major Major compiler version * @param minor Minor compiler version - * @param access_flags Access rights defined by bit flags + * @param accessFlags Access rights defined by bit flags * @param constantPool Array of constants * @param interfaces Implemented interfaces * @param fields Class fields @@ -119,22 +174,20 @@ public int hashCode( final Object o ) { * @param attributes Class attributes * @param source Read from file or generated in memory? */ - public JavaClass(final int classNameIndex, final int superclassNameIndex, - final String fileName, final int major, final int minor, final int access_flags, - final ConstantPool constantPool, int[] interfaces, Field[] fields, - Method[] methods, Attribute[] attributes, final byte source) { - super(access_flags); + public JavaClass(final int classNameIndex, final int superclassNameIndex, final String fileName, final int major, final int minor, final int accessFlags, + final ConstantPool constantPool, int[] interfaces, Field[] fields, Method[] methods, Attribute[] attributes, final byte source) { + super(accessFlags); if (interfaces == null) { - interfaces = new int[0]; + interfaces = Const.EMPTY_INT_ARRAY; } if (attributes == null) { - attributes = new Attribute[0]; + attributes = Attribute.EMPTY_ARRAY; } if (fields == null) { - fields = new Field[0]; + fields = Field.EMPTY_FIELD_ARRAY; } if (methods == null) { - methods = new Method[0]; + methods = Method.EMPTY_METHOD_ARRAY; } this.classNameIndex = classNameIndex; this.superclassNameIndex = superclassNameIndex; @@ -154,9 +207,9 @@ public JavaClass(final int classNameIndex, final int superclassNameIndex, break; } } - /* According to the specification the following entries must be of type - * `ConstantClass' but we check that anyway via the - * `ConstPool.getConstant' method. + /* + * According to the specification the following entries must be of type 'ConstantClass' but we check that anyway via the + * 'ConstPool.getConstant' method. */ className = constantPool.getConstantString(classNameIndex, Const.CONSTANT_Class); className = Utility.compactClassName(className, false); @@ -168,8 +221,7 @@ public JavaClass(final int classNameIndex, final int superclassNameIndex, } if (superclassNameIndex > 0) { // May be zero -> class is java.lang.Object - superclassName = constantPool.getConstantString(superclassNameIndex, - Const.CONSTANT_Class); + superclassName = constantPool.getConstantString(superclassNameIndex, Const.CONSTANT_Class); superclassName = Utility.compactClassName(superclassName, false); } else { superclassName = "java.lang.Object"; @@ -181,125 +233,80 @@ public JavaClass(final int classNameIndex, final int superclassNameIndex, } } - /** - * Constructor gets all contents as arguments. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * - * @param classNameIndex Class name - * @param superclassNameIndex Superclass name - * @param fileName File name - * @param major Major compiler version - * @param minor Minor compiler version - * @param access_flags Access rights defined by bit flags - * @param constantPool Array of constants - * @param interfaces Implemented interfaces - * @param fields Class fields - * @param methods Class methods - * @param attributes Class attributes + * @param v Visitor object */ - public JavaClass(final int classNameIndex, final int superclassNameIndex, - final String fileName, final int major, final int minor, final int access_flags, - final ConstantPool constantPool, final int[] interfaces, final Field[] fields, - final Method[] methods, final Attribute[] attributes) { - this(classNameIndex, superclassNameIndex, fileName, major, minor, access_flags, - constantPool, interfaces, fields, methods, attributes, HEAP); + @Override + public void accept(final Visitor v) { + v.visitJavaClass(this); } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Return the natural ordering of two JavaClasses. This ordering is based on the class name * - * @param v Visitor object + * @since 6.0 */ @Override - public void accept( final Visitor v ) { - v.visitJavaClass(this); + public int compareTo(final JavaClass obj) { + return getClassName().compareTo(obj.getClassName()); } - - /* Print debug information depending on `JavaClass.debug' - */ - static void Debug( final String str ) { - if (debug) { - System.out.println(str); + private void computeNestedTypeStatus() { + if (computedNestedTypeStatus) { + return; } - } - - - /** - * Dump class to a file. - * - * @param file Output file - * @throws IOException - */ - public void dump(final File file) throws IOException { - final String parent = file.getParent(); - if (parent != null) { - final File dir = new File(parent); - if (!dir.mkdirs()) { // either was not created or already existed - if (!dir.isDirectory()) { - throw new IOException("Could not create the directory " + dir); - } + for (final Attribute attribute : this.attributes) { + if (attribute instanceof InnerClasses) { + ((InnerClasses) attribute).forEach(innerClass -> { + boolean innerClassAttributeRefersToMe = false; + String innerClassName = constantPool.getConstantString(innerClass.getInnerClassIndex(), Const.CONSTANT_Class); + innerClassName = Utility.compactClassName(innerClassName, false); + if (innerClassName.equals(getClassName())) { + innerClassAttributeRefersToMe = true; + } + if (innerClassAttributeRefersToMe) { + this.isNested = true; + if (innerClass.getInnerNameIndex() == 0) { + this.isAnonymous = true; + } + } + }); } } - try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(file))) { - dump(dos); - } - } - - - /** - * Dump class to a file named fileName. - * - * @param _file_name Output file name - * @throws IOException - */ - public void dump( final String _file_name ) throws IOException { - dump(new File(_file_name)); + this.computedNestedTypeStatus = true; } - /** - * @return class in binary format + * @return deep copy of this class */ - public byte[] getBytes() { - final ByteArrayOutputStream s = new ByteArrayOutputStream(); - final DataOutputStream ds = new DataOutputStream(s); + public JavaClass copy() { try { - dump(ds); - } catch (final IOException e) { - System.err.println("Error dumping class: " + e.getMessage()); - } finally { - try { - ds.close(); - } catch (final IOException e2) { - System.err.println("Error dumping class: " + e2.getMessage()); - } + final JavaClass c = (JavaClass) clone(); + c.constantPool = constantPool.copy(); + c.interfaces = interfaces.clone(); + c.interfaceNames = interfaceNames.clone(); + c.fields = new Field[fields.length]; + Arrays.setAll(c.fields, i -> fields[i].copy(c.constantPool)); + c.methods = new Method[methods.length]; + Arrays.setAll(c.methods, i -> methods[i].copy(c.constantPool)); + c.attributes = new Attribute[attributes.length]; + Arrays.setAll(c.attributes, i -> attributes[i].copy(c.constantPool)); + return c; + } catch (final CloneNotSupportedException e) { + return null; } - return s.toByteArray(); } - - /** - * Dump Java class to output stream in binary format. - * - * @param file Output stream - * @throws IOException - */ - public void dump( final OutputStream file ) throws IOException { - dump(new DataOutputStream(file)); - } - - /** * Dump Java class to output stream in binary format. * * @param file Output stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeInt(Const.JVM_CLASSFILE_MAGIC); file.writeShort(minor); file.writeShort(major); @@ -330,12 +337,79 @@ public void dump( final DataOutputStream file ) throws IOException { file.flush(); } + /** + * Dump class to a file. + * + * @param file Output file + * @throws IOException if an I/O error occurs. + */ + public void dump(final File file) throws IOException { + final String parent = file.getParent(); + if (parent != null) { + final File dir = new File(parent); + if (!dir.mkdirs() && !dir.isDirectory()) { + throw new IOException("Could not create the directory " + dir); + } + } + try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(file))) { + dump(dos); + } + } + + /** + * Dump Java class to output stream in binary format. + * + * @param file Output stream + * @throws IOException if an I/O error occurs. + */ + public void dump(final OutputStream file) throws IOException { + dump(new DataOutputStream(file)); + } + + /** + * Dump class to a file named fileName. + * + * @param fileName Output file name + * @throws IOException if an I/O error occurs. + */ + public void dump(final String fileName) throws IOException { + dump(new File(fileName)); + } /** - * @return Attributes of the class. + * Return value as defined by given BCELComparator strategy. By default two JavaClass objects are said to be equal when + * their class names are equal. + * + * @see Object#equals(Object) */ - public Attribute[] getAttributes() { - return attributes; + @Override + public boolean equals(final Object obj) { + return bcelComparator.equals(this, obj); + } + + /** + * Get all interfaces implemented by this JavaClass (transitively). + * + * @throws ClassNotFoundException if any of the class's superclasses or interfaces can't be found. + */ + public JavaClass[] getAllInterfaces() throws ClassNotFoundException { + final ClassQueue queue = new ClassQueue(); + final Set allInterfaces = new TreeSet<>(); + queue.enqueue(this); + while (!queue.empty()) { + final JavaClass clazz = queue.dequeue(); + final JavaClass souper = clazz.getSuperClass(); + final JavaClass[] interfaces = clazz.getInterfaces(); + if (clazz.isInterface()) { + allInterfaces.add(clazz); + } else if (souper != null) { + queue.enqueue(souper); + } + for (final JavaClass iface : interfaces) { + queue.enqueue(iface); + } + } + return allInterfaces.toArray(JavaClass.EMPTY_ARRAY); } /** @@ -351,20 +425,31 @@ public AnnotationEntry[] getAnnotationEntries() { } /** - * @return Class name. + * @return Attributes of the class. */ - public String getClassName() { - return className; + public Attribute[] getAttributes() { + return attributes; } - /** - * @return Package name. + * @return class in binary format */ - public String getPackageName() { - return packageName; + public byte[] getBytes() { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (DataOutputStream dos = new DataOutputStream(baos)) { + dump(dos); + } catch (final IOException e) { + e.printStackTrace(); + } + return baos.toByteArray(); } + /** + * @return Class name. + */ + public String getClassName() { + return className; + } /** * @return Class name index. @@ -373,7 +458,6 @@ public int getClassNameIndex() { return classNameIndex; } - /** * @return Constant pool. */ @@ -381,17 +465,14 @@ public ConstantPool getConstantPool() { return constantPool; } - /** - * @return Fields, i.e., variables of the class. Like the JVM spec - * mandates for the classfile format, these fields are those specific to - * this class, and not those of the superclass or superinterfaces. + * @return Fields, i.e., variables of the class. Like the JVM spec mandates for the classfile format, these fields are + * those specific to this class, and not those of the superclass or superinterfaces. */ public Field[] getFields() { return fields; } - /** * @return File name of class, aka SourceFile attribute value */ @@ -399,6 +480,12 @@ public String getFileName() { return fileName; } + /** + * @return Indices in constant pool of implemented interfaces. + */ + public int[] getInterfaceIndices() { + return interfaces; + } /** * @return Names of implemented interfaces. @@ -407,15 +494,20 @@ public String[] getInterfaceNames() { return interfaceNames; } - /** - * @return Indices in constant pool of implemented interfaces. + * Get interfaces directly implemented by this JavaClass. + * + * @throws ClassNotFoundException if any of the class's interfaces can't be found. */ - public int[] getInterfaceIndices() { - return interfaces; + public JavaClass[] getInterfaces() throws ClassNotFoundException { + final String[] interfaces = getInterfaceNames(); + final JavaClass[] classes = new JavaClass[interfaces.length]; + for (int i = 0; i < interfaces.length; i++) { + classes[i] = repository.loadClass(interfaces[i]); + } + return classes; } - /** * @return Major number of class file version. */ @@ -423,29 +515,24 @@ public int getMajor() { return major; } - /** - * @return Methods of the class. + * @return A {@link Method} corresponding to java.lang.reflect.Method if any */ - public Method[] getMethods() { - return methods; - } - - - /** - * @return A {@link Method} corresponding to - * java.lang.reflect.Method if any - */ - public Method getMethod( final java.lang.reflect.Method m ) { + public Method getMethod(final java.lang.reflect.Method m) { for (final Method method : methods) { - if (m.getName().equals(method.getName()) && (m.getModifiers() == method.getModifiers()) - && Type.getSignature(m).equals(method.getSignature())) { + if (m.getName().equals(method.getName()) && m.getModifiers() == method.getModifiers() && Type.getSignature(m).equals(method.getSignature())) { return method; } } return null; } + /** + * @return Methods of the class. + */ + public Method[] getMethods() { + return methods; + } /** * @return Minor number of class file version. @@ -454,19 +541,78 @@ public int getMinor() { return minor; } + /** + * @return Package name. + */ + public String getPackageName() { + return packageName; + } + + /** + * Gets the ClassRepository which holds its definition. By default this is the same as + * SyntheticRepository.getInstance(); + */ + public com.sun.org.apache.bcel.internal.util.Repository getRepository() { + return repository; + } + + /** + * @return returns either HEAP (generated), FILE, or ZIP + */ + public final byte getSource() { + return source; + } /** - * @return sbsolute path to file where this class was read from + * @return file name where this class was read from */ public String getSourceFileName() { return sourceFileName; } + /** + * Gets the source file path including the package path. + * + * @return path to original source file of parsed class, relative to original source directory. + * @since 6.7.0 + */ + public String getSourceFilePath() { + final StringBuilder outFileName = new StringBuilder(); + if (!packageName.isEmpty()) { + outFileName.append(Utility.packageToPath(packageName)); + outFileName.append('/'); + } + outFileName.append(sourceFileName); + return outFileName.toString(); + } /** - * returns the super class name of this class. In the case that this class is - * java.lang.Object, it will return itself (java.lang.Object). This is probably incorrect - * but isn't fixed at this time to not break existing clients. + * @return the superclass for this JavaClass object, or null if this is java.lang.Object + * @throws ClassNotFoundException if the superclass can't be found + */ + public JavaClass getSuperClass() throws ClassNotFoundException { + if ("java.lang.Object".equals(getClassName())) { + return null; + } + return repository.loadClass(getSuperclassName()); + } + + /** + * @return list of super classes of this class in ascending order, i.e., java.lang.Object is always the last element + * @throws ClassNotFoundException if any of the superclasses can't be found + */ + public JavaClass[] getSuperClasses() throws ClassNotFoundException { + JavaClass clazz = this; + final List allSuperClasses = new ArrayList<>(); + for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) { + allSuperClasses.add(clazz); + } + return allSuperClasses.toArray(JavaClass.EMPTY_ARRAY); + } + + /** + * returns the super class name of this class. In the case that this class is java.lang.Object, it will return itself + * (java.lang.Object). This is probably incorrect but isn't fixed at this time to not break existing clients. * * @return Superclass name. */ @@ -474,7 +620,6 @@ public String getSuperclassName() { return superclassName; } - /** * @return Class name index. */ @@ -482,129 +627,196 @@ public int getSuperclassNameIndex() { return superclassNameIndex; } + /** + * Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name. + * + * @see Object#hashCode() + */ + @Override + public int hashCode() { + return bcelComparator.hashCode(this); + } + + /** + * @return true, if this class is an implementation of interface inter + * @throws ClassNotFoundException if superclasses or superinterfaces of this class can't be found + */ + public boolean implementationOf(final JavaClass inter) throws ClassNotFoundException { + if (!inter.isInterface()) { + throw new IllegalArgumentException(inter.getClassName() + " is no interface"); + } + if (this.equals(inter)) { + return true; + } + final JavaClass[] superInterfaces = getAllInterfaces(); + for (final JavaClass superInterface : superInterfaces) { + if (superInterface.equals(inter)) { + return true; + } + } + return false; + } + + /** + * Equivalent to runtime "instanceof" operator. + * + * @return true if this JavaClass is derived from the super class + * @throws ClassNotFoundException if superclasses or superinterfaces of this object can't be found + */ + public final boolean instanceOf(final JavaClass superclass) throws ClassNotFoundException { + if (this.equals(superclass)) { + return true; + } + for (final JavaClass clazz : getSuperClasses()) { + if (clazz.equals(superclass)) { + return true; + } + } + if (superclass.isInterface()) { + return implementationOf(superclass); + } + return false; + } + + /** + * @since 6.0 + */ + public final boolean isAnonymous() { + computeNestedTypeStatus(); + return this.isAnonymous; + } + + public final boolean isClass() { + return (super.getAccessFlags() & Const.ACC_INTERFACE) == 0; + } + + /** + * @since 6.0 + */ + public final boolean isNested() { + computeNestedTypeStatus(); + return this.isNested; + } + + public final boolean isSuper() { + return (super.getAccessFlags() & Const.ACC_SUPER) != 0; + } + /** * @param attributes . */ - public void setAttributes( final Attribute[] attributes ) { + public void setAttributes(final Attribute[] attributes) { this.attributes = attributes; } - /** * @param className . */ - public void setClassName( final String className ) { + public void setClassName(final String className) { this.className = className; } - /** * @param classNameIndex . */ - public void setClassNameIndex( final int classNameIndex ) { + public void setClassNameIndex(final int classNameIndex) { this.classNameIndex = classNameIndex; } - /** * @param constantPool . */ - public void setConstantPool( final ConstantPool constantPool ) { + public void setConstantPool(final ConstantPool constantPool) { this.constantPool = constantPool; } - /** * @param fields . */ - public void setFields( final Field[] fields ) { + public void setFields(final Field[] fields) { this.fields = fields; } - /** * Set File name of class, aka SourceFile attribute value */ - public void setFileName( final String fileName ) { + public void setFileName(final String fileName) { this.fileName = fileName; } - /** * @param interfaceNames . */ - public void setInterfaceNames( final String[] interfaceNames ) { + public void setInterfaceNames(final String[] interfaceNames) { this.interfaceNames = interfaceNames; } - /** * @param interfaces . */ - public void setInterfaces( final int[] interfaces ) { + public void setInterfaces(final int[] interfaces) { this.interfaces = interfaces; } - /** * @param major . */ - public void setMajor( final int major ) { + public void setMajor(final int major) { this.major = major; } - /** * @param methods . */ - public void setMethods( final Method[] methods ) { + public void setMethods(final Method[] methods) { this.methods = methods; } - /** * @param minor . */ - public void setMinor( final int minor ) { + public void setMinor(final int minor) { this.minor = minor; } + /** + * Sets the ClassRepository which loaded the JavaClass. Should be called immediately after parsing is done. + */ + public void setRepository(final com.sun.org.apache.bcel.internal.util.Repository repository) { // TODO make protected? + this.repository = repository; + } /** * Set absolute path to file this class was read from. */ - public void setSourceFileName( final String sourceFileName ) { + public void setSourceFileName(final String sourceFileName) { this.sourceFileName = sourceFileName; } - /** * @param superclassName . */ - public void setSuperclassName( final String superclassName ) { + public void setSuperclassName(final String superclassName) { this.superclassName = superclassName; } - /** * @param superclassNameIndex . */ - public void setSuperclassNameIndex( final int superclassNameIndex ) { + public void setSuperclassNameIndex(final int superclassNameIndex) { this.superclassNameIndex = superclassNameIndex; } - /** * @return String representing class contents. */ @Override public String toString() { String access = Utility.accessToString(super.getAccessFlags(), true); - access = access.isEmpty() ? "" : (access + " "); + access = access.isEmpty() ? "" : access + " "; final StringBuilder buf = new StringBuilder(128); - buf.append(access).append(Utility.classOrInterface(super.getAccessFlags())).append(" ").append( - className).append(" extends ").append( - Utility.compactClassName(superclassName, false)).append('\n'); + buf.append(access).append(Utility.classOrInterface(super.getAccessFlags())).append(" ").append(className).append(" extends ") + .append(Utility.compactClassName(superclassName, false)).append('\n'); final int size = interfaces.length; if (size > 0) { buf.append("implements\t\t"); @@ -629,7 +841,7 @@ public String toString() { } } final AnnotationEntry[] annotations = getAnnotationEntries(); - if (annotations!=null && annotations.length>0) { + if (annotations != null && annotations.length > 0) { buf.append("\nAnnotation(s):\n"); for (final AnnotationEntry annotation : annotations) { buf.append(indent(annotation)); @@ -649,286 +861,4 @@ public String toString() { } return buf.toString(); } - - - private static String indent( final Object obj ) { - final StringTokenizer tok = new StringTokenizer(obj.toString(), "\n"); - final StringBuilder buf = new StringBuilder(); - while (tok.hasMoreTokens()) { - buf.append("\t").append(tok.nextToken()).append("\n"); - } - return buf.toString(); - } - - - /** - * @return deep copy of this class - */ - public JavaClass copy() { - JavaClass c = null; - try { - c = (JavaClass) clone(); - c.constantPool = constantPool.copy(); - c.interfaces = interfaces.clone(); - c.interfaceNames = interfaceNames.clone(); - c.fields = new Field[fields.length]; - for (int i = 0; i < fields.length; i++) { - c.fields[i] = fields[i].copy(c.constantPool); - } - c.methods = new Method[methods.length]; - for (int i = 0; i < methods.length; i++) { - c.methods[i] = methods[i].copy(c.constantPool); - } - c.attributes = new Attribute[attributes.length]; - for (int i = 0; i < attributes.length; i++) { - c.attributes[i] = attributes[i].copy(c.constantPool); - } - } catch (final CloneNotSupportedException e) { - // TODO should this throw? - } - return c; - } - - - public final boolean isSuper() { - return (super.getAccessFlags() & Const.ACC_SUPER) != 0; - } - - - public final boolean isClass() { - return (super.getAccessFlags() & Const.ACC_INTERFACE) == 0; - } - - /** - * @since 6.0 - */ - public final boolean isAnonymous() { - computeNestedTypeStatus(); - return this.isAnonymous; - } - - /** - * @since 6.0 - */ - public final boolean isNested() { - computeNestedTypeStatus(); - return this.isNested; - } - - private void computeNestedTypeStatus() { - if (computedNestedTypeStatus) { - return; - } - for (final Attribute attribute : this.attributes) { - if (attribute instanceof InnerClasses) { - final InnerClass[] innerClasses = ((InnerClasses) attribute).getInnerClasses(); - for (final InnerClass innerClasse : innerClasses) { - boolean innerClassAttributeRefersToMe = false; - String inner_class_name = constantPool.getConstantString(innerClasse.getInnerClassIndex(), - Const.CONSTANT_Class); - inner_class_name = Utility.compactClassName(inner_class_name, false); - if (inner_class_name.equals(getClassName())) { - innerClassAttributeRefersToMe = true; - } - if (innerClassAttributeRefersToMe) { - this.isNested = true; - if (innerClasse.getInnerNameIndex() == 0) { - this.isAnonymous = true; - } - } - } - } - } - this.computedNestedTypeStatus = true; - } - - - /** @return returns either HEAP (generated), FILE, or ZIP - */ - public final byte getSource() { - return source; - } - - - /********************* New repository functionality *********************/ - /** - * Gets the ClassRepository which holds its definition. By default - * this is the same as SyntheticRepository.getInstance(); - */ - public com.sun.org.apache.bcel.internal.util.Repository getRepository() { - return repository; - } - - - /** - * Sets the ClassRepository which loaded the JavaClass. - * Should be called immediately after parsing is done. - */ - public void setRepository( final com.sun.org.apache.bcel.internal.util.Repository repository ) { // TODO make protected? - this.repository = repository; - } - - - /** Equivalent to runtime "instanceof" operator. - * - * @return true if this JavaClass is derived from the super class - * @throws ClassNotFoundException if superclasses or superinterfaces - * of this object can't be found - */ - public final boolean instanceOf( final JavaClass super_class ) throws ClassNotFoundException { - if (this.equals(super_class)) { - return true; - } - final JavaClass[] super_classes = getSuperClasses(); - for (final JavaClass super_classe : super_classes) { - if (super_classe.equals(super_class)) { - return true; - } - } - if (super_class.isInterface()) { - return implementationOf(super_class); - } - return false; - } - - - /** - * @return true, if this class is an implementation of interface inter - * @throws ClassNotFoundException if superclasses or superinterfaces - * of this class can't be found - */ - public boolean implementationOf( final JavaClass inter ) throws ClassNotFoundException { - if (!inter.isInterface()) { - throw new IllegalArgumentException(inter.getClassName() + " is no interface"); - } - if (this.equals(inter)) { - return true; - } - final JavaClass[] super_interfaces = getAllInterfaces(); - for (final JavaClass super_interface : super_interfaces) { - if (super_interface.equals(inter)) { - return true; - } - } - return false; - } - - - /** - * @return the superclass for this JavaClass object, or null if this - * is java.lang.Object - * @throws ClassNotFoundException if the superclass can't be found - */ - public JavaClass getSuperClass() throws ClassNotFoundException { - if ("java.lang.Object".equals(getClassName())) { - return null; - } - return repository.loadClass(getSuperclassName()); - } - - - /** - * @return list of super classes of this class in ascending order, i.e., - * java.lang.Object is always the last element - * @throws ClassNotFoundException if any of the superclasses can't be found - */ - public JavaClass[] getSuperClasses() throws ClassNotFoundException { - JavaClass clazz = this; - final List allSuperClasses = new ArrayList<>(); - for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) { - allSuperClasses.add(clazz); - } - return allSuperClasses.toArray(new JavaClass[allSuperClasses.size()]); - } - - - /** - * Get interfaces directly implemented by this JavaClass. - */ - public JavaClass[] getInterfaces() throws ClassNotFoundException { - final String[] _interfaces = getInterfaceNames(); - final JavaClass[] classes = new JavaClass[_interfaces.length]; - for (int i = 0; i < _interfaces.length; i++) { - classes[i] = repository.loadClass(_interfaces[i]); - } - return classes; - } - - - /** - * Get all interfaces implemented by this JavaClass (transitively). - */ - public JavaClass[] getAllInterfaces() throws ClassNotFoundException { - final ClassQueue queue = new ClassQueue(); - final Set allInterfaces = new TreeSet<>(); - queue.enqueue(this); - while (!queue.empty()) { - final JavaClass clazz = queue.dequeue(); - final JavaClass souper = clazz.getSuperClass(); - final JavaClass[] _interfaces = clazz.getInterfaces(); - if (clazz.isInterface()) { - allInterfaces.add(clazz); - } else { - if (souper != null) { - queue.enqueue(souper); - } - } - for (final JavaClass _interface : _interfaces) { - queue.enqueue(_interface); - } - } - return allInterfaces.toArray(new JavaClass[allInterfaces.size()]); - } - - - /** - * @return Comparison strategy object - */ - public static BCELComparator getComparator() { - return bcelComparator; - } - - - /** - * @param comparator Comparison strategy object - */ - public static void setComparator( final BCELComparator comparator ) { - bcelComparator = comparator; - } - - - /** - * Return value as defined by given BCELComparator strategy. - * By default two JavaClass objects are said to be equal when - * their class names are equal. - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals( final Object obj ) { - return bcelComparator.equals(this, obj); - } - - - /** - * Return the natural ordering of two JavaClasses. - * This ordering is based on the class name - * @since 6.0 - */ - @Override - public int compareTo( final JavaClass obj ) { - return getClassName().compareTo(obj.getClassName()); - } - - - /** - * Return value as defined by given BCELComparator strategy. - * By default return the hashcode of the class name. - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - return bcelComparator.hashCode(this); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java index f90b88f1cce..4380d04bc06 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java @@ -25,30 +25,23 @@ import java.io.DataOutputStream; import java.io.IOException; +import com.sun.org.apache.bcel.internal.util.Args; + /** - * This class represents a (PC offset, line number) pair, i.e., a line number in - * the source that corresponds to a relative address in the byte code. This - * is used for debugging purposes. + * This class represents a (PC offset, line number) pair, i.e., a line number in the source that corresponds to a + * relative address in the byte code. This is used for debugging purposes. * - * @see LineNumberTable + * @see LineNumberTable */ public final class LineNumber implements Cloneable, Node { + static final LineNumber[] EMPTY_ARRAY = {}; + /** Program Counter (PC) corresponds to line */ - private short startPc; + private int startPc; /** number in source file */ - private short lineNumber; - - /** - * Initialize from another object. - * - * @param c the object to copy - */ - public LineNumber(final LineNumber c) { - this(c.getStartPC(), c.getLineNumber()); - } - + private int lineNumber; /** * Construct object from file stream. @@ -60,29 +53,46 @@ public LineNumber(final LineNumber c) { this(file.readUnsignedShort(), file.readUnsignedShort()); } - /** * @param startPc Program Counter (PC) corresponds to * @param lineNumber line number in source file */ public LineNumber(final int startPc, final int lineNumber) { - this.startPc = (short) startPc; - this.lineNumber = (short)lineNumber; + this.startPc = Args.requireU2(startPc, "startPc"); + this.lineNumber = Args.requireU2(lineNumber, "lineNumber"); } + /** + * Initialize from another object. + * + * @param c the object to copy + */ + public LineNumber(final LineNumber c) { + this(c.getStartPC(), c.getLineNumber()); + } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitLineNumber(this); } + /** + * @return deep copy of this object + */ + public LineNumber copy() { + try { + return (LineNumber) clone(); + } catch (final CloneNotSupportedException e) { + // TODO should this throw? + } + return null; + } /** * Dump line number/pc pair to file stream in binary format. @@ -90,62 +100,44 @@ public void accept( final Visitor v ) { * @param file Output file stream * @throws IOException if an I/O Exception occurs in writeShort */ - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeShort(startPc); file.writeShort(lineNumber); } - /** * @return Corresponding source line */ public int getLineNumber() { - return 0xffff & lineNumber; + return lineNumber & 0xffff; } - /** * @return PC in code */ public int getStartPC() { - return 0xffff & startPc; + return startPc & 0xffff; } - /** * @param lineNumber the source line number */ - public void setLineNumber( final int lineNumber ) { + public void setLineNumber(final int lineNumber) { this.lineNumber = (short) lineNumber; } - /** * @param startPc the pc for this line number */ - public void setStartPC( final int startPc ) { + public void setStartPC(final int startPc) { this.startPc = (short) startPc; } - /** * @return String representation */ @Override public String toString() { - return "LineNumber(" + startPc + ", " + lineNumber + ")"; - } - - - /** - * @return deep copy of this object - */ - public LineNumber copy() { - try { - return (LineNumber) clone(); - } catch (final CloneNotSupportedException e) { - // TODO should this throw? - } - return null; + return "LineNumber(" + getStartPC() + ", " + getLineNumber() + ")"; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java index 7bad272fff3..6251fc514cc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java @@ -19,78 +19,96 @@ */ package com.sun.org.apache.bcel.internal.classfile; -import com.sun.org.apache.bcel.internal.Const; import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.stream.Stream; + +import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; import jdk.xml.internal.SecuritySupport; /** - * This class represents a table of line numbers for debugging - * purposes. This attribute is used by the Code attribute. It - * contains pairs of PCs and line numbers. + * This class represents a table of line numbers for debugging purposes. This attribute is used by the Code + * attribute. It contains pairs of PCs and line numbers. * - * @see Code + * @see Code * @see LineNumber * @LastModified: May 2021 */ -public final class LineNumberTable extends Attribute { +public final class LineNumberTable extends Attribute implements Iterable { private static final int MAX_LINE_LENGTH = 72; private LineNumber[] lineNumberTable; // Table of line/numbers pairs - - /* - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. + /** + * Construct object from input stream. + * + * @param nameIndex Index of name + * @param length Content length in bytes + * @param input Input stream + * @param constantPool Array of constants + * @throws IOException if an I/O Exception occurs in readUnsignedShort */ - public LineNumberTable(final LineNumberTable c) { - this(c.getNameIndex(), c.getLength(), c.getLineNumberTable(), c.getConstantPool()); + LineNumberTable(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, (LineNumber[]) null, constantPool); + final int lineNumberTableLength = input.readUnsignedShort(); + lineNumberTable = new LineNumber[lineNumberTableLength]; + for (int i = 0; i < lineNumberTableLength; i++) { + lineNumberTable[i] = new LineNumber(input); + } } - /* - * @param name_index Index of name + * @param nameIndex Index of name + * * @param length Content length in bytes + * * @param lineNumberTable Table of line/numbers pairs - * @param constant_pool Array of constants + * + * @param constantPool Array of constants */ - public LineNumberTable(final int name_index, final int length, final LineNumber[] line_number_table, - final ConstantPool constant_pool) { - super(Const.ATTR_LINE_NUMBER_TABLE, name_index, length, constant_pool); - this.lineNumberTable = line_number_table; + public LineNumberTable(final int nameIndex, final int length, final LineNumber[] lineNumberTable, final ConstantPool constantPool) { + super(Const.ATTR_LINE_NUMBER_TABLE, nameIndex, length, constantPool); + this.lineNumberTable = lineNumberTable != null ? lineNumberTable : LineNumber.EMPTY_ARRAY; + Args.requireU2(this.lineNumberTable.length, "lineNumberTable.length"); } - /** - * Construct object from input stream. - * @param name_index Index of name - * @param length Content length in bytes - * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException if an I/O Exception occurs in readUnsignedShort + /* + * Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a + * physical copy. */ - LineNumberTable(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) - throws IOException { - this(name_index, length, (LineNumber[]) null, constant_pool); - final int line_number_table_length = input.readUnsignedShort(); - lineNumberTable = new LineNumber[line_number_table_length]; - for (int i = 0; i < line_number_table_length; i++) { - lineNumberTable[i] = new LineNumber(input); - } + public LineNumberTable(final LineNumberTable c) { + this(c.getNameIndex(), c.getLength(), c.getLineNumberTable(), c.getConstantPool()); } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitLineNumberTable(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + // TODO could use the lower level constructor and thereby allow + // lineNumberTable to be made final + final LineNumberTable c = (LineNumberTable) clone(); + c.lineNumberTable = new LineNumber[lineNumberTable.length]; + Arrays.setAll(c.lineNumberTable, i -> lineNumberTable[i].copy()); + c.setConstantPool(constantPool); + return c; + } + /** * Dump line number table attribute to file stream in binary format. * @@ -98,7 +116,7 @@ public void accept( final Visitor v ) { * @throws IOException if an I/O Exception occurs in writeShort */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(lineNumberTable.length); for (final LineNumber lineNumber : lineNumberTable) { @@ -113,98 +131,87 @@ public LineNumber[] getLineNumberTable() { return lineNumberTable; } - /** - * @param lineNumberTable the line number entries for this table - */ - public void setLineNumberTable( final LineNumber[] lineNumberTable ) { - this.lineNumberTable = lineNumberTable; - } - - /** - * @return String representation. - */ - @Override - public String toString() { - final StringBuilder buf = new StringBuilder(); - final StringBuilder line = new StringBuilder(); - - for (int i = 0; i < lineNumberTable.length; i++) { - line.append(lineNumberTable[i].toString()); - if (i < lineNumberTable.length - 1) { - line.append(", "); - } - if ((line.length() > MAX_LINE_LENGTH) && (i < lineNumberTable.length - 1)) { - line.append(SecuritySupport.NEWLINE); - buf.append(line); - line.setLength(0); - } - } - buf.append(line); - return buf.toString(); - } - /** * Map byte code positions to source code lines. * * @param pos byte code offset * @return corresponding line in source code */ - public int getSourceLine( final int pos ) { + public int getSourceLine(final int pos) { int l = 0; int r = lineNumberTable.length - 1; if (r < 0) { return -1; } - int min_index = -1; + int minIndex = -1; int min = -1; - /* Do a binary search since the array is ordered. + /* + * Do a binary search since the array is ordered. */ do { - final int i = (l + r) >>> 1; + final int i = l + r >>> 1; final int j = lineNumberTable[i].getStartPC(); if (j == pos) { return lineNumberTable[i].getLineNumber(); - } else if (pos < j) { + } + if (pos < j) { r = i - 1; } else { l = i + 1; } - /* If exact match can't be found (which is the most common case) - * return the line number that corresponds to the greatest index less - * than pos. + /* + * If exact match can't be found (which is the most common case) return the line number that corresponds to the greatest + * index less than pos. */ if (j < pos && j > min) { min = j; - min_index = i; + minIndex = i; } } while (l <= r); - /* It's possible that we did not find any valid entry for the bytecode - * offset we were looking for. + /* + * It's possible that we did not find any valid entry for the bytecode offset we were looking for. */ - if (min_index < 0) { + if (minIndex < 0) { return -1; } - return lineNumberTable[min_index].getLineNumber(); + return lineNumberTable[minIndex].getLineNumber(); + } + + public int getTableLength() { + return lineNumberTable == null ? 0 : lineNumberTable.length; + } + + @Override + public Iterator iterator() { + return Stream.of(lineNumberTable).iterator(); } /** - * @return deep copy of this attribute + * @param lineNumberTable the line number entries for this table + */ + public void setLineNumberTable(final LineNumber[] lineNumberTable) { + this.lineNumberTable = lineNumberTable; + } + + /** + * @return String representation. */ @Override - public Attribute copy( final ConstantPool _constant_pool ) { - // TODO could use the lower level constructor and thereby allow - // lineNumberTable to be made final - final LineNumberTable c = (LineNumberTable) clone(); - c.lineNumberTable = new LineNumber[lineNumberTable.length]; + public String toString() { + final StringBuilder buf = new StringBuilder(); + final StringBuilder line = new StringBuilder(); for (int i = 0; i < lineNumberTable.length; i++) { - c.lineNumberTable[i] = lineNumberTable[i].copy(); + line.append(lineNumberTable[i].toString()); + if (i < lineNumberTable.length - 1) { + line.append(", "); + } + if (line.length() > MAX_LINE_LENGTH && i < lineNumberTable.length - 1) { + line.append(SecuritySupport.NEWLINE); + buf.append(line); + line.setLength(0); + } } - c.setConstantPool(_constant_pool); - return c; - } - - - public int getTableLength() { - return lineNumberTable == null ? 0 : lineNumberTable.length; + buf.append(line); + return buf.toString(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariable.java index f0605cfebe6..91d99c18288 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariable.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -24,119 +24,129 @@ import java.io.DataOutputStream; import java.io.IOException; -import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class represents a local variable within a method. It contains its - * scope, name, signature and index on the method's frame. It is used both - * to represent an element of the LocalVariableTable as well as an element - * of the LocalVariableTypeTable. The nomenclature used here may be a bit confusing; - * while the two items have the same layout in a class file, a LocalVariableTable - * attribute contains a descriptor_index, not a signatureIndex. The + * This class represents a local variable within a method. It contains its scope, name, signature and index on the + * method's frame. It is used both to represent an element of the LocalVariableTable as well as an element of the + * LocalVariableTypeTable. The nomenclature used here may be a bit confusing; while the two items have the same layout + * in a class file, a LocalVariableTable attribute contains a descriptor_index, not a signatureIndex. The * LocalVariableTypeTable attribute does have a signatureIndex. + * * @see com.sun.org.apache.bcel.internal.classfile.Utility for more details on the difference. * - * @see LocalVariableTable - * @see LocalVariableTypeTable - * @LastModified: May 2021 + * @see LocalVariableTable + * @see LocalVariableTypeTable + * @LastModified: Feb 2023 */ public final class LocalVariable implements Cloneable, Node { - private int startPc; // Range in which the variable is valid + static final LocalVariable[] EMPTY_ARRAY = {}; + + /** Range in which the variable is valid. */ + private int startPc; + private int length; - private int nameIndex; // Index in constant pool of variable name - // Technically, a decscriptor_index for a local variable table entry - // and a signatureIndex for a local variable type table entry. - private int signatureIndex; // Index of variable signature - private int index; /* Variable is index'th local variable on - * this method's frame. - */ - private ConstantPool constantPool; - private int origIndex; // never changes; used to match up with LocalVariableTypeTable entries + /** Index in constant pool of variable name. */ + private int nameIndex; /** - * Initializes from another LocalVariable. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. - * - * @param localVariable Another LocalVariable. + * Technically, a decscriptor_index for a local variable table entry and a signatureIndex for a local variable type table entry. Index of variable signature */ - public LocalVariable(final LocalVariable localVariable) { - this(localVariable.getStartPC(), localVariable.getLength(), localVariable.getNameIndex(), - localVariable.getSignatureIndex(), localVariable.getIndex(), localVariable.getConstantPool()); - this.origIndex = localVariable.getOrigIndex(); - } + private int signatureIndex; + + /* + * Variable is index'th local variable on this method's frame. + */ + private int index; + + private ConstantPool constantPool; + + /** Never changes; used to match up with LocalVariableTypeTable entries. */ + private final int origIndex; /** * Constructs object from file stream. + * * @param file Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ - LocalVariable(final DataInput file, final ConstantPool constant_pool) throws IOException { - this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file - .readUnsignedShort(), file.readUnsignedShort(), constant_pool); + LocalVariable(final DataInput file, final ConstantPool constantPool) throws IOException { + this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), constantPool); } - /** * @param startPc Range in which the variable * @param length ... is valid * @param nameIndex Index in constant pool of variable name * @param signatureIndex Index of variable's signature - * @param index Variable is `index'th local variable on the method's frame + * @param index Variable is 'index'th local variable on the method's frame * @param constantPool Array of constants */ - public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, - final ConstantPool constantPool) { - this.startPc = startPc; - this.length = length; - this.nameIndex = nameIndex; - this.signatureIndex = signatureIndex; - this.index = index; - this.constantPool = constantPool; - this.origIndex = index; + public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool) { + this(startPc, length, nameIndex, signatureIndex, index, constantPool, index); } - /** * @param startPc Range in which the variable * @param length ... is valid * @param nameIndex Index in constant pool of variable name * @param signatureIndex Index of variable's signature - * @param index Variable is `index'th local variable on the method's frame + * @param index Variable is 'index'th local variable on the method's frame * @param constantPool Array of constants - * @param origIndex Variable is `index'th local variable on the method's frame prior to any changes + * @param origIndex Variable is 'index'th local variable on the method's frame prior to any changes */ - public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, - final ConstantPool constantPool, final int origIndex) { - this.startPc = startPc; - this.length = length; - this.nameIndex = nameIndex; - this.signatureIndex = signatureIndex; - this.index = index; + public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool, + final int origIndex) { + this.startPc = Args.requireU2(startPc, "startPc"); + this.length = Args.requireU2(length, "length"); + this.nameIndex = Args.requireU2(nameIndex, "nameIndex"); + this.signatureIndex = Args.requireU2(signatureIndex, "signatureIndex"); + this.index = Args.requireU2(index, "index"); + this.origIndex = Args.requireU2(origIndex, "origIndex"); this.constantPool = constantPool; - this.origIndex = origIndex; } + /** + * Initializes from another LocalVariable. Note that both objects use the same references (shallow copy). Use copy() for + * a physical copy. + * + * @param localVariable Another LocalVariable. + */ + public LocalVariable(final LocalVariable localVariable) { + this(localVariable.getStartPC(), localVariable.getLength(), localVariable.getNameIndex(), localVariable.getSignatureIndex(), localVariable.getIndex(), + localVariable.getConstantPool()); + } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitLocalVariable(this); } + /** + * @return deep copy of this object + */ + public LocalVariable copy() { + try { + return (LocalVariable) clone(); + } catch (final CloneNotSupportedException e) { + // TODO should this throw? + } + return null; + } /** * Dumps local variable to file stream in binary format. * * @param dataOutputStream Output file stream - * @exception IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. * @see java.io.FilterOutputStream#out */ public void dump(final DataOutputStream dataOutputStream) throws IOException { @@ -154,6 +164,12 @@ public ConstantPool getConstantPool() { return constantPool; } + /** + * @return index of register where variable is stored + */ + public int getIndex() { + return index; + } /** * @return Variable is valid within getStartPC() .. getStartPC()+getLength() @@ -162,17 +178,13 @@ public int getLength() { return length; } - /** * @return Variable name. */ public String getName() { - ConstantUtf8 c; - c = (ConstantUtf8) constantPool.getConstant(nameIndex, Const.CONSTANT_Utf8); - return c.getBytes(); + return constantPool.getConstantUtf8(nameIndex).getBytes(); } - /** * @return Index in constant pool of variable name. */ @@ -180,17 +192,20 @@ public int getNameIndex() { return nameIndex; } + /** + * @return index of register where variable was originally stored + */ + public int getOrigIndex() { + return origIndex; + } /** * @return Signature. */ public String getSignature() { - ConstantUtf8 c; - c = (ConstantUtf8) constantPool.getConstant(signatureIndex, Const.CONSTANT_Utf8); - return c.getBytes(); + return constantPool.getConstantUtf8(signatureIndex).getBytes(); } - /** * @return Index in constant pool of variable signature. */ @@ -198,23 +213,6 @@ public int getSignatureIndex() { return signatureIndex; } - - /** - * @return index of register where variable is stored - */ - public int getIndex() { - return index; - } - - - /** - * @return index of register where variable was originally stored - */ - public int getOrigIndex() { - return origIndex; - } - - /** * @return Start of range where the variable is valid */ @@ -222,67 +220,48 @@ public int getStartPC() { return startPc; } - - /* - * Helper method shared with LocalVariableTypeTable - */ - String toStringShared( final boolean typeTable ) { - final String name = getName(); - final String signature = Utility.signatureToString(getSignature(), false); - final String label = "LocalVariable" + (typeTable ? "Types" : "" ); - return label + "(startPc = " + startPc + ", length = " + length + ", index = " - + index + ":" + signature + " " + name + ")"; - } - - /** * @param constantPool Constant pool to be used for this object. */ - public void setConstantPool( final ConstantPool constantPool ) { + public void setConstantPool(final ConstantPool constantPool) { this.constantPool = constantPool; } + /** + * @param index the index in the local variable table of this variable + */ + public void setIndex(final int index) { // TODO unused + this.index = index; + } /** * @param length the length of this local variable */ - public void setLength( final int length ) { + public void setLength(final int length) { this.length = length; } - /** * @param nameIndex the index into the constant pool for the name of this variable */ - public void setNameIndex( final int nameIndex ) { // TODO unused + public void setNameIndex(final int nameIndex) { // TODO unused this.nameIndex = nameIndex; } - /** * @param signatureIndex the index into the constant pool for the signature of this variable */ - public void setSignatureIndex( final int signatureIndex ) { // TODO unused + public void setSignatureIndex(final int signatureIndex) { // TODO unused this.signatureIndex = signatureIndex; } - - /** - * @param index the index in the local variable table of this variable - */ - public void setIndex( final int index ) { // TODO unused - this.index = index; - } - - /** * @param startPc Specify range where the local variable is valid. */ - public void setStartPC( final int startPc ) { // TODO unused + public void setStartPC(final int startPc) { // TODO unused this.startPc = startPc; } - /** * @return string representation. */ @@ -291,16 +270,13 @@ public String toString() { return toStringShared(false); } - - /** - * @return deep copy of this object + /* + * Helper method shared with LocalVariableTypeTable */ - public LocalVariable copy() { - try { - return (LocalVariable) clone(); - } catch (final CloneNotSupportedException e) { - // TODO should this throw? - } - return null; + String toStringShared(final boolean typeTable) { + final String name = getName(); + final String signature = Utility.signatureToString(getSignature(), false); + final String label = "LocalVariable" + (typeTable ? "Types" : ""); + return label + "(startPc = " + startPc + ", length = " + length + ", index = " + index + ":" + signature + " " + name + ")"; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java index 12bf71d2467..fd56e14a539 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java @@ -24,83 +24,95 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.stream.Stream; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class represents colection of local variables in a - * method. This attribute is contained in the Code attribute. + * This class represents colection of local variables in a method. This attribute is contained in the Code + * attribute. * - * @see Code + * @see Code * @see LocalVariable */ -public class LocalVariableTable extends Attribute { +public class LocalVariableTable extends Attribute implements Iterable { private LocalVariable[] localVariableTable; // variables - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. + * Construct object from input stream. + * + * @param nameIndex Index in constant pool + * @param length Content length in bytes + * @param input Input stream + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - public LocalVariableTable(final LocalVariableTable c) { - this(c.getNameIndex(), c.getLength(), c.getLocalVariableTable(), c.getConstantPool()); + LocalVariableTable(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, (LocalVariable[]) null, constantPool); + final int localVariableTableLength = input.readUnsignedShort(); + localVariableTable = new LocalVariable[localVariableTableLength]; + for (int i = 0; i < localVariableTableLength; i++) { + localVariableTable[i] = new LocalVariable(input, constantPool); + } } - /** - * @param nameIndex Index in constant pool to `LocalVariableTable' + * @param nameIndex Index in constant pool to 'LocalVariableTable' * @param length Content length in bytes * @param localVariableTable Table of local variables * @param constantPool Array of constants */ - public LocalVariableTable(final int nameIndex, final int length, final LocalVariable[] localVariableTable, - final ConstantPool constantPool) { + public LocalVariableTable(final int nameIndex, final int length, final LocalVariable[] localVariableTable, final ConstantPool constantPool) { super(Const.ATTR_LOCAL_VARIABLE_TABLE, nameIndex, length, constantPool); - this.localVariableTable = localVariableTable; + this.localVariableTable = localVariableTable != null ? localVariableTable : LocalVariable.EMPTY_ARRAY; + Args.requireU2(this.localVariableTable.length, "localVariableTable.length"); } - /** - * Construct object from input stream. - * @param name_index Index in constant pool - * @param length Content length in bytes - * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a + * physical copy. + * + * @param c Source to copy. */ - LocalVariableTable(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) - throws IOException { - this(name_index, length, (LocalVariable[]) null, constant_pool); - final int local_variable_table_length = input.readUnsignedShort(); - localVariableTable = new LocalVariable[local_variable_table_length]; - for (int i = 0; i < local_variable_table_length; i++) { - localVariableTable[i] = new LocalVariable(input, constant_pool); - } + public LocalVariableTable(final LocalVariableTable c) { + this(c.getNameIndex(), c.getLength(), c.getLocalVariableTable(), c.getConstantPool()); } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitLocalVariableTable(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final LocalVariableTable c = (LocalVariableTable) clone(); + c.localVariableTable = new LocalVariable[localVariableTable.length]; + Arrays.setAll(c.localVariableTable, i -> localVariableTable[i].copy()); + c.setConstantPool(constantPool); + return c; + } /** * Dump local variable table attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public final void dump( final DataOutputStream file ) throws IOException { + public final void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(localVariableTable.length); for (final LocalVariable variable : localVariableTable) { @@ -108,26 +120,17 @@ public final void dump( final DataOutputStream file ) throws IOException { } } - - /** - * @return Array of local variables of method. - */ - public final LocalVariable[] getLocalVariableTable() { - return localVariableTable; - } - - /** * * @param index the variable slot * * @return the first LocalVariable that matches the slot or null if not found * - * @deprecated since 5.2 because multiple variables can share the - * same slot, use getLocalVariable(int index, int pc) instead. + * @deprecated since 5.2 because multiple variables can share the same slot, use getLocalVariable(int index, int pc) + * instead. */ @java.lang.Deprecated - public final LocalVariable getLocalVariable( final int index ) { + public final LocalVariable getLocalVariable(final int index) { for (final LocalVariable variable : localVariableTable) { if (variable.getIndex() == index) { return variable; @@ -136,7 +139,6 @@ public final LocalVariable getLocalVariable( final int index ) { return null; } - /** * * @param index the variable slot @@ -144,12 +146,12 @@ public final LocalVariable getLocalVariable( final int index ) { * * @return the LocalVariable that matches or null if not found */ - public final LocalVariable getLocalVariable( final int index, final int pc ) { + public final LocalVariable getLocalVariable(final int index, final int pc) { for (final LocalVariable variable : localVariableTable) { if (variable.getIndex() == index) { - final int start_pc = variable.getStartPC(); - final int end_pc = start_pc + variable.getLength(); - if ((pc >= start_pc) && (pc <= end_pc)) { + final int startPc = variable.getStartPC(); + final int endPc = startPc + variable.getLength(); + if (pc >= startPc && pc <= endPc) { return variable; } } @@ -157,11 +159,25 @@ public final LocalVariable getLocalVariable( final int index, final int pc ) { return null; } + /** + * @return Array of local variables of method. + */ + public final LocalVariable[] getLocalVariableTable() { + return localVariableTable; + } + + public final int getTableLength() { + return localVariableTable == null ? 0 : localVariableTable.length; + } - public final void setLocalVariableTable( final LocalVariable[] local_variable_table ) { - this.localVariableTable = local_variable_table; + @Override + public Iterator iterator() { + return Stream.of(localVariableTable).iterator(); } + public final void setLocalVariableTable(final LocalVariable[] localVariableTable) { + this.localVariableTable = localVariableTable; + } /** * @return String representation. @@ -177,24 +193,4 @@ public final String toString() { } return buf.toString(); } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - final LocalVariableTable c = (LocalVariableTable) clone(); - c.localVariableTable = new LocalVariable[localVariableTable.length]; - for (int i = 0; i < localVariableTable.length; i++) { - c.localVariableTable[i] = localVariableTable[i].copy(); - } - c.setConstantPool(_constant_pool); - return c; - } - - - public final int getTableLength() { - return localVariableTable == null ? 0 : localVariableTable.length; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java index bdd5d7a1bd1..08868a82de8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java @@ -23,8 +23,12 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.stream.Stream; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; // The new table is used when generic types are about... @@ -57,35 +61,49 @@ /** * @since 6.0 */ -public class LocalVariableTypeTable extends Attribute { +public class LocalVariableTypeTable extends Attribute implements Iterable { - private LocalVariable[] localVariableTypeTable; // variables - - public LocalVariableTypeTable(final LocalVariableTypeTable c) { - this(c.getNameIndex(), c.getLength(), c.getLocalVariableTypeTable(), c.getConstantPool()); - } - - public LocalVariableTypeTable(final int name_index, final int length, final LocalVariable[] local_variable_table, final ConstantPool constant_pool) { - super(Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE, name_index, length, constant_pool); - this.localVariableTypeTable = local_variable_table; - } + private LocalVariable[] localVariableTypeTable; // variables LocalVariableTypeTable(final int nameIdx, final int len, final DataInput input, final ConstantPool cpool) throws IOException { this(nameIdx, len, (LocalVariable[]) null, cpool); - final int local_variable_type_table_length = input.readUnsignedShort(); - localVariableTypeTable = new LocalVariable[local_variable_type_table_length]; + final int localVariableTypeTableLength = input.readUnsignedShort(); + localVariableTypeTable = new LocalVariable[localVariableTypeTableLength]; - for (int i = 0; i < local_variable_type_table_length; i++) { + for (int i = 0; i < localVariableTypeTableLength; i++) { localVariableTypeTable[i] = new LocalVariable(input, cpool); } } + public LocalVariableTypeTable(final int nameIndex, final int length, final LocalVariable[] localVariableTypeTable, final ConstantPool constantPool) { + super(Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE, nameIndex, length, constantPool); + this.localVariableTypeTable = localVariableTypeTable != null ? localVariableTypeTable : LocalVariable.EMPTY_ARRAY; + Args.requireU2(this.localVariableTypeTable.length, "localVariableTypeTable.length"); + } + + public LocalVariableTypeTable(final LocalVariableTypeTable c) { + this(c.getNameIndex(), c.getLength(), c.getLocalVariableTypeTable(), c.getConstantPool()); + } + @Override public void accept(final Visitor v) { v.visitLocalVariableTypeTable(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final LocalVariableTypeTable c = (LocalVariableTypeTable) clone(); + + c.localVariableTypeTable = new LocalVariable[localVariableTypeTable.length]; + Arrays.setAll(c.localVariableTypeTable, i -> localVariableTypeTable[i].copy()); + c.setConstantPool(constantPool); + return c; + } + @Override public final void dump(final DataOutputStream file) throws IOException { super.dump(file); @@ -95,10 +113,6 @@ public final void dump(final DataOutputStream file) throws IOException { } } - public final LocalVariable[] getLocalVariableTypeTable() { - return localVariableTypeTable; - } - public final LocalVariable getLocalVariable(final int index) { for (final LocalVariable variable : localVariableTypeTable) { if (variable.getIndex() == index) { @@ -109,8 +123,21 @@ public final LocalVariable getLocalVariable(final int index) { return null; } - public final void setLocalVariableTable(final LocalVariable[] local_variable_table) { - this.localVariableTypeTable = local_variable_table; + public final LocalVariable[] getLocalVariableTypeTable() { + return localVariableTypeTable; + } + + public final int getTableLength() { + return localVariableTypeTable == null ? 0 : localVariableTypeTable.length; + } + + @Override + public Iterator iterator() { + return Stream.of(localVariableTypeTable).iterator(); + } + + public final void setLocalVariableTable(final LocalVariable[] localVariableTable) { + this.localVariableTypeTable = localVariableTable; } /** @@ -130,24 +157,4 @@ public final String toString() { return buf.toString(); } - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy(final ConstantPool constant_pool) { - final LocalVariableTypeTable c = (LocalVariableTypeTable) clone(); - - c.localVariableTypeTable = new LocalVariable[localVariableTypeTable.length]; - for (int i = 0; i < localVariableTypeTable.length; i++) { - c.localVariableTypeTable[i] = localVariableTypeTable[i].copy(); - } - - c.setConstantPool(constant_pool); - return c; - } - - public final int getTableLength() { - return localVariableTypeTable == null ? 0 : localVariableTypeTable.length; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java index e1b22937082..ba2623eec08 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java @@ -24,93 +24,133 @@ import java.io.IOException; import java.util.Objects; -import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.generic.Type; import com.sun.org.apache.bcel.internal.util.BCELComparator; /** - * This class represents the method info structure, i.e., the representation - * for a method in the class. See JVM specification for details. - * A method has access flags, a name, a signature and a number of attributes. - * + * This class represents the method info structure, i.e., the representation for a method in the class. See JVM + * specification for details. A method has access flags, a name, a signature and a number of attributes. */ public final class Method extends FieldOrMethod { + /** + * Empty array constant. + * + * @since 6.6.0 + */ + public static final Method[] EMPTY_ARRAY = {}; + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals( final Object o1, final Object o2 ) { + public boolean equals(final Object o1, final Object o2) { final Method THIS = (Method) o1; final Method THAT = (Method) o2; - return Objects.equals(THIS.getName(), THAT.getName()) - && Objects.equals(THIS.getSignature(), THAT.getSignature()); + return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature()); } - @Override - public int hashCode( final Object o ) { + public int hashCode(final Object o) { final Method THIS = (Method) o; return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); } }; - // annotations defined on the parameters of a method - private ParameterAnnotationEntry[] parameterAnnotationEntries; + /** + * Empty array. + */ + static final Method[] EMPTY_METHOD_ARRAY = {}; /** - * Empty constructor, all attributes have to be defined via `setXXX' - * methods. Use at your own risk. + * @return Comparison strategy object */ - public Method() { + public static BCELComparator getComparator() { + return bcelComparator; } - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. + * @param comparator Comparison strategy object */ - public Method(final Method c) { - super(c); + public static void setComparator(final BCELComparator comparator) { + bcelComparator = comparator; } + // annotations defined on the parameters of a method + private ParameterAnnotationEntry[] parameterAnnotationEntries; + + /** + * Empty constructor, all attributes have to be defined via 'setXXX' methods. Use at your own risk. + */ + public Method() { + } /** * Construct object from file stream. + * * @param file Input stream - * @throws IOException - * @throws ClassFormatException + * @throws IOException if an I/O error occurs. + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ - Method(final DataInput file, final ConstantPool constant_pool) throws IOException, - ClassFormatException { - super(file, constant_pool); + Method(final DataInput file, final ConstantPool constantPool) throws IOException, ClassFormatException { + super(file, constantPool); } - /** - * @param access_flags Access rights of method - * @param name_index Points to field name in constant pool - * @param signature_index Points to encoded signature + * @param accessFlags Access rights of method + * @param nameIndex Points to field name in constant pool + * @param signatureIndex Points to encoded signature * @param attributes Collection of attributes - * @param constant_pool Array of constants + * @param constantPool Array of constants */ - public Method(final int access_flags, final int name_index, final int signature_index, final Attribute[] attributes, - final ConstantPool constant_pool) { - super(access_flags, name_index, signature_index, attributes, constant_pool); + public Method(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, final ConstantPool constantPool) { + super(accessFlags, nameIndex, signatureIndex, attributes, constantPool); } + /** + * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a + * physical copy. + * + * @param c Source to copy. + */ + public Method(final Method c) { + super(c); + } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitMethod(this); } + /** + * @return deep copy of this method + */ + public Method copy(final ConstantPool constantPool) { + return (Method) copy_(constantPool); + } + + /** + * Return value as defined by given BCELComparator strategy. By default two method objects are said to be equal when + * their names and signatures are equal. + * + * @see Object#equals(Object) + */ + @Override + public boolean equals(final Object obj) { + return bcelComparator.equals(this, obj); + } + + /** + * @return array of method argument types + */ + public Type[] getArgumentTypes() { + return Type.getArgumentTypes(getSignature()); + } /** * @return Code attribute of method, if any @@ -124,10 +164,9 @@ public Code getCode() { return null; } - /** - * @return ExceptionTable attribute of method, if any, i.e., list all - * exceptions the method may throw not exception handlers! + * @return ExceptionTable attribute of method, if any, i.e., list all exceptions the method may throw not exception + * handlers! */ public ExceptionTable getExceptionTable() { for (final Attribute attribute : super.getAttributes()) { @@ -138,34 +177,60 @@ public ExceptionTable getExceptionTable() { return null; } - - /** @return LocalVariableTable of code attribute if any, i.e. the call is forwarded - * to the Code atribute. + /** + * @return LineNumberTable of code attribute if any, i.e. the call is forwarded to the Code atribute. */ - public LocalVariableTable getLocalVariableTable() { + public LineNumberTable getLineNumberTable() { final Code code = getCode(); if (code == null) { return null; } - return code.getLocalVariableTable(); + return code.getLineNumberTable(); } - - /** @return LineNumberTable of code attribute if any, i.e. the call is forwarded - * to the Code atribute. + /** + * @return LocalVariableTable of code attribute if any, i.e. the call is forwarded to the Code atribute. */ - public LineNumberTable getLineNumberTable() { + public LocalVariableTable getLocalVariableTable() { final Code code = getCode(); if (code == null) { return null; } - return code.getLineNumberTable(); + return code.getLocalVariableTable(); } + /** + * @return Annotations on the parameters of a method + * @since 6.0 + */ + public ParameterAnnotationEntry[] getParameterAnnotationEntries() { + if (parameterAnnotationEntries == null) { + parameterAnnotationEntries = ParameterAnnotationEntry.createParameterAnnotationEntries(getAttributes()); + } + return parameterAnnotationEntries; + } /** - * Return string representation close to declaration format, - * `public static void main(String[] args) throws IOException', e.g. + * @return return type of method + */ + public Type getReturnType() { + return Type.getReturnType(getSignature()); + } + + /** + * Return value as defined by given BCELComparator strategy. By default return the hashcode of the method's name XOR + * signature. + * + * @see Object#hashCode() + */ + @Override + public int hashCode() { + return bcelComparator.hashCode(this); + } + + /** + * Return string representation close to declaration format, 'public static void main(String[] args) throws + * IOException', e.g. * * @return String representation of the method. */ @@ -173,15 +238,14 @@ public LineNumberTable getLineNumberTable() { public String toString() { final String access = Utility.accessToString(super.getAccessFlags()); // Get name and signature from constant pool - ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(super.getSignatureIndex(), Const.CONSTANT_Utf8); + ConstantUtf8 c = super.getConstantPool().getConstantUtf8(super.getSignatureIndex()); String signature = c.getBytes(); - c = (ConstantUtf8) super.getConstantPool().getConstant(super.getNameIndex(), Const.CONSTANT_Utf8); + c = super.getConstantPool().getConstantUtf8(super.getNameIndex()); final String name = c.getBytes(); - signature = Utility.methodSignatureToString(signature, name, access, true, - getLocalVariableTable()); + signature = Utility.methodSignatureToString(signature, name, access, true, getLocalVariableTable()); final StringBuilder buf = new StringBuilder(signature); for (final Attribute attribute : super.getAttributes()) { - if (!((attribute instanceof Code) || (attribute instanceof ExceptionTable))) { + if (!(attribute instanceof Code || attribute instanceof ExceptionTable)) { buf.append(" [").append(attribute).append("]"); } } @@ -194,80 +258,4 @@ public String toString() { } return buf.toString(); } - - - /** - * @return deep copy of this method - */ - public Method copy( final ConstantPool _constant_pool ) { - return (Method) copy_(_constant_pool); - } - - - /** - * @return return type of method - */ - public Type getReturnType() { - return Type.getReturnType(getSignature()); - } - - - /** - * @return array of method argument types - */ - public Type[] getArgumentTypes() { - return Type.getArgumentTypes(getSignature()); - } - - - /** - * @return Comparison strategy object - */ - public static BCELComparator getComparator() { - return bcelComparator; - } - - - /** - * @param comparator Comparison strategy object - */ - public static void setComparator( final BCELComparator comparator ) { - bcelComparator = comparator; - } - - - /** - * Return value as defined by given BCELComparator strategy. - * By default two method objects are said to be equal when - * their names and signatures are equal. - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals( final Object obj ) { - return bcelComparator.equals(this, obj); - } - - - /** - * Return value as defined by given BCELComparator strategy. - * By default return the hashcode of the method's name XOR signature. - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - return bcelComparator.hashCode(this); - } - - /** - * @return Annotations on the parameters of a method - * @since 6.0 - */ - public ParameterAnnotationEntry[] getParameterAnnotationEntries() { - if (parameterAnnotationEntries == null) { - parameterAnnotationEntries = ParameterAnnotationEntry.createParameterAnnotationEntries(getAttributes()); - } - return parameterAnnotationEntries; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java index 86155336302..ffc1a20f80a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java @@ -30,11 +30,11 @@ /** * Entry of the parameters table. * - * @see - * The class File Format : The MethodParameters Attribute + * @see The class File Format : + * The MethodParameters Attribute * @since 6.0 */ -public class MethodParameter implements Cloneable { +public class MethodParameter implements Cloneable, Node { /** Index of the CONSTANT_Utf8_info structure in the constant_pool table representing the name of the parameter */ private int nameIndex; @@ -49,76 +49,77 @@ public MethodParameter() { * Construct object from input stream. * * @param input Input stream - * @throws java.io.IOException - * @throws ClassFormatException + * @throws IOException if an I/O error occurs. + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ MethodParameter(final DataInput input) throws IOException { nameIndex = input.readUnsignedShort(); accessFlags = input.readUnsignedShort(); } - public int getNameIndex() { - return nameIndex; + @Override + public void accept(final Visitor v) { + v.visitMethodParameter(this); } - public void setNameIndex(final int name_index) { - this.nameIndex = name_index; + /** + * @return deep copy of this object + */ + public MethodParameter copy() { + try { + return (MethodParameter) clone(); + } catch (final CloneNotSupportedException e) { + // TODO should this throw? + } + return null; } /** - * Returns the name of the parameter. + * Dump object to file stream on binary format. + * + * @param file Output file stream + * @throws IOException if an I/O error occurs. */ - public String getParameterName(final ConstantPool constant_pool) { - if (nameIndex == 0) { - return null; - } - return ((ConstantUtf8) constant_pool.getConstant(nameIndex, Const.CONSTANT_Utf8)).getBytes(); - } + public final void dump(final DataOutputStream file) throws IOException { + file.writeShort(nameIndex); + file.writeShort(accessFlags); + } public int getAccessFlags() { return accessFlags; } - public void setAccessFlags(final int access_flags) { - this.accessFlags = access_flags; + public int getNameIndex() { + return nameIndex; } - public boolean isFinal() { - return (accessFlags & Const.ACC_FINAL) != 0; + /** + * Returns the name of the parameter. + */ + public String getParameterName(final ConstantPool constantPool) { + if (nameIndex == 0) { + return null; + } + return constantPool.getConstantUtf8(nameIndex).getBytes(); } - public boolean isSynthetic() { - return (accessFlags & Const.ACC_SYNTHETIC) != 0; + public boolean isFinal() { + return (accessFlags & Const.ACC_FINAL) != 0; } public boolean isMandated() { return (accessFlags & Const.ACC_MANDATED) != 0; } - public void accept(final Visitor v) { - v.visitMethodParameter(this); + public boolean isSynthetic() { + return (accessFlags & Const.ACC_SYNTHETIC) != 0; } - /** - * Dump object to file stream on binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(final DataOutputStream file) throws IOException { - file.writeShort(nameIndex); - file.writeShort(accessFlags); + public void setAccessFlags(final int accessFlags) { + this.accessFlags = accessFlags; } - /** - * @return deep copy of this object - */ - public MethodParameter copy() { - try { - return (MethodParameter) clone(); - } catch (final CloneNotSupportedException e) { - // TODO should this throw? - } - return null; + public void setNameIndex(final int nameIndex) { + this.nameIndex = nameIndex; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java index 0ee75fb6355..5b5d1d77f6f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java @@ -24,52 +24,50 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.stream.Stream; import com.sun.org.apache.bcel.internal.Const; /** * This class represents a MethodParameters attribute. * - * @see - * The class File Format : The MethodParameters Attribute + * @see The class File Format : + * The MethodParameters Attribute * @since 6.0 */ -public class MethodParameters extends Attribute { +public class MethodParameters extends Attribute implements Iterable { - private MethodParameter[] parameters = new MethodParameter[0]; + /** + * Empty array. + */ + private static final MethodParameter[] EMPTY_METHOD_PARAMETER_ARRAY = {}; + + private MethodParameter[] parameters = EMPTY_METHOD_PARAMETER_ARRAY; - MethodParameters(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException { - super(Const.ATTR_METHOD_PARAMETERS, name_index, length, constant_pool); + MethodParameters(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + super(Const.ATTR_METHOD_PARAMETERS, nameIndex, length, constantPool); - final int parameters_count = input.readUnsignedByte(); - parameters = new MethodParameter[parameters_count]; - for (int i = 0; i < parameters_count; i++) { + final int parameterCount = input.readUnsignedByte(); + parameters = new MethodParameter[parameterCount]; + for (int i = 0; i < parameterCount; i++) { parameters[i] = new MethodParameter(input); } } - public MethodParameter[] getParameters() { - return parameters; - } - - public void setParameters(final MethodParameter[] parameters) { - this.parameters = parameters; - } - @Override public void accept(final Visitor v) { v.visitMethodParameters(this); } @Override - public Attribute copy(final ConstantPool _constant_pool) { + public Attribute copy(final ConstantPool constantPool) { final MethodParameters c = (MethodParameters) clone(); c.parameters = new MethodParameter[parameters.length]; - for (int i = 0; i < parameters.length; i++) { - c.parameters[i] = parameters[i].copy(); - } - c.setConstantPool(_constant_pool); + Arrays.setAll(c.parameters, i -> parameters[i].copy()); + c.setConstantPool(constantPool); return c; } @@ -77,14 +75,27 @@ public Attribute copy(final ConstantPool _constant_pool) { * Dump method parameters attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump(final DataOutputStream file) throws IOException { - super.dump(file); - file.writeByte(parameters.length); + public void dump(final DataOutputStream file) throws IOException { + super.dump(file); + file.writeByte(parameters.length); for (final MethodParameter parameter : parameters) { parameter.dump(file); } } + + public MethodParameter[] getParameters() { + return parameters; + } + + @Override + public Iterator iterator() { + return Stream.of(parameters).iterator(); + } + + public void setParameters(final MethodParameter[] parameters) { + this.parameters = parameters; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java index ffb87b1123b..00eebe18245 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java @@ -24,19 +24,26 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from Attribute and represents the list of - * modules required, exported, opened or provided by a module. - * There may be at most one Module attribute in a ClassFile structure. + * This class is derived from Attribute and represents the list of modules required, exported, opened or + * provided by a module. There may be at most one Module attribute in a ClassFile structure. * - * @see Attribute + * @see Attribute * @since 6.4.0 */ public final class Module extends Attribute { + /** + * The module file name extension. + * + * @since 6.7.0 + */ + public static final String EXTENSION = ".jmod"; + private final int moduleNameIndex; private final int moduleFlags; private final int moduleVersionIndex; @@ -50,34 +57,35 @@ public final class Module extends Attribute { /** * Construct object from input stream. - * @param name_index Index in constant pool + * + * @param nameIndex Index in constant pool * @param length Content length in bytes * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - Module(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException { - super(Const.ATTR_MODULE, name_index, length, constant_pool); + Module(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + super(Const.ATTR_MODULE, nameIndex, length, constantPool); moduleNameIndex = input.readUnsignedShort(); moduleFlags = input.readUnsignedShort(); moduleVersionIndex = input.readUnsignedShort(); - final int requires_count = input.readUnsignedShort(); - requiresTable = new ModuleRequires[requires_count]; - for (int i = 0; i < requires_count; i++) { + final int requiresCount = input.readUnsignedShort(); + requiresTable = new ModuleRequires[requiresCount]; + for (int i = 0; i < requiresCount; i++) { requiresTable[i] = new ModuleRequires(input); } - final int exports_count = input.readUnsignedShort(); - exportsTable = new ModuleExports[exports_count]; - for (int i = 0; i < exports_count; i++) { + final int exportsCount = input.readUnsignedShort(); + exportsTable = new ModuleExports[exportsCount]; + for (int i = 0; i < exportsCount; i++) { exportsTable[i] = new ModuleExports(input); } - final int opens_count = input.readUnsignedShort(); - opensTable = new ModuleOpens[opens_count]; - for (int i = 0; i < opens_count; i++) { + final int opensCount = input.readUnsignedShort(); + opensTable = new ModuleOpens[opensCount]; + for (int i = 0; i < opensCount; i++) { opensTable[i] = new ModuleOpens(input); } @@ -87,72 +95,57 @@ public final class Module extends Attribute { usesIndex[i] = input.readUnsignedShort(); } - final int provides_count = input.readUnsignedShort(); - providesTable = new ModuleProvides[provides_count]; - for (int i = 0; i < provides_count; i++) { + final int providesCount = input.readUnsignedShort(); + providesTable = new ModuleProvides[providesCount]; + for (int i = 0; i < providesCount; i++) { providesTable[i] = new ModuleProvides(input); } } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitModule(this); } // TODO add more getters and setters? /** - * @return table of required modules - * @see ModuleRequires + * @return deep copy of this attribute */ - public ModuleRequires[] getRequiresTable() { - return requiresTable; - } - + @Override + public Attribute copy(final ConstantPool constantPool) { + final Module c = (Module) clone(); - /** - * @return table of exported interfaces - * @see ModuleExports - */ - public ModuleExports[] getExportsTable() { - return exportsTable; - } + c.requiresTable = new ModuleRequires[requiresTable.length]; + Arrays.setAll(c.requiresTable, i -> requiresTable[i].copy()); + c.exportsTable = new ModuleExports[exportsTable.length]; + Arrays.setAll(c.exportsTable, i -> exportsTable[i].copy()); - /** - * @return table of provided interfaces - * @see ModuleOpens - */ - public ModuleOpens[] getOpensTable() { - return opensTable; - } + c.opensTable = new ModuleOpens[opensTable.length]; + Arrays.setAll(c.opensTable, i -> opensTable[i].copy()); + c.providesTable = new ModuleProvides[providesTable.length]; + Arrays.setAll(c.providesTable, i -> providesTable[i].copy()); - /** - * @return table of provided interfaces - * @see ModuleProvides - */ - public ModuleProvides[] getProvidesTable() { - return providesTable; + c.setConstantPool(constantPool); + return c; } - /** * Dump Module attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(moduleNameIndex); @@ -185,6 +178,37 @@ public void dump( final DataOutputStream file ) throws IOException { } } + /** + * @return table of exported interfaces + * @see ModuleExports + */ + public ModuleExports[] getExportsTable() { + return exportsTable; + } + + /** + * @return table of provided interfaces + * @see ModuleOpens + */ + public ModuleOpens[] getOpensTable() { + return opensTable; + } + + /** + * @return table of provided interfaces + * @see ModuleProvides + */ + public ModuleProvides[] getProvidesTable() { + return providesTable; + } + + /** + * @return table of required modules + * @see ModuleRequires + */ + public ModuleRequires[] getRequiresTable() { + return requiresTable; + } /** * @return String representation, i.e., a list of packages. @@ -194,10 +218,10 @@ public String toString() { final ConstantPool cp = super.getConstantPool(); final StringBuilder buf = new StringBuilder(); buf.append("Module:\n"); - buf.append(" name: ") .append(cp.getConstantString(moduleNameIndex, Const.CONSTANT_Module).replace('/', '.')).append("\n"); - buf.append(" flags: ") .append(String.format("%04x", moduleFlags)).append("\n"); + buf.append(" name: ").append(Utility.pathToPackage(cp.getConstantString(moduleNameIndex, Const.CONSTANT_Module))).append("\n"); + buf.append(" flags: ").append(String.format("%04x", moduleFlags)).append("\n"); final String version = moduleVersionIndex == 0 ? "0" : cp.getConstantString(moduleVersionIndex, Const.CONSTANT_Utf8); - buf.append(" version: ") .append(version).append("\n"); + buf.append(" version: ").append(version).append("\n"); buf.append(" requires(").append(requiresTable.length).append("):\n"); for (final ModuleRequires module : requiresTable) { @@ -216,8 +240,8 @@ public String toString() { buf.append(" uses(").append(usesIndex.length).append("):\n"); for (final int index : usesIndex) { - final String class_name = cp.getConstantString(index, Const.CONSTANT_Class); - buf.append(" ").append(Utility.compactClassName(class_name, false)).append("\n"); + final String className = cp.getConstantString(index, Const.CONSTANT_Class); + buf.append(" ").append(Utility.compactClassName(className, false)).append("\n"); } buf.append(" provides(").append(providesTable.length).append("):\n"); @@ -225,38 +249,6 @@ public String toString() { buf.append(" ").append(module.toString(cp)).append("\n"); } - return buf.substring(0, buf.length()-1); // remove the last newline - } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - final Module c = (Module) clone(); - - c.requiresTable = new ModuleRequires[requiresTable.length]; - for (int i = 0; i < requiresTable.length; i++) { - c.requiresTable[i] = requiresTable[i].copy(); - } - - c.exportsTable = new ModuleExports[exportsTable.length]; - for (int i = 0; i < exportsTable.length; i++) { - c.exportsTable[i] = exportsTable[i].copy(); - } - - c.opensTable = new ModuleOpens[opensTable.length]; - for (int i = 0; i < opensTable.length; i++) { - c.opensTable[i] = opensTable[i].copy(); - } - - c.providesTable = new ModuleProvides[providesTable.length]; - for (int i = 0; i < providesTable.length; i++) { - c.providesTable[i] = providesTable[i].copy(); - } - - c.setConstantPool(_constant_pool); - return c; + return buf.substring(0, buf.length() - 1); // remove the last newline } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java index ec581c8baf1..8a97f4b6d08 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java @@ -28,19 +28,18 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class represents an entry in the exports table of the Module attribute. - * Each entry describes a package which may open the parent module. + * This class represents an entry in the exports table of the Module attribute. Each entry describes a package which may + * open the parent module. * - * @see Module + * @see Module * @since 6.4.0 */ public final class ModuleExports implements Cloneable, Node { - private final int exportsIndex; // points to CONSTANT_Package_info + private final int exportsIndex; // points to CONSTANT_Package_info private final int exportsFlags; private final int exportsToCount; - private final int[] exportsToIndex; // points to CONSTANT_Module_info - + private final int[] exportsToIndex; // points to CONSTANT_Module_info /** * Construct object from file stream. @@ -58,28 +57,38 @@ public final class ModuleExports implements Cloneable, Node { } } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitModuleExports(this); } // TODO add more getters and setters? + /** + * @return deep copy of this object + */ + public ModuleExports copy() { + try { + return (ModuleExports) clone(); + } catch (final CloneNotSupportedException e) { + // TODO should this throw? + } + return null; + } + /** * Dump table entry to file stream in binary format. * * @param file Output file stream * @throws IOException if an I/O Exception occurs in writeShort */ - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeShort(exportsIndex); file.writeShort(exportsFlags); file.writeShort(exportsToCount); @@ -88,7 +97,6 @@ public void dump( final DataOutputStream file ) throws IOException { } } - /** * @return String representation */ @@ -97,33 +105,19 @@ public String toString() { return "exports(" + exportsIndex + ", " + exportsFlags + ", " + exportsToCount + ", ...)"; } - /** * @return Resolved string representation */ - public String toString( final ConstantPool constant_pool ) { + public String toString(final ConstantPool constantPool) { final StringBuilder buf = new StringBuilder(); - final String package_name = constant_pool.constantToString(exportsIndex, Const.CONSTANT_Package); - buf.append(Utility.compactClassName(package_name, false)); + final String packageName = constantPool.constantToString(exportsIndex, Const.CONSTANT_Package); + buf.append(Utility.compactClassName(packageName, false)); buf.append(", ").append(String.format("%04x", exportsFlags)); buf.append(", to(").append(exportsToCount).append("):\n"); for (final int index : exportsToIndex) { - final String module_name = constant_pool.getConstantString(index, Const.CONSTANT_Module); - buf.append(" ").append(Utility.compactClassName(module_name, false)).append("\n"); - } - return buf.substring(0, buf.length()-1); // remove the last newline - } - - - /** - * @return deep copy of this object - */ - public ModuleExports copy() { - try { - return (ModuleExports) clone(); - } catch (final CloneNotSupportedException e) { - // TODO should this throw? + final String moduleName = constantPool.getConstantString(index, Const.CONSTANT_Module); + buf.append(" ").append(Utility.compactClassName(moduleName, false)).append("\n"); } - return null; + return buf.substring(0, buf.length() - 1); // remove the last newline } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java index 7b6d89ed69a..a6ffd882862 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java @@ -26,66 +26,73 @@ import java.io.IOException; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class is derived from Attribute and indicates the main class of a module. - * There may be at most one ModuleMainClass attribute in a ClassFile structure. + * This class is derived from Attribute and indicates the main class of a module. There may be at most one + * ModuleMainClass attribute in a ClassFile structure. * - * @see Attribute + * @see Attribute */ public final class ModuleMainClass extends Attribute { private int mainClassIndex; - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. + * Construct object from input stream. + * + * @param nameIndex Index in constant pool + * @param length Content length in bytes + * @param input Input stream + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - public ModuleMainClass(final ModuleMainClass c) { - this(c.getNameIndex(), c.getLength(), c.getHostClassIndex(), c.getConstantPool()); + ModuleMainClass(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, 0, constantPool); + mainClassIndex = input.readUnsignedShort(); } - /** - * @param name_index Index in constant pool + * @param nameIndex Index in constant pool * @param length Content length in bytes * @param mainClassIndex Host class index * @param constantPool Array of constants */ - public ModuleMainClass(final int name_index, final int length, final int mainClassIndex, - final ConstantPool constantPool) { - super(Const.ATTR_NEST_MEMBERS, name_index, length, constantPool); - this.mainClassIndex = mainClassIndex; + public ModuleMainClass(final int nameIndex, final int length, final int mainClassIndex, final ConstantPool constantPool) { + super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool); + this.mainClassIndex = Args.requireU2(mainClassIndex, "mainClassIndex"); } - /** - * Construct object from input stream. - * @param nameIndex Index in constant pool - * @param length Content length in bytes - * @param input Input stream - * @param constantPool Array of constants - * @throws IOException + * Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a + * physical copy. + * + * @param c Source to copy. */ - ModuleMainClass(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { - this(nameIndex, length, 0, constantPool); - mainClassIndex = input.readUnsignedShort(); + public ModuleMainClass(final ModuleMainClass c) { + this(c.getNameIndex(), c.getLength(), c.getHostClassIndex(), c.getConstantPool()); } - /** - * Called by objects that are traversing the nodes of the tree implicitly - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e., + * the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitModuleMainClass(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final ModuleMainClass c = (ModuleMainClass) clone(); + c.setConstantPool(constantPool); + return c; + } /** * Dump ModuleMainClass attribute to file stream in binary format. @@ -94,12 +101,11 @@ public void accept( final Visitor v ) { * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(mainClassIndex); } - /** * @return index into constant pool of host class name. */ @@ -107,15 +113,13 @@ public int getHostClassIndex() { return mainClassIndex; } - /** * @param mainClassIndex the host class index */ - public void setHostClassIndex( final int mainClassIndex ) { + public void setHostClassIndex(final int mainClassIndex) { this.mainClassIndex = mainClassIndex; } - /** * @return String representation */ @@ -123,19 +127,8 @@ public void setHostClassIndex( final int mainClassIndex ) { public String toString() { final StringBuilder buf = new StringBuilder(); buf.append("ModuleMainClass: "); - final String class_name = super.getConstantPool().getConstantString(mainClassIndex, Const.CONSTANT_Class); - buf.append(Utility.compactClassName(class_name, false)); + final String className = super.getConstantPool().getConstantString(mainClassIndex, Const.CONSTANT_Class); + buf.append(Utility.compactClassName(className, false)); return buf.toString(); } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - final ModuleMainClass c = (ModuleMainClass) clone(); - c.setConstantPool(_constant_pool); - return c; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java index 341228ea3a3..06b404df72b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java @@ -28,19 +28,18 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class represents an entry in the opens table of the Module attribute. - * Each entry describes a package which the parent module opens. + * This class represents an entry in the opens table of the Module attribute. Each entry describes a package which the + * parent module opens. * - * @see Module + * @see Module * @since 6.4.0 */ public final class ModuleOpens implements Cloneable, Node { - private final int opensIndex; // points to CONSTANT_Package_info + private final int opensIndex; // points to CONSTANT_Package_info private final int opensFlags; private final int opensToCount; - private final int[] opensToIndex; // points to CONSTANT_Module_info - + private final int[] opensToIndex; // points to CONSTANT_Module_info /** * Construct object from file stream. @@ -58,28 +57,38 @@ public final class ModuleOpens implements Cloneable, Node { } } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitModuleOpens(this); } // TODO add more getters and setters? + /** + * @return deep copy of this object + */ + public ModuleOpens copy() { + try { + return (ModuleOpens) clone(); + } catch (final CloneNotSupportedException e) { + // TODO should this throw? + } + return null; + } + /** * Dump table entry to file stream in binary format. * * @param file Output file stream * @throws IOException if an I/O Exception occurs in writeShort */ - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeShort(opensIndex); file.writeShort(opensFlags); file.writeShort(opensToCount); @@ -88,7 +97,6 @@ public void dump( final DataOutputStream file ) throws IOException { } } - /** * @return String representation */ @@ -97,33 +105,19 @@ public String toString() { return "opens(" + opensIndex + ", " + opensFlags + ", " + opensToCount + ", ...)"; } - /** * @return Resolved string representation */ - public String toString( final ConstantPool constant_pool ) { + public String toString(final ConstantPool constantPool) { final StringBuilder buf = new StringBuilder(); - final String package_name = constant_pool.constantToString(opensIndex, Const.CONSTANT_Package); - buf.append(Utility.compactClassName(package_name, false)); + final String packageName = constantPool.constantToString(opensIndex, Const.CONSTANT_Package); + buf.append(Utility.compactClassName(packageName, false)); buf.append(", ").append(String.format("%04x", opensFlags)); buf.append(", to(").append(opensToCount).append("):\n"); for (final int index : opensToIndex) { - final String module_name = constant_pool.getConstantString(index, Const.CONSTANT_Module); - buf.append(" ").append(Utility.compactClassName(module_name, false)).append("\n"); - } - return buf.substring(0, buf.length()-1); // remove the last newline - } - - - /** - * @return deep copy of this object - */ - public ModuleOpens copy() { - try { - return (ModuleOpens) clone(); - } catch (final CloneNotSupportedException e) { - // TODO should this throw? + final String moduleName = constantPool.getConstantString(index, Const.CONSTANT_Module); + buf.append(" ").append(Utility.compactClassName(moduleName, false)).append("\n"); } - return null; + return buf.substring(0, buf.length() - 1); // remove the last newline } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java index 1e1cb98731d..96367e02d2d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -24,81 +23,94 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class is derived from Attribute and represents the list of packages that are exported or opened by the Module attribute. - * There may be at most one ModulePackages attribute in a ClassFile structure. + * This class is derived from Attribute and represents the list of packages that are exported or opened by the + * Module attribute. There may be at most one ModulePackages attribute in a ClassFile structure. * - * @see Attribute + * @see Attribute + * @LastModified: Feb 2023 */ public final class ModulePackages extends Attribute { private int[] packageIndexTable; - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. + * Construct object from input stream. + * + * @param nameIndex Index in constant pool + * @param length Content length in bytes + * @param input Input stream + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - public ModulePackages(final ModulePackages c) { - this(c.getNameIndex(), c.getLength(), c.getPackageIndexTable(), c.getConstantPool()); + ModulePackages(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, (int[]) null, constantPool); + final int packageCount = input.readUnsignedShort(); + packageIndexTable = new int[packageCount]; + for (int i = 0; i < packageCount; i++) { + packageIndexTable[i] = input.readUnsignedShort(); + } } - /** * @param nameIndex Index in constant pool * @param length Content length in bytes * @param packageIndexTable Table of indices in constant pool * @param constantPool Array of constants */ - public ModulePackages(final int nameIndex, final int length, final int[] packageIndexTable, - final ConstantPool constantPool) { + public ModulePackages(final int nameIndex, final int length, final int[] packageIndexTable, final ConstantPool constantPool) { super(Const.ATTR_MODULE_PACKAGES, nameIndex, length, constantPool); - this.packageIndexTable = packageIndexTable != null ? packageIndexTable : new int[0]; + this.packageIndexTable = packageIndexTable != null ? packageIndexTable : Const.EMPTY_INT_ARRAY; + Args.requireU2(this.packageIndexTable.length, "packageIndexTable.length"); } - /** - * Construct object from input stream. - * @param name_index Index in constant pool - * @param length Content length in bytes - * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a + * physical copy. + * + * @param c Source to copy. */ - ModulePackages(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException { - this(name_index, length, (int[]) null, constant_pool); - final int number_of_packages = input.readUnsignedShort(); - packageIndexTable = new int[number_of_packages]; - for (int i = 0; i < number_of_packages; i++) { - packageIndexTable[i] = input.readUnsignedShort(); - } + public ModulePackages(final ModulePackages c) { + this(c.getNameIndex(), c.getLength(), c.getPackageIndexTable(), c.getConstantPool()); } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitModulePackages(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final ModulePackages c = (ModulePackages) clone(); + if (packageIndexTable != null) { + c.packageIndexTable = packageIndexTable.clone(); + } + c.setConstantPool(constantPool); + return c; + } /** * Dump ModulePackages attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(packageIndexTable.length); for (final int index : packageIndexTable) { @@ -106,15 +118,6 @@ public void dump( final DataOutputStream file ) throws IOException { } } - - /** - * @return array of indices into constant pool of package names. - */ - public int[] getPackageIndexTable() { - return packageIndexTable; - } - - /** * @return Length of package table. */ @@ -122,29 +125,29 @@ public int getNumberOfPackages() { return packageIndexTable == null ? 0 : packageIndexTable.length; } + /** + * @return array of indices into constant pool of package names. + */ + public int[] getPackageIndexTable() { + return packageIndexTable; + } /** * @return string array of package names */ public String[] getPackageNames() { final String[] names = new String[packageIndexTable.length]; - for (int i = 0; i < packageIndexTable.length; i++) { - names[i] = super.getConstantPool().getConstantString(packageIndexTable[i], - Const.CONSTANT_Package).replace('/', '.'); - } + Arrays.setAll(names, i -> Utility.pathToPackage(super.getConstantPool().getConstantString(packageIndexTable[i], Const.CONSTANT_Package))); return names; } - /** - * @param packageIndexTable the list of package indexes - * Also redefines number_of_packages according to table length. + * @param packageIndexTable the list of package indexes Also redefines number_of_packages according to table length. */ - public void setPackageIndexTable( final int[] packageIndexTable ) { - this.packageIndexTable = packageIndexTable != null ? packageIndexTable : new int[0]; + public void setPackageIndexTable(final int[] packageIndexTable) { + this.packageIndexTable = packageIndexTable != null ? packageIndexTable : Const.EMPTY_INT_ARRAY; } - /** * @return String representation, i.e., a list of packages. */ @@ -155,25 +158,9 @@ public String toString() { buf.append(packageIndexTable.length); buf.append("):\n"); for (final int index : packageIndexTable) { - final String package_name = super.getConstantPool().getConstantString(index, Const.CONSTANT_Package); - buf.append(" ").append(Utility.compactClassName(package_name, false)).append("\n"); + final String packageName = super.getConstantPool().getConstantString(index, Const.CONSTANT_Package); + buf.append(" ").append(Utility.compactClassName(packageName, false)).append("\n"); } - return buf.substring(0, buf.length()-1); // remove the last newline - } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - final ModulePackages c = (ModulePackages) clone(); - if (packageIndexTable != null) { - c.packageIndexTable = new int[packageIndexTable.length]; - System.arraycopy(packageIndexTable, 0, c.packageIndexTable, 0, - packageIndexTable.length); - } - c.setConstantPool(_constant_pool); - return c; + return buf.substring(0, buf.length() - 1); // remove the last newline } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java index 8cbeecc3f26..f6c6058dfbb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java @@ -28,18 +28,17 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class represents an entry in the provides table of the Module attribute. - * Each entry describes a service implementation that the parent module provides. + * This class represents an entry in the provides table of the Module attribute. Each entry describes a service + * implementation that the parent module provides. * - * @see Module + * @see Module * @since 6.4.0 */ public final class ModuleProvides implements Cloneable, Node { - private final int providesIndex; // points to CONSTANT_Class_info + private final int providesIndex; // points to CONSTANT_Class_info private final int providesWithCount; - private final int[] providesWithIndex; // points to CONSTANT_Class_info - + private final int[] providesWithIndex; // points to CONSTANT_Class_info /** * Construct object from file stream. @@ -56,28 +55,38 @@ public final class ModuleProvides implements Cloneable, Node { } } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitModuleProvides(this); } // TODO add more getters and setters? + /** + * @return deep copy of this object + */ + public ModuleProvides copy() { + try { + return (ModuleProvides) clone(); + } catch (final CloneNotSupportedException e) { + // TODO should this throw? + } + return null; + } + /** * Dump table entry to file stream in binary format. * * @param file Output file stream * @throws IOException if an I/O Exception occurs in writeShort */ - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeShort(providesIndex); file.writeShort(providesWithCount); for (final int entry : providesWithIndex) { @@ -85,7 +94,6 @@ public void dump( final DataOutputStream file ) throws IOException { } } - /** * @return String representation */ @@ -94,32 +102,18 @@ public String toString() { return "provides(" + providesIndex + ", " + providesWithCount + ", ...)"; } - /** * @return Resolved string representation */ - public String toString( final ConstantPool constant_pool ) { + public String toString(final ConstantPool constantPool) { final StringBuilder buf = new StringBuilder(); - final String interface_name = constant_pool.constantToString(providesIndex, Const.CONSTANT_Class); - buf.append(Utility.compactClassName(interface_name, false)); + final String interfaceName = constantPool.constantToString(providesIndex, Const.CONSTANT_Class); + buf.append(Utility.compactClassName(interfaceName, false)); buf.append(", with(").append(providesWithCount).append("):\n"); for (final int index : providesWithIndex) { - final String class_name = constant_pool.getConstantString(index, Const.CONSTANT_Class); - buf.append(" ").append(Utility.compactClassName(class_name, false)).append("\n"); - } - return buf.substring(0, buf.length()-1); // remove the last newline - } - - - /** - * @return deep copy of this object - */ - public ModuleProvides copy() { - try { - return (ModuleProvides) clone(); - } catch (final CloneNotSupportedException e) { - // TODO should this throw? + final String className = constantPool.getConstantString(index, Const.CONSTANT_Class); + buf.append(" ").append(Utility.compactClassName(className, false)).append("\n"); } - return null; + return buf.substring(0, buf.length() - 1); // remove the last newline } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java index a368197220d..c9c26c20649 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java @@ -28,18 +28,17 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class represents an entry in the requires table of the Module attribute. - * Each entry describes a module on which the parent module depends. + * This class represents an entry in the requires table of the Module attribute. Each entry describes a module on which + * the parent module depends. * - * @see Module + * @see Module * @since 6.4.0 */ public final class ModuleRequires implements Cloneable, Node { - private final int requiresIndex; // points to CONSTANT_Module_info + private final int requiresIndex; // points to CONSTANT_Module_info private final int requiresFlags; - private final int requiresVersionIndex; // either 0 or points to CONSTANT_Utf8_info - + private final int requiresVersionIndex; // either 0 or points to CONSTANT_Utf8_info /** * Construct object from file stream. @@ -53,34 +52,43 @@ public final class ModuleRequires implements Cloneable, Node { requiresVersionIndex = file.readUnsignedShort(); } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitModuleRequires(this); } // TODO add more getters and setters? + /** + * @return deep copy of this object + */ + public ModuleRequires copy() { + try { + return (ModuleRequires) clone(); + } catch (final CloneNotSupportedException e) { + // TODO should this throw? + } + return null; + } + /** * Dump table entry to file stream in binary format. * * @param file Output file stream * @throws IOException if an I/O Exception occurs in writeShort */ - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeShort(requiresIndex); file.writeShort(requiresFlags); file.writeShort(requiresVersionIndex); } - /** * @return String representation */ @@ -89,30 +97,16 @@ public String toString() { return "requires(" + requiresIndex + ", " + String.format("%04x", requiresFlags) + ", " + requiresVersionIndex + ")"; } - /** * @return Resolved string representation */ - public String toString( final ConstantPool constant_pool ) { + public String toString(final ConstantPool constantPool) { final StringBuilder buf = new StringBuilder(); - final String module_name = constant_pool.constantToString(requiresIndex, Const.CONSTANT_Module); - buf.append(Utility.compactClassName(module_name, false)); + final String moduleName = constantPool.constantToString(requiresIndex, Const.CONSTANT_Module); + buf.append(Utility.compactClassName(moduleName, false)); buf.append(", ").append(String.format("%04x", requiresFlags)); - final String version = requiresVersionIndex == 0 ? "0" : constant_pool.getConstantString(requiresVersionIndex, Const.CONSTANT_Utf8); + final String version = requiresVersionIndex == 0 ? "0" : constantPool.getConstantString(requiresVersionIndex, Const.CONSTANT_Utf8); buf.append(", ").append(version); return buf.toString(); } - - - /** - * @return deep copy of this object - */ - public ModuleRequires copy() { - try { - return (ModuleRequires) clone(); - } catch (final CloneNotSupportedException e) { - // TODO should this throw? - } - return null; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestHost.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestHost.java index b9a0a1d68a4..48ba454c930 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestHost.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestHost.java @@ -26,67 +26,73 @@ import java.io.IOException; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class is derived from Attribute and records the nest host of the nest - * to which the current class or interface claims to belong. - * There may be at most one NestHost attribute in a ClassFile structure. + * This class is derived from Attribute and records the nest host of the nest to which the current class or + * interface claims to belong. There may be at most one NestHost attribute in a ClassFile structure. * - * @see Attribute + * @see Attribute */ public final class NestHost extends Attribute { private int hostClassIndex; - /** - * Initializes from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. + * Constructs object from input stream. + * + * @param nameIndex Index in constant pool + * @param length Content length in bytes + * @param input Input stream + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - public NestHost(final NestHost c) { - this(c.getNameIndex(), c.getLength(), c.getHostClassIndex(), c.getConstantPool()); + NestHost(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, 0, constantPool); + hostClassIndex = input.readUnsignedShort(); } - /** * @param nameIndex Index in constant pool * @param length Content length in bytes * @param hostClassIndex Host class index * @param constantPool Array of constants */ - public NestHost(final int nameIndex, final int length, final int hostClassIndex, - final ConstantPool constantPool) { + public NestHost(final int nameIndex, final int length, final int hostClassIndex, final ConstantPool constantPool) { super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool); - this.hostClassIndex = hostClassIndex; + this.hostClassIndex = Args.requireU2(hostClassIndex, "hostClassIndex"); } - /** - * Constructs object from input stream. - * @param name_index Index in constant pool - * @param length Content length in bytes - * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * Initializes from another object. Note that both objects use the same references (shallow copy). Use copy() for a + * physical copy. + * + * @param c Source to copy. */ - NestHost(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException { - this(name_index, length, 0, constant_pool); - hostClassIndex = input.readUnsignedShort(); + public NestHost(final NestHost c) { + this(c.getNameIndex(), c.getLength(), c.getHostClassIndex(), c.getConstantPool()); } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitNestHost(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final NestHost c = (NestHost) clone(); + c.setConstantPool(constantPool); + return c; + } /** * Dumps NestHost attribute to file stream in binary format. @@ -95,12 +101,11 @@ public void accept( final Visitor v ) { * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(hostClassIndex); } - /** * @return index into constant pool of host class name. */ @@ -108,15 +113,13 @@ public int getHostClassIndex() { return hostClassIndex; } - /** * @param hostClassIndex the host class index */ - public void setHostClassIndex( final int hostClassIndex ) { + public void setHostClassIndex(final int hostClassIndex) { this.hostClassIndex = hostClassIndex; } - /** * @return String representation */ @@ -124,19 +127,8 @@ public void setHostClassIndex( final int hostClassIndex ) { public String toString() { final StringBuilder buf = new StringBuilder(); buf.append("NestHost: "); - final String class_name = super.getConstantPool().getConstantString(hostClassIndex, Const.CONSTANT_Class); - buf.append(Utility.compactClassName(class_name, false)); + final String className = super.getConstantPool().getConstantString(hostClassIndex, Const.CONSTANT_Class); + buf.append(Utility.compactClassName(className, false)); return buf.toString(); } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - final NestHost c = (NestHost) clone(); - c.setConstantPool(_constant_pool); - return c; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java index 73a853af6e6..05d982ca6e8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -24,82 +23,95 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class is derived from Attribute and records the classes and interfaces that - * are authorized to claim membership in the nest hosted by the current class or interface. - * There may be at most one NestMembers attribute in a ClassFile structure. + * This class is derived from Attribute and records the classes and interfaces that are authorized to claim + * membership in the nest hosted by the current class or interface. There may be at most one NestMembers attribute in a + * ClassFile structure. * - * @see Attribute + * @see Attribute + * @LastModified: Feb 2023 */ public final class NestMembers extends Attribute { private int[] classes; - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. + * Construct object from input stream. + * + * @param nameIndex Index in constant pool + * @param length Content length in bytes + * @param input Input stream + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - public NestMembers(final NestMembers c) { - this(c.getNameIndex(), c.getLength(), c.getClasses(), c.getConstantPool()); + NestMembers(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, (int[]) null, constantPool); + final int classCount = input.readUnsignedShort(); + classes = new int[classCount]; + for (int i = 0; i < classCount; i++) { + classes[i] = input.readUnsignedShort(); + } } - /** - * @param name_index Index in constant pool + * @param nameIndex Index in constant pool * @param length Content length in bytes * @param classes Table of indices in constant pool - * @param constant_pool Array of constants + * @param constantPool Array of constants */ - public NestMembers(final int name_index, final int length, final int[] classes, - final ConstantPool constant_pool) { - super(Const.ATTR_NEST_MEMBERS, name_index, length, constant_pool); - this.classes = classes != null ? classes : new int[0]; + public NestMembers(final int nameIndex, final int length, final int[] classes, final ConstantPool constantPool) { + super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool); + this.classes = classes != null ? classes : Const.EMPTY_INT_ARRAY; + Args.requireU2(this.classes.length, "classes.length"); } - /** - * Construct object from input stream. - * @param name_index Index in constant pool - * @param length Content length in bytes - * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a + * physical copy. + * + * @param c Source to copy. */ - NestMembers(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException { - this(name_index, length, (int[]) null, constant_pool); - final int number_of_classes = input.readUnsignedShort(); - classes = new int[number_of_classes]; - for (int i = 0; i < number_of_classes; i++) { - classes[i] = input.readUnsignedShort(); - } + public NestMembers(final NestMembers c) { + this(c.getNameIndex(), c.getLength(), c.getClasses(), c.getConstantPool()); } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitNestMembers(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final NestMembers c = (NestMembers) clone(); + if (classes.length > 0) { + c.classes = classes.clone(); + } + c.setConstantPool(constantPool); + return c; + } /** * Dump NestMembers attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(classes.length); for (final int index : classes) { @@ -107,7 +119,6 @@ public void dump( final DataOutputStream file ) throws IOException { } } - /** * @return array of indices into constant pool of class names. */ @@ -115,36 +126,28 @@ public int[] getClasses() { return classes; } - - /** - * @return Length of classes table. - */ - public int getNumberClasses() { - return classes == null ? 0 : classes.length; - } - - /** * @return string array of class names */ public String[] getClassNames() { final String[] names = new String[classes.length]; - for (int i = 0; i < classes.length; i++) { - names[i] = super.getConstantPool().getConstantString(classes[i], - Const.CONSTANT_Class).replace('/', '.'); - } + Arrays.setAll(names, i -> Utility.pathToPackage(super.getConstantPool().getConstantString(classes[i], Const.CONSTANT_Class))); return names; } - /** - * @param classes the list of class indexes - * Also redefines number_of_classes according to table length. + * @return Length of classes table. */ - public void setClasses( final int[] classes ) { - this.classes = classes != null ? classes : new int[0]; + public int getNumberClasses() { + return classes.length; } + /** + * @param classes the list of class indexes Also redefines number_of_classes according to table length. + */ + public void setClasses(final int[] classes) { + this.classes = classes != null ? classes : Const.EMPTY_INT_ARRAY; + } /** * @return String representation, i.e., a list of classes. @@ -156,25 +159,9 @@ public String toString() { buf.append(classes.length); buf.append("):\n"); for (final int index : classes) { - final String class_name = super.getConstantPool().getConstantString(index, Const.CONSTANT_Class); - buf.append(" ").append(Utility.compactClassName(class_name, false)).append("\n"); + final String className = super.getConstantPool().getConstantString(index, Const.CONSTANT_Class); + buf.append(" ").append(Utility.compactClassName(className, false)).append("\n"); } - return buf.substring(0, buf.length()-1); // remove the last newline - } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - final NestMembers c = (NestMembers) clone(); - if (classes != null) { - c.classes = new int[classes.length]; - System.arraycopy(classes, 0, c.classes, 0, - classes.length); - } - c.setConstantPool(_constant_pool); - return c; + return buf.substring(0, buf.length() - 1); // remove the last newline } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java index 45d48e2aa39..c0395732d79 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java @@ -23,9 +23,8 @@ /** * Denote class to have an accept method(); - * */ public interface Node { - void accept( Visitor obj ); + void accept(Visitor obj); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java index fed7464e779..9b1dd4c7b41 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java @@ -28,83 +28,83 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class is derived from Attribute and represents a reference - * to a PMG attribute. + * This class is derived from Attribute and represents a reference to a PMG attribute. * - * @see Attribute + * @see Attribute */ public final class PMGClass extends Attribute { private int pmgClassIndex; private int pmgIndex; - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. - */ - public PMGClass(final PMGClass pgmClass) { - this(pgmClass.getNameIndex(), pgmClass.getLength(), pgmClass.getPMGIndex(), pgmClass.getPMGClassIndex(), - pgmClass.getConstantPool()); - } - - /** * Construct object from input stream. - * @param name_index Index in constant pool to CONSTANT_Utf8 + * + * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - PMGClass(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) - throws IOException { - this(name_index, length, input.readUnsignedShort(), input.readUnsignedShort(), constant_pool); + PMGClass(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, input.readUnsignedShort(), input.readUnsignedShort(), constantPool); } - /** - * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes * @param pmgIndex index in constant pool for source file name * @param pmgClassIndex Index in constant pool to CONSTANT_Utf8 * @param constantPool Array of constants */ - public PMGClass(final int name_index, final int length, final int pmgIndex, final int pmgClassIndex, - final ConstantPool constantPool) { - super(Const.ATTR_PMG, name_index, length, constantPool); + public PMGClass(final int nameIndex, final int length, final int pmgIndex, final int pmgClassIndex, final ConstantPool constantPool) { + super(Const.ATTR_PMG, nameIndex, length, constantPool); this.pmgIndex = pmgIndex; this.pmgClassIndex = pmgClassIndex; } + /** + * Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a + * physical copy. + * + * @param pgmClass Source to copy. + */ + public PMGClass(final PMGClass pgmClass) { + this(pgmClass.getNameIndex(), pgmClass.getLength(), pgmClass.getPMGIndex(), pgmClass.getPMGClassIndex(), pgmClass.getConstantPool()); + } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { println("Visiting non-standard PMGClass object"); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + return (Attribute) clone(); + } /** * Dump source file attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(pmgIndex); file.writeShort(pmgClassIndex); } - /** * @return Index in constant pool of source file name. */ @@ -112,15 +112,13 @@ public int getPMGClassIndex() { return pmgClassIndex; } - /** - * @param pmgClassIndex + * @return PMG class name. */ - public void setPMGClassIndex( final int pmgClassIndex ) { - this.pmgClassIndex = pmgClassIndex; + public String getPMGClassName() { + return super.getConstantPool().getConstantUtf8(pmgClassIndex).getBytes(); } - /** * @return Index in constant pool of source file name. */ @@ -128,35 +126,27 @@ public int getPMGIndex() { return pmgIndex; } - /** - * @param pmgIndex + * @return PMG name. */ - public void setPMGIndex( final int pmgIndex ) { - this.pmgIndex = pmgIndex; + public String getPMGName() { + return super.getConstantPool().getConstantUtf8(pmgIndex).getBytes(); } - /** - * @return PMG name. + * @param pmgClassIndex */ - public String getPMGName() { - final ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(pmgIndex, - Const.CONSTANT_Utf8); - return c.getBytes(); + public void setPMGClassIndex(final int pmgClassIndex) { + this.pmgClassIndex = pmgClassIndex; } - /** - * @return PMG class name. + * @param pmgIndex */ - public String getPMGClassName() { - final ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(pmgClassIndex, - Const.CONSTANT_Utf8); - return c.getBytes(); + public void setPMGIndex(final int pmgIndex) { + this.pmgIndex = pmgIndex; } - /** * @return String representation */ @@ -164,13 +154,4 @@ public String getPMGClassName() { public String toString() { return "PMGClass(" + getPMGName() + ", " + getPMGClassName() + ")"; } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - return (Attribute) clone(); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java index f652ad7ca11..a3070fa7e0c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java @@ -35,44 +35,48 @@ */ public class ParameterAnnotationEntry implements Node { - private final AnnotationEntry[] annotationTable; + static final ParameterAnnotationEntry[] EMPTY_ARRAY = {}; + public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attrs) { + // Find attributes that contain parameter annotation data + final List accumulatedAnnotations = new ArrayList<>(attrs.length); + for (final Attribute attribute : attrs) { + if (attribute instanceof ParameterAnnotations) { + final ParameterAnnotations runtimeAnnotations = (ParameterAnnotations) attribute; + Collections.addAll(accumulatedAnnotations, runtimeAnnotations.getParameterAnnotationEntries()); + } + } + return accumulatedAnnotations.toArray(ParameterAnnotationEntry.EMPTY_ARRAY); + } + + private final AnnotationEntry[] annotationTable; /** * Construct object from input stream. * * @param input Input stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ - ParameterAnnotationEntry(final DataInput input, final ConstantPool constant_pool) throws IOException { - final int annotation_table_length = input.readUnsignedShort(); - annotationTable = new AnnotationEntry[annotation_table_length]; - for (int i = 0; i < annotation_table_length; i++) { + ParameterAnnotationEntry(final DataInput input, final ConstantPool constantPool) throws IOException { + final int annotationTableLength = input.readUnsignedShort(); + annotationTable = new AnnotationEntry[annotationTableLength]; + for (int i = 0; i < annotationTableLength; i++) { // TODO isRuntimeVisible - annotationTable[i] = AnnotationEntry.read(input, constant_pool, false); + annotationTable[i] = AnnotationEntry.read(input, constantPool, false); } } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitParameterAnnotationEntry(this); } - /** - * returns the array of annotation entries in this annotation - */ - public AnnotationEntry[] getAnnotationEntries() { - return annotationTable; - } - public void dump(final DataOutputStream dos) throws IOException { dos.writeShort(annotationTable.length); for (final AnnotationEntry entry : annotationTable) { @@ -80,15 +84,10 @@ public void dump(final DataOutputStream dos) throws IOException { } } - public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attrs) { - // Find attributes that contain parameter annotation data - final List accumulatedAnnotations = new ArrayList<>(attrs.length); - for (final Attribute attribute : attrs) { - if (attribute instanceof ParameterAnnotations) { - final ParameterAnnotations runtimeAnnotations = (ParameterAnnotations)attribute; - Collections.addAll(accumulatedAnnotations, runtimeAnnotations.getParameterAnnotationEntries()); - } - } - return accumulatedAnnotations.toArray(new ParameterAnnotationEntry[accumulatedAnnotations.size()]); - } + /** + * returns the array of annotation entries in this annotation + */ + public AnnotationEntry[] getAnnotationEntries() { + return annotationTable; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java index 2370ed76aff..4817793120f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java @@ -24,36 +24,36 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Iterator; +import java.util.stream.Stream; /** * base class for parameter annotations * * @since 6.0 */ -public abstract class ParameterAnnotations extends Attribute { +public abstract class ParameterAnnotations extends Attribute implements Iterable { /** Table of parameter annotations */ private ParameterAnnotationEntry[] parameterAnnotationTable; /** - * @param parameter_annotation_type the subclass type of the parameter annotation - * @param name_index Index pointing to the name Code + * @param parameterAnnotationType the subclass type of the parameter annotation + * @param nameIndex Index pointing to the name Code * @param length Content length in bytes * @param input Input stream - * @param constant_pool Array of constants + * @param constantPool Array of constants */ - ParameterAnnotations(final byte parameter_annotation_type, final int name_index, final int length, - final DataInput input, final ConstantPool constant_pool) throws IOException { - this(parameter_annotation_type, name_index, length, (ParameterAnnotationEntry[]) null, - constant_pool); - final int num_parameters = input.readUnsignedByte(); - parameterAnnotationTable = new ParameterAnnotationEntry[num_parameters]; - for (int i = 0; i < num_parameters; i++) { - parameterAnnotationTable[i] = new ParameterAnnotationEntry(input, constant_pool); + ParameterAnnotations(final byte parameterAnnotationType, final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) + throws IOException { + this(parameterAnnotationType, nameIndex, length, (ParameterAnnotationEntry[]) null, constantPool); + final int numParameters = input.readUnsignedByte(); + parameterAnnotationTable = new ParameterAnnotationEntry[numParameters]; + for (int i = 0; i < numParameters; i++) { + parameterAnnotationTable[i] = new ParameterAnnotationEntry(input, constantPool); } } - /** * @param parameterAnnotationType the subclass type of the parameter annotation * @param nameIndex Index pointing to the name Code @@ -62,65 +62,64 @@ public abstract class ParameterAnnotations extends Attribute { * @param constantPool Array of constants */ public ParameterAnnotations(final byte parameterAnnotationType, final int nameIndex, final int length, - final ParameterAnnotationEntry[] parameterAnnotationTable, final ConstantPool constantPool) { + final ParameterAnnotationEntry[] parameterAnnotationTable, final ConstantPool constantPool) { super(parameterAnnotationType, nameIndex, length, constantPool); this.parameterAnnotationTable = parameterAnnotationTable; } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitParameterAnnotation(this); } - /** - * @param parameterAnnotationTable the entries to set in this parameter annotation + * @return deep copy of this attribute */ - public final void setParameterAnnotationTable(final ParameterAnnotationEntry[] parameterAnnotationTable ) { - this.parameterAnnotationTable = parameterAnnotationTable; + @Override + public Attribute copy(final ConstantPool constantPool) { + return (Attribute) clone(); } + @Override + public void dump(final DataOutputStream dos) throws IOException { + super.dump(dos); + dos.writeByte(parameterAnnotationTable.length); + + for (final ParameterAnnotationEntry element : parameterAnnotationTable) { + element.dump(dos); + } + + } /** - * @return the parameter annotation entry table + * returns the array of parameter annotation entries in this parameter annotation */ - public final ParameterAnnotationEntry[] getParameterAnnotationTable() { + public ParameterAnnotationEntry[] getParameterAnnotationEntries() { return parameterAnnotationTable; } - /** - * returns the array of parameter annotation entries in this parameter annotation + * @return the parameter annotation entry table */ - public ParameterAnnotationEntry[] getParameterAnnotationEntries() { + public final ParameterAnnotationEntry[] getParameterAnnotationTable() { return parameterAnnotationTable; } @Override - public void dump(final DataOutputStream dos) throws IOException - { - super.dump(dos); - dos.writeByte(parameterAnnotationTable.length); - - for (final ParameterAnnotationEntry element : parameterAnnotationTable) { - element.dump(dos); - } - + public Iterator iterator() { + return Stream.of(parameterAnnotationTable).iterator(); } /** - * @return deep copy of this attribute + * @param parameterAnnotationTable the entries to set in this parameter annotation */ - @Override - public Attribute copy( final ConstantPool constant_pool ) { - return (Attribute) clone(); + public final void setParameterAnnotationTable(final ParameterAnnotationEntry[] parameterAnnotationTable) { + this.parameterAnnotationTable = parameterAnnotationTable; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java index 7c65eb6de22..7afb8719559 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java @@ -28,41 +28,33 @@ import com.sun.org.apache.bcel.internal.Const; /** - * represents an annotation that is represented in the class file but is not - * provided to the JVM. + * represents an annotation that is represented in the class file but is not provided to the JVM. * * @since 6.0 */ -public class RuntimeInvisibleAnnotations extends Annotations -{ +public class RuntimeInvisibleAnnotations extends Annotations { + /** - * @param name_index - * Index pointing to the name Code - * @param length - * Content length in bytes - * @param input - * Input stream - * @param constant_pool - * Array of constants + * @param nameIndex Index pointing to the name Code + * @param length Content length in bytes + * @param input Input stream + * @param constantPool Array of constants + * @throws IOException Thrown when an I/O exception of some sort has occurred. */ - public RuntimeInvisibleAnnotations(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) - throws IOException - { - super(Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS, name_index, length, input, constant_pool, false); + public RuntimeInvisibleAnnotations(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + super(Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS, nameIndex, length, input, constantPool, false); } /** * @return deep copy of this attribute */ @Override - public Attribute copy(final ConstantPool constant_pool) - { + public Attribute copy(final ConstantPool constantPool) { return (Attribute) clone(); } @Override - public final void dump(final DataOutputStream dos) throws IOException - { + public final void dump(final DataOutputStream dos) throws IOException { super.dump(dos); writeAnnotations(dos); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java index 1717f752972..e4c3276f968 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java @@ -27,21 +27,21 @@ import com.sun.org.apache.bcel.internal.Const; /** - * Represents a parameter annotation that is represented in the class file - * but is not provided to the JVM. + * Represents a parameter annotation that is represented in the class file but is not provided to the JVM. * * @since 6.0 */ public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations { /** - * @param name_index Index pointing to the name Code + * @param nameIndex Index pointing to the name Code * @param length Content length in bytes * @param input Input stream - * @param constant_pool Array of constants + * @param constantPool Array of constants + * @throws IOException Thrown when an I/O exception of some sort has occurred. */ - public RuntimeInvisibleParameterAnnotations(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) - throws IOException { - super(Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, name_index, length, input, constant_pool); + public RuntimeInvisibleParameterAnnotations(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) + throws IOException { + super(Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, nameIndex, length, input, constantPool); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java index a4b5745118a..c91c77387b9 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java @@ -28,40 +28,33 @@ import com.sun.org.apache.bcel.internal.Const; /** - * represents an annotation that is represented in the class file and is - * provided to the JVM. + * represents an annotation that is represented in the class file and is provided to the JVM. * * @since 6.0 */ -public class RuntimeVisibleAnnotations extends Annotations -{ +public class RuntimeVisibleAnnotations extends Annotations { + /** - * @param name_index - * Index pointing to the name Code - * @param length - * Content length in bytes - * @param input - * Input stream - * @param constant_pool - * Array of constants + * @param nameIndex Index pointing to the name Code + * @param length Content length in bytes + * @param input Input stream + * @param constantPool Array of constants + * @throws IOException Thrown when an I/O exception of some sort has occurred. */ - public RuntimeVisibleAnnotations(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException - { - super(Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS, name_index, length, input, constant_pool, true); + public RuntimeVisibleAnnotations(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + super(Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS, nameIndex, length, input, constantPool, true); } /** * @return deep copy of this attribute */ @Override - public Attribute copy(final ConstantPool constant_pool) - { + public Attribute copy(final ConstantPool constantPool) { return (Attribute) clone(); } @Override - public final void dump(final DataOutputStream dos) throws IOException - { + public final void dump(final DataOutputStream dos) throws IOException { super.dump(dos); writeAnnotations(dos); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java index a85f51827d3..7e5d7eaaca3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java @@ -27,21 +27,21 @@ import com.sun.org.apache.bcel.internal.Const; /** - * Represents a parameter annotation that is represented in the class file - * and is provided to the JVM. + * Represents a parameter annotation that is represented in the class file and is provided to the JVM. * * @since 6.0 */ public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations { /** - * @param name_index Index pointing to the name Code + * @param nameIndex Index pointing to the name Code * @param length Content length in bytes * @param input Input stream - * @param constant_pool Array of constants + * @param constantPool Array of constants + * @throws IOException Thrown when an I/O exception of some sort has occurred. */ - public RuntimeVisibleParameterAnnotations(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) - throws IOException { - super(Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, name_index, length, input, constant_pool); + public RuntimeVisibleParameterAnnotations(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) + throws IOException { + super(Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, nameIndex, length, input, constantPool); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java index 45c138c6ad0..4f5d3a341b3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java @@ -25,122 +25,32 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Objects; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class is derived from Attribute and represents a reference - * to a GJ attribute. + * This class is derived from Attribute and represents a reference to a GJ attribute. * - * @see Attribute + * @see Attribute */ public final class Signature extends Attribute { - private int signatureIndex; - - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - public Signature(final Signature c) { - this(c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c.getConstantPool()); - } - - - /** - * Construct object from file stream. - * @param name_index Index in constant pool to CONSTANT_Utf8 - * @param length Content length in bytes - * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException - */ - Signature(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) - throws IOException { - this(name_index, length, input.readUnsignedShort(), constant_pool); - } - - - /** - * @param name_index Index in constant pool to CONSTANT_Utf8 - * @param length Content length in bytes - * @param signatureIndex Index in constant pool to CONSTANT_Utf8 - * @param constant_pool Array of constants - */ - public Signature(final int name_index, final int length, final int signatureIndex, final ConstantPool constant_pool) { - super(Const.ATTR_SIGNATURE, name_index, length, constant_pool); - this.signatureIndex = signatureIndex; - } - - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - @Override - public void accept( final Visitor v ) { - //System.err.println("Visiting non-standard Signature object"); - v.visitSignature(this); - } - - - /** - * Dump source file attribute to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - @Override - public void dump( final DataOutputStream file ) throws IOException { - super.dump(file); - file.writeShort(signatureIndex); - } - - - /** - * @return Index in constant pool of source file name. - */ - public int getSignatureIndex() { - return signatureIndex; - } - - - /** - * @param signatureIndex the index info the constant pool of this signature - */ - public void setSignatureIndex( final int signatureIndex ) { - this.signatureIndex = signatureIndex; - } - - - /** - * @return GJ signature. - */ - public String getSignature() { - final ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(signatureIndex, - Const.CONSTANT_Utf8); - return c.getBytes(); - } - /** * Extends ByteArrayInputStream to make 'unreading' chars possible. */ private static final class MyByteArrayInputStream extends ByteArrayInputStream { MyByteArrayInputStream(final String data) { - super(data.getBytes()); + super(data.getBytes(StandardCharsets.UTF_8)); } - String getData() { - return new String(buf); + return new String(buf, StandardCharsets.UTF_8); } - void unread() { if (pos > 0) { pos--; @@ -148,19 +58,59 @@ void unread() { } } - - private static boolean identStart( final int ch ) { + private static boolean identStart(final int ch) { return ch == 'T' || ch == 'L'; } + // @since 6.0 is no longer final + public static boolean isActualParameterList(final String s) { + return s.startsWith("L") && s.endsWith(">;"); + } + + // @since 6.0 is no longer final + public static boolean isFormalParameterList(final String s) { + return s.startsWith("<") && s.indexOf(':') > 0; + } + + private static void matchGJIdent(final MyByteArrayInputStream in, final StringBuilder buf) { + int ch; + matchIdent(in, buf); + ch = in.read(); + if (ch == '<' || ch == '(') { // Parameterized or method + // System.out.println("Enter <"); + buf.append((char) ch); + matchGJIdent(in, buf); + while ((ch = in.read()) != '>' && ch != ')') { // List of parameters + if (ch == -1) { + throw new IllegalArgumentException("Illegal signature: " + in.getData() + " reaching EOF"); + } + // System.out.println("Still no >"); + buf.append(", "); + in.unread(); + matchGJIdent(in, buf); // Recursive call + } + // System.out.println("Exit >"); + buf.append((char) ch); + } else { + in.unread(); + } + ch = in.read(); + if (identStart(ch)) { + in.unread(); + matchGJIdent(in, buf); + } else if (ch == ')') { + in.unread(); + } else if (ch != ';') { + throw new IllegalArgumentException("Illegal signature: " + in.getData() + " read " + (char) ch); + } + } - private static void matchIdent( final MyByteArrayInputStream in, final StringBuilder buf ) { + private static void matchIdent(final MyByteArrayInputStream in, final StringBuilder buf) { int ch; if ((ch = in.read()) == -1) { - throw new IllegalArgumentException("Illegal signature: " + in.getData() - + " no ident, reaching EOF"); + throw new IllegalArgumentException("Illegal signature: " + in.getData() + " no ident, reaching EOF"); } - //System.out.println("return from ident:" + (char)ch); + // System.out.println("return from ident:" + (char)ch); if (!identStart(ch)) { final StringBuilder buf2 = new StringBuilder(); int count = 1; @@ -170,11 +120,15 @@ private static void matchIdent( final MyByteArrayInputStream in, final StringBui ch = in.read(); } if (ch == ':') { // Ok, formal parameter - in.skip("Ljava/lang/Object".length()); + final int skipExpected = "Ljava/lang/Object".length(); + final long skipActual = in.skip(skipExpected); + if (skipActual != skipExpected) { + throw new IllegalStateException(String.format("Unexpected skip: expected=%,d, actual=%,d", skipExpected, skipActual)); + } buf.append(buf2); ch = in.read(); in.unread(); - //System.out.println("so far:" + buf2 + ":next:" +(char)ch); + // System.out.println("so far:" + buf2 + ":next:" +(char)ch); } else { for (int i = 0; i < count; i++) { in.unread(); @@ -187,87 +141,118 @@ private static void matchIdent( final MyByteArrayInputStream in, final StringBui do { buf2.append((char) ch); ch = in.read(); - //System.out.println("within ident:"+ (char)ch); - } while ((ch != -1) && (Character.isJavaIdentifierPart((char) ch) || (ch == '/'))); - buf.append(buf2.toString().replace('/', '.')); - //System.out.println("regular return ident:"+ (char)ch + ":" + buf2); + // System.out.println("within ident:"+ (char)ch); + } while (ch != -1 && (Character.isJavaIdentifierPart((char) ch) || ch == '/')); + buf.append(Utility.pathToPackage(buf2.toString())); + // System.out.println("regular return ident:"+ (char)ch + ":" + buf2); if (ch != -1) { in.unread(); } } - - private static void matchGJIdent( final MyByteArrayInputStream in, final StringBuilder buf ) { - int ch; - matchIdent(in, buf); - ch = in.read(); - if ((ch == '<') || ch == '(') { // Parameterized or method - //System.out.println("Enter <"); - buf.append((char) ch); - matchGJIdent(in, buf); - while (((ch = in.read()) != '>') && (ch != ')')) { // List of parameters - if (ch == -1) { - throw new IllegalArgumentException("Illegal signature: " + in.getData() - + " reaching EOF"); - } - //System.out.println("Still no >"); - buf.append(", "); - in.unread(); - matchGJIdent(in, buf); // Recursive call - } - //System.out.println("Exit >"); - buf.append((char) ch); - } else { - in.unread(); - } - ch = in.read(); - if (identStart(ch)) { - in.unread(); - matchGJIdent(in, buf); - } else if (ch == ')') { - in.unread(); - return; - } else if (ch != ';') { - throw new IllegalArgumentException("Illegal signature: " + in.getData() + " read " + (char) ch); - } - } - - - public static String translate( final String s ) { - //System.out.println("Sig:" + s); + public static String translate(final String s) { + // System.out.println("Sig:" + s); final StringBuilder buf = new StringBuilder(); matchGJIdent(new MyByteArrayInputStream(s), buf); return buf.toString(); } + private int signatureIndex; - // @since 6.0 is no longer final - public static boolean isFormalParameterList( final String s ) { - return s.startsWith("<") && (s.indexOf(':') > 0); + /** + * Construct object from file stream. + * + * @param nameIndex Index in constant pool to CONSTANT_Utf8 + * @param length Content length in bytes + * @param input Input stream + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. + */ + Signature(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, input.readUnsignedShort(), constantPool); } - - // @since 6.0 is no longer final - public static boolean isActualParameterList( final String s ) { - return s.startsWith("L") && s.endsWith(">;"); + /** + * @param nameIndex Index in constant pool to CONSTANT_Utf8 + * @param length Content length in bytes + * @param signatureIndex Index in constant pool to CONSTANT_Utf8 + * @param constantPool Array of constants + */ + public Signature(final int nameIndex, final int length, final int signatureIndex, final ConstantPool constantPool) { + super(Const.ATTR_SIGNATURE, nameIndex, Args.require(length, 2, "Signature length attribute"), constantPool); + this.signatureIndex = signatureIndex; + // validate: + Objects.requireNonNull(constantPool.getConstantUtf8(signatureIndex), "constantPool.getConstantUtf8(signatureIndex)"); } + /** + * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a + * physical copy. + * + * @param c Source to copy. + */ + public Signature(final Signature c) { + this(c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c.getConstantPool()); + } /** - * @return String representation + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object */ @Override - public String toString() { - final String s = getSignature(); - return "Signature: " + s; + public void accept(final Visitor v) { + // System.err.println("Visiting non-standard Signature object"); + v.visitSignature(this); } - /** * @return deep copy of this attribute */ @Override - public Attribute copy( final ConstantPool _constant_pool ) { + public Attribute copy(final ConstantPool constantPool) { return (Attribute) clone(); } + + /** + * Dump source file attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException if an I/O error occurs. + */ + @Override + public void dump(final DataOutputStream file) throws IOException { + super.dump(file); + file.writeShort(signatureIndex); + } + + /** + * @return GJ signature. + */ + public String getSignature() { + return super.getConstantPool().getConstantUtf8(signatureIndex).getBytes(); + } + + /** + * @return Index in constant pool of source file name. + */ + public int getSignatureIndex() { + return signatureIndex; + } + + /** + * @param signatureIndex the index info the constant pool of this signature + */ + public void setSignatureIndex(final int signatureIndex) { + this.signatureIndex = signatureIndex; + } + + /** + * @return String representation + */ + @Override + public String toString() { + return "Signature: " + getSignature(); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java index 7b3050ea427..5e4e98d94df 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java @@ -29,201 +29,155 @@ /** * @since 6.0 */ -public class SimpleElementValue extends ElementValue -{ +public class SimpleElementValue extends ElementValue { private int index; - public SimpleElementValue(final int type, final int index, final ConstantPool cpool) - { + public SimpleElementValue(final int type, final int index, final ConstantPool cpool) { super(type, cpool); this.index = index; } + @Override + public void dump(final DataOutputStream dos) throws IOException { + final int type = super.getType(); + dos.writeByte(type); // u1 kind of value + switch (type) { + case PRIMITIVE_INT: + case PRIMITIVE_BYTE: + case PRIMITIVE_CHAR: + case PRIMITIVE_FLOAT: + case PRIMITIVE_LONG: + case PRIMITIVE_BOOLEAN: + case PRIMITIVE_SHORT: + case PRIMITIVE_DOUBLE: + case STRING: + dos.writeShort(getIndex()); + break; + default: + throw new ClassFormatException("SimpleElementValue doesnt know how to write out type " + type); + } + } + /** * @return Value entry index in the cpool */ - public int getIndex() - { + public int getIndex() { return index; } - public void setIndex(final int index) - { - this.index = index; - } - - public String getValueString() - { - if (super.getType() != STRING) { - throw new IllegalStateException( - "Dont call getValueString() on a non STRING ElementValue"); - } - final ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(getIndex(), - Const.CONSTANT_Utf8); - return c.getBytes(); - } - - public int getValueInt() - { - if (super.getType() != PRIMITIVE_INT) { - throw new IllegalStateException( - "Dont call getValueString() on a non STRING ElementValue"); + public boolean getValueBoolean() { + if (super.getType() != PRIMITIVE_BOOLEAN) { + throw new IllegalStateException("Dont call getValueBoolean() on a non BOOLEAN ElementValue"); } - final ConstantInteger c = (ConstantInteger) super.getConstantPool().getConstant(getIndex(), - Const.CONSTANT_Integer); - return c.getBytes(); + final ConstantInteger bo = (ConstantInteger) super.getConstantPool().getConstant(getIndex()); + return bo.getBytes() != 0; } - public byte getValueByte() - { + public byte getValueByte() { if (super.getType() != PRIMITIVE_BYTE) { - throw new IllegalStateException( - "Dont call getValueByte() on a non BYTE ElementValue"); + throw new IllegalStateException("Dont call getValueByte() on a non BYTE ElementValue"); } - final ConstantInteger c = (ConstantInteger) super.getConstantPool().getConstant(getIndex(), - Const.CONSTANT_Integer); - return (byte) c.getBytes(); + return (byte) super.getConstantPool().getConstantInteger(getIndex()).getBytes(); } - public char getValueChar() - { + public char getValueChar() { if (super.getType() != PRIMITIVE_CHAR) { - throw new IllegalStateException( - "Dont call getValueChar() on a non CHAR ElementValue"); + throw new IllegalStateException("Dont call getValueChar() on a non CHAR ElementValue"); } - final ConstantInteger c = (ConstantInteger) super.getConstantPool().getConstant(getIndex(), - Const.CONSTANT_Integer); - return (char) c.getBytes(); + return (char) super.getConstantPool().getConstantInteger(getIndex()).getBytes(); } - public long getValueLong() - { - if (super.getType() != PRIMITIVE_LONG) { - throw new IllegalStateException( - "Dont call getValueLong() on a non LONG ElementValue"); + public double getValueDouble() { + if (super.getType() != PRIMITIVE_DOUBLE) { + throw new IllegalStateException("Dont call getValueDouble() on a non DOUBLE ElementValue"); } - final ConstantLong j = (ConstantLong) super.getConstantPool().getConstant(getIndex()); - return j.getBytes(); + final ConstantDouble d = (ConstantDouble) super.getConstantPool().getConstant(getIndex()); + return d.getBytes(); } - public float getValueFloat() - { + public float getValueFloat() { if (super.getType() != PRIMITIVE_FLOAT) { - throw new IllegalStateException( - "Dont call getValueFloat() on a non FLOAT ElementValue"); + throw new IllegalStateException("Dont call getValueFloat() on a non FLOAT ElementValue"); } final ConstantFloat f = (ConstantFloat) super.getConstantPool().getConstant(getIndex()); return f.getBytes(); } - public double getValueDouble() - { - if (super.getType() != PRIMITIVE_DOUBLE) { - throw new IllegalStateException( - "Dont call getValueDouble() on a non DOUBLE ElementValue"); + public int getValueInt() { + if (super.getType() != PRIMITIVE_INT) { + throw new IllegalStateException("Dont call getValueInt() on a non INT ElementValue"); } - final ConstantDouble d = (ConstantDouble) super.getConstantPool().getConstant(getIndex()); - return d.getBytes(); + return super.getConstantPool().getConstantInteger(getIndex()).getBytes(); } - public boolean getValueBoolean() - { - if (super.getType() != PRIMITIVE_BOOLEAN) { - throw new IllegalStateException( - "Dont call getValueBoolean() on a non BOOLEAN ElementValue"); + public long getValueLong() { + if (super.getType() != PRIMITIVE_LONG) { + throw new IllegalStateException("Dont call getValueLong() on a non LONG ElementValue"); } - final ConstantInteger bo = (ConstantInteger) super.getConstantPool().getConstant(getIndex()); - return bo.getBytes() != 0; + final ConstantLong j = (ConstantLong) super.getConstantPool().getConstant(getIndex()); + return j.getBytes(); } - public short getValueShort() - { + public short getValueShort() { if (super.getType() != PRIMITIVE_SHORT) { - throw new IllegalStateException( - "Dont call getValueShort() on a non SHORT ElementValue"); + throw new IllegalStateException("Dont call getValueShort() on a non SHORT ElementValue"); } final ConstantInteger s = (ConstantInteger) super.getConstantPool().getConstant(getIndex()); return (short) s.getBytes(); } - @Override - public String toString() - { - return stringifyValue(); + public String getValueString() { + if (super.getType() != STRING) { + throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue"); + } + return super.getConstantPool().getConstantUtf8(getIndex()).getBytes(); + } + + public void setIndex(final int index) { + this.index = index; } // Whatever kind of value it is, return it as a string @Override - public String stringifyValue() - { + public String stringifyValue() { final ConstantPool cpool = super.getConstantPool(); - final int _type = super.getType(); - switch (_type) - { + final int type = super.getType(); + switch (type) { case PRIMITIVE_INT: - final ConstantInteger c = (ConstantInteger) cpool.getConstant(getIndex(), - Const.CONSTANT_Integer); - return Integer.toString(c.getBytes()); + return Integer.toString(cpool.getConstantInteger(getIndex()).getBytes()); case PRIMITIVE_LONG: - final ConstantLong j = (ConstantLong) cpool.getConstant(getIndex(), - Const.CONSTANT_Long); + final ConstantLong j = cpool.getConstant(getIndex(), Const.CONSTANT_Long, ConstantLong.class); return Long.toString(j.getBytes()); case PRIMITIVE_DOUBLE: - final ConstantDouble d = (ConstantDouble) cpool.getConstant(getIndex(), - Const.CONSTANT_Double); + final ConstantDouble d = cpool.getConstant(getIndex(), Const.CONSTANT_Double, ConstantDouble.class); return Double.toString(d.getBytes()); case PRIMITIVE_FLOAT: - final ConstantFloat f = (ConstantFloat) cpool.getConstant(getIndex(), - Const.CONSTANT_Float); + final ConstantFloat f = cpool.getConstant(getIndex(), Const.CONSTANT_Float, ConstantFloat.class); return Float.toString(f.getBytes()); case PRIMITIVE_SHORT: - final ConstantInteger s = (ConstantInteger) cpool.getConstant(getIndex(), - Const.CONSTANT_Integer); + final ConstantInteger s = cpool.getConstantInteger(getIndex()); return Integer.toString(s.getBytes()); case PRIMITIVE_BYTE: - final ConstantInteger b = (ConstantInteger) cpool.getConstant(getIndex(), - Const.CONSTANT_Integer); + final ConstantInteger b = cpool.getConstantInteger(getIndex()); return Integer.toString(b.getBytes()); case PRIMITIVE_CHAR: - final ConstantInteger ch = (ConstantInteger) cpool.getConstant( - getIndex(), Const.CONSTANT_Integer); - return String.valueOf((char)ch.getBytes()); + final ConstantInteger ch = cpool.getConstantInteger(getIndex()); + return String.valueOf((char) ch.getBytes()); case PRIMITIVE_BOOLEAN: - final ConstantInteger bo = (ConstantInteger) cpool.getConstant( - getIndex(), Const.CONSTANT_Integer); + final ConstantInteger bo = cpool.getConstantInteger(getIndex()); if (bo.getBytes() == 0) { return "false"; } return "true"; case STRING: - final ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(getIndex(), - Const.CONSTANT_Utf8); - return cu8.getBytes(); + return cpool.getConstantUtf8(getIndex()).getBytes(); default: - throw new IllegalStateException("SimpleElementValue class does not know how to stringify type " + _type); + throw new IllegalStateException("SimpleElementValue class does not know how to stringify type " + type); } } @Override - public void dump(final DataOutputStream dos) throws IOException - { - final int _type = super.getType(); - dos.writeByte(_type); // u1 kind of value - switch (_type) - { - case PRIMITIVE_INT: - case PRIMITIVE_BYTE: - case PRIMITIVE_CHAR: - case PRIMITIVE_FLOAT: - case PRIMITIVE_LONG: - case PRIMITIVE_BOOLEAN: - case PRIMITIVE_SHORT: - case PRIMITIVE_DOUBLE: - case STRING: - dos.writeShort(getIndex()); - break; - default: - throw new IllegalStateException("SimpleElementValue doesnt know how to write out type " + _type); - } + public String toString() { + return stringifyValue(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java index dc030f5b226..e9ceed21957 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java @@ -26,88 +26,87 @@ import java.io.IOException; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class is derived from Attribute and represents a reference - * to the source file of this class. At most one SourceFile attribute - * should appear per classfile. The intention of this class is that it is - * instantiated from the Attribute.readAttribute() method. + * This class is derived from Attribute and represents a reference to the source file of this class. At most + * one SourceFile attribute should appear per classfile. The intention of this class is that it is instantiated from the + * Attribute.readAttribute() method. * - * @see Attribute + * @see Attribute */ public final class SourceFile extends Attribute { private int sourceFileIndex; - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - public SourceFile(final SourceFile c) { - this(c.getNameIndex(), c.getLength(), c.getSourceFileIndex(), c.getConstantPool()); - } - - /** * Construct object from input stream. - * @param name_index Index in constant pool to CONSTANT_Utf8 + * + * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - SourceFile(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) - throws IOException { - this(name_index, length, input.readUnsignedShort(), constant_pool); + SourceFile(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, input.readUnsignedShort(), constantPool); } - /** - * @param name_index Index in constant pool to CONSTANT_Utf8, which - * should represent the string "SourceFile". + * @param nameIndex Index in constant pool to CONSTANT_Utf8, which should represent the string "SourceFile". * @param length Content length in bytes, the value should be 2. - * @param constantPool The constant pool that this attribute is - * associated with. - * @param sourceFileIndex Index in constant pool to CONSTANT_Utf8. This - * string will be interpreted as the name of the file from which this - * class was compiled. It will not be interpreted as indicating the name - * of the directory contqining the file or an absolute path; this - * information has to be supplied the consumer of this attribute - in - * many cases, the JVM. + * @param constantPool The constant pool that this attribute is associated with. + * @param sourceFileIndex Index in constant pool to CONSTANT_Utf8. This string will be interpreted as the name of the + * file from which this class was compiled. It will not be interpreted as indicating the name of the directory + * contqining the file or an absolute path; this information has to be supplied the consumer of this attribute - + * in many cases, the JVM. */ - public SourceFile(final int name_index, final int length, final int sourceFileIndex, final ConstantPool constantPool) { - super(Const.ATTR_SOURCE_FILE, name_index, length, constantPool); - this.sourceFileIndex = sourceFileIndex; + public SourceFile(final int nameIndex, final int length, final int sourceFileIndex, final ConstantPool constantPool) { + super(Const.ATTR_SOURCE_FILE, nameIndex, Args.require(length, 2, "SourceFile length attribute"), constantPool); + this.sourceFileIndex = Args.requireU2(sourceFileIndex, 0, constantPool.getLength(), "SourceFile source file index"); } + /** + * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a + * physical copy. + * + * @param c Source to copy. + */ + public SourceFile(final SourceFile c) { + this(c.getNameIndex(), c.getLength(), c.getSourceFileIndex(), c.getConstantPool()); + } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitSourceFile(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + return (Attribute) clone(); + } /** * Dump source file attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); file.writeShort(sourceFileIndex); } - /** * @return Index in constant pool of source file name. */ @@ -115,25 +114,20 @@ public int getSourceFileIndex() { return sourceFileIndex; } - /** - * @param sourceFileIndex + * @return Source file name. */ - public void setSourceFileIndex( final int sourceFileIndex ) { - this.sourceFileIndex = sourceFileIndex; + public String getSourceFileName() { + return super.getConstantPool().getConstantUtf8(sourceFileIndex).getBytes(); } - /** - * @return Source file name. + * @param sourceFileIndex */ - public String getSourceFileName() { - final ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(sourceFileIndex, - Const.CONSTANT_Utf8); - return c.getBytes(); + public void setSourceFileIndex(final int sourceFileIndex) { + this.sourceFileIndex = sourceFileIndex; } - /** * @return String representation */ @@ -141,13 +135,4 @@ public String getSourceFileName() { public String toString() { return "SourceFile: " + getSourceFileName(); } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - return (Attribute) clone(); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java index e5f4b8c69b7..1f8ce5ea410 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java @@ -23,142 +23,144 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class represents a stack map attribute used for - * preverification of Java classes for the Java Platform, Micro Edition - * (Java ME). This attribute is used by the KVM - * and contained within the Code attribute of a method. See CLDC specification - * 5.3.1.2 + * This class represents a stack map attribute used for preverification of Java classes for the + * Java 2 Micro Edition (J2ME). This attribute is used by the + * KVM and contained within the Code attribute of a method. See CLDC + * specification 5.3.1.2 * - * @see Code - * @see StackMapEntry - * @see StackMapType + *
    + * StackMapTable_attribute {
    + *   u2              attribute_name_index;
    + *   u4              attribute_length;
    + *   u2              number_of_entries;
    + *   stack_map_frame entries[number_of_entries];
    + * }
    + * 
    + * + * @see Code + * @see StackMapEntry + * @see StackMapType * @LastModified: Oct 2020 */ public final class StackMap extends Attribute { - private StackMapEntry[] map; // Table of stack map entries + private StackMapEntry[] table; // Table of stack map entries + /** + * Construct object from input stream. + * + * @param nameIndex Index of name + * @param length Content length in bytes + * @param dataInput Input stream + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. + */ + StackMap(final int nameIndex, final int length, final DataInput dataInput, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, (StackMapEntry[]) null, constantPool); + final int mapLength = dataInput.readUnsignedShort(); + table = new StackMapEntry[mapLength]; + for (int i = 0; i < mapLength; i++) { + table[i] = new StackMapEntry(dataInput, constantPool); + } + } /* - * @param name_index Index of name + * @param nameIndex Index of name + * * @param length Content length in bytes + * * @param map Table of stack map entries - * @param constant_pool Array of constants + * + * @param constantPool Array of constants */ - public StackMap(final int name_index, final int length, final StackMapEntry[] map, final ConstantPool constant_pool) { - super(Const.ATTR_STACK_MAP, name_index, length, constant_pool); - this.map = map; + public StackMap(final int nameIndex, final int length, final StackMapEntry[] table, final ConstantPool constantPool) { + super(Const.ATTR_STACK_MAP, nameIndex, length, constantPool); + this.table = table != null ? table : StackMapEntry.EMPTY_ARRAY; + Args.requireU2(this.table.length, "table.length"); } - /** - * Construct object from input stream. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * - * @param name_index Index of name - * @param length Content length in bytes - * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * @param v Visitor object */ - StackMap(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException { - this(name_index, length, (StackMapEntry[]) null, constant_pool); - final int map_length = input.readUnsignedShort(); - map = new StackMapEntry[map_length]; - for (int i = 0; i < map_length; i++) { - map[i] = new StackMapEntry(input, constant_pool); - } + @Override + public void accept(final Visitor v) { + v.visitStackMap(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final StackMap c = (StackMap) clone(); + c.table = new StackMapEntry[table.length]; + Arrays.setAll(c.table, i -> table[i].copy()); + c.setConstantPool(constantPool); + return c; + } /** * Dump stack map table attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); - file.writeShort(map.length); - for (final StackMapEntry entry : map) { + file.writeShort(table.length); + for (final StackMapEntry entry : table) { entry.dump(file); } } + public int getMapLength() { + return table.length; + } /** * @return Array of stack map entries */ public StackMapEntry[] getStackMap() { - return map; + return table; } - /** - * @param map Array of stack map entries + * @param table Array of stack map entries */ - public void setStackMap( final StackMapEntry[] map ) { - this.map = map; + public void setStackMap(final StackMapEntry[] table) { + this.table = table != null ? table : StackMapEntry.EMPTY_ARRAY; int len = 2; // Length of 'number_of_entries' field prior to the array of stack maps - for (final StackMapEntry element : map) { + for (final StackMapEntry element : this.table) { len += element.getMapEntrySize(); } setLength(len); } - /** * @return String representation. */ @Override public String toString() { final StringBuilder buf = new StringBuilder("StackMap("); - for (int i = 0; i < map.length; i++) { - buf.append(map[i]); - if (i < map.length - 1) { + int runningOffset = -1; // no +1 on first entry + for (int i = 0; i < table.length; i++) { + runningOffset = table[i].getByteCodeOffset() + runningOffset + 1; + buf.append(String.format("%n@%03d %s", runningOffset, table[i])); + if (i < table.length - 1) { buf.append(", "); } } buf.append(')'); return buf.toString(); } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - final StackMap c = (StackMap) clone(); - c.map = new StackMapEntry[map.length]; - for (int i = 0; i < map.length; i++) { - c.map[i] = map[i].copy(); - } - c.setConstantPool(_constant_pool); - return c; - } - - - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - @Override - public void accept( final Visitor v ) { - v.visitStackMap(this); - } - - - public int getMapLength() { - return map == null ? 0 : map.length; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java index eaf233a079b..110e30392ab 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java @@ -24,18 +24,33 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; + import com.sun.org.apache.bcel.internal.Const; /** - * This class represents a stack map entry recording the types of - * local variables and the the of stack items at a given byte code offset. - * See CLDC specification 5.3.1.2 + * This class represents a stack map entry recording the types of local variables and the of stack items at a given + * byte code offset. See CLDC specification 5.3.1.2. + * + * See also https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.4 * - * @see StackMap - * @see StackMapType + *
    + * union stack_map_frame {
    + *   same_frame;
    + *   same_locals_1_stack_item_frame;
    + *   same_locals_1_stack_item_frame_extended;
    + *   chop_frame;
    + *   same_frame_extended;
    + *   append_frame;
    + *   full_frame;
    + * }
    + * 
    + * @see StackMap + * @see StackMapType */ -public final class StackMapEntry implements Node, Cloneable -{ +public final class StackMapEntry implements Node, Cloneable { + + static final StackMapEntry[] EMPTY_ARRAY = {}; private int frameType; private int byteCodeOffset; @@ -43,53 +58,49 @@ public final class StackMapEntry implements Node, Cloneable private StackMapType[] typesOfStackItems; private ConstantPool constantPool; - /** * Construct object from input stream. * - * @param input Input stream - * @throws IOException + * @param dataInput Input stream + * @throws IOException if an I/O error occurs. */ - StackMapEntry(final DataInput input, final ConstantPool constantPool) throws IOException { - this(input.readByte() & 0xFF, -1, null, null, constantPool); + StackMapEntry(final DataInput dataInput, final ConstantPool constantPool) throws IOException { + this(dataInput.readByte() & 0xFF, -1, null, null, constantPool); if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) { byteCodeOffset = frameType - Const.SAME_FRAME; - } else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && - frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { + } else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { byteCodeOffset = frameType - Const.SAME_LOCALS_1_STACK_ITEM_FRAME; - typesOfStackItems = new StackMapType[1]; - typesOfStackItems[0] = new StackMapType(input, constantPool); + typesOfStackItems = new StackMapType[] { new StackMapType(dataInput, constantPool) }; } else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { - byteCodeOffset = input.readShort(); - typesOfStackItems = new StackMapType[1]; - typesOfStackItems[0] = new StackMapType(input, constantPool); + byteCodeOffset = dataInput.readUnsignedShort(); + typesOfStackItems = new StackMapType[] { new StackMapType(dataInput, constantPool) }; } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) { - byteCodeOffset = input.readShort(); + byteCodeOffset = dataInput.readUnsignedShort(); } else if (frameType == Const.SAME_FRAME_EXTENDED) { - byteCodeOffset = input.readShort(); + byteCodeOffset = dataInput.readUnsignedShort(); } else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) { - byteCodeOffset = input.readShort(); - final int number_of_locals = frameType - 251; - typesOfLocals = new StackMapType[number_of_locals]; - for (int i = 0; i < number_of_locals; i++) { - typesOfLocals[i] = new StackMapType(input, constantPool); + byteCodeOffset = dataInput.readUnsignedShort(); + final int numberOfLocals = frameType - 251; + typesOfLocals = new StackMapType[numberOfLocals]; + for (int i = 0; i < numberOfLocals; i++) { + typesOfLocals[i] = new StackMapType(dataInput, constantPool); } } else if (frameType == Const.FULL_FRAME) { - byteCodeOffset = input.readShort(); - final int number_of_locals = input.readShort(); - typesOfLocals = new StackMapType[number_of_locals]; - for (int i = 0; i < number_of_locals; i++) { - typesOfLocals[i] = new StackMapType(input, constantPool); + byteCodeOffset = dataInput.readUnsignedShort(); + final int numberOfLocals = dataInput.readUnsignedShort(); + typesOfLocals = new StackMapType[numberOfLocals]; + for (int i = 0; i < numberOfLocals; i++) { + typesOfLocals[i] = new StackMapType(dataInput, constantPool); } - final int number_of_stack_items = input.readShort(); - typesOfStackItems = new StackMapType[number_of_stack_items]; - for (int i = 0; i < number_of_stack_items; i++) { - typesOfStackItems[i] = new StackMapType(input, constantPool); + final int numberOfStackItems = dataInput.readUnsignedShort(); + typesOfStackItems = new StackMapType[numberOfStackItems]; + for (int i = 0; i < numberOfStackItems; i++) { + typesOfStackItems[i] = new StackMapType(dataInput, constantPool); } } else { /* Can't happen */ - throw new ClassFormatException ("Invalid frame type found while parsing stack map table: " + frameType); + throw new ClassFormatException("Invalid frame type found while parsing stack map table: " + frameType); } } @@ -102,17 +113,21 @@ public final class StackMapEntry implements Node, Cloneable * @param numberOfStackItems NOT USED * @param typesOfStackItems array ot {@link StackMapType}s of stack items * @param constantPool the constant pool - * @deprecated Since 6.0, use {@link #StackMapEntry(int, int, StackMapType[], StackMapType[], ConstantPool)} - * instead + * @deprecated Since 6.0, use {@link #StackMapEntry(int, int, StackMapType[], StackMapType[], ConstantPool)} instead */ @java.lang.Deprecated - public StackMapEntry(final int byteCodeOffset, final int numberOfLocals, - final StackMapType[] typesOfLocals, final int numberOfStackItems, - final StackMapType[] typesOfStackItems, final ConstantPool constantPool) { + public StackMapEntry(final int byteCodeOffset, final int numberOfLocals, final StackMapType[] typesOfLocals, final int numberOfStackItems, + final StackMapType[] typesOfStackItems, final ConstantPool constantPool) { this.byteCodeOffset = byteCodeOffset; - this.typesOfLocals = typesOfLocals != null ? typesOfLocals : new StackMapType[0]; - this.typesOfStackItems = typesOfStackItems != null ? typesOfStackItems : new StackMapType[0]; + this.typesOfLocals = typesOfLocals != null ? typesOfLocals : StackMapType.EMPTY_ARRAY; + this.typesOfStackItems = typesOfStackItems != null ? typesOfStackItems : StackMapType.EMPTY_ARRAY; this.constantPool = constantPool; + if (numberOfLocals < 0) { + throw new IllegalArgumentException("numberOfLocals < 0"); + } + if (numberOfStackItems < 0) { + throw new IllegalArgumentException("numberOfStackItems < 0"); + } } /** @@ -124,29 +139,53 @@ public StackMapEntry(final int byteCodeOffset, final int numberOfLocals, * @param typesOfStackItems array ot {@link StackMapType}s of stack items * @param constantPool the constant pool */ - public StackMapEntry(final int tag, final int byteCodeOffset, - final StackMapType[] typesOfLocals, - final StackMapType[] typesOfStackItems, final ConstantPool constantPool) { + public StackMapEntry(final int tag, final int byteCodeOffset, final StackMapType[] typesOfLocals, final StackMapType[] typesOfStackItems, + final ConstantPool constantPool) { this.frameType = tag; this.byteCodeOffset = byteCodeOffset; - this.typesOfLocals = typesOfLocals != null ? typesOfLocals : new StackMapType[0]; - this.typesOfStackItems = typesOfStackItems != null ? typesOfStackItems : new StackMapType[0]; + this.typesOfLocals = typesOfLocals != null ? typesOfLocals : StackMapType.EMPTY_ARRAY; + this.typesOfStackItems = typesOfStackItems != null ? typesOfStackItems : StackMapType.EMPTY_ARRAY; this.constantPool = constantPool; } + /** + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitStackMapEntry(this); + } + + /** + * @return deep copy of this object + */ + public StackMapEntry copy() { + StackMapEntry e; + try { + e = (StackMapEntry) clone(); + } catch (final CloneNotSupportedException ex) { + throw new Error("Clone Not Supported"); + } + + e.typesOfLocals = new StackMapType[typesOfLocals.length]; + Arrays.setAll(e.typesOfLocals, i -> typesOfLocals[i].copy()); + e.typesOfStackItems = new StackMapType[typesOfStackItems.length]; + Arrays.setAll(e.typesOfStackItems, i -> typesOfStackItems[i].copy()); + return e; + } /** * Dump stack map entry * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.write(frameType); - if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) { - // nothing to be done - } else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && - frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { + if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { typesOfStackItems[0].dump(file); } else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { file.writeShort(byteCodeOffset); @@ -170,63 +209,26 @@ public void dump( final DataOutputStream file ) throws IOException { for (final StackMapType type : typesOfStackItems) { type.dump(file); } - } else { + } else if (!(frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX)) { /* Can't happen */ - throw new ClassFormatException ("Invalid Stack map table tag: " + frameType); + throw new ClassFormatException("Invalid Stack map table tag: " + frameType); } } + public int getByteCodeOffset() { + return byteCodeOffset; + } /** - * @return String representation. + * @return Constant pool used by this object. */ - @Override - public String toString() { - final StringBuilder buf = new StringBuilder(64); - buf.append("("); - if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) { - buf.append("SAME"); - } else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && - frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { - buf.append("SAME_LOCALS_1_STACK"); - } else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { - buf.append("SAME_LOCALS_1_STACK_EXTENDED"); - } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) { - buf.append("CHOP ").append(String.valueOf(251-frameType)); - } else if (frameType == Const.SAME_FRAME_EXTENDED) { - buf.append("SAME_EXTENDED"); - } else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) { - buf.append("APPEND ").append(String.valueOf(frameType-251)); - } else if (frameType == Const.FULL_FRAME) { - buf.append("FULL"); - } else { - buf.append("UNKNOWN (").append(frameType).append(")"); - } - buf.append(", offset delta=").append(byteCodeOffset); - if (typesOfLocals.length > 0) { - buf.append(", locals={"); - for (int i = 0; i < typesOfLocals.length; i++) { - buf.append(typesOfLocals[i]); - if (i < typesOfLocals.length - 1) { - buf.append(", "); - } - } - buf.append("}"); - } - if (typesOfStackItems.length > 0) { - buf.append(", stack items={"); - for (int i = 0; i < typesOfStackItems.length; i++) { - buf.append(typesOfStackItems[i]); - if (i < typesOfStackItems.length - 1) { - buf.append(", "); - } - } - buf.append("}"); - } - buf.append(")"); - return buf.toString(); + public ConstantPool getConstantPool() { + return constantPool; } + public int getFrameType() { + return frameType; + } /** * Calculate stack map entry size @@ -235,205 +237,183 @@ public String toString() { int getMapEntrySize() { if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) { return 1; - } else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && - frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { + } + if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { return 1 + (typesOfStackItems[0].hasIndex() ? 3 : 1); - } else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { + } + if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { return 3 + (typesOfStackItems[0].hasIndex() ? 3 : 1); - } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) { - return 3; - } else if (frameType == Const.SAME_FRAME_EXTENDED) { + } + if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX || frameType == Const.SAME_FRAME_EXTENDED) { return 3; - } else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) { + } + if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) { int len = 3; - for (final StackMapType types_of_local : typesOfLocals) { - len += types_of_local.hasIndex() ? 3 : 1; - } - return len; - } else if (frameType == Const.FULL_FRAME) { - int len = 7; - for (final StackMapType types_of_local : typesOfLocals) { - len += types_of_local.hasIndex() ? 3 : 1; - } - for (final StackMapType types_of_stack_item : typesOfStackItems) { - len += types_of_stack_item.hasIndex() ? 3 : 1; + for (final StackMapType typesOfLocal : typesOfLocals) { + len += typesOfLocal.hasIndex() ? 3 : 1; } return len; - } else { + } + if (frameType != Const.FULL_FRAME) { throw new IllegalStateException("Invalid StackMap frameType: " + frameType); } + int len = 7; + for (final StackMapType typesOfLocal : typesOfLocals) { + len += typesOfLocal.hasIndex() ? 3 : 1; + } + for (final StackMapType typesOfStackItem : typesOfStackItems) { + len += typesOfStackItem.hasIndex() ? 3 : 1; + } + return len; } + public int getNumberOfLocals() { + return typesOfLocals.length; + } - public void setFrameType( final int f ) { - if (f >= Const.SAME_FRAME && f <= Const.SAME_FRAME_MAX) { - byteCodeOffset = f - Const.SAME_FRAME; - } else if (f >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && - f <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { - byteCodeOffset = f - Const.SAME_LOCALS_1_STACK_ITEM_FRAME; - } else if (f == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { // CHECKSTYLE IGNORE EmptyBlock - } else if (f >= Const.CHOP_FRAME && f <= Const.CHOP_FRAME_MAX) { // CHECKSTYLE IGNORE EmptyBlock - } else if (f == Const.SAME_FRAME_EXTENDED) { // CHECKSTYLE IGNORE EmptyBlock - } else if (f >= Const.APPEND_FRAME && f <= Const.APPEND_FRAME_MAX) { // CHECKSTYLE IGNORE EmptyBlock - } else if (f == Const.FULL_FRAME) { // CHECKSTYLE IGNORE EmptyBlock - } else { - throw new IllegalArgumentException("Invalid StackMap frameType"); - } - frameType = f; + public int getNumberOfStackItems() { + return typesOfStackItems.length; } + public StackMapType[] getTypesOfLocals() { + return typesOfLocals; + } - public int getFrameType() { - return frameType; + public StackMapType[] getTypesOfStackItems() { + return typesOfStackItems; } + private boolean invalidFrameType(final int f) { + // @formatter:off + return f != Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED + && !(f >= Const.CHOP_FRAME && f <= Const.CHOP_FRAME_MAX) + && f != Const.SAME_FRAME_EXTENDED + && !(f >= Const.APPEND_FRAME && f <= Const.APPEND_FRAME_MAX) + && f != Const.FULL_FRAME; + // @formatter:on + } - public void setByteCodeOffset( final int new_offset ) { - if (new_offset < 0 || new_offset > 32767) { - throw new IllegalArgumentException("Invalid StackMap offset: " + new_offset); + public void setByteCodeOffset(final int newOffset) { + if (newOffset < 0 || newOffset > 32767) { + throw new IllegalArgumentException("Invalid StackMap offset: " + newOffset); } - if (frameType >= Const.SAME_FRAME && - frameType <= Const.SAME_FRAME_MAX) { - if (new_offset > Const.SAME_FRAME_MAX) { + if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) { + if (newOffset > Const.SAME_FRAME_MAX) { frameType = Const.SAME_FRAME_EXTENDED; } else { - frameType = new_offset; + frameType = newOffset; } - } else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && - frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { - if (new_offset > Const.SAME_FRAME_MAX) { + } else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { + if (newOffset > Const.SAME_FRAME_MAX) { frameType = Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED; } else { - frameType = Const.SAME_LOCALS_1_STACK_ITEM_FRAME + new_offset; + frameType = Const.SAME_LOCALS_1_STACK_ITEM_FRAME + newOffset; } - } else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { // CHECKSTYLE IGNORE EmptyBlock - } else if (frameType >= Const.CHOP_FRAME && - frameType <= Const.CHOP_FRAME_MAX) { // CHECKSTYLE IGNORE EmptyBlock - } else if (frameType == Const.SAME_FRAME_EXTENDED) { // CHECKSTYLE IGNORE EmptyBlock - } else if (frameType >= Const.APPEND_FRAME && - frameType <= Const.APPEND_FRAME_MAX) { // CHECKSTYLE IGNORE EmptyBlock - } else if (frameType == Const.FULL_FRAME) { // CHECKSTYLE IGNORE EmptyBlock - } else { + } else if (invalidFrameType(frameType)) { throw new IllegalStateException("Invalid StackMap frameType: " + frameType); } - byteCodeOffset = new_offset; + byteCodeOffset = newOffset; } - /** - * Update the distance (as an offset delta) from this StackMap - * entry to the next. Note that this might cause the the - * frame type to change. Note also that delta may be negative. - * - * @param delta offset delta + * @param constantPool Constant pool to be used for this object. */ - public void updateByteCodeOffset(final int delta) { - setByteCodeOffset(byteCodeOffset + delta); + public void setConstantPool(final ConstantPool constantPool) { + this.constantPool = constantPool; } - - public int getByteCodeOffset() { - return byteCodeOffset; + public void setFrameType(final int ft) { + if (ft >= Const.SAME_FRAME && ft <= Const.SAME_FRAME_MAX) { + byteCodeOffset = ft - Const.SAME_FRAME; + } else if (ft >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && ft <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { + byteCodeOffset = ft - Const.SAME_LOCALS_1_STACK_ITEM_FRAME; + } else if (invalidFrameType(ft)) { + throw new IllegalArgumentException("Invalid StackMap frameType"); + } + frameType = ft; } - /** * * @deprecated since 6.0 */ @java.lang.Deprecated - public void setNumberOfLocals( final int n ) { // TODO unused - } - - - public int getNumberOfLocals() { - return typesOfLocals.length; + public void setNumberOfLocals(final int n) { // TODO unused } - - public void setTypesOfLocals( final StackMapType[] types ) { - typesOfLocals = types != null ? types : new StackMapType[0]; - } - - - public StackMapType[] getTypesOfLocals() { - return typesOfLocals; - } - - /** * * @deprecated since 6.0 */ @java.lang.Deprecated - public void setNumberOfStackItems( final int n ) { // TODO unused - } - - - public int getNumberOfStackItems() { - return typesOfStackItems.length; + public void setNumberOfStackItems(final int n) { // TODO unused } - - public void setTypesOfStackItems( final StackMapType[] types ) { - typesOfStackItems = types != null ? types : new StackMapType[0]; + public void setTypesOfLocals(final StackMapType[] types) { + typesOfLocals = types != null ? types : StackMapType.EMPTY_ARRAY; } - - public StackMapType[] getTypesOfStackItems() { - return typesOfStackItems; + public void setTypesOfStackItems(final StackMapType[] types) { + typesOfStackItems = types != null ? types : StackMapType.EMPTY_ARRAY; } - /** - * @return deep copy of this object + * @return String representation. */ - public StackMapEntry copy() { - StackMapEntry e; - try { - e = (StackMapEntry) clone(); - } catch (final CloneNotSupportedException ex) { - throw new Error("Clone Not Supported"); + @Override + public String toString() { + final StringBuilder buf = new StringBuilder(64); + buf.append("("); + if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) { + buf.append("SAME"); + } else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { + buf.append("SAME_LOCALS_1_STACK"); + } else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { + buf.append("SAME_LOCALS_1_STACK_EXTENDED"); + } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) { + buf.append("CHOP ").append(String.valueOf(251 - frameType)); + } else if (frameType == Const.SAME_FRAME_EXTENDED) { + buf.append("SAME_EXTENDED"); + } else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) { + buf.append("APPEND ").append(String.valueOf(frameType - 251)); + } else if (frameType == Const.FULL_FRAME) { + buf.append("FULL"); + } else { + buf.append("UNKNOWN (").append(frameType).append(")"); } - - e.typesOfLocals = new StackMapType[typesOfLocals.length]; - for (int i = 0; i < typesOfLocals.length; i++) { - e.typesOfLocals[i] = typesOfLocals[i].copy(); + buf.append(", offset delta=").append(byteCodeOffset); + if (typesOfLocals.length > 0) { + buf.append(", locals={"); + for (int i = 0; i < typesOfLocals.length; i++) { + buf.append(typesOfLocals[i]); + if (i < typesOfLocals.length - 1) { + buf.append(", "); + } + } + buf.append("}"); } - e.typesOfStackItems = new StackMapType[typesOfStackItems.length]; - for (int i = 0; i < typesOfStackItems.length; i++) { - e.typesOfStackItems[i] = typesOfStackItems[i].copy(); + if (typesOfStackItems.length > 0) { + buf.append(", stack items={"); + for (int i = 0; i < typesOfStackItems.length; i++) { + buf.append(typesOfStackItems[i]); + if (i < typesOfStackItems.length - 1) { + buf.append(", "); + } + } + buf.append("}"); } - return e; + buf.append(")"); + return buf.toString(); } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Update the distance (as an offset delta) from this StackMap entry to the next. Note that this might cause the + * frame type to change. Note also that delta may be negative. * - * @param v Visitor object - */ - @Override - public void accept( final Visitor v ) { - v.visitStackMapEntry(this); - } - - - /** - * @return Constant pool used by this object. - */ - public ConstantPool getConstantPool() { - return constantPool; - } - - - /** - * @param constantPool Constant pool to be used for this object. + * @param delta offset delta */ - public void setConstantPool( final ConstantPool constantPool ) { - this.constantPool = constantPool; + public void updateByteCodeOffset(final int delta) { + setByteCodeOffset(byteCodeOffset + delta); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java index 8d7c3871a09..4575b31dfce 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java @@ -28,143 +28,135 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This class represents the type of a local variable or item on stack - * used in the StackMap entries. + * This class represents the type of a local variable or item on stack used in the StackMap entries. * - * @see StackMapEntry - * @see StackMap - * @see Const + * @see StackMapEntry + * @see StackMap + * @see Const */ public final class StackMapType implements Cloneable { + public static final StackMapType[] EMPTY_ARRAY = {}; // must be public because BCELifier code generator writes calls to it + private byte type; private int index = -1; // Index to CONSTANT_Class or offset private ConstantPool constantPool; - - /** - * Construct object from file stream. - * @param file Input stream - * @throws IOException - */ - StackMapType(final DataInput file, final ConstantPool constant_pool) throws IOException { - this(file.readByte(), -1, constant_pool); - if (hasIndex()) { - this.index = file.readShort(); - } - this.constantPool = constant_pool; - } - - /** * @param type type tag as defined in the Constants interface * @param index index to constant pool, or byte code offset */ - public StackMapType(final byte type, final int index, final ConstantPool constant_pool) { - if ((type < Const.ITEM_Bogus) || (type > Const.ITEM_NewObject)) { - throw new IllegalArgumentException("Illegal type for StackMapType: " + type); - } - this.type = type; + public StackMapType(final byte type, final int index, final ConstantPool constantPool) { + this.type = checkType(type); this.index = index; - this.constantPool = constant_pool; + this.constantPool = constantPool; } - - public void setType( final byte t ) { - if ((t < Const.ITEM_Bogus) || (t > Const.ITEM_NewObject)) { - throw new IllegalArgumentException("Illegal type for StackMapType: " + t); + /** + * Construct object from file stream. + * + * @param file Input stream + * @throws IOException if an I/O error occurs. + */ + StackMapType(final DataInput file, final ConstantPool constantPool) throws IOException { + this(file.readByte(), -1, constantPool); + if (hasIndex()) { + this.index = file.readUnsignedShort(); } - type = t; + this.constantPool = constantPool; } - - public byte getType() { + private byte checkType(final byte type) { + if (type < Const.ITEM_Bogus || type > Const.ITEM_NewObject) { + throw new ClassFormatException("Illegal type for StackMapType: " + type); + } return type; } - - public void setIndex( final int t ) { - index = t; - } - - - /** @return index to constant pool if type == ITEM_Object, or offset - * in byte code, if type == ITEM_NewObject, and -1 otherwise + /** + * @return deep copy of this object */ - public int getIndex() { - return index; + public StackMapType copy() { + try { + return (StackMapType) clone(); + } catch (final CloneNotSupportedException e) { + // TODO should this throw? + } + return null; } - /** * Dump type entries to file. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { file.writeByte(type); if (hasIndex()) { file.writeShort(getIndex()); } } + /** + * @return Constant pool used by this object. + */ + public ConstantPool getConstantPool() { + return constantPool; + } - /** @return true, if type is either ITEM_Object or ITEM_NewObject + /** + * @return index to constant pool if type == ITEM_Object, or offset in byte code, if type == ITEM_NewObject, and -1 + * otherwise + */ + public int getIndex() { + return index; + } + + public byte getType() { + return type; + } + + /** + * @return true, if type is either ITEM_Object or ITEM_NewObject */ public boolean hasIndex() { return type == Const.ITEM_Object || type == Const.ITEM_NewObject; } - private String printIndex() { if (type == Const.ITEM_Object) { if (index < 0) { return ", class="; } return ", class=" + constantPool.constantToString(index, Const.CONSTANT_Class); - } else if (type == Const.ITEM_NewObject) { + } + if (type == Const.ITEM_NewObject) { return ", offset=" + index; - } else { - return ""; } + return ""; } - /** - * @return String representation + * @param constantPool Constant pool to be used for this object. */ - @Override - public String toString() { - return "(type=" + Const.getItemName(type) + printIndex() + ")"; + public void setConstantPool(final ConstantPool constantPool) { + this.constantPool = constantPool; } - - /** - * @return deep copy of this object - */ - public StackMapType copy() { - try { - return (StackMapType) clone(); - } catch (final CloneNotSupportedException e) { - // TODO should this throw? - } - return null; + public void setIndex(final int index) { + this.index = index; } - - /** - * @return Constant pool used by this object. - */ - public ConstantPool getConstantPool() { - return constantPool; + public void setType(final byte type) { + this.type = checkType(type); } - /** - * @param constantPool Constant pool to be used for this object. + * @return String representation */ - public void setConstantPool( final ConstantPool constantPool ) { - this.constantPool = constantPool; + @Override + public String toString() { + return "(type=" + Const.getItemName(type) + printIndex() + ")"; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java index 4cd5827f950..3683fd6437e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java @@ -26,58 +26,42 @@ import java.io.IOException; import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; /** - * This class is derived from Attribute and declares this class as - * `synthetic', i.e., it needs special handling. The JVM specification - * states "A class member that does not appear in the source code must be - * marked using a Synthetic attribute." It may appear in the ClassFile - * attribute table, a field_info table or a method_info table. This class - * is intended to be instantiated from the - * Attribute.readAttribute() method. + * This class is derived from Attribute and declares this class as 'synthetic', i.e., it needs special + * handling. The JVM specification states "A class member that does not appear in the source code must be marked using a + * Synthetic attribute." It may appear in the ClassFile attribute table, a field_info table or a method_info table. This + * class is intended to be instantiated from the Attribute.readAttribute() method. * - * @see Attribute + * @see Attribute */ public final class Synthetic extends Attribute { private byte[] bytes; - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use copy() for a physical copy. - */ - public Synthetic(final Synthetic c) { - this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool()); - } - - /** - * @param name_index Index in constant pool to CONSTANT_Utf8, which - * should represent the string "Synthetic". + * @param nameIndex Index in constant pool to CONSTANT_Utf8, which should represent the string "Synthetic". * @param length Content length in bytes - should be zero. * @param bytes Attribute contents - * @param constant_pool The constant pool this attribute is associated - * with. + * @param constantPool The constant pool this attribute is associated with. */ - public Synthetic(final int name_index, final int length, final byte[] bytes, final ConstantPool constant_pool) { - super(Const.ATTR_SYNTHETIC, name_index, length, constant_pool); + public Synthetic(final int nameIndex, final int length, final byte[] bytes, final ConstantPool constantPool) { + super(Const.ATTR_SYNTHETIC, nameIndex, Args.require0(length, "Synthetic attribute length"), constantPool); this.bytes = bytes; } - /** * Construct object from input stream. * - * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - Synthetic(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) - throws IOException { - this(name_index, length, (byte[]) null, constant_pool); + Synthetic(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, (byte[]) null, constantPool); if (length > 0) { bytes = new byte[length]; input.readFully(bytes); @@ -85,35 +69,54 @@ public Synthetic(final int name_index, final int length, final byte[] bytes, fin } } + /** + * Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a + * physical copy. + * + * @param c Source to copy. + */ + public Synthetic(final Synthetic c) { + this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool()); + } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitSynthetic(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final Synthetic c = (Synthetic) clone(); + if (bytes != null) { + c.bytes = bytes.clone(); + } + c.setConstantPool(constantPool); + return c; + } /** * Dump source file attribute to file stream in binary format. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); if (super.getLength() > 0) { file.write(bytes, 0, super.getLength()); } } - /** * @return data bytes. */ @@ -121,15 +124,13 @@ public byte[] getBytes() { return bytes; } - /** * @param bytes */ - public void setBytes( final byte[] bytes ) { + public void setBytes(final byte[] bytes) { this.bytes = bytes; } - /** * @return String representation. */ @@ -141,19 +142,4 @@ public String toString() { } return buf.toString(); } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - final Synthetic c = (Synthetic) clone(); - if (bytes != null) { - c.bytes = new byte[bytes.length]; - System.arraycopy(bytes, 0, c.bytes, 0, bytes.length); - } - c.setConstantPool(_constant_pool); - return c; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Unknown.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Unknown.java index 9b93a91e0c9..3500e472c85 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Unknown.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Unknown.java @@ -24,19 +24,15 @@ import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; +import java.util.Arrays; import com.sun.org.apache.bcel.internal.Const; /** - * This class represents a reference to an unknown (i.e., - * application-specific) attribute of a class. It is instantiated from the - * {@link Attribute#readAttribute(java.io.DataInput, ConstantPool)} method. - * Applications that need to read in application-specific attributes should create an - * {@link UnknownAttributeReader} implementation and attach it via + * This class represents a reference to an unknown (i.e., application-specific) attribute of a class. It is instantiated + * from the {@link Attribute#readAttribute(java.io.DataInput, ConstantPool)} method. Applications that need to read in + * application-specific attributes should create an {@link UnknownAttributeReader} implementation and attach it via * {@link Attribute#addAttributeReader(String, UnknownAttributeReader)}. - * * @see Attribute * @see UnknownAttributeReader @@ -44,93 +40,87 @@ public final class Unknown extends Attribute { private byte[] bytes; - private final String name; - private static final Map unknownAttributes = new HashMap<>(); - - - /** @return array of unknown attributes, but just one for each kind. - */ - static Unknown[] getUnknownAttributes() { - final Unknown[] unknowns = new Unknown[unknownAttributes.size()]; - unknownAttributes.values().toArray(unknowns); - unknownAttributes.clear(); - return unknowns; - } - - - /** - * Initialize from another object. Note that both objects use the same - * references (shallow copy). Use clone() for a physical copy. - */ - public Unknown(final Unknown c) { - this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool()); - } + private final String name; /** - * Create a non-standard attribute. + * Constructs a new instance for a non-standard attribute. * - * @param name_index Index in constant pool + * @param nameIndex Index in constant pool * @param length Content length in bytes * @param bytes Attribute contents - * @param constant_pool Array of constants + * @param constantPool Array of constants */ - public Unknown(final int name_index, final int length, final byte[] bytes, final ConstantPool constant_pool) { - super(Const.ATTR_UNKNOWN, name_index, length, constant_pool); + public Unknown(final int nameIndex, final int length, final byte[] bytes, final ConstantPool constantPool) { + super(Const.ATTR_UNKNOWN, nameIndex, length, constantPool); this.bytes = bytes; - name = ((ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8)) - .getBytes(); - unknownAttributes.put(name, this); + this.name = constantPool.getConstantUtf8(nameIndex).getBytes(); } - /** - * Construct object from input stream. + * Constructs a new instance from an input stream. * - * @param name_index Index in constant pool + * @param nameIndex Index in constant pool * @param length Content length in bytes * @param input Input stream - * @param constant_pool Array of constants - * @throws IOException + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. */ - Unknown(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) - throws IOException { - this(name_index, length, (byte[]) null, constant_pool); + Unknown(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException { + this(nameIndex, length, (byte[]) null, constantPool); if (length > 0) { bytes = new byte[length]; input.readFully(bytes); } } + /** + * Constructs a new instance from another instance. Note that both objects use the same references (shallow copy). Use clone() for a physical copy. + * + * @param unknown Source. + */ + public Unknown(final Unknown unknown) { + this(unknown.getNameIndex(), unknown.getLength(), unknown.getBytes(), unknown.getConstantPool()); + } /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. + * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. + * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitUnknown(this); } + /** + * @return deep copy of this attribute + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final Unknown c = (Unknown) clone(); + if (bytes != null) { + c.bytes = bytes.clone(); + } + c.setConstantPool(constantPool); + return c; + } /** - * Dump unknown bytes to file stream. + * Dumps unknown bytes to file stream. * * @param file Output file stream - * @throws IOException + * @throws IOException if an I/O error occurs. */ @Override - public void dump( final DataOutputStream file ) throws IOException { + public void dump(final DataOutputStream file) throws IOException { super.dump(file); if (super.getLength() > 0) { file.write(bytes, 0, super.getLength()); } } - /** * @return data bytes. */ @@ -138,7 +128,6 @@ public byte[] getBytes() { return bytes; } - /** * @return name of attribute. */ @@ -147,15 +136,13 @@ public String getName() { return name; } - /** * @param bytes the bytes to set */ - public void setBytes( final byte[] bytes ) { + public void setBytes(final byte[] bytes) { this.bytes = bytes; } - /** * @return String representation. */ @@ -165,28 +152,13 @@ public String toString() { return "(Unknown attribute " + name + ")"; } String hex; - if (super.getLength() > 10) { - final byte[] tmp = new byte[10]; - System.arraycopy(bytes, 0, tmp, 0, 10); + final int limit = 10; + if (super.getLength() > limit) { + final byte[] tmp = Arrays.copyOf(bytes, limit); hex = Utility.toHexString(tmp) + "... (truncated)"; } else { hex = Utility.toHexString(bytes); } return "(Unknown attribute " + name + ": " + hex + ")"; } - - - /** - * @return deep copy of this attribute - */ - @Override - public Attribute copy( final ConstantPool _constant_pool ) { - final Unknown c = (Unknown) clone(); - if (bytes != null) { - c.bytes = new byte[bytes.length]; - System.arraycopy(bytes, 0, c.bytes, 0, bytes.length); - } - c.setConstantPool(_constant_pool); - return c; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/UnknownAttributeReader.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/UnknownAttributeReader.java index f08266e5ba2..2c1cae9ee3d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/UnknownAttributeReader.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/UnknownAttributeReader.java @@ -22,9 +22,8 @@ package com.sun.org.apache.bcel.internal.classfile; /** - * Unknown (non-standard) attributes may be read via user-defined factory - * objects that can be registered with the Attribute.addAttributeReader - * method. These factory objects should implement this interface. + * Unknown (non-standard) attributes may be read via user-defined factory objects that can be registered with the + * Attribute.addAttributeReader method. These factory objects should implement this interface. * * @see Attribute * @since 6.0 @@ -32,22 +31,20 @@ public interface UnknownAttributeReader { /** - * When this attribute reader is added via the static method Attribute.addAttributeReader, - * an attribute name is associated with it. As the class file parser parses attributes, - * it will call various AttributeReaders based on the name of the attributes it is constructing. + * When this attribute reader is added via the static method Attribute.addAttributeReader, an attribute name is + * associated with it. As the class file parser parses attributes, it will call various AttributeReaders based on the + * name of the attributes it is constructing. * - * @param name_index An index into the constant pool, indexing a ConstantUtf8 - * that represents the name of the attribute. - * @param length The length of the data contained in the attribute. This is written - * into the constant pool and should agree with what the factory expects the length to be. - * @param file This is the data input that the factory needs to read its data from. - * @param constant_pool This is the constant pool associated with the Attribute that we are constructing. + * @param nameIndex An index into the constant pool, indexing a ConstantUtf8 that represents the name of the attribute. + * @param length The length of the data contained in the attribute. This is written into the constant pool and should + * agree with what the factory expects the length to be. + * @param file This is the data input that the factory needs to read its data from. + * @param constantPool This is the constant pool associated with the Attribute that we are constructing. * - * @return The user-defined AttributeReader should take this data and use - * it to construct an attribute. In the case of errors, a null can be - * returned which will cause the parsing of the class file to fail. + * @return The user-defined AttributeReader should take this data and use it to construct an attribute. In the case of + * errors, a null can be returned which will cause the parsing of the class file to fail. * * @see Attribute#addAttributeReader(String, UnknownAttributeReader) */ - Attribute createAttribute( int name_index, int length, java.io.DataInput file, ConstantPool constant_pool ); + Attribute createAttribute(int nameIndex, int length, java.io.DataInput file, ConstantPool constantPool); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java index 8577bdff728..12dbbe4828a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,6 +31,7 @@ import java.io.Reader; import java.io.Writer; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.zip.GZIPInputStream; @@ -42,78 +43,167 @@ /** * Utility functions that do not really belong to any class in particular. * - * @LastModified: May 2021 + * @LastModified: Feb 2023 */ // @since 6.0 methods are no longer final public abstract class Utility { - private static int unwrap( final ThreadLocal tl ) { - return tl.get(); - } + /** + * Decode characters into bytes. Used by decode() + */ + private static class JavaReader extends FilterReader { - private static void wrap( final ThreadLocal tl, final int value ) { - tl.set(value); + public JavaReader(final Reader in) { + super(in); + } + + @Override + public int read() throws IOException { + final int b = in.read(); + if (b != ESCAPE_CHAR) { + return b; + } + final int i = in.read(); + if (i < 0) { + return -1; + } + if (i >= '0' && i <= '9' || i >= 'a' && i <= 'f') { // Normal escape + final int j = in.read(); + if (j < 0) { + return -1; + } + final char[] tmp = {(char) i, (char) j}; + return Integer.parseInt(new String(tmp), 16); + } + return MAP_CHAR[i]; + } + + @Override + public int read(final char[] cbuf, final int off, final int len) throws IOException { + for (int i = 0; i < len; i++) { + cbuf[off + i] = (char) read(); + } + return len; + } } - /* How many chars have been consumed - * during parsing in typeSignatureToString(). - * Read by methodSignatureToString(). - * Set by side effect, but only internally. + /** + * Encode bytes into valid java identifier characters. Used by + * encode() */ - private static ThreadLocal consumed_chars = new ThreadLocal() { + private static class JavaWriter extends FilterWriter { + + public JavaWriter(final Writer out) { + super(out); + } + + @Override + public void write(final char[] cbuf, final int off, final int len) throws IOException { + for (int i = 0; i < len; i++) { + write(cbuf[off + i]); + } + } + + @Override + public void write(final int b) throws IOException { + if (isJavaIdentifierPart((char) b) && b != ESCAPE_CHAR) { + out.write(b); + } else { + out.write(ESCAPE_CHAR); // Escape character + // Special escape + if (b >= 0 && b < FREE_CHARS) { + out.write(CHAR_MAP[b]); + } else { // Normal escape + final char[] tmp = Integer.toHexString(b).toCharArray(); + if (tmp.length == 1) { + out.write('0'); + out.write(tmp[0]); + } else { + out.write(tmp[0]); + out.write(tmp[1]); + } + } + } + } + @Override - protected Integer initialValue() { - return 0; + public void write(final String str, final int off, final int len) throws IOException { + write(str.toCharArray(), off, len); } - }; - - /* The `WIDE' instruction is used in the - * byte code to allow 16-bit wide indices - * for local variables. This opcode - * precedes an `ILOAD', e.g.. The opcode - * immediately following takes an extra - * byte which is combined with the - * following byte to form a - * 16-bit value. + } + + /* + * How many chars have been consumed during parsing in typeSignatureToString(). Read by methodSignatureToString(). Set + * by side effect, but only internally. + */ + private static final ThreadLocal CONSUMER_CHARS = ThreadLocal.withInitial(() -> Integer.valueOf(0)); + + /* + * The 'WIDE' instruction is used in the byte code to allow 16-bit wide indices for local variables. This opcode + * precedes an 'ILOAD', e.g.. The opcode immediately following takes an extra byte which is combined with the following + * byte to form a 16-bit value. */ - private static boolean wide = false; + private static boolean wide; + // A-Z, g-z, _, $ + private static final int FREE_CHARS = 48; + + private static final int[] CHAR_MAP = new int[FREE_CHARS]; + + private static final int[] MAP_CHAR = new int[256]; // Reverse map + + private static final char ESCAPE_CHAR = '$'; + + static { + int j = 0; + for (int i = 'A'; i <= 'Z'; i++) { + CHAR_MAP[j] = i; + MAP_CHAR[i] = j; + j++; + } + for (int i = 'g'; i <= 'z'; i++) { + CHAR_MAP[j] = i; + MAP_CHAR[i] = j; + j++; + } + CHAR_MAP[j] = '$'; + MAP_CHAR['$'] = j; + j++; + CHAR_MAP[j] = '_'; + MAP_CHAR['_'] = j; + } /** - * Convert bit field of flags into string such as `static final'. + * Convert bit field of flags into string such as 'static final'. * - * @param access_flags Access flags + * @param accessFlags Access flags * @return String representation of flags */ - public static String accessToString( final int access_flags ) { - return accessToString(access_flags, false); + public static String accessToString(final int accessFlags) { + return accessToString(accessFlags, false); } - /** - * Convert bit field of flags into string such as `static final'. + * Convert bit field of flags into string such as 'static final'. * - * Special case: Classes compiled with new compilers and with the - * `ACC_SUPER' flag would be said to be "synchronized". This is - * because SUN used the same value for the flags `ACC_SUPER' and - * `ACC_SYNCHRONIZED'. + * Special case: Classes compiled with new compilers and with the 'ACC_SUPER' flag would be said to be "synchronized". + * This is because SUN used the same value for the flags 'ACC_SUPER' and 'ACC_SYNCHRONIZED'. * - * @param access_flags Access flags - * @param for_class access flags are for class qualifiers ? + * @param accessFlags Access flags + * @param forClass access flags are for class qualifiers ? * @return String representation of flags */ - public static String accessToString( final int access_flags, final boolean for_class ) { + public static String accessToString(final int accessFlags, final boolean forClass) { final StringBuilder buf = new StringBuilder(); int p = 0; for (int i = 0; p < Const.MAX_ACC_FLAG_I; i++) { // Loop through known flags p = pow2(i); - if ((access_flags & p) != 0) { - /* Special case: Classes compiled with new compilers and with the - * `ACC_SUPER' flag would be said to be "synchronized". This is - * because SUN used the same value for the flags `ACC_SUPER' and - * `ACC_SYNCHRONIZED'. + if ((accessFlags & p) != 0) { + /* + * Special case: Classes compiled with new compilers and with the 'ACC_SUPER' flag would be said to be "synchronized". + * This is because SUN used the same value for the flags 'ACC_SUPER' and 'ACC_SYNCHRONIZED'. */ - if (for_class && ((p == Const.ACC_SUPER) || (p == Const.ACC_INTERFACE))) { + if (forClass && (p == Const.ACC_SUPER || p == Const.ACC_INTERFACE)) { continue; } buf.append(Const.getAccessName(i)).append(" "); @@ -122,42 +212,55 @@ public static String accessToString( final int access_flags, final boolean for_c return buf.toString().trim(); } + /** + * Convert (signed) byte to (unsigned) short value, i.e., all negative values become positive. + */ + private static short byteToShort(final byte b) { + return b < 0 ? (short) (256 + b) : (short) b; + } /** - * @param access_flags the class flags + * @param accessFlags the class flags * * @return "class" or "interface", depending on the ACC_INTERFACE flag */ - public static String classOrInterface( final int access_flags ) { - return ((access_flags & Const.ACC_INTERFACE) != 0) ? "interface" : "class"; + public static String classOrInterface(final int accessFlags) { + return (accessFlags & Const.ACC_INTERFACE) != 0 ? "interface" : "class"; + } + + /** + * @return 'flag' with bit 'i' set to 0 + */ + public static int clearBit(final int flag, final int i) { + final int bit = pow2(i); + return (flag & bit) == 0 ? flag : flag ^ bit; } + public static String codeToString(final byte[] code, final ConstantPool constantPool, final int index, final int length) { + return codeToString(code, constantPool, index, length, true); + } /** - * Disassemble a byte array of JVM byte codes starting from code line - * `index' and return the disassembled string representation. Decode only - * `num' opcodes (including their operands), use -1 if you want to - * decompile everything. + * Disassemble a byte array of JVM byte codes starting from code line 'index' and return the disassembled string + * representation. Decode only 'num' opcodes (including their operands), use -1 if you want to decompile everything. * - * @param code byte code array - * @param constant_pool Array of constants - * @param index offset in `code' array - * (number of opcodes, not bytes!) - * @param length number of opcodes to decompile, -1 for all - * @param verbose be verbose, e.g. print constant pool index + * @param code byte code array + * @param constantPool Array of constants + * @param index offset in 'code' array (number of opcodes, not bytes!) + * @param length number of opcodes to decompile, -1 for all + * @param verbose be verbose, e.g. print constant pool index * @return String representation of byte codes */ - public static String codeToString( final byte[] code, final ConstantPool constant_pool, final int index, - final int length, final boolean verbose ) { + public static String codeToString(final byte[] code, final ConstantPool constantPool, final int index, final int length, final boolean verbose) { final StringBuilder buf = new StringBuilder(code.length * 20); // Should be sufficient // CHECKSTYLE IGNORE MagicNumber try (ByteSequence stream = new ByteSequence(code)) { for (int i = 0; i < index; i++) { - codeToString(stream, constant_pool, verbose); + codeToString(stream, constantPool, verbose); } for (int i = 0; stream.available() > 0; i++) { - if ((length < 0) || (i < length)) { + if (length < 0 || i < length) { final String indices = fillup(stream.getIndex() + ":", 6, true, ' '); - buf.append(indices).append(codeToString(stream, constant_pool, verbose)).append('\n'); + buf.append(indices).append(codeToString(stream, constantPool, verbose)).append('\n'); } } } catch (final IOException e) { @@ -166,28 +269,25 @@ public static String codeToString( final byte[] code, final ConstantPool constan return buf.toString(); } - - public static String codeToString( final byte[] code, final ConstantPool constant_pool, final int index, final int length ) { - return codeToString(code, constant_pool, index, length, true); + public static String codeToString(final ByteSequence bytes, final ConstantPool constantPool) throws IOException { + return codeToString(bytes, constantPool, true); } - /** - * Disassemble a stream of byte codes and return the - * string representation. + * Disassemble a stream of byte codes and return the string representation. * - * @param bytes stream of bytes - * @param constant_pool Array of constants - * @param verbose be verbose, e.g. print constant pool index + * @param bytes stream of bytes + * @param constantPool Array of constants + * @param verbose be verbose, e.g. print constant pool index * @return String representation of byte code * * @throws IOException if a failure from reading from the bytes argument occurs */ @SuppressWarnings("fallthrough") // by design for case Const.INSTANCEOF - public static String codeToString(final ByteSequence bytes, final ConstantPool constant_pool, + public static String codeToString(final ByteSequence bytes, final ConstantPool constantPool, final boolean verbose) throws IOException { final short opcode = (short) bytes.readUnsignedByte(); - int default_offset = 0; + int defaultOffset = 0; int low; int high; int npairs; @@ -195,441 +295,612 @@ public static String codeToString(final ByteSequence bytes, final ConstantPool c int vindex; int constant; int[] match; - int[] jump_table; - int no_pad_bytes = 0; + int[] jumpTable; + int noPadBytes = 0; int offset; final StringBuilder buf = new StringBuilder(Const.getOpcodeName(opcode)); - /* Special case: Skip (0-3) padding bytes, i.e., the - * following bytes are 4-byte-aligned + /* + * Special case: Skip (0-3) padding bytes, i.e., the following bytes are 4-byte-aligned */ - if ((opcode == Const.TABLESWITCH) || (opcode == Const.LOOKUPSWITCH)) { + if (opcode == Const.TABLESWITCH || opcode == Const.LOOKUPSWITCH) { final int remainder = bytes.getIndex() % 4; - no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder; - for (int i = 0; i < no_pad_bytes; i++) { + noPadBytes = remainder == 0 ? 0 : 4 - remainder; + for (int i = 0; i < noPadBytes; i++) { byte b; if ((b = bytes.readByte()) != 0) { - System.err.println("Warning: Padding byte != 0 in " - + Const.getOpcodeName(opcode) + ":" + b); + System.err.println("Warning: Padding byte != 0 in " + Const.getOpcodeName(opcode) + ":" + b); } } // Both cases have a field default_offset in common - default_offset = bytes.readInt(); + defaultOffset = bytes.readInt(); } switch (opcode) { - /* Table switch has variable length arguments. - */ - case Const.TABLESWITCH: - low = bytes.readInt(); - high = bytes.readInt(); - offset = bytes.getIndex() - 12 - no_pad_bytes - 1; - default_offset += offset; - buf.append("\tdefault = ").append(default_offset).append(", low = ").append(low) - .append(", high = ").append(high).append("("); - jump_table = new int[high - low + 1]; - for (int i = 0; i < jump_table.length; i++) { - jump_table[i] = offset + bytes.readInt(); - buf.append(jump_table[i]); - if (i < jump_table.length - 1) { - buf.append(", "); - } - } - buf.append(")"); - break; - /* Lookup switch has variable length arguments. - */ - case Const.LOOKUPSWITCH: { - npairs = bytes.readInt(); - offset = bytes.getIndex() - 8 - no_pad_bytes - 1; - match = new int[npairs]; - jump_table = new int[npairs]; - default_offset += offset; - buf.append("\tdefault = ").append(default_offset).append(", npairs = ").append( - npairs).append(" ("); - for (int i = 0; i < npairs; i++) { - match[i] = bytes.readInt(); - jump_table[i] = offset + bytes.readInt(); - buf.append("(").append(match[i]).append(", ").append(jump_table[i]).append(")"); - if (i < npairs - 1) { - buf.append(", "); - } + /* + * Table switch has variable length arguments. + */ + case Const.TABLESWITCH: + low = bytes.readInt(); + high = bytes.readInt(); + offset = bytes.getIndex() - 12 - noPadBytes - 1; + defaultOffset += offset; + buf.append("\tdefault = ").append(defaultOffset).append(", low = ").append(low).append(", high = ").append(high).append("("); + jumpTable = new int[high - low + 1]; + for (int i = 0; i < jumpTable.length; i++) { + jumpTable[i] = offset + bytes.readInt(); + buf.append(jumpTable[i]); + if (i < jumpTable.length - 1) { + buf.append(", "); } - buf.append(")"); } - break; - /* Two address bytes + offset from start of byte stream form the - * jump target - */ - case Const.GOTO: - case Const.IFEQ: - case Const.IFGE: - case Const.IFGT: - case Const.IFLE: - case Const.IFLT: - case Const.JSR: - case Const.IFNE: - case Const.IFNONNULL: - case Const.IFNULL: - case Const.IF_ACMPEQ: - case Const.IF_ACMPNE: - case Const.IF_ICMPEQ: - case Const.IF_ICMPGE: - case Const.IF_ICMPGT: - case Const.IF_ICMPLE: - case Const.IF_ICMPLT: - case Const.IF_ICMPNE: - buf.append("\t\t#").append((bytes.getIndex() - 1) + bytes.readShort()); - break; - /* 32-bit wide jumps - */ - case Const.GOTO_W: - case Const.JSR_W: - buf.append("\t\t#").append((bytes.getIndex() - 1) + bytes.readInt()); - break; - /* Index byte references local variable (register) - */ - case Const.ALOAD: - case Const.ASTORE: - case Const.DLOAD: - case Const.DSTORE: - case Const.FLOAD: - case Const.FSTORE: - case Const.ILOAD: - case Const.ISTORE: - case Const.LLOAD: - case Const.LSTORE: - case Const.RET: - if (wide) { - vindex = bytes.readUnsignedShort(); - wide = false; // Clear flag - } else { - vindex = bytes.readUnsignedByte(); + buf.append(")"); + break; + /* + * Lookup switch has variable length arguments. + */ + case Const.LOOKUPSWITCH: { + npairs = bytes.readInt(); + offset = bytes.getIndex() - 8 - noPadBytes - 1; + match = new int[npairs]; + jumpTable = new int[npairs]; + defaultOffset += offset; + buf.append("\tdefault = ").append(defaultOffset).append(", npairs = ").append(npairs).append(" ("); + for (int i = 0; i < npairs; i++) { + match[i] = bytes.readInt(); + jumpTable[i] = offset + bytes.readInt(); + buf.append("(").append(match[i]).append(", ").append(jumpTable[i]).append(")"); + if (i < npairs - 1) { + buf.append(", "); } - buf.append("\t\t%").append(vindex); - break; - /* - * Remember wide byte which is used to form a 16-bit address in the - * following instruction. Relies on that the method is called again with - * the following opcode. - */ - case Const.WIDE: - wide = true; - buf.append("\t(wide)"); - break; - /* Array of basic type. - */ - case Const.NEWARRAY: - buf.append("\t\t<").append(Const.getTypeName(bytes.readByte())).append(">"); - break; - /* Access object/class fields. - */ - case Const.GETFIELD: - case Const.GETSTATIC: - case Const.PUTFIELD: - case Const.PUTSTATIC: - index = bytes.readUnsignedShort(); - buf.append("\t\t").append( - constant_pool.constantToString(index, Const.CONSTANT_Fieldref)).append( - verbose ? " (" + index + ")" : ""); - break; - /* Operands are references to classes in constant pool - */ - case Const.NEW: - case Const.CHECKCAST: - buf.append("\t"); - //$FALL-THROUGH$ - case Const.INSTANCEOF: - index = bytes.readUnsignedShort(); - buf.append("\t<").append( - constant_pool.constantToString(index, Const.CONSTANT_Class)) - .append(">").append(verbose ? " (" + index + ")" : ""); - break; - /* Operands are references to methods in constant pool - */ - case Const.INVOKESPECIAL: - case Const.INVOKESTATIC: - index = bytes.readUnsignedShort(); - final Constant c = constant_pool.getConstant(index); - // With Java8 operand may be either a CONSTANT_Methodref - // or a CONSTANT_InterfaceMethodref. (markro) - buf.append("\t").append( - constant_pool.constantToString(index, c.getTag())) - .append(verbose ? " (" + index + ")" : ""); - break; - case Const.INVOKEVIRTUAL: - index = bytes.readUnsignedShort(); - buf.append("\t").append( - constant_pool.constantToString(index, Const.CONSTANT_Methodref)) - .append(verbose ? " (" + index + ")" : ""); - break; - case Const.INVOKEINTERFACE: - index = bytes.readUnsignedShort(); - final int nargs = bytes.readUnsignedByte(); // historical, redundant - buf.append("\t").append( - constant_pool - .constantToString(index, Const.CONSTANT_InterfaceMethodref)) - .append(verbose ? " (" + index + ")\t" : "").append(nargs).append("\t") - .append(bytes.readUnsignedByte()); // Last byte is a reserved space - break; - case Const.INVOKEDYNAMIC: - index = bytes.readUnsignedShort(); - buf.append("\t").append( - constant_pool - .constantToString(index, Const.CONSTANT_InvokeDynamic)) - .append(verbose ? " (" + index + ")\t" : "") - .append(bytes.readUnsignedByte()) // Thrid byte is a reserved space - .append(bytes.readUnsignedByte()); // Last byte is a reserved space - break; - /* Operands are references to items in constant pool - */ - case Const.LDC_W: - case Const.LDC2_W: - index = bytes.readUnsignedShort(); - buf.append("\t\t").append( - constant_pool.constantToString(index, constant_pool.getConstant(index) - .getTag())).append(verbose ? " (" + index + ")" : ""); - break; - case Const.LDC: - index = bytes.readUnsignedByte(); - buf.append("\t\t").append( - constant_pool.constantToString(index, constant_pool.getConstant(index) - .getTag())).append(verbose ? " (" + index + ")" : ""); - break; - /* Array of references. - */ - case Const.ANEWARRAY: - index = bytes.readUnsignedShort(); - buf.append("\t\t<").append( - compactClassName(constant_pool.getConstantString(index, - Const.CONSTANT_Class), false)).append(">").append( - verbose ? " (" + index + ")" : ""); - break; - /* Multidimensional array of references. - */ - case Const.MULTIANEWARRAY: { - index = bytes.readUnsignedShort(); - final int dimensions = bytes.readUnsignedByte(); - buf.append("\t<").append( - compactClassName(constant_pool.getConstantString(index, - Const.CONSTANT_Class), false)).append(">\t").append(dimensions) - .append(verbose ? " (" + index + ")" : ""); } - break; - /* Increment local variable. - */ - case Const.IINC: - if (wide) { - vindex = bytes.readUnsignedShort(); - constant = bytes.readShort(); - wide = false; - } else { - vindex = bytes.readUnsignedByte(); - constant = bytes.readByte(); - } - buf.append("\t\t%").append(vindex).append("\t").append(constant); - break; - default: - if (Const.getNoOfOperands(opcode) > 0) { - for (int i = 0; i < Const.getOperandTypeCount(opcode); i++) { - buf.append("\t\t"); - switch (Const.getOperandType(opcode, i)) { - case Const.T_BYTE: - buf.append(bytes.readByte()); - break; - case Const.T_SHORT: - buf.append(bytes.readShort()); - break; - case Const.T_INT: - buf.append(bytes.readInt()); - break; - default: // Never reached - throw new IllegalStateException("Unreachable default case reached!"); - } + buf.append(")"); + } + break; + /* + * Two address bytes + offset from start of byte stream form the jump target + */ + case Const.GOTO: + case Const.IFEQ: + case Const.IFGE: + case Const.IFGT: + case Const.IFLE: + case Const.IFLT: + case Const.JSR: + case Const.IFNE: + case Const.IFNONNULL: + case Const.IFNULL: + case Const.IF_ACMPEQ: + case Const.IF_ACMPNE: + case Const.IF_ICMPEQ: + case Const.IF_ICMPGE: + case Const.IF_ICMPGT: + case Const.IF_ICMPLE: + case Const.IF_ICMPLT: + case Const.IF_ICMPNE: + buf.append("\t\t#").append(bytes.getIndex() - 1 + bytes.readShort()); + break; + /* + * 32-bit wide jumps + */ + case Const.GOTO_W: + case Const.JSR_W: + buf.append("\t\t#").append(bytes.getIndex() - 1 + bytes.readInt()); + break; + /* + * Index byte references local variable (register) + */ + case Const.ALOAD: + case Const.ASTORE: + case Const.DLOAD: + case Const.DSTORE: + case Const.FLOAD: + case Const.FSTORE: + case Const.ILOAD: + case Const.ISTORE: + case Const.LLOAD: + case Const.LSTORE: + case Const.RET: + if (wide) { + vindex = bytes.readUnsignedShort(); + wide = false; // Clear flag + } else { + vindex = bytes.readUnsignedByte(); + } + buf.append("\t\t%").append(vindex); + break; + /* + * Remember wide byte which is used to form a 16-bit address in the following instruction. Relies on that the method is + * called again with the following opcode. + */ + case Const.WIDE: + wide = true; + buf.append("\t(wide)"); + break; + /* + * Array of basic type. + */ + case Const.NEWARRAY: + buf.append("\t\t<").append(Const.getTypeName(bytes.readByte())).append(">"); + break; + /* + * Access object/class fields. + */ + case Const.GETFIELD: + case Const.GETSTATIC: + case Const.PUTFIELD: + case Const.PUTSTATIC: + index = bytes.readUnsignedShort(); + buf.append("\t\t").append(constantPool.constantToString(index, Const.CONSTANT_Fieldref)).append(verbose ? " (" + index + ")" : ""); + break; + /* + * Operands are references to classes in constant pool + */ + case Const.NEW: + case Const.CHECKCAST: + buf.append("\t"); + //$FALL-THROUGH$ + case Const.INSTANCEOF: + index = bytes.readUnsignedShort(); + buf.append("\t<").append(constantPool.constantToString(index, Const.CONSTANT_Class)).append(">").append(verbose ? " (" + index + ")" : ""); + break; + /* + * Operands are references to methods in constant pool + */ + case Const.INVOKESPECIAL: + case Const.INVOKESTATIC: + index = bytes.readUnsignedShort(); + final Constant c = constantPool.getConstant(index); + // With Java8 operand may be either a CONSTANT_Methodref + // or a CONSTANT_InterfaceMethodref. (markro) + buf.append("\t").append(constantPool.constantToString(index, c.getTag())).append(verbose ? " (" + index + ")" : ""); + break; + case Const.INVOKEVIRTUAL: + index = bytes.readUnsignedShort(); + buf.append("\t").append(constantPool.constantToString(index, Const.CONSTANT_Methodref)).append(verbose ? " (" + index + ")" : ""); + break; + case Const.INVOKEINTERFACE: + index = bytes.readUnsignedShort(); + final int nargs = bytes.readUnsignedByte(); // historical, redundant + buf.append("\t").append(constantPool.constantToString(index, Const.CONSTANT_InterfaceMethodref)).append(verbose ? " (" + index + ")\t" : "") + .append(nargs).append("\t").append(bytes.readUnsignedByte()); // Last byte is a reserved space + break; + case Const.INVOKEDYNAMIC: + index = bytes.readUnsignedShort(); + buf.append("\t").append(constantPool.constantToString(index, Const.CONSTANT_InvokeDynamic)).append(verbose ? " (" + index + ")\t" : "") + .append(bytes.readUnsignedByte()) // Thrid byte is a reserved space + .append(bytes.readUnsignedByte()); // Last byte is a reserved space + break; + /* + * Operands are references to items in constant pool + */ + case Const.LDC_W: + case Const.LDC2_W: + index = bytes.readUnsignedShort(); + buf.append("\t\t").append(constantPool.constantToString(index, constantPool.getConstant(index).getTag())) + .append(verbose ? " (" + index + ")" : ""); + break; + case Const.LDC: + index = bytes.readUnsignedByte(); + buf.append("\t\t").append(constantPool.constantToString(index, constantPool.getConstant(index).getTag())) + .append(verbose ? " (" + index + ")" : ""); + break; + /* + * Array of references. + */ + case Const.ANEWARRAY: + index = bytes.readUnsignedShort(); + buf.append("\t\t<").append(compactClassName(constantPool.getConstantString(index, Const.CONSTANT_Class), false)).append(">") + .append(verbose ? " (" + index + ")" : ""); + break; + /* + * Multidimensional array of references. + */ + case Const.MULTIANEWARRAY: { + index = bytes.readUnsignedShort(); + final int dimensions = bytes.readUnsignedByte(); + buf.append("\t<").append(compactClassName(constantPool.getConstantString(index, Const.CONSTANT_Class), false)).append(">\t").append(dimensions) + .append(verbose ? " (" + index + ")" : ""); + } + break; + /* + * Increment local variable. + */ + case Const.IINC: + if (wide) { + vindex = bytes.readUnsignedShort(); + constant = bytes.readShort(); + wide = false; + } else { + vindex = bytes.readUnsignedByte(); + constant = bytes.readByte(); + } + buf.append("\t\t%").append(vindex).append("\t").append(constant); + break; + default: + if (Const.getNoOfOperands(opcode) > 0) { + for (int i = 0; i < Const.getOperandTypeCount(opcode); i++) { + buf.append("\t\t"); + switch (Const.getOperandType(opcode, i)) { + case Const.T_BYTE: + buf.append(bytes.readByte()); + break; + case Const.T_SHORT: + buf.append(bytes.readShort()); + break; + case Const.T_INT: + buf.append(bytes.readInt()); + break; + default: // Never reached + throw new IllegalStateException("Unreachable default case reached!"); } } + } } return buf.toString(); } - - public static String codeToString( final ByteSequence bytes, final ConstantPool constant_pool ) - throws IOException { - return codeToString(bytes, constant_pool, true); - } - - /** - * Shorten long class names, java/lang/String becomes - * String. + * Shorten long class names, java/lang/String becomes String. * * @param str The long class name * @return Compacted class name */ - public static String compactClassName( final String str ) { + public static String compactClassName(final String str) { return compactClassName(str, true); } - /** - * Shorten long class names, java/lang/String becomes - * java.lang.String, - * e.g.. If chopit is true the prefix java.lang - * is also removed. + * Shorten long class names, java/lang/String becomes java.lang.String, e.g.. If chopit is + * true the prefix java.lang is also removed. * * @param str The long class name * @param chopit flag that determines whether chopping is executed or not * @return Compacted class name */ - public static String compactClassName( final String str, final boolean chopit ) { + public static String compactClassName(final String str, final boolean chopit) { return compactClassName(str, "java.lang.", chopit); } - /** - * Shorten long class name str, i.e., chop off the prefix, - * if the - * class name starts with this string and the flag chopit is true. - * Slashes / are converted to dots .. + * Shorten long class name str, i.e., chop off the prefix, if the class name starts with this string + * and the flag chopit is true. Slashes / are converted to dots .. * * @param str The long class name * @param prefix The prefix the get rid off * @param chopit flag that determines whether chopping is executed or not * @return Compacted class name */ - public static String compactClassName( String str, final String prefix, final boolean chopit ) { + public static String compactClassName(String str, final String prefix, final boolean chopit) { final int len = prefix.length(); - str = str.replace('/', '.'); // Is `/' on all systems, even DOS - if (chopit) { - // If string starts with `prefix' and contains no further dots - if (str.startsWith(prefix) && (str.substring(len).indexOf('.') == -1)) { - str = str.substring(len); - } + str = pathToPackage(str); // Is '/' on all systems, even DOS + // If string starts with 'prefix' and contains no further dots + if (chopit && str.startsWith(prefix) && str.substring(len).indexOf('.') == -1) { + str = str.substring(len); } return str; } - - /** - * @return `flag' with bit `i' set to 1 - */ - public static int setBit( final int flag, final int i ) { - return flag | pow2(i); - } - - /** - * @return `flag' with bit `i' set to 0 + * Escape all occurrences of newline chars '\n', quotes \", etc. */ - public static int clearBit( final int flag, final int i ) { - final int bit = pow2(i); - return (flag & bit) == 0 ? flag : flag ^ bit; + public static String convertString(final String label) { + final char[] ch = label.toCharArray(); + final StringBuilder buf = new StringBuilder(); + for (final char element : ch) { + switch (element) { + case '\n': + buf.append("\\n"); + break; + case '\r': + buf.append("\\r"); + break; + case '\"': + buf.append("\\\""); + break; + case '\'': + buf.append("\\'"); + break; + case '\\': + buf.append("\\\\"); + break; + default: + buf.append(element); + break; + } + } + return buf.toString(); } - - /** - * @return true, if bit `i' in `flag' is set - */ - public static boolean isSet( final int flag, final int i ) { - return (flag & pow2(i)) != 0; + private static int countBrackets(final String brackets) { + final char[] chars = brackets.toCharArray(); + int count = 0; + boolean open = false; + for (final char c : chars) { + switch (c) { + case '[': + if (open) { + throw new IllegalArgumentException("Illegally nested brackets:" + brackets); + } + open = true; + break; + case ']': + if (!open) { + throw new IllegalArgumentException("Illegally nested brackets:" + brackets); + } + open = false; + count++; + break; + default: + // Don't care + break; + } + } + if (open) { + throw new IllegalArgumentException("Illegally nested brackets:" + brackets); + } + return count; } - /** - * Converts string containing the method return and argument types - * to a byte code method signature. + * Decode a string back to a byte array. * - * @param ret Return type of method - * @param argv Types of method arguments - * @return Byte code representation of method signature + * @param s the string to convert + * @param uncompress use gzip to uncompress the stream of bytes * - * @throws ClassFormatException if the signature is for Void + * @throws IOException if there's a gzip exception */ - public static String methodTypeToSignature( final String ret, final String[] argv ) - throws ClassFormatException { - final StringBuilder buf = new StringBuilder("("); - String str; - if (argv != null) { - for (final String element : argv) { - str = getSignature(element); - if (str.endsWith("V")) { - throw new ClassFormatException("Invalid type: " + element); - } - buf.append(str); + public static byte[] decode(final String s, final boolean uncompress) throws IOException { + byte[] bytes; + try (JavaReader jr = new JavaReader(new CharArrayReader(s.toCharArray())); ByteArrayOutputStream bos = new ByteArrayOutputStream()) { + int ch; + while ((ch = jr.read()) >= 0) { + bos.write(ch); } + bytes = bos.toByteArray(); } - str = getSignature(ret); - buf.append(")").append(str); - return buf.toString(); + if (uncompress) { + final GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(bytes)); + final byte[] tmp = new byte[bytes.length * 3]; // Rough estimate + int count = 0; + int b; + while ((b = gis.read()) >= 0) { + tmp[count++] = (byte) b; + } + bytes = Arrays.copyOf(tmp, count); + } + return bytes; } - /** - * Converts argument list portion of method signature to string with all class names compacted. + * Encode byte array it into Java identifier string, i.e., a string that only contains the following characters: (a, ... + * z, A, ... Z, 0, ... 9, _, $). The encoding algorithm itself is not too clever: if the current byte's ASCII value + * already is a valid Java identifier part, leave it as it is. Otherwise it writes the escape character($) followed by: * - * @param signature Method signature - * @return String Array of argument types - * @throws ClassFormatException - */ - public static String[] methodSignatureArgumentTypes( final String signature ) - throws ClassFormatException { - return methodSignatureArgumentTypes(signature, true); - } - - - /** - * Converts argument list portion of method signature to string. + *
      + *
    • the ASCII value as a hexadecimal string, if the value is not in the range 200..247
    • + *
    • a Java identifier char not used in a lowercase hexadecimal string, if the value is in the range 200..247
    • + *
    * - * @param signature Method signature - * @param chopit flag that determines whether chopping is executed or not - * @return String Array of argument types - * @throws ClassFormatException - */ - public static String[] methodSignatureArgumentTypes( final String signature, final boolean chopit ) - throws ClassFormatException { + *

    + * This operation inflates the original byte array by roughly 40-50% + *

    + * + * @param bytes the byte array to convert + * @param compress use gzip to minimize string + * + * @throws IOException if there's a gzip exception + */ + public static String encode(byte[] bytes, final boolean compress) throws IOException { + if (compress) { + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); GZIPOutputStream gos = new GZIPOutputStream(baos)) { + gos.write(bytes, 0, bytes.length); + gos.finish(); + bytes = baos.toByteArray(); + } + } + final CharArrayWriter caw = new CharArrayWriter(); + try (JavaWriter jw = new JavaWriter(caw)) { + for (final byte b : bytes) { + final int in = b & 0x000000ff; // Normalize to unsigned + jw.write(in); + } + } + return caw.toString(); + } + + /** + * Fillup char with up to length characters with char 'fill' and justify it left or right. + * + * @param str string to format + * @param length length of desired string + * @param leftJustify format left or right + * @param fill fill character + * @return formatted string + */ + public static String fillup(final String str, final int length, final boolean leftJustify, final char fill) { + final int len = length - str.length(); + final char[] buf = new char[Math.max(len, 0)]; + Arrays.fill(buf, fill); + if (leftJustify) { + return str + new String(buf); + } + return new String(buf) + str; + } + + /** + * Return a string for an integer justified left or right and filled up with 'fill' characters if necessary. + * + * @param i integer to format + * @param length length of desired string + * @param leftJustify format left or right + * @param fill fill character + * @return formatted int + */ + public static String format(final int i, final int length, final boolean leftJustify, final char fill) { + return fillup(Integer.toString(i), length, leftJustify, fill); + } + + /** + * WARNING: + * + * There is some nomenclature confusion through much of the BCEL code base with respect to the terms Descriptor and + * Signature. For the offical definitions see: + * + * @see Descriptors in The Java + * Virtual Machine Specification + * + * @see Signatures in The Java + * Virtual Machine Specification + * + * In brief, a descriptor is a string representing the type of a field or method. Signatures are similar, but more + * complex. Signatures are used to encode declarations written in the Java programming language that use types + * outside the type system of the Java Virtual Machine. They are used to describe the type of any class, interface, + * constructor, method or field whose declaration uses type variables or parameterized types. + * + * To parse a descriptor, call typeSignatureToString. To parse a signature, call signatureToString. + * + * Note that if the signature string is a single, non-generic item, the call to signatureToString reduces to a call + * to typeSignatureToString. Also note, that if you only wish to parse the first item in a longer signature string, + * you should call typeSignatureToString directly. + */ + + /** + * Parse Java type such as "char", or "java.lang.String[]" and return the signature in byte code format, e.g. "C" or + * "[Ljava/lang/String;" respectively. + * + * @param type Java type + * @return byte code signature + */ + public static String getSignature(String type) { + final StringBuilder buf = new StringBuilder(); + final char[] chars = type.toCharArray(); + boolean charFound = false; + boolean delim = false; + int index = -1; + loop: for (int i = 0; i < chars.length; i++) { + switch (chars[i]) { + case ' ': + case '\t': + case '\n': + case '\r': + case '\f': + if (charFound) { + delim = true; + } + break; + case '[': + if (!charFound) { + throw new IllegalArgumentException("Illegal type: " + type); + } + index = i; + break loop; + default: + charFound = true; + if (!delim) { + buf.append(chars[i]); + } + } + } + int brackets = 0; + if (index > 0) { + brackets = countBrackets(type.substring(index)); + } + type = buf.toString(); + buf.setLength(0); + for (int i = 0; i < brackets; i++) { + buf.append('['); + } + boolean found = false; + for (int i = Const.T_BOOLEAN; i <= Const.T_VOID && !found; i++) { + if (Const.getTypeName(i).equals(type)) { + found = true; + buf.append(Const.getShortTypeName(i)); + } + } + if (!found) { + buf.append('L').append(packageToPath(type)).append(';'); + } + return buf.toString(); + } + + /** + * @param ch the character to test if it's part of an identifier + * + * @return true, if character is one of (a, ... z, A, ... Z, 0, ... 9, _) + */ + public static boolean isJavaIdentifierPart(final char ch) { + return ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9' || ch == '_'; + } + + /** + * @return true, if bit 'i' in 'flag' is set + */ + public static boolean isSet(final int flag, final int i) { + return (flag & pow2(i)) != 0; + } + + /** + * Converts argument list portion of method signature to string with all class names compacted. + * + * @param signature Method signature + * @return String Array of argument types + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file + */ + public static String[] methodSignatureArgumentTypes(final String signature) throws ClassFormatException { + return methodSignatureArgumentTypes(signature, true); + } + + /** + * Converts argument list portion of method signature to string. + * + * @param signature Method signature + * @param chopit flag that determines whether chopping is executed or not + * @return String Array of argument types + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file + */ + public static String[] methodSignatureArgumentTypes(final String signature, final boolean chopit) throws ClassFormatException { final List vec = new ArrayList<>(); int index; try { - // Skip any type arguments to read argument declarations between `(' and `)' + // Skip any type arguments to read argument declarations between '(' and ')' index = signature.indexOf('(') + 1; if (index <= 0) { throw new ClassFormatException("Invalid method signature: " + signature); } while (signature.charAt(index) != ')') { vec.add(typeSignatureToString(signature.substring(index), chopit)); - //corrected concurrent private static field acess - index += unwrap(consumed_chars); // update position + // corrected concurrent private static field acess + index += unwrap(CONSUMER_CHARS); // update position } } catch (final StringIndexOutOfBoundsException e) { // Should never occur throw new ClassFormatException("Invalid method signature: " + signature, e); } - return vec.toArray(new String[vec.size()]); + return vec.toArray(Const.EMPTY_STRING_ARRAY); } - /** * Converts return type portion of method signature to string with all class names compacted. * - * @param signature Method signature + * @param signature Method signature * @return String representation of method return type - * @throws ClassFormatException + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ - public static String methodSignatureReturnType( final String signature ) throws ClassFormatException { + public static String methodSignatureReturnType(final String signature) throws ClassFormatException { return methodSignatureReturnType(signature, true); } - /** * Converts return type portion of method signature to string. * - * @param signature Method signature - * @param chopit flag that determines whether chopping is executed or not + * @param signature Method signature + * @param chopit flag that determines whether chopping is executed or not * @return String representation of method return type - * @throws ClassFormatException + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ - public static String methodSignatureReturnType( final String signature, final boolean chopit ) throws ClassFormatException { + public static String methodSignatureReturnType(final String signature, final boolean chopit) throws ClassFormatException { int index; String type; try { - // Read return type after `)' + // Read return type after ')' index = signature.lastIndexOf(')') + 1; if (index <= 0) { throw new ClassFormatException("Invalid method signature: " + signature); @@ -641,81 +912,77 @@ public static String methodSignatureReturnType( final String signature, final bo return type; } - /** * Converts method signature to string with all class names compacted. * - * @param signature to convert - * @param name of method - * @param access flags of method + * @param signature to convert + * @param name of method + * @param access flags of method * @return Human readable signature */ - public static String methodSignatureToString( final String signature, final String name, final String access ) { + public static String methodSignatureToString(final String signature, final String name, final String access) { return methodSignatureToString(signature, name, access, true); } - /** * Converts method signature to string. * - * @param signature to convert - * @param name of method - * @param access flags of method - * @param chopit flag that determines whether chopping is executed or not + * @param signature to convert + * @param name of method + * @param access flags of method + * @param chopit flag that determines whether chopping is executed or not * @return Human readable signature */ - public static String methodSignatureToString( final String signature, final String name, final String access, final boolean chopit ) { + public static String methodSignatureToString(final String signature, final String name, final String access, final boolean chopit) { return methodSignatureToString(signature, name, access, chopit, null); } - /** - * This method converts a method signature string into a Java type declaration like - * `void main(String[])' and throws a `ClassFormatException' when the parsed - * type is invalid. + * This method converts a method signature string into a Java type declaration like 'void main(String[])' and throws a + * 'ClassFormatException' when the parsed type is invalid. * - * @param signature Method signature - * @param name Method name - * @param access Method access rights - * @param chopit flag that determines whether chopping is executed or not - * @param vars the LocalVariableTable for the method + * @param signature Method signature + * @param name Method name + * @param access Method access rights + * @param chopit flag that determines whether chopping is executed or not + * @param vars the LocalVariableTable for the method * @return Java type declaration - * @throws ClassFormatException + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file */ - public static String methodSignatureToString( final String signature, final String name, - final String access, final boolean chopit, final LocalVariableTable vars ) throws ClassFormatException { + public static String methodSignatureToString(final String signature, final String name, final String access, final boolean chopit, + final LocalVariableTable vars) throws ClassFormatException { final StringBuilder buf = new StringBuilder("("); String type; int index; - int var_index = access.contains("static") ? 0 : 1; + int varIndex = access.contains("static") ? 0 : 1; try { - // Skip any type arguments to read argument declarations between `(' and `)' + // Skip any type arguments to read argument declarations between '(' and ')' index = signature.indexOf('(') + 1; if (index <= 0) { throw new ClassFormatException("Invalid method signature: " + signature); } while (signature.charAt(index) != ')') { - final String param_type = typeSignatureToString(signature.substring(index), chopit); - buf.append(param_type); + final String paramType = typeSignatureToString(signature.substring(index), chopit); + buf.append(paramType); if (vars != null) { - final LocalVariable l = vars.getLocalVariable(var_index, 0); + final LocalVariable l = vars.getLocalVariable(varIndex, 0); if (l != null) { buf.append(" ").append(l.getName()); } } else { - buf.append(" arg").append(var_index); + buf.append(" arg").append(varIndex); } - if ("double".equals(param_type) || "long".equals(param_type)) { - var_index += 2; + if ("double".equals(paramType) || "long".equals(paramType)) { + varIndex += 2; } else { - var_index++; + varIndex++; } buf.append(", "); - //corrected concurrent private static field acess - index += unwrap(consumed_chars); // update position + // corrected concurrent private static field acess + index += unwrap(CONSUMER_CHARS); // update position } index++; // update position - // Read return type after `)' + // Read return type after ')' type = typeSignatureToString(signature.substring(index), chopit); } catch (final StringIndexOutOfBoundsException e) { // Should never occur throw new ClassFormatException("Invalid method signature: " + signature, e); @@ -725,15 +992,101 @@ public static String methodSignatureToString( final String signature, final Stri buf.setLength(buf.length() - 2); } buf.append(")"); - return access + ((access.length() > 0) ? " " : "") + // May be an empty string - type + " " + name + buf.toString(); + return access + (!access.isEmpty() ? " " : "") + // May be an empty string + type + " " + name + buf.toString(); + } + + /** + * Converts string containing the method return and argument types to a byte code method signature. + * + * @param ret Return type of method + * @param argv Types of method arguments + * @return Byte code representation of method signature + * + * @throws ClassFormatException if the signature is for Void + */ + public static String methodTypeToSignature(final String ret, final String[] argv) throws ClassFormatException { + final StringBuilder buf = new StringBuilder("("); + String str; + if (argv != null) { + for (final String element : argv) { + str = getSignature(element); + if (str.endsWith("V")) { + throw new ClassFormatException("Invalid type: " + element); + } + buf.append(str); + } + } + str = getSignature(ret); + buf.append(")").append(str); + return buf.toString(); + } + + /** + * Converts '.'s to '/'s. + * + * @param name Source + * @return converted value + * @since 6.7.0 + */ + public static String packageToPath(final String name) { + return name.replace('.', '/'); } + /** + * Converts a path to a package name. + * + * @param str the source path. + * @return a package name. + * @since 6.6.0 + */ + public static String pathToPackage(final String str) { + return str.replace('/', '.'); + } - private static int pow2( final int n ) { + private static int pow2(final int n) { return 1 << n; } + public static String printArray(final Object[] obj) { + return printArray(obj, true); + } + + public static String printArray(final Object[] obj, final boolean braces) { + return printArray(obj, braces, false); + } + + public static String printArray(final Object[] obj, final boolean braces, final boolean quote) { + if (obj == null) { + return null; + } + final StringBuilder buf = new StringBuilder(); + if (braces) { + buf.append('{'); + } + for (int i = 0; i < obj.length; i++) { + if (obj[i] != null) { + buf.append(quote ? "\"" : "").append(obj[i]).append(quote ? "\"" : ""); + } else { + buf.append("null"); + } + if (i < obj.length - 1) { + buf.append(", "); + } + } + if (braces) { + buf.append('}'); + } + return buf.toString(); + } + + public static void printArray(final PrintStream out, final Object[] obj) { + out.println(printArray(obj, true)); + } + + public static void printArray(final PrintWriter out, final Object[] obj) { + out.println(printArray(obj, true)); + } /** * Replace all occurrences of old in str with new. @@ -743,20 +1096,20 @@ private static int pow2( final int n ) { * @param new_ Replacement string * @return new String object */ - public static String replace( String str, final String old, final String new_ ) { + public static String replace(String str, final String old, final String new_) { int index; - int old_index; + int oldIndex; try { - if (str.contains(old)) { // `old' found in str + if (str.contains(old)) { // 'old' found in str final StringBuilder buf = new StringBuilder(); - old_index = 0; // String start offset + oldIndex = 0; // String start offset // While we have something to replace - while ((index = str.indexOf(old, old_index)) != -1) { - buf.append(str.substring(old_index, index)); // append prefix + while ((index = str.indexOf(old, oldIndex)) != -1) { + buf.append(str, oldIndex, index); // append prefix buf.append(new_); // append replacement - old_index = index + old.length(); // Skip `old'.length chars + oldIndex = index + old.length(); // Skip 'old'.length chars } - buf.append(str.substring(old_index)); // append rest of string + buf.append(str.substring(oldIndex)); // append rest of string str = buf.toString(); } } catch (final StringIndexOutOfBoundsException e) { // Should not occur @@ -765,81 +1118,69 @@ public static String replace( String str, final String old, final String new_ ) return str; } - /** - * WARNING: - * - * There is some nomenclature confusion through much of the BCEL code base with - * respect to the terms Descriptor and Signature. For the offical definitions see: - * - * @see - * Descriptors in The Java Virtual Machine Specification - * - * @see - * Signatures in The Java Virtual Machine Specification - * - * In brief, a descriptor is a string representing the type of a field or method. - * Signatures are similar, but more complex. Signatures are used to encode declarations - * written in the Java programming language that use types outside the type system of the - * Java Virtual Machine. They are used to describe the type of any class, interface, - * constructor, method or field whose declaration uses type variables or parameterized types. - * - * To parse a descriptor, call typeSignatureToString. - * To parse a signature, call signatureToString. - * - * Note that if the signature string is a single, non-generic item, the call to - * signatureToString reduces to a call to typeSignatureToString. - * Also note, that if you only wish to parse the first item in a longer signature - * string, you should call typeSignatureToString directly. + * Map opcode names to opcode numbers. E.g., return Constants.ALOAD for "aload" */ + public static short searchOpcode(String name) { + name = name.toLowerCase(Locale.ENGLISH); + for (short i = 0; i < Const.OPCODE_NAMES_LENGTH; i++) { + if (Const.getOpcodeName(i).equals(name)) { + return i; + } + } + return -1; + } + /** + * @return 'flag' with bit 'i' set to 1 + */ + public static int setBit(final int flag, final int i) { + return flag | pow2(i); + } /** - * Converts a signature to a string with all class names compacted. - * Class, Method and Type signatures are supported. + * Converts a signature to a string with all class names compacted. Class, Method and Type signatures are supported. * Enum and Interface signatures are not supported. * - * @param signature signature to convert + * @param signature signature to convert * @return String containg human readable signature */ - public static String signatureToString( final String signature ) { + public static String signatureToString(final String signature) { return signatureToString(signature, true); } - /** - * Converts a signature to a string. - * Class, Method and Type signatures are supported. - * Enum and Interface signatures are not supported. + * Converts a signature to a string. Class, Method and Type signatures are supported. Enum and Interface signatures are + * not supported. * - * @param signature signature to convert - * @param chopit flag that determines whether chopping is executed or not + * @param signature signature to convert + * @param chopit flag that determines whether chopping is executed or not * @return String containg human readable signature */ - public static String signatureToString( final String signature, final boolean chopit ) { + public static String signatureToString(final String signature, final boolean chopit) { String type = ""; String typeParams = ""; int index = 0; if (signature.charAt(0) == '<') { // we have type paramters typeParams = typeParamTypesToString(signature, chopit); - index += unwrap(consumed_chars); // update position + index += unwrap(CONSUMER_CHARS); // update position } if (signature.charAt(index) == '(') { // We have a Method signature. // add types of arguments type = typeParams + typeSignaturesToString(signature.substring(index), chopit, ')'); - index += unwrap(consumed_chars); // update position + index += unwrap(CONSUMER_CHARS); // update position // add return type type = type + typeSignatureToString(signature.substring(index), chopit); - index += unwrap(consumed_chars); // update position + index += unwrap(CONSUMER_CHARS); // update position // ignore any throws information in the signature return type; } // Could be Class or Type... type = typeSignatureToString(signature.substring(index), chopit); - index += unwrap(consumed_chars); // update position - if ((typeParams.length() == 0) && (index == signature.length())) { + index += unwrap(CONSUMER_CHARS); // update position + if (typeParams.isEmpty() && index == signature.length()) { // We have a Type signature. return type; } @@ -850,379 +1191,49 @@ public static String signatureToString( final String signature, final boolean ch if (index < signature.length()) { typeClass.append(" implements "); typeClass.append(typeSignatureToString(signature.substring(index), chopit)); - index += unwrap(consumed_chars); // update position + index += unwrap(CONSUMER_CHARS); // update position } while (index < signature.length()) { typeClass.append(", "); typeClass.append(typeSignatureToString(signature.substring(index), chopit)); - index += unwrap(consumed_chars); // update position + index += unwrap(CONSUMER_CHARS); // update position } return typeClass.toString(); } - /** - * Converts a type parameter list signature to a string. + * Convert bytes into hexadecimal string * - * @param signature signature to convert - * @param chopit flag that determines whether chopping is executed or not - * @return String containg human readable signature + * @param bytes an array of bytes to convert to hexadecimal + * + * @return bytes as hexadecimal string, e.g. 00 fa 12 ... */ - private static String typeParamTypesToString( final String signature, final boolean chopit ) { - // The first character is guranteed to be '<' - final StringBuilder typeParams = new StringBuilder("<"); - int index = 1; // skip the '<' - // get the first TypeParameter - typeParams.append(typeParamTypeToString(signature.substring(index), chopit)); - index += unwrap(consumed_chars); // update position - // are there more TypeParameters? - while (signature.charAt(index) != '>') { - typeParams.append(", "); - typeParams.append(typeParamTypeToString(signature.substring(index), chopit)); - index += unwrap(consumed_chars); // update position + public static String toHexString(final byte[] bytes) { + final StringBuilder buf = new StringBuilder(); + for (int i = 0; i < bytes.length; i++) { + final short b = byteToShort(bytes[i]); + final String hex = Integer.toHexString(b); + if (b < 0x10) { + buf.append('0'); + } + buf.append(hex); + if (i < bytes.length - 1) { + buf.append(' '); + } } - wrap(consumed_chars, index + 1); // account for the '>' char - return typeParams.append(">").toString(); + return buf.toString(); } - /** - * Converts a type parameter signature to a string. + * Return type of method signature as a byte value as defined in Constants * - * @param signature signature to convert - * @param chopit flag that determines whether chopping is executed or not - * @return String containg human readable signature + * @param signature in format described above + * @return type of method signature + * @see Const + * + * @throws ClassFormatException if signature is not a method signature */ - private static String typeParamTypeToString( final String signature, final boolean chopit ) { - int index = signature.indexOf(':'); - if (index <= 0) { - throw new ClassFormatException("Invalid type parameter signature: " + signature); - } - // get the TypeParameter identifier - final StringBuilder typeParam = new StringBuilder(signature.substring(0, index)); - index++; // account for the ':' - if (signature.charAt(index) != ':') { - // we have a class bound - typeParam.append(" extends "); - typeParam.append(typeSignatureToString(signature.substring(index), chopit)); - index += unwrap(consumed_chars); // update position - } - // look for interface bounds - while (signature.charAt(index) == ':') { - index++; // skip over the ':' - typeParam.append(" & "); - typeParam.append(typeSignatureToString(signature.substring(index), chopit)); - index += unwrap(consumed_chars); // update position - } - wrap(consumed_chars, index); - return typeParam.toString(); - } - - - /** - * Converts a list of type signatures to a string. - * - * @param signature signature to convert - * @param chopit flag that determines whether chopping is executed or not - * @param term character indicating the end of the list - * @return String containg human readable signature - */ - private static String typeSignaturesToString( final String signature, final boolean chopit, final char term ) { - // The first character will be an 'open' that matches the 'close' contained in term. - final StringBuilder typeList = new StringBuilder(signature.substring(0, 1)); - int index = 1; // skip the 'open' character - // get the first Type in the list - if (signature.charAt(index) != term) { - typeList.append(typeSignatureToString(signature.substring(index), chopit)); - index += unwrap(consumed_chars); // update position - } - // are there more types in the list? - while (signature.charAt(index) != term) { - typeList.append(", "); - typeList.append(typeSignatureToString(signature.substring(index), chopit)); - index += unwrap(consumed_chars); // update position - } - wrap(consumed_chars, index + 1); // account for the term char - return typeList.append(term).toString(); - } - - - /** - * - * This method converts a type signature string into a Java type declaration such as - * `String[]' and throws a `ClassFormatException' when the parsed type is invalid. - * - * @param signature type signature - * @param chopit flag that determines whether chopping is executed or not - * @return string containing human readable type signature - * @throws ClassFormatException - * @since 6.4.0 - */ - public static String typeSignatureToString( final String signature, final boolean chopit ) throws ClassFormatException { - //corrected concurrent private static field acess - wrap(consumed_chars, 1); // This is the default, read just one char like `B' - try { - switch (signature.charAt(0)) { - case 'B': - return "byte"; - case 'C': - return "char"; - case 'D': - return "double"; - case 'F': - return "float"; - case 'I': - return "int"; - case 'J': - return "long"; - case 'T': { // TypeVariableSignature - final int index = signature.indexOf(';'); // Look for closing `;' - if (index < 0) { - throw new ClassFormatException("Invalid type variable signature: " + signature); - } - //corrected concurrent private static field acess - wrap(consumed_chars, index + 1); // "Tblabla;" `T' and `;' are removed - return compactClassName(signature.substring(1, index), chopit); - } - case 'L': { // Full class name - // should this be a while loop? can there be more than - // one generic clause? (markro) - int fromIndex = signature.indexOf('<'); // generic type? - if (fromIndex < 0) { - fromIndex = 0; - } else { - fromIndex = signature.indexOf('>', fromIndex); - if (fromIndex < 0) { - throw new ClassFormatException("Invalid signature: " + signature); - } - } - final int index = signature.indexOf(';', fromIndex); // Look for closing `;' - if (index < 0) { - throw new ClassFormatException("Invalid signature: " + signature); - } - - // check to see if there are any TypeArguments - final int bracketIndex = signature.substring(0, index).indexOf('<'); - if (bracketIndex < 0) { - // just a class identifier - wrap(consumed_chars, index + 1); // "Lblabla;" `L' and `;' are removed - return compactClassName(signature.substring(1, index), chopit); - } - // but make sure we are not looking past the end of the current item - fromIndex = signature.indexOf(';'); - if (fromIndex < 0) { - throw new ClassFormatException("Invalid signature: " + signature); - } - if (fromIndex < bracketIndex) { - // just a class identifier - wrap(consumed_chars, fromIndex + 1); // "Lblabla;" `L' and `;' are removed - return compactClassName(signature.substring(1, fromIndex), chopit); - } - - // we have TypeArguments; build up partial result - // as we recurse for each TypeArgument - final StringBuilder type = new StringBuilder(compactClassName(signature.substring(1, bracketIndex), chopit)).append("<"); - int consumed_chars = bracketIndex + 1; // Shadows global var - - // check for wildcards - if (signature.charAt(consumed_chars) == '+') { - type.append("? extends "); - consumed_chars++; - } else if (signature.charAt(consumed_chars) == '-') { - type.append("? super "); - consumed_chars++; - } - - // get the first TypeArgument - if (signature.charAt(consumed_chars) == '*') { - type.append("?"); - consumed_chars++; - } else { - type.append(typeSignatureToString(signature.substring(consumed_chars), chopit)); - // update our consumed count by the number of characters the for type argument - consumed_chars = unwrap(Utility.consumed_chars) + consumed_chars; - wrap(Utility.consumed_chars, consumed_chars); - } - - // are there more TypeArguments? - while (signature.charAt(consumed_chars) != '>') { - type.append(", "); - // check for wildcards - if (signature.charAt(consumed_chars) == '+') { - type.append("? extends "); - consumed_chars++; - } else if (signature.charAt(consumed_chars) == '-') { - type.append("? super "); - consumed_chars++; - } - if (signature.charAt(consumed_chars) == '*') { - type.append("?"); - consumed_chars++; - } else { - type.append(typeSignatureToString(signature.substring(consumed_chars), chopit)); - // update our consumed count by the number of characters the for type argument - consumed_chars = unwrap(Utility.consumed_chars) + consumed_chars; - wrap(Utility.consumed_chars, consumed_chars); - } - } - - // process the closing ">" - consumed_chars++; - type.append(">"); - - if (signature.charAt(consumed_chars) == '.') { - // we have a ClassTypeSignatureSuffix - type.append("."); - // convert SimpleClassTypeSignature to fake ClassTypeSignature - // and then recurse to parse it - type.append(typeSignatureToString("L" + signature.substring(consumed_chars+1), chopit)); - // update our consumed count by the number of characters the for type argument - // note that this count includes the "L" we added, but that is ok - // as it accounts for the "." we didn't consume - consumed_chars = unwrap(Utility.consumed_chars) + consumed_chars; - wrap(Utility.consumed_chars, consumed_chars); - return type.toString(); - } - if (signature.charAt(consumed_chars) != ';') { - throw new ClassFormatException("Invalid signature: " + signature); - } - wrap(Utility.consumed_chars, consumed_chars + 1); // remove final ";" - return type.toString(); - } - case 'S': - return "short"; - case 'Z': - return "boolean"; - case '[': { // Array declaration - int n; - StringBuilder brackets; - String type; - int consumed_chars; // Shadows global var - brackets = new StringBuilder(); // Accumulate []'s - // Count opening brackets and look for optional size argument - for (n = 0; signature.charAt(n) == '['; n++) { - brackets.append("[]"); - } - consumed_chars = n; // Remember value - // The rest of the string denotes a `' - type = typeSignatureToString(signature.substring(n), chopit); - //corrected concurrent private static field acess - //Utility.consumed_chars += consumed_chars; is replaced by: - final int _temp = unwrap(Utility.consumed_chars) + consumed_chars; - wrap(Utility.consumed_chars, _temp); - return type + brackets.toString(); - } - case 'V': - return "void"; - default: - throw new ClassFormatException("Invalid signature: `" + signature + "'"); - } - } catch (final StringIndexOutOfBoundsException e) { // Should never occur - throw new ClassFormatException("Invalid signature: " + signature, e); - } - } - - - /** Parse Java type such as "char", or "java.lang.String[]" and return the - * signature in byte code format, e.g. "C" or "[Ljava/lang/String;" respectively. - * - * @param type Java type - * @return byte code signature - */ - public static String getSignature( String type ) { - final StringBuilder buf = new StringBuilder(); - final char[] chars = type.toCharArray(); - boolean char_found = false; - boolean delim = false; - int index = -1; - loop: for (int i = 0; i < chars.length; i++) { - switch (chars[i]) { - case ' ': - case '\t': - case '\n': - case '\r': - case '\f': - if (char_found) { - delim = true; - } - break; - case '[': - if (!char_found) { - throw new IllegalArgumentException("Illegal type: " + type); - } - index = i; - break loop; - default: - char_found = true; - if (!delim) { - buf.append(chars[i]); - } - } - } - int brackets = 0; - if (index > 0) { - brackets = countBrackets(type.substring(index)); - } - type = buf.toString(); - buf.setLength(0); - for (int i = 0; i < brackets; i++) { - buf.append('['); - } - boolean found = false; - for (int i = Const.T_BOOLEAN; (i <= Const.T_VOID) && !found; i++) { - if (Const.getTypeName(i).equals(type)) { - found = true; - buf.append(Const.getShortTypeName(i)); - } - } - if (!found) { - buf.append('L').append(type.replace('.', '/')).append(';'); - } - return buf.toString(); - } - - - private static int countBrackets( final String brackets ) { - final char[] chars = brackets.toCharArray(); - int count = 0; - boolean open = false; - for (final char c : chars) { - switch (c) { - case '[': - if (open) { - throw new IllegalArgumentException("Illegally nested brackets:" + brackets); - } - open = true; - break; - case ']': - if (!open) { - throw new IllegalArgumentException("Illegally nested brackets:" + brackets); - } - open = false; - count++; - break; - default: - // Don't care - break; - } - } - if (open) { - throw new IllegalArgumentException("Illegally nested brackets:" + brackets); - } - return count; - } - - - /** - * Return type of method signature as a byte value as defined in Constants - * - * @param signature in format described above - * @return type of method signature - * @see Const - * - * @throws ClassFormatException if signature is not a method signature - */ - public static byte typeOfMethodSignature( final String signature ) throws ClassFormatException { + public static byte typeOfMethodSignature(final String signature) throws ClassFormatException { int index; try { if (signature.charAt(0) != '(') { @@ -1235,425 +1246,317 @@ public static byte typeOfMethodSignature( final String signature ) throws ClassF } } - /** * Return type of signature as a byte value as defined in Constants * - * @param signature in format described above + * @param signature in format described above * @return type of signature - * @see Const + * @see Const * * @throws ClassFormatException if signature isn't a known type */ - public static byte typeOfSignature( final String signature ) throws ClassFormatException { + public static byte typeOfSignature(final String signature) throws ClassFormatException { try { switch (signature.charAt(0)) { - case 'B': - return Const.T_BYTE; - case 'C': - return Const.T_CHAR; - case 'D': - return Const.T_DOUBLE; - case 'F': - return Const.T_FLOAT; - case 'I': - return Const.T_INT; - case 'J': - return Const.T_LONG; - case 'L': - case 'T': - return Const.T_REFERENCE; - case '[': - return Const.T_ARRAY; - case 'V': - return Const.T_VOID; - case 'Z': - return Const.T_BOOLEAN; - case 'S': - return Const.T_SHORT; - case '!': - case '+': - case '*': - return typeOfSignature(signature.substring(1)); - default: - throw new ClassFormatException("Invalid method signature: " + signature); + case 'B': + return Const.T_BYTE; + case 'C': + return Const.T_CHAR; + case 'D': + return Const.T_DOUBLE; + case 'F': + return Const.T_FLOAT; + case 'I': + return Const.T_INT; + case 'J': + return Const.T_LONG; + case 'L': + case 'T': + return Const.T_REFERENCE; + case '[': + return Const.T_ARRAY; + case 'V': + return Const.T_VOID; + case 'Z': + return Const.T_BOOLEAN; + case 'S': + return Const.T_SHORT; + case '!': + case '+': + case '*': + return typeOfSignature(signature.substring(1)); + default: + throw new ClassFormatException("Invalid method signature: " + signature); } } catch (final StringIndexOutOfBoundsException e) { throw new ClassFormatException("Invalid method signature: " + signature, e); } } - - /** Map opcode names to opcode numbers. E.g., return Constants.ALOAD for "aload" - */ - public static short searchOpcode( String name ) { - name = name.toLowerCase(Locale.ENGLISH); - for (short i = 0; i < Const.OPCODE_NAMES_LENGTH; i++) { - if (Const.getOpcodeName(i).equals(name)) { - return i; - } - } - return -1; - } - - /** - * Convert (signed) byte to (unsigned) short value, i.e., all negative - * values become positive. - */ - private static short byteToShort( final byte b ) { - return (b < 0) ? (short) (256 + b) : (short) b; - } - - - /** Convert bytes into hexadecimal string - * - * @param bytes an array of bytes to convert to hexadecimal + * Converts a type parameter list signature to a string. * - * @return bytes as hexadecimal string, e.g. 00 fa 12 ... + * @param signature signature to convert + * @param chopit flag that determines whether chopping is executed or not + * @return String containg human readable signature */ - public static String toHexString( final byte[] bytes ) { - final StringBuilder buf = new StringBuilder(); - for (int i = 0; i < bytes.length; i++) { - final short b = byteToShort(bytes[i]); - final String hex = Integer.toHexString(b); - if (b < 0x10) { - buf.append('0'); - } - buf.append(hex); - if (i < bytes.length - 1) { - buf.append(' '); - } + private static String typeParamTypesToString(final String signature, final boolean chopit) { + // The first character is guranteed to be '<' + final StringBuilder typeParams = new StringBuilder("<"); + int index = 1; // skip the '<' + // get the first TypeParameter + typeParams.append(typeParamTypeToString(signature.substring(index), chopit)); + index += unwrap(CONSUMER_CHARS); // update position + // are there more TypeParameters? + while (signature.charAt(index) != '>') { + typeParams.append(", "); + typeParams.append(typeParamTypeToString(signature.substring(index), chopit)); + index += unwrap(CONSUMER_CHARS); // update position } - return buf.toString(); - } - - - /** - * Return a string for an integer justified left or right and filled up with - * `fill' characters if necessary. - * - * @param i integer to format - * @param length length of desired string - * @param left_justify format left or right - * @param fill fill character - * @return formatted int - */ - public static String format( final int i, final int length, final boolean left_justify, final char fill ) { - return fillup(Integer.toString(i), length, left_justify, fill); + wrap(CONSUMER_CHARS, index + 1); // account for the '>' char + return typeParams.append(">").toString(); } - /** - * Fillup char with up to length characters with char `fill' and justify it left or right. + * Converts a type parameter signature to a string. * - * @param str string to format - * @param length length of desired string - * @param left_justify format left or right - * @param fill fill character - * @return formatted string + * @param signature signature to convert + * @param chopit flag that determines whether chopping is executed or not + * @return String containg human readable signature */ - public static String fillup( final String str, final int length, final boolean left_justify, final char fill ) { - final int len = length - str.length(); - final char[] buf = new char[(len < 0) ? 0 : len]; - for (int j = 0; j < buf.length; j++) { - buf[j] = fill; - } - if (left_justify) { - return str + new String(buf); - } - return new String(buf) + str; - } - - - static boolean equals( final byte[] a, final byte[] b ) { - int size; - if ((size = a.length) != b.length) { - return false; - } - for (int i = 0; i < size; i++) { - if (a[i] != b[i]) { - return false; - } - } - return true; - } - - - public static void printArray( final PrintStream out, final Object[] obj ) { - out.println(printArray(obj, true)); - } - - - public static void printArray( final PrintWriter out, final Object[] obj ) { - out.println(printArray(obj, true)); - } - - - public static String printArray( final Object[] obj ) { - return printArray(obj, true); - } - - - public static String printArray( final Object[] obj, final boolean braces ) { - return printArray(obj, braces, false); - } - - - public static String printArray( final Object[] obj, final boolean braces, final boolean quote ) { - if (obj == null) { - return null; - } - final StringBuilder buf = new StringBuilder(); - if (braces) { - buf.append('{'); + private static String typeParamTypeToString(final String signature, final boolean chopit) { + int index = signature.indexOf(':'); + if (index <= 0) { + throw new ClassFormatException("Invalid type parameter signature: " + signature); } - for (int i = 0; i < obj.length; i++) { - if (obj[i] != null) { - buf.append(quote ? "\"" : "").append(obj[i]).append(quote ? "\"" : ""); - } else { - buf.append("null"); - } - if (i < obj.length - 1) { - buf.append(", "); - } + // get the TypeParameter identifier + final StringBuilder typeParam = new StringBuilder(signature.substring(0, index)); + index++; // account for the ':' + if (signature.charAt(index) != ':') { + // we have a class bound + typeParam.append(" extends "); + typeParam.append(typeSignatureToString(signature.substring(index), chopit)); + index += unwrap(CONSUMER_CHARS); // update position } - if (braces) { - buf.append('}'); + // look for interface bounds + while (signature.charAt(index) == ':') { + index++; // skip over the ':' + typeParam.append(" & "); + typeParam.append(typeSignatureToString(signature.substring(index), chopit)); + index += unwrap(CONSUMER_CHARS); // update position } - return buf.toString(); - } - - - /** - * @param ch the character to test if it's part of an identifier - * - * @return true, if character is one of (a, ... z, A, ... Z, 0, ... 9, _) - */ - public static boolean isJavaIdentifierPart( final char ch ) { - return ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) - || ((ch >= '0') && (ch <= '9')) || (ch == '_'); + wrap(CONSUMER_CHARS, index); + return typeParam.toString(); } - /** - * Encode byte array it into Java identifier string, i.e., a string - * that only contains the following characters: (a, ... z, A, ... Z, - * 0, ... 9, _, $). The encoding algorithm itself is not too - * clever: if the current byte's ASCII value already is a valid Java - * identifier part, leave it as it is. Otherwise it writes the - * escape character($) followed by: - * - *
      - *
    • the ASCII value as a hexadecimal string, if the value is not in the range 200..247
    • - *
    • a Java identifier char not used in a lowercase hexadecimal string, if the value is in the range 200..247
    • - *
    - * - *

    This operation inflates the original byte array by roughly 40-50%

    - * - * @param bytes the byte array to convert - * @param compress use gzip to minimize string + * Converts a list of type signatures to a string. * - * @throws IOException if there's a gzip exception + * @param signature signature to convert + * @param chopit flag that determines whether chopping is executed or not + * @param term character indicating the end of the list + * @return String containg human readable signature */ - public static String encode(byte[] bytes, final boolean compress) throws IOException { - if (compress) { - try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); - GZIPOutputStream gos = new GZIPOutputStream(baos)) { - gos.write(bytes, 0, bytes.length); - bytes = baos.toByteArray(); - } + private static String typeSignaturesToString(final String signature, final boolean chopit, final char term) { + // The first character will be an 'open' that matches the 'close' contained in term. + final StringBuilder typeList = new StringBuilder(signature.substring(0, 1)); + int index = 1; // skip the 'open' character + // get the first Type in the list + if (signature.charAt(index) != term) { + typeList.append(typeSignatureToString(signature.substring(index), chopit)); + index += unwrap(CONSUMER_CHARS); // update position } - final CharArrayWriter caw = new CharArrayWriter(); - try (JavaWriter jw = new JavaWriter(caw)) { - for (final byte b : bytes) { - final int in = b & 0x000000ff; // Normalize to unsigned - jw.write(in); - } + // are there more types in the list? + while (signature.charAt(index) != term) { + typeList.append(", "); + typeList.append(typeSignatureToString(signature.substring(index), chopit)); + index += unwrap(CONSUMER_CHARS); // update position } - return caw.toString(); + wrap(CONSUMER_CHARS, index + 1); // account for the term char + return typeList.append(term).toString(); } - /** - * Decode a string back to a byte array. * - * @param s the string to convert - * @param uncompress use gzip to uncompress the stream of bytes + * This method converts a type signature string into a Java type declaration such as 'String[]' and throws a + * 'ClassFormatException' when the parsed type is invalid. * - * @throws IOException if there's a gzip exception - */ - public static byte[] decode(final String s, final boolean uncompress) throws IOException { - byte[] bytes; - try (JavaReader jr = new JavaReader(new CharArrayReader(s.toCharArray())); - ByteArrayOutputStream bos = new ByteArrayOutputStream()) { - int ch; - while ((ch = jr.read()) >= 0) { - bos.write(ch); - } - bytes = bos.toByteArray(); - } - if (uncompress) { - final GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(bytes)); - final byte[] tmp = new byte[bytes.length * 3]; // Rough estimate - int count = 0; - int b; - while ((b = gis.read()) >= 0) { - tmp[count++] = (byte) b; - } - bytes = new byte[count]; - System.arraycopy(tmp, 0, bytes, 0, count); - } - return bytes; - } - - // A-Z, g-z, _, $ - private static final int FREE_CHARS = 48; - private static int[] CHAR_MAP = new int[FREE_CHARS]; - private static int[] MAP_CHAR = new int[256]; // Reverse map - private static final char ESCAPE_CHAR = '$'; - static { - int j = 0; - for (int i = 'A'; i <= 'Z'; i++) { - CHAR_MAP[j] = i; - MAP_CHAR[i] = j; - j++; - } - for (int i = 'g'; i <= 'z'; i++) { - CHAR_MAP[j] = i; - MAP_CHAR[i] = j; - j++; - } - CHAR_MAP[j] = '$'; - MAP_CHAR['$'] = j; - j++; - CHAR_MAP[j] = '_'; - MAP_CHAR['_'] = j; - } - - /** - * Decode characters into bytes. - * Used by decode() + * @param signature type signature + * @param chopit flag that determines whether chopping is executed or not + * @return string containing human readable type signature + * @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file + * @since 6.4.0 */ - private static class JavaReader extends FilterReader { - - public JavaReader(final Reader in) { - super(in); - } - - - @Override - public int read() throws IOException { - final int b = in.read(); - if (b != ESCAPE_CHAR) { - return b; - } - final int i = in.read(); - if (i < 0) { - return -1; - } - if (((i >= '0') && (i <= '9')) || ((i >= 'a') && (i <= 'f'))) { // Normal escape - final int j = in.read(); - if (j < 0) { - return -1; + public static String typeSignatureToString(final String signature, final boolean chopit) throws ClassFormatException { + // corrected concurrent private static field acess + wrap(CONSUMER_CHARS, 1); // This is the default, read just one char like 'B' + try { + switch (signature.charAt(0)) { + case 'B': + return "byte"; + case 'C': + return "char"; + case 'D': + return "double"; + case 'F': + return "float"; + case 'I': + return "int"; + case 'J': + return "long"; + case 'T': { // TypeVariableSignature + final int index = signature.indexOf(';'); // Look for closing ';' + if (index < 0) { + throw new ClassFormatException("Invalid type variable signature: " + signature); } - final char[] tmp = { - (char) i, (char) j - }; - final int s = Integer.parseInt(new String(tmp), 16); - return s; + // corrected concurrent private static field acess + wrap(CONSUMER_CHARS, index + 1); // "Tblabla;" 'T' and ';' are removed + return compactClassName(signature.substring(1, index), chopit); } - return MAP_CHAR[i]; - } - - - @Override - public int read( final char[] cbuf, final int off, final int len ) throws IOException { - for (int i = 0; i < len; i++) { - cbuf[off + i] = (char) read(); - } - return len; - } - } + case 'L': { // Full class name + // should this be a while loop? can there be more than + // one generic clause? (markro) + int fromIndex = signature.indexOf('<'); // generic type? + if (fromIndex < 0) { + fromIndex = 0; + } else { + fromIndex = signature.indexOf('>', fromIndex); + if (fromIndex < 0) { + throw new ClassFormatException("Invalid signature: " + signature); + } + } + final int index = signature.indexOf(';', fromIndex); // Look for closing ';' + if (index < 0) { + throw new ClassFormatException("Invalid signature: " + signature); + } - /** - * Encode bytes into valid java identifier characters. - * Used by encode() - */ - private static class JavaWriter extends FilterWriter { + // check to see if there are any TypeArguments + final int bracketIndex = signature.substring(0, index).indexOf('<'); + if (bracketIndex < 0) { + // just a class identifier + wrap(CONSUMER_CHARS, index + 1); // "Lblabla;" 'L' and ';' are removed + return compactClassName(signature.substring(1, index), chopit); + } + // but make sure we are not looking past the end of the current item + fromIndex = signature.indexOf(';'); + if (fromIndex < 0) { + throw new ClassFormatException("Invalid signature: " + signature); + } + if (fromIndex < bracketIndex) { + // just a class identifier + wrap(CONSUMER_CHARS, fromIndex + 1); // "Lblabla;" 'L' and ';' are removed + return compactClassName(signature.substring(1, fromIndex), chopit); + } - public JavaWriter(final Writer out) { - super(out); - } + // we have TypeArguments; build up partial result + // as we recurse for each TypeArgument + final StringBuilder type = new StringBuilder(compactClassName(signature.substring(1, bracketIndex), chopit)).append("<"); + int consumedChars = bracketIndex + 1; // Shadows global var + + // check for wildcards + if (signature.charAt(consumedChars) == '+') { + type.append("? extends "); + consumedChars++; + } else if (signature.charAt(consumedChars) == '-') { + type.append("? super "); + consumedChars++; + } + // get the first TypeArgument + if (signature.charAt(consumedChars) == '*') { + type.append("?"); + consumedChars++; + } else { + type.append(typeSignatureToString(signature.substring(consumedChars), chopit)); + // update our consumed count by the number of characters the for type argument + consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars; + wrap(Utility.CONSUMER_CHARS, consumedChars); + } - @Override - public void write( final int b ) throws IOException { - if (isJavaIdentifierPart((char) b) && (b != ESCAPE_CHAR)) { - out.write(b); - } else { - out.write(ESCAPE_CHAR); // Escape character - // Special escape - if (b >= 0 && b < FREE_CHARS) { - out.write(CHAR_MAP[b]); - } else { // Normal escape - final char[] tmp = Integer.toHexString(b).toCharArray(); - if (tmp.length == 1) { - out.write('0'); - out.write(tmp[0]); + // are there more TypeArguments? + while (signature.charAt(consumedChars) != '>') { + type.append(", "); + // check for wildcards + if (signature.charAt(consumedChars) == '+') { + type.append("? extends "); + consumedChars++; + } else if (signature.charAt(consumedChars) == '-') { + type.append("? super "); + consumedChars++; + } + if (signature.charAt(consumedChars) == '*') { + type.append("?"); + consumedChars++; } else { - out.write(tmp[0]); - out.write(tmp[1]); + type.append(typeSignatureToString(signature.substring(consumedChars), chopit)); + // update our consumed count by the number of characters the for type argument + consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars; + wrap(Utility.CONSUMER_CHARS, consumedChars); } } - } - } - - @Override - public void write( final char[] cbuf, final int off, final int len ) throws IOException { - for (int i = 0; i < len; i++) { - write(cbuf[off + i]); + // process the closing ">" + consumedChars++; + type.append(">"); + + if (signature.charAt(consumedChars) == '.') { + // we have a ClassTypeSignatureSuffix + type.append("."); + // convert SimpleClassTypeSignature to fake ClassTypeSignature + // and then recurse to parse it + type.append(typeSignatureToString("L" + signature.substring(consumedChars + 1), chopit)); + // update our consumed count by the number of characters the for type argument + // note that this count includes the "L" we added, but that is ok + // as it accounts for the "." we didn't consume + consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars; + wrap(Utility.CONSUMER_CHARS, consumedChars); + return type.toString(); + } + if (signature.charAt(consumedChars) != ';') { + throw new ClassFormatException("Invalid signature: " + signature); + } + wrap(Utility.CONSUMER_CHARS, consumedChars + 1); // remove final ";" + return type.toString(); } - } - - - @Override - public void write( final String str, final int off, final int len ) throws IOException { - write(str.toCharArray(), off, len); + case 'S': + return "short"; + case 'Z': + return "boolean"; + case '[': { // Array declaration + int n; + StringBuilder brackets; + String type; + int consumedChars; // Shadows global var + brackets = new StringBuilder(); // Accumulate []'s + // Count opening brackets and look for optional size argument + for (n = 0; signature.charAt(n) == '['; n++) { + brackets.append("[]"); + } + consumedChars = n; // Remember value + // The rest of the string denotes a '' + type = typeSignatureToString(signature.substring(n), chopit); + // corrected concurrent private static field acess + // Utility.consumed_chars += consumed_chars; is replaced by: + final int temp = unwrap(Utility.CONSUMER_CHARS) + consumedChars; + wrap(Utility.CONSUMER_CHARS, temp); + return type + brackets.toString(); + } + case 'V': + return "void"; + default: + throw new ClassFormatException("Invalid signature: '" + signature + "'"); + } + } catch (final StringIndexOutOfBoundsException e) { // Should never occur + throw new ClassFormatException("Invalid signature: " + signature, e); } } + private static int unwrap(final ThreadLocal tl) { + return tl.get(); + } - /** - * Escape all occurences of newline chars '\n', quotes \", etc. - */ - public static String convertString( final String label ) { - final char[] ch = label.toCharArray(); - final StringBuilder buf = new StringBuilder(); - for (final char element : ch) { - switch (element) { - case '\n': - buf.append("\\n"); - break; - case '\r': - buf.append("\\r"); - break; - case '\"': - buf.append("\\\""); - break; - case '\'': - buf.append("\\'"); - break; - case '\\': - buf.append("\\\\"); - break; - default: - buf.append(element); - break; - } - } - return buf.toString(); + private static void wrap(final ThreadLocal tl, final int value) { + tl.set(value); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java index 01fe6a79d4a..74cb8400d3e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java @@ -22,13 +22,30 @@ package com.sun.org.apache.bcel.internal.classfile; /** - * Interface to make use of the Visitor pattern programming style. I.e. a class - * that implements this interface can traverse the contents of a Java class just - * by calling the `accept' method which all classes have. - * + * Interface to make use of the Visitor pattern programming style. I.e. a class that implements this interface can + * traverse the contents of a Java class just by calling the 'accept' method which all classes have. */ -public interface Visitor -{ +public interface Visitor { + /** + * @since 6.0 + */ + void visitAnnotation(Annotations obj); + + /** + * @since 6.0 + */ + void visitAnnotationDefault(AnnotationDefault obj); + + /** + * @since 6.0 + */ + void visitAnnotationEntry(AnnotationEntry obj); + + /** + * @since 6.0 + */ + void visitBootstrapMethods(BootstrapMethods obj); + void visitCode(Code obj); void visitCodeException(CodeException obj); @@ -37,6 +54,13 @@ public interface Visitor void visitConstantDouble(ConstantDouble obj); + /** + * @since 6.3 + */ + default void visitConstantDynamic(final ConstantDynamic constantDynamic) { + // empty + } + void visitConstantFieldref(ConstantFieldref obj); void visitConstantFloat(ConstantFloat obj); @@ -49,10 +73,30 @@ public interface Visitor void visitConstantLong(ConstantLong obj); + /** + * @since 6.0 + */ + void visitConstantMethodHandle(ConstantMethodHandle obj); + void visitConstantMethodref(ConstantMethodref obj); + /** + * @since 6.0 + */ + void visitConstantMethodType(ConstantMethodType obj); + + /** + * @since 6.1 + */ + void visitConstantModule(ConstantModule constantModule); + void visitConstantNameAndType(ConstantNameAndType obj); + /** + * @since 6.1 + */ + void visitConstantPackage(ConstantPackage constantPackage); + void visitConstantPool(ConstantPool obj); void visitConstantString(ConstantString obj); @@ -63,6 +107,11 @@ public interface Visitor void visitDeprecated(Deprecated obj); + /** + * @since 6.0 + */ + void visitEnclosingMethod(EnclosingMethod obj); + void visitExceptionTable(ExceptionTable obj); void visitField(Field obj); @@ -81,59 +130,12 @@ public interface Visitor void visitLocalVariableTable(LocalVariableTable obj); - void visitMethod(Method obj); - - void visitSignature(Signature obj); - - void visitSourceFile(SourceFile obj); - - void visitSynthetic(Synthetic obj); - - void visitUnknown(Unknown obj); - - void visitStackMap(StackMap obj); - - void visitStackMapEntry(StackMapEntry obj); - - /** - * @since 6.0 - */ - void visitAnnotation(Annotations obj); - - /** - * @since 6.0 - */ - void visitParameterAnnotation(ParameterAnnotations obj); - - /** - * @since 6.0 - */ - void visitAnnotationEntry(AnnotationEntry obj); - - /** - * @since 6.0 - */ - void visitAnnotationDefault(AnnotationDefault obj); - /** * @since 6.0 */ void visitLocalVariableTypeTable(LocalVariableTypeTable obj); - /** - * @since 6.0 - */ - void visitEnclosingMethod(EnclosingMethod obj); - - /** - * @since 6.0 - */ - void visitBootstrapMethods(BootstrapMethods obj); - - /** - * @since 6.0 - */ - void visitMethodParameters(MethodParameters obj); + void visitMethod(Method obj); /** * @since 6.4.0 @@ -145,34 +147,7 @@ default void visitMethodParameter(final MethodParameter obj) { /** * @since 6.0 */ - void visitConstantMethodType(ConstantMethodType obj); - - /** - * @since 6.0 - */ - void visitConstantMethodHandle(ConstantMethodHandle obj); - - /** - * @since 6.0 - */ - void visitParameterAnnotationEntry(ParameterAnnotationEntry obj); - - /** - * @since 6.1 - */ - void visitConstantPackage(ConstantPackage constantPackage); - - /** - * @since 6.1 - */ - void visitConstantModule(ConstantModule constantModule); - - /** - * @since 6.3 - */ - default void visitConstantDynamic(final ConstantDynamic constantDynamic) { - // empty - } + void visitMethodParameters(MethodParameters obj); /** * @since 6.4.0 @@ -184,14 +159,14 @@ default void visitModule(final Module constantModule) { /** * @since 6.4.0 */ - default void visitModuleRequires(final ModuleRequires constantModule) { + default void visitModuleExports(final ModuleExports constantModule) { // empty } /** * @since 6.4.0 */ - default void visitModuleExports(final ModuleExports constantModule) { + default void visitModuleMainClass(final ModuleMainClass obj) { // empty } @@ -205,21 +180,21 @@ default void visitModuleOpens(final ModuleOpens constantModule) { /** * @since 6.4.0 */ - default void visitModuleProvides(final ModuleProvides constantModule) { + default void visitModulePackages(final ModulePackages constantModule) { // empty } /** * @since 6.4.0 */ - default void visitModulePackages(final ModulePackages constantModule) { + default void visitModuleProvides(final ModuleProvides constantModule) { // empty } /** * @since 6.4.0 */ - default void visitModuleMainClass(final ModuleMainClass obj) { + default void visitModuleRequires(final ModuleRequires constantModule) { // empty } @@ -236,4 +211,26 @@ default void visitNestHost(final NestHost obj) { default void visitNestMembers(final NestMembers obj) { // empty } + + /** + * @since 6.0 + */ + void visitParameterAnnotation(ParameterAnnotations obj); + + /** + * @since 6.0 + */ + void visitParameterAnnotationEntry(ParameterAnnotationEntry obj); + + void visitSignature(Signature obj); + + void visitSourceFile(SourceFile obj); + + void visitStackMap(StackMap obj); + + void visitStackMapEntry(StackMapEntry obj); + + void visitSynthetic(Synthetic obj); + + void visitUnknown(Unknown obj); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AALOAD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AALOAD.java index b03235eb9bc..19bd38d0a7d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AALOAD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AALOAD.java @@ -23,28 +23,28 @@ /** * AALOAD - Load reference from array - *
    Stack: ..., arrayref, index -> value
    * + *
    + * Stack: ..., arrayref, index -> value
    + * 
    */ public class AALOAD extends ArrayInstruction implements StackProducer { - /** Load reference from array + /** + * Load reference from array */ public AALOAD() { super(com.sun.org.apache.bcel.internal.Const.AALOAD); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AASTORE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AASTORE.java index 1dab21a2ff5..9561ab4c77b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AASTORE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AASTORE.java @@ -22,29 +22,29 @@ package com.sun.org.apache.bcel.internal.generic; /** - * AASTORE - Store into reference array - *
    Stack: ..., arrayref, index, value -> ...
    + * AASTORE - Store into reference array * + *
    + * Stack: ..., arrayref, index, value -> ...
    + * 
    */ public class AASTORE extends ArrayInstruction implements StackConsumer { - /** Store into reference array + /** + * Store into reference array */ public AASTORE() { super(com.sun.org.apache.bcel.internal.Const.AASTORE); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ACONST_NULL.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ACONST_NULL.java index a15aa1af40d..95556b9d085 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ACONST_NULL.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ACONST_NULL.java @@ -23,8 +23,10 @@ /** * ACONST_NULL - Push null reference - *
    Stack: ... -> ..., null
    * + *
    + * Stack: ... -> ..., null
    + * 
    */ public class ACONST_NULL extends Instruction implements PushInstruction, TypedInstruction { @@ -35,28 +37,25 @@ public ACONST_NULL() { super(com.sun.org.apache.bcel.internal.Const.ACONST_NULL, (short) 1); } - - /** @return Type.NULL - */ - @Override - public Type getType( final ConstantPoolGen cp ) { - return Type.NULL; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitPushInstruction(this); v.visitTypedInstruction(this); v.visitACONST_NULL(this); } + + /** + * @return Type.NULL + */ + @Override + public Type getType(final ConstantPoolGen cp) { + return Type.NULL; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ALOAD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ALOAD.java index ec2bcb657b0..8db0f9fadeb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ALOAD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ALOAD.java @@ -20,43 +20,40 @@ package com.sun.org.apache.bcel.internal.generic; -import com.sun.org.apache.bcel.internal.Const; - /** * ALOAD - Load reference from local variable - *
    Stack: ... -> ..., objectref
    * + *
    + * Stack: ... -> ..., objectref
    + * 
    * @LastModified: Jan 2020 */ public class ALOAD extends LoadInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ ALOAD() { - super(Const.ALOAD, Const.ALOAD_0); + super(com.sun.org.apache.bcel.internal.Const.ALOAD, com.sun.org.apache.bcel.internal.Const.ALOAD_0); } - - /** Load reference from local variable + /** + * Load reference from local variable + * * @param n index of local variable */ public ALOAD(final int n) { - super(Const.ALOAD, Const.ALOAD_0, n); + super(com.sun.org.apache.bcel.internal.Const.ALOAD, com.sun.org.apache.bcel.internal.Const.ALOAD_0, n); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { super.accept(v); v.visitALOAD(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ANEWARRAY.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ANEWARRAY.java index f81d6213ae5..eabf15c38b4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ANEWARRAY.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ANEWARRAY.java @@ -24,43 +24,32 @@ import com.sun.org.apache.bcel.internal.ExceptionConst; /** - * ANEWARRAY - Create new array of references - *
    Stack: ..., count -> ..., arrayref
    + * ANEWARRAY - Create new array of references * + *
    + * Stack: ..., count -> ..., arrayref
    + * 
    */ -public class ANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction, - ExceptionThrower, StackConsumer, StackProducer { +public class ANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction, ExceptionThrower, StackConsumer, StackProducer { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ ANEWARRAY() { } - public ANEWARRAY(final int index) { super(com.sun.org.apache.bcel.internal.Const.ANEWARRAY, index); } - - @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_CLASS_AND_INTERFACE_RESOLUTION, - ExceptionConst.NEGATIVE_ARRAY_SIZE_EXCEPTION); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitLoadClass(this); v.visitAllocationInstruction(this); v.visitExceptionThrower(this); @@ -70,13 +59,17 @@ public void accept( final Visitor v ) { v.visitANEWARRAY(this); } + @Override + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_CLASS_AND_INTERFACE_RESOLUTION, ExceptionConst.NEGATIVE_ARRAY_SIZE_EXCEPTION); + } @Override - public ObjectType getLoadClassType( final ConstantPoolGen cpg ) { + public ObjectType getLoadClassType(final ConstantPoolGen cpg) { Type t = getType(cpg); if (t instanceof ArrayType) { t = ((ArrayType) t).getBasicType(); } - return (t instanceof ObjectType) ? (ObjectType) t : null; + return t instanceof ObjectType ? (ObjectType) t : null; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARETURN.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARETURN.java index 7231236e28b..ff2428d457c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARETURN.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARETURN.java @@ -22,9 +22,11 @@ package com.sun.org.apache.bcel.internal.generic; /** - * ARETURN - Return reference from method - *
    Stack: ..., objectref -> <empty>
    + * ARETURN - Return reference from method * + *
    + * Stack: ..., objectref -> <empty>
    + * 
    */ public class ARETURN extends ReturnInstruction { @@ -35,17 +37,14 @@ public ARETURN() { super(com.sun.org.apache.bcel.internal.Const.ARETURN); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java index 287a86de707..2d7188e9174 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -23,43 +23,40 @@ import com.sun.org.apache.bcel.internal.ExceptionConst; /** - * ARRAYLENGTH - Get length of array - *
    Stack: ..., arrayref -> ..., length
    + * ARRAYLENGTH - Get length of array * - * @LastModified: Jun 2019 + *
    + * Stack: ..., arrayref -> ..., length
    + * 
    + * @LastModified: Feb 2023 */ -public class ARRAYLENGTH extends Instruction - implements ExceptionThrower, StackProducer, StackConsumer /* since 6.0 */ { +public class ARRAYLENGTH extends Instruction implements ExceptionThrower, StackProducer, StackConsumer /* since 6.0 */ { - /** Get length of array + /** + * Get length of array */ public ARRAYLENGTH() { super(com.sun.org.apache.bcel.internal.Const.ARRAYLENGTH, (short) 1); } - - /** @return exceptions this instruction may cause - */ - @Override - public Class[] getExceptions() { - return new Class[] { - ExceptionConst.NULL_POINTER_EXCEPTION - }; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitStackProducer(this); v.visitARRAYLENGTH(this); } + + /** + * @return exceptions this instruction may cause + */ + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConst.NULL_POINTER_EXCEPTION}; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ASTORE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ASTORE.java index e68b2935762..7852c66466f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ASTORE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ASTORE.java @@ -19,43 +19,40 @@ */ package com.sun.org.apache.bcel.internal.generic; -import com.sun.org.apache.bcel.internal.Const; - /** * ASTORE - Store reference into local variable - *
    Stack ..., objectref -> ... 
    * + *
    + * Stack ..., objectref -> ...
    + * 
    * @LastModified: Jan 2020 */ public class ASTORE extends StoreInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ ASTORE() { - super(Const.ASTORE, Const.ASTORE_0); + super(com.sun.org.apache.bcel.internal.Const.ASTORE, com.sun.org.apache.bcel.internal.Const.ASTORE_0); } - - /** Store reference into local variable + /** + * Store reference into local variable + * * @param n index of local variable */ public ASTORE(final int n) { - super(Const.ASTORE, Const.ASTORE_0, n); + super(com.sun.org.apache.bcel.internal.Const.ASTORE, com.sun.org.apache.bcel.internal.Const.ASTORE_0, n); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { super.accept(v); v.visitASTORE(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java index 50d38bc353c..bb2e953f850 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java @@ -23,43 +23,39 @@ import com.sun.org.apache.bcel.internal.ExceptionConst; /** - * ATHROW - Throw exception - *
    Stack: ..., objectref -> objectref
    + * ATHROW - Throw exception * - * @LastModified: Jan 2020 + *
    + * Stack: ..., objectref -> objectref
    + * 
    */ public class ATHROW extends Instruction implements UnconditionalBranch, ExceptionThrower { /** - * Throw exception + * Throw exception */ public ATHROW() { super(com.sun.org.apache.bcel.internal.Const.ATHROW, (short) 1); } - - /** @return exceptions this instruction may cause - */ - @Override - public Class[] getExceptions() { - return new Class[] { - ExceptionConst.THROWABLE - }; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitUnconditionalBranch(this); v.visitExceptionThrower(this); v.visitATHROW(this); } + + /** + * @return exceptions this instruction may cause + */ + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConst.THROWABLE}; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AllocationInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AllocationInstruction.java index bf88d81087c..8e8626d32d0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AllocationInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AllocationInstruction.java @@ -23,7 +23,6 @@ /** * Denote family of instructions that allocates space in the heap. - * */ public interface AllocationInstruction { } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationElementValueGen.java index e58f6006969..1ed232d7292 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationElementValueGen.java @@ -30,61 +30,48 @@ /** * @since 6.0 */ -public class AnnotationElementValueGen extends ElementValueGen -{ +public class AnnotationElementValueGen extends ElementValueGen { // For annotation element values, this is the annotation private final AnnotationEntryGen a; - public AnnotationElementValueGen(final AnnotationEntryGen a, final ConstantPoolGen cpool) - { + public AnnotationElementValueGen(final AnnotationElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) { + super(ANNOTATION, cpool); + a = new AnnotationEntryGen(value.getAnnotationEntry(), cpool, copyPoolEntries); + } + + public AnnotationElementValueGen(final AnnotationEntryGen a, final ConstantPoolGen cpool) { super(ANNOTATION, cpool); this.a = a; } - public AnnotationElementValueGen(final int type, final AnnotationEntryGen annotation, - final ConstantPoolGen cpool) - { + public AnnotationElementValueGen(final int type, final AnnotationEntryGen annotation, final ConstantPoolGen cpool) { super(type, cpool); if (type != ANNOTATION) { - throw new IllegalArgumentException( - "Only element values of type annotation can be built with this ctor - type specified: " + type); + throw new IllegalArgumentException("Only element values of type annotation can be built with this ctor - type specified: " + type); } this.a = annotation; } - public AnnotationElementValueGen(final AnnotationElementValue value, - final ConstantPoolGen cpool, final boolean copyPoolEntries) - { - super(ANNOTATION, cpool); - a = new AnnotationEntryGen(value.getAnnotationEntry(), cpool, copyPoolEntries); - } - @Override - public void dump(final DataOutputStream dos) throws IOException - { + public void dump(final DataOutputStream dos) throws IOException { dos.writeByte(super.getElementValueType()); // u1 type of value (ANNOTATION == '@') a.dump(dos); } - @Override - public String stringifyValue() - { - throw new UnsupportedOperationException("Not implemented yet"); + public AnnotationEntryGen getAnnotation() { + return a; } /** * Return immutable variant of this AnnotationElementValueGen */ @Override - public ElementValue getElementValue() - { - return new AnnotationElementValue(super.getElementValueType(), - a.getAnnotation(), - getConstantPool().getConstantPool()); + public ElementValue getElementValue() { + return new AnnotationElementValue(super.getElementValueType(), a.getAnnotation(), getConstantPool().getConstantPool()); } - public AnnotationEntryGen getAnnotation() - { - return a; + @Override + public String stringifyValue() { + throw new UnsupportedOperationException("Not implemented yet"); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java index 0223ee1b598..ea01a837175 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java @@ -43,173 +43,25 @@ * @LastModified: Jan 2020 */ public class AnnotationEntryGen { - private int typeIndex; - - private List evs; - - private final ConstantPoolGen cpool; - - private boolean isRuntimeVisible = false; - - /** - * Here we are taking a fixed annotation of type Annotation and building a - * modifiable AnnotationGen object. If the pool passed in is for a different - * class file, then copyPoolEntries should have been passed as true as that - * will force us to do a deep copy of the annotation and move the cpool - * entries across. We need to copy the type and the element name value pairs - * and the visibility. - */ - public AnnotationEntryGen(final AnnotationEntry a, final ConstantPoolGen cpool, - final boolean copyPoolEntries) { - this.cpool = cpool; - if (copyPoolEntries) { - typeIndex = cpool.addUtf8(a.getAnnotationType()); - } else { - typeIndex = a.getAnnotationTypeIndex(); - } - isRuntimeVisible = a.isRuntimeVisible(); - evs = copyValues(a.getElementValuePairs(), cpool, copyPoolEntries); - } - - private List copyValues(final ElementValuePair[] in, final ConstantPoolGen cpool, - final boolean copyPoolEntries) { - final List out = new ArrayList<>(); - for (final ElementValuePair nvp : in) { - out.add(new ElementValuePairGen(nvp, cpool, copyPoolEntries)); - } - return out; - } - - private AnnotationEntryGen(final ConstantPoolGen cpool) { - this.cpool = cpool; - } - - /** - * Retrieve an immutable version of this AnnotationGen - */ - public AnnotationEntry getAnnotation() { - final AnnotationEntry a = new AnnotationEntry(typeIndex, cpool.getConstantPool(), - isRuntimeVisible); - for (final ElementValuePairGen element : evs) { - a.addElementNameValuePair(element.getElementNameValuePair()); - } - return a; - } - - public AnnotationEntryGen(final ObjectType type, - final List elements, final boolean vis, - final ConstantPoolGen cpool) { - this.cpool = cpool; - this.typeIndex = cpool.addUtf8(type.getSignature()); - evs = elements; - isRuntimeVisible = vis; - } - - public static AnnotationEntryGen read(final DataInput dis, - final ConstantPoolGen cpool, final boolean b) throws IOException { - final AnnotationEntryGen a = new AnnotationEntryGen(cpool); - a.typeIndex = dis.readUnsignedShort(); - final int elemValuePairCount = dis.readUnsignedShort(); - for (int i = 0; i < elemValuePairCount; i++) { - final int nidx = dis.readUnsignedShort(); - a.addElementNameValuePair(new ElementValuePairGen(nidx, - ElementValueGen.readElementValue(dis, cpool), cpool)); - } - a.isRuntimeVisible(b); - return a; - } - - public void dump(final DataOutputStream dos) throws IOException { - dos.writeShort(typeIndex); // u2 index of type name in cpool - dos.writeShort(evs.size()); // u2 element_value pair count - for (final ElementValuePairGen envp : evs) { - envp.dump(dos); - } - } - - public void addElementNameValuePair(final ElementValuePairGen evp) { - if (evs == null) { - evs = new ArrayList<>(); - } - evs.add(evp); - } - public int getTypeIndex() { - return typeIndex; - } - - public final String getTypeSignature() { - // ConstantClass c = (ConstantClass)cpool.getConstant(typeIndex); - final ConstantUtf8 utf8 = (ConstantUtf8) cpool - .getConstant(typeIndex/* c.getNameIndex() */); - return utf8.getBytes(); - } - - public final String getTypeName() { - return getTypeSignature();// BCELBUG: Should I use this instead? - // Utility.signatureToString(getTypeSignature()); - } + static final AnnotationEntryGen[] EMPTY_ARRAY = {}; /** - * Returns list of ElementNameValuePair objects - */ - public List getValues() { - return evs; - } - - @Override - public String toString() { - final StringBuilder s = new StringBuilder(32); // CHECKSTYLE IGNORE MagicNumber - s.append("AnnotationGen:[").append(getTypeName()).append(" #").append(evs.size()).append(" {"); - for (int i = 0; i < evs.size(); i++) { - s.append(evs.get(i)); - if (i + 1 < evs.size()) { - s.append(","); - } - } - s.append("}]"); - return s.toString(); - } - - public String toShortString() { - final StringBuilder s = new StringBuilder(); - s.append("@").append(getTypeName()).append("("); - for (int i = 0; i < evs.size(); i++) { - s.append(evs.get(i)); - if (i + 1 < evs.size()) { - s.append(","); - } - } - s.append(")"); - return s.toString(); - } - - private void isRuntimeVisible(final boolean b) { - isRuntimeVisible = b; - } - - public boolean isRuntimeVisible() { - return isRuntimeVisible; - } - - - /** - * Converts a list of AnnotationGen objects into a set of attributes - * that can be attached to the class file. + * Converts a list of AnnotationGen objects into a set of attributes that can be attached to the class file. * - * @param cp The constant pool gen where we can create the necessary name refs + * @param cp The constant pool gen where we can create the necessary name refs * @param annotationEntryGens An array of AnnotationGen objects */ static Attribute[] getAnnotationAttributes(final ConstantPoolGen cp, final AnnotationEntryGen[] annotationEntryGens) { if (annotationEntryGens.length == 0) { - return new Attribute[0]; + return Attribute.EMPTY_ARRAY; } try { int countVisible = 0; int countInvisible = 0; - // put the annotations in the right output stream + // put the annotations in the right output stream for (final AnnotationEntryGen a : annotationEntryGens) { if (a.isRuntimeVisible()) { countVisible++; @@ -220,8 +72,7 @@ static Attribute[] getAnnotationAttributes(final ConstantPoolGen cp, final Annot final ByteArrayOutputStream rvaBytes = new ByteArrayOutputStream(); final ByteArrayOutputStream riaBytes = new ByteArrayOutputStream(); - try (DataOutputStream rvaDos = new DataOutputStream(rvaBytes); - DataOutputStream riaDos = new DataOutputStream(riaBytes)) { + try (DataOutputStream rvaDos = new DataOutputStream(rvaBytes); DataOutputStream riaDos = new DataOutputStream(riaBytes)) { rvaDos.writeShort(countVisible); riaDos.writeShort(countInvisible); @@ -251,17 +102,15 @@ static Attribute[] getAnnotationAttributes(final ConstantPoolGen cp, final Annot final List newAttributes = new ArrayList<>(); if (rvaData.length > 2) { - newAttributes.add( - new RuntimeVisibleAnnotations(rvaIndex, rvaData.length, - new DataInputStream(new ByteArrayInputStream(rvaData)), cp.getConstantPool())); + newAttributes + .add(new RuntimeVisibleAnnotations(rvaIndex, rvaData.length, new DataInputStream(new ByteArrayInputStream(rvaData)), cp.getConstantPool())); } if (riaData.length > 2) { newAttributes.add( - new RuntimeInvisibleAnnotations(riaIndex, riaData.length, - new DataInputStream(new ByteArrayInputStream(riaData)), cp.getConstantPool())); + new RuntimeInvisibleAnnotations(riaIndex, riaData.length, new DataInputStream(new ByteArrayInputStream(riaData)), cp.getConstantPool())); } - return newAttributes.toArray(new Attribute[newAttributes.size()]); + return newAttributes.toArray(Attribute.EMPTY_ARRAY); } catch (final IOException e) { System.err.println("IOException whilst processing annotations"); e.printStackTrace(); @@ -269,15 +118,12 @@ static Attribute[] getAnnotationAttributes(final ConstantPoolGen cp, final Annot return null; } - /** - * Annotations against a class are stored in one of four attribute kinds: - * - RuntimeVisibleParameterAnnotations - * - RuntimeInvisibleParameterAnnotations + * Annotations against a class are stored in one of four attribute kinds: - RuntimeVisibleParameterAnnotations - + * RuntimeInvisibleParameterAnnotations */ - static Attribute[] getParameterAnnotationAttributes( - final ConstantPoolGen cp, - final List[] /*Array of lists, array size depends on #params */vec) { + static Attribute[] getParameterAnnotationAttributes(final ConstantPoolGen cp, + final List[] /* Array of lists, array size depends on #params */ vec) { final int[] visCount = new int[vec.length]; int totalVisCount = 0; final int[] invisCount = new int[vec.length]; @@ -338,25 +184,158 @@ static Attribute[] getParameterAnnotationAttributes( } final List newAttributes = new ArrayList<>(); if (totalVisCount > 0) { - newAttributes - .add(new RuntimeVisibleParameterAnnotations(rvaIndex, - rvaData.length, - new DataInputStream(new ByteArrayInputStream(rvaData)), - cp.getConstantPool())); + newAttributes.add(new RuntimeVisibleParameterAnnotations(rvaIndex, rvaData.length, new DataInputStream(new ByteArrayInputStream(rvaData)), + cp.getConstantPool())); } if (totalInvisCount > 0) { - newAttributes - .add(new RuntimeInvisibleParameterAnnotations(riaIndex, - riaData.length, - new DataInputStream(new ByteArrayInputStream(riaData)), - cp.getConstantPool())); + newAttributes.add(new RuntimeInvisibleParameterAnnotations(riaIndex, riaData.length, new DataInputStream(new ByteArrayInputStream(riaData)), + cp.getConstantPool())); } - return newAttributes.toArray(new Attribute[newAttributes.size()]); + return newAttributes.toArray(Attribute.EMPTY_ARRAY); } catch (final IOException e) { - System.err.println("IOException whilst processing parameter annotations." + - e.getMessage()); + System.err.println("IOException whilst processing parameter annotations"); + e.printStackTrace(); } return null; } + public static AnnotationEntryGen read(final DataInput dis, final ConstantPoolGen cpool, final boolean b) throws IOException { + final AnnotationEntryGen a = new AnnotationEntryGen(cpool); + a.typeIndex = dis.readUnsignedShort(); + final int elemValuePairCount = dis.readUnsignedShort(); + for (int i = 0; i < elemValuePairCount; i++) { + final int nidx = dis.readUnsignedShort(); + a.addElementNameValuePair(new ElementValuePairGen(nidx, ElementValueGen.readElementValue(dis, cpool), cpool)); + } + a.isRuntimeVisible(b); + return a; + } + + private int typeIndex; + + private List evs; + + private final ConstantPoolGen cpool; + + private boolean isRuntimeVisible; + + /** + * Here we are taking a fixed annotation of type Annotation and building a modifiable AnnotationGen object. If the pool + * passed in is for a different class file, then copyPoolEntries should have been passed as true as that will force us + * to do a deep copy of the annotation and move the cpool entries across. We need to copy the type and the element name + * value pairs and the visibility. + */ + public AnnotationEntryGen(final AnnotationEntry a, final ConstantPoolGen cpool, final boolean copyPoolEntries) { + this.cpool = cpool; + if (copyPoolEntries) { + typeIndex = cpool.addUtf8(a.getAnnotationType()); + } else { + typeIndex = a.getAnnotationTypeIndex(); + } + isRuntimeVisible = a.isRuntimeVisible(); + evs = copyValues(a.getElementValuePairs(), cpool, copyPoolEntries); + } + + private AnnotationEntryGen(final ConstantPoolGen cpool) { + this.cpool = cpool; + } + + public AnnotationEntryGen(final ObjectType type, final List elements, final boolean vis, final ConstantPoolGen cpool) { + this.cpool = cpool; + this.typeIndex = cpool.addUtf8(type.getSignature()); + evs = elements; + isRuntimeVisible = vis; + } + + public void addElementNameValuePair(final ElementValuePairGen evp) { + if (evs == null) { + evs = new ArrayList<>(); + } + evs.add(evp); + } + + private List copyValues(final ElementValuePair[] in, final ConstantPoolGen cpool, final boolean copyPoolEntries) { + final List out = new ArrayList<>(); + for (final ElementValuePair nvp : in) { + out.add(new ElementValuePairGen(nvp, cpool, copyPoolEntries)); + } + return out; + } + + public void dump(final DataOutputStream dos) throws IOException { + dos.writeShort(typeIndex); // u2 index of type name in cpool + dos.writeShort(evs.size()); // u2 element_value pair count + for (final ElementValuePairGen envp : evs) { + envp.dump(dos); + } + } + + /** + * Retrieve an immutable version of this AnnotationGen + */ + public AnnotationEntry getAnnotation() { + final AnnotationEntry a = new AnnotationEntry(typeIndex, cpool.getConstantPool(), isRuntimeVisible); + for (final ElementValuePairGen element : evs) { + a.addElementNameValuePair(element.getElementNameValuePair()); + } + return a; + } + + public int getTypeIndex() { + return typeIndex; + } + + public final String getTypeName() { + return getTypeSignature();// BCELBUG: Should I use this instead? + // Utility.signatureToString(getTypeSignature()); + } + + public final String getTypeSignature() { + // ConstantClass c = (ConstantClass)cpool.getConstant(typeIndex); + final ConstantUtf8 utf8 = (ConstantUtf8) cpool.getConstant(typeIndex/* c.getNameIndex() */); + return utf8.getBytes(); + } + + /** + * Returns list of ElementNameValuePair objects + */ + public List getValues() { + return evs; + } + + public boolean isRuntimeVisible() { + return isRuntimeVisible; + } + + private void isRuntimeVisible(final boolean b) { + isRuntimeVisible = b; + } + + public String toShortString() { + final StringBuilder s = new StringBuilder(); + s.append("@").append(getTypeName()).append("("); + for (int i = 0; i < evs.size(); i++) { + s.append(evs.get(i)); + if (i + 1 < evs.size()) { + s.append(","); + } + } + s.append(")"); + return s.toString(); + } + + @Override + public String toString() { + final StringBuilder s = new StringBuilder(32); // CHECKSTYLE IGNORE MagicNumber + s.append("AnnotationGen:[").append(getTypeName()).append(" #").append(evs.size()).append(" {"); + for (int i = 0; i < evs.size(); i++) { + s.append(evs.get(i)); + if (i + 1 < evs.size()) { + s.append(","); + } + } + s.append("}]"); + return s.toString(); + } + } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArithmeticInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArithmeticInstruction.java index cea2317e395..752ab1155c7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArithmeticInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArithmeticInstruction.java @@ -25,19 +25,15 @@ /** * Super class for the family of arithmetic instructions. - * */ -public abstract class ArithmeticInstruction extends Instruction implements TypedInstruction, - StackProducer, StackConsumer { +public abstract class ArithmeticInstruction extends Instruction implements TypedInstruction, StackProducer, StackConsumer { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ ArithmeticInstruction() { } - /** * @param opcode of instruction */ @@ -45,55 +41,55 @@ protected ArithmeticInstruction(final short opcode) { super(opcode, (short) 1); } - - /** @return type associated with the instruction + /** + * @return type associated with the instruction */ @Override - public Type getType( final ConstantPoolGen cp ) { - final short _opcode = super.getOpcode(); - switch (_opcode) { - case Const.DADD: - case Const.DDIV: - case Const.DMUL: - case Const.DNEG: - case Const.DREM: - case Const.DSUB: - return Type.DOUBLE; - case Const.FADD: - case Const.FDIV: - case Const.FMUL: - case Const.FNEG: - case Const.FREM: - case Const.FSUB: - return Type.FLOAT; - case Const.IADD: - case Const.IAND: - case Const.IDIV: - case Const.IMUL: - case Const.INEG: - case Const.IOR: - case Const.IREM: - case Const.ISHL: - case Const.ISHR: - case Const.ISUB: - case Const.IUSHR: - case Const.IXOR: - return Type.INT; - case Const.LADD: - case Const.LAND: - case Const.LDIV: - case Const.LMUL: - case Const.LNEG: - case Const.LOR: - case Const.LREM: - case Const.LSHL: - case Const.LSHR: - case Const.LSUB: - case Const.LUSHR: - case Const.LXOR: - return Type.LONG; - default: // Never reached - throw new ClassGenException("Unknown type " + _opcode); + public Type getType(final ConstantPoolGen cp) { + final short opcode = super.getOpcode(); + switch (opcode) { + case Const.DADD: + case Const.DDIV: + case Const.DMUL: + case Const.DNEG: + case Const.DREM: + case Const.DSUB: + return Type.DOUBLE; + case Const.FADD: + case Const.FDIV: + case Const.FMUL: + case Const.FNEG: + case Const.FREM: + case Const.FSUB: + return Type.FLOAT; + case Const.IADD: + case Const.IAND: + case Const.IDIV: + case Const.IMUL: + case Const.INEG: + case Const.IOR: + case Const.IREM: + case Const.ISHL: + case Const.ISHR: + case Const.ISUB: + case Const.IUSHR: + case Const.IXOR: + return Type.INT; + case Const.LADD: + case Const.LAND: + case Const.LDIV: + case Const.LMUL: + case Const.LNEG: + case Const.LOR: + case Const.LREM: + case Const.LSHL: + case Const.LSHR: + case Const.LSUB: + case Const.LUSHR: + case Const.LXOR: + return Type.LONG; + default: // Never reached + throw new ClassGenException("Unknown type " + opcode); } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java index b20f6ba848b..71374877efe 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java @@ -32,25 +32,33 @@ /** * @since 6.0 */ -public class ArrayElementValueGen extends ElementValueGen -{ +public class ArrayElementValueGen extends ElementValueGen { // J5TODO: Should we make this an array or a list? A list would be easier to // modify ... private final List evalues; - public ArrayElementValueGen(final ConstantPoolGen cp) - { + /** + * @param value + * @param cpool + */ + public ArrayElementValueGen(final ArrayElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) { + super(ARRAY, cpool); + evalues = new ArrayList<>(); + final ElementValue[] in = value.getElementValuesArray(); + for (final ElementValue element : in) { + evalues.add(ElementValueGen.copy(element, cpool, copyPoolEntries)); + } + } + + public ArrayElementValueGen(final ConstantPoolGen cp) { super(ARRAY, cp); evalues = new ArrayList<>(); } - public ArrayElementValueGen(final int type, final ElementValue[] datums, - final ConstantPoolGen cpool) - { + public ArrayElementValueGen(final int type, final ElementValue[] datums, final ConstantPoolGen cpool) { super(type, cpool); if (type != ARRAY) { - throw new IllegalArgumentException( - "Only element values of type array can be built with this ctor - type specified: " + type); + throw new IllegalArgumentException("Only element values of type array can be built with this ctor - type specified: " + type); } this.evalues = new ArrayList<>(); for (final ElementValue datum : datums) { @@ -58,50 +66,42 @@ public ArrayElementValueGen(final int type, final ElementValue[] datums, } } + public void addElement(final ElementValueGen gen) { + evalues.add(gen); + } + + @Override + public void dump(final DataOutputStream dos) throws IOException { + dos.writeByte(super.getElementValueType()); // u1 type of value (ARRAY == '[') + dos.writeShort(evalues.size()); + for (final ElementValueGen element : evalues) { + element.dump(dos); + } + } + /** * Return immutable variant of this ArrayElementValueGen */ @Override - public ElementValue getElementValue() - { + public ElementValue getElementValue() { final ElementValue[] immutableData = new ElementValue[evalues.size()]; int i = 0; for (final ElementValueGen element : evalues) { immutableData[i++] = element.getElementValue(); } - return new ArrayElementValue(super.getElementValueType(), - immutableData, - getConstantPool().getConstantPool()); + return new ArrayElementValue(super.getElementValueType(), immutableData, getConstantPool().getConstantPool()); } - /** - * @param value - * @param cpool - */ - public ArrayElementValueGen(final ArrayElementValue value, final ConstantPoolGen cpool, - final boolean copyPoolEntries) - { - super(ARRAY, cpool); - evalues = new ArrayList<>(); - final ElementValue[] in = value.getElementValuesArray(); - for (final ElementValue element : in) { - evalues.add(ElementValueGen.copy(element, cpool, copyPoolEntries)); - } + public List getElementValues() { + return evalues; } - @Override - public void dump(final DataOutputStream dos) throws IOException - { - dos.writeByte(super.getElementValueType()); // u1 type of value (ARRAY == '[') - dos.writeShort(evalues.size()); - for (final ElementValueGen element : evalues) { - element.dump(dos); - } + public int getElementValuesSize() { + return evalues.size(); } @Override - public String stringifyValue() - { + public String stringifyValue() { final StringBuilder sb = new StringBuilder(); sb.append("["); String comma = ""; @@ -113,19 +113,4 @@ public String stringifyValue() sb.append("]"); return sb.toString(); } - - public List getElementValues() - { - return evalues; - } - - public int getElementValuesSize() - { - return evalues.size(); - } - - public void addElement(final ElementValueGen gen) - { - evalues.add(gen); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayInstruction.java index 50b0dbff7ce..538c180712a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayInstruction.java @@ -25,19 +25,15 @@ /** * Super class for instructions dealing with array access such as IALOAD. - * */ -public abstract class ArrayInstruction extends Instruction implements ExceptionThrower, - TypedInstruction { +public abstract class ArrayInstruction extends Instruction implements ExceptionThrower, TypedInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ ArrayInstruction() { } - /** * @param opcode of instruction */ @@ -45,45 +41,44 @@ protected ArrayInstruction(final short opcode) { super(opcode, (short) 1); } - @Override public Class[] getExceptions() { return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_ARRAY_EXCEPTION); } - - /** @return type associated with the instruction + /** + * @return type associated with the instruction */ @Override - public Type getType( final ConstantPoolGen cp ) { - final short _opcode = super.getOpcode(); - switch (_opcode) { - case com.sun.org.apache.bcel.internal.Const.IALOAD: - case com.sun.org.apache.bcel.internal.Const.IASTORE: - return Type.INT; - case com.sun.org.apache.bcel.internal.Const.CALOAD: - case com.sun.org.apache.bcel.internal.Const.CASTORE: - return Type.CHAR; - case com.sun.org.apache.bcel.internal.Const.BALOAD: - case com.sun.org.apache.bcel.internal.Const.BASTORE: - return Type.BYTE; - case com.sun.org.apache.bcel.internal.Const.SALOAD: - case com.sun.org.apache.bcel.internal.Const.SASTORE: - return Type.SHORT; - case com.sun.org.apache.bcel.internal.Const.LALOAD: - case com.sun.org.apache.bcel.internal.Const.LASTORE: - return Type.LONG; - case com.sun.org.apache.bcel.internal.Const.DALOAD: - case com.sun.org.apache.bcel.internal.Const.DASTORE: - return Type.DOUBLE; - case com.sun.org.apache.bcel.internal.Const.FALOAD: - case com.sun.org.apache.bcel.internal.Const.FASTORE: - return Type.FLOAT; - case com.sun.org.apache.bcel.internal.Const.AALOAD: - case com.sun.org.apache.bcel.internal.Const.AASTORE: - return Type.OBJECT; - default: - throw new ClassGenException("Unknown case in switch" + _opcode); + public Type getType(final ConstantPoolGen cp) { + final short opcode = super.getOpcode(); + switch (opcode) { + case com.sun.org.apache.bcel.internal.Const.IALOAD: + case com.sun.org.apache.bcel.internal.Const.IASTORE: + return Type.INT; + case com.sun.org.apache.bcel.internal.Const.CALOAD: + case com.sun.org.apache.bcel.internal.Const.CASTORE: + return Type.CHAR; + case com.sun.org.apache.bcel.internal.Const.BALOAD: + case com.sun.org.apache.bcel.internal.Const.BASTORE: + return Type.BYTE; + case com.sun.org.apache.bcel.internal.Const.SALOAD: + case com.sun.org.apache.bcel.internal.Const.SASTORE: + return Type.SHORT; + case com.sun.org.apache.bcel.internal.Const.LALOAD: + case com.sun.org.apache.bcel.internal.Const.LASTORE: + return Type.LONG; + case com.sun.org.apache.bcel.internal.Const.DALOAD: + case com.sun.org.apache.bcel.internal.Const.DASTORE: + return Type.DOUBLE; + case com.sun.org.apache.bcel.internal.Const.FALOAD: + case com.sun.org.apache.bcel.internal.Const.FASTORE: + return Type.FLOAT; + case com.sun.org.apache.bcel.internal.Const.AALOAD: + case com.sun.org.apache.bcel.internal.Const.AASTORE: + return Type.OBJECT; + default: + throw new ClassGenException("Unknown case in switch" + opcode); } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java index 3b20c7336e8..138999ebe90 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java @@ -24,56 +24,55 @@ /** * Denotes array type, such as int[][] - * */ public final class ArrayType extends ReferenceType { - private int dimensions; - private Type basicType; - + private final int dimensions; + private final Type basicType; /** * Convenience constructor for array type, e.g. int[] * * @param type array type, e.g. T_INT + * @param dimensions array dimensions */ public ArrayType(final byte type, final int dimensions) { this(BasicType.getType(type), dimensions); } - /** * Convenience constructor for reference array type, e.g. Object[] * - * @param class_name complete name of class (java.lang.String, e.g.) + * @param className complete name of class (java.lang.String, e.g.) + * @param dimensions array dimensions */ - public ArrayType(final String class_name, final int dimensions) { - this(ObjectType.getInstance(class_name), dimensions); + public ArrayType(final String className, final int dimensions) { + this(ObjectType.getInstance(className), dimensions); } - /** * Constructor for array of given type * * @param type type of array (may be an array itself) + * @param dimensions array dimensions */ public ArrayType(final Type type, final int dimensions) { super(Const.T_ARRAY, ""); - if ((dimensions < 1) || (dimensions > Const.MAX_BYTE)) { + if (dimensions < 1 || dimensions > Const.MAX_BYTE) { throw new ClassGenException("Invalid number of dimensions: " + dimensions); } switch (type.getType()) { - case Const.T_ARRAY: - final ArrayType array = (ArrayType) type; - this.dimensions = dimensions + array.dimensions; - basicType = array.basicType; - break; - case Const.T_VOID: - throw new ClassGenException("Invalid type: void[]"); - default: // Basic type or reference - this.dimensions = dimensions; - basicType = type; - break; + case Const.T_ARRAY: + final ArrayType array = (ArrayType) type; + this.dimensions = dimensions + array.dimensions; + basicType = array.basicType; + break; + case Const.T_VOID: + throw new ClassGenException("Invalid type: void[]"); + default: // Basic type or reference + this.dimensions = dimensions; + basicType = type; + break; } final StringBuilder buf = new StringBuilder(); for (int i = 0; i < this.dimensions; i++) { @@ -83,6 +82,17 @@ public ArrayType(final Type type, final int dimensions) { super.setSignature(buf.toString()); } + /** + * @return true if both type objects refer to the same array type. + */ + @Override + public boolean equals(final Object type) { + if (type instanceof ArrayType) { + final ArrayType array = (ArrayType) type; + return array.dimensions == dimensions && array.basicType.equals(basicType); + } + return false; + } /** * @return basic type of array, i.e., for int[][][] the basic type is int @@ -91,6 +101,24 @@ public Type getBasicType() { return basicType; } + /** + * Gets the name of referenced class. + * + * @return name of referenced class. + * @since 6.7.0 + */ + @Override + @Deprecated + public String getClassName() { + return signature; + } + + /** + * @return number of dimensions of array + */ + public int getDimensions() { + return dimensions; + } /** * @return element type of array, i.e., for int[][][] the element type is int[][] @@ -102,30 +130,11 @@ public Type getElementType() { return new ArrayType(basicType, dimensions - 1); } - - /** @return number of dimensions of array - */ - public int getDimensions() { - return dimensions; - } - - - /** @return a hash code value for the object. + /** + * @return a hash code value for the object. */ @Override public int hashCode() { return basicType.hashCode() ^ dimensions; } - - - /** @return true if both type objects refer to the same array type. - */ - @Override - public boolean equals( final Object _type ) { - if (_type instanceof ArrayType) { - final ArrayType array = (ArrayType) _type; - return (array.dimensions == dimensions) && array.basicType.equals(basicType); - } - return false; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BALOAD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BALOAD.java index 27f11125889..dc14c3fcdb1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BALOAD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BALOAD.java @@ -22,28 +22,28 @@ /** * BALOAD - Load byte or boolean from array - *
    Stack: ..., arrayref, index -> ..., value
    * + *
    + * Stack: ..., arrayref, index -> ..., value
    + * 
    */ public class BALOAD extends ArrayInstruction implements StackProducer { - /** Load byte or boolean from array + /** + * Load byte or boolean from array */ public BALOAD() { super(com.sun.org.apache.bcel.internal.Const.BALOAD); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BASTORE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BASTORE.java index 9a71e9f6e1b..da73a504beb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BASTORE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BASTORE.java @@ -21,29 +21,29 @@ package com.sun.org.apache.bcel.internal.generic; /** - * BASTORE - Store into byte or boolean array - *
    Stack: ..., arrayref, index, value -> ...
    + * BASTORE - Store into byte or boolean array * + *
    + * Stack: ..., arrayref, index, value -> ...
    + * 
    */ public class BASTORE extends ArrayInstruction implements StackConsumer { - /** Store byte or boolean into array + /** + * Store byte or boolean into array */ public BASTORE() { super(com.sun.org.apache.bcel.internal.Const.BASTORE); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BIPUSH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BIPUSH.java index d5cd303508e..264fe1cb54d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BIPUSH.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BIPUSH.java @@ -27,87 +27,79 @@ /** * BIPUSH - Push byte on stack * - *
    Stack: ... -> ..., value
    - * + *
    + * Stack: ... -> ..., value
    + * 
    */ public class BIPUSH extends Instruction implements ConstantPushInstruction { private byte b; - /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ BIPUSH() { } - - /** Push byte on stack + /** + * Push byte on stack */ public BIPUSH(final byte b) { super(com.sun.org.apache.bcel.internal.Const.BIPUSH, (short) 2); this.b = b; } - /** - * Dump instruction as byte code to stream out. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object */ @Override - public void dump( final DataOutputStream out ) throws IOException { - super.dump(out); - out.writeByte(b); + public void accept(final Visitor v) { + v.visitPushInstruction(this); + v.visitStackProducer(this); + v.visitTypedInstruction(this); + v.visitConstantPushInstruction(this); + v.visitBIPUSH(this); } - /** - * @return mnemonic for instruction + * Dump instruction as byte code to stream out. */ @Override - public String toString( final boolean verbose ) { - return super.toString(verbose) + " " + b; + public void dump(final DataOutputStream out) throws IOException { + super.dump(out); + out.writeByte(b); } - /** - * Read needed data (e.g. index) from file. + * @return Type.BYTE */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { - super.setLength(2); - b = bytes.readByte(); + public Type getType(final ConstantPoolGen cp) { + return Type.BYTE; } - @Override public Number getValue() { return Integer.valueOf(b); } - - /** @return Type.BYTE + /** + * Read needed data (e.g. index) from file. */ @Override - public Type getType( final ConstantPoolGen cp ) { - return Type.BYTE; + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { + super.setLength(2); + b = bytes.readByte(); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. - * - * @param v Visitor object + * @return mnemonic for instruction */ @Override - public void accept( final Visitor v ) { - v.visitPushInstruction(this); - v.visitStackProducer(this); - v.visitTypedInstruction(this); - v.visitConstantPushInstruction(this); - v.visitBIPUSH(this); + public String toString(final boolean verbose) { + return super.toString(verbose) + " " + b; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BREAKPOINT.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BREAKPOINT.java index 857f628df51..a4fc7be058f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BREAKPOINT.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BREAKPOINT.java @@ -22,7 +22,6 @@ /** * BREAKPOINT, JVM dependent, ignored by default - * */ public class BREAKPOINT extends Instruction { @@ -30,17 +29,14 @@ public BREAKPOINT() { super(com.sun.org.apache.bcel.internal.Const.BREAKPOINT, (short) 1); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitBREAKPOINT(this); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BasicType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BasicType.java index 8d201b861a3..71bc5491186 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BasicType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BasicType.java @@ -24,63 +24,61 @@ /** * Denotes basic type such as int. - * */ public final class BasicType extends Type { + // @since 6.0 no longer final + public static BasicType getType(final byte type) { + switch (type) { + case Const.T_VOID: + return VOID; + case Const.T_BOOLEAN: + return BOOLEAN; + case Const.T_BYTE: + return BYTE; + case Const.T_SHORT: + return SHORT; + case Const.T_CHAR: + return CHAR; + case Const.T_INT: + return INT; + case Const.T_LONG: + return LONG; + case Const.T_DOUBLE: + return DOUBLE; + case Const.T_FLOAT: + return FLOAT; + default: + throw new ClassGenException("Invalid type: " + type); + } + } + /** - * Constructor for basic types such as int, long, `void' + * Constructor for basic types such as int, long, 'void' * * @param type one of T_INT, T_BOOLEAN, ..., T_VOID * @see Const */ BasicType(final byte type) { super(type, Const.getShortTypeName(type)); - if ((type < Const.T_BOOLEAN) || (type > Const.T_VOID)) { + if (type < Const.T_BOOLEAN || type > Const.T_VOID) { throw new ClassGenException("Invalid type: " + type); } } - - // @since 6.0 no longer final - public static BasicType getType( final byte type ) { - switch (type) { - case Const.T_VOID: - return VOID; - case Const.T_BOOLEAN: - return BOOLEAN; - case Const.T_BYTE: - return BYTE; - case Const.T_SHORT: - return SHORT; - case Const.T_CHAR: - return CHAR; - case Const.T_INT: - return INT; - case Const.T_LONG: - return LONG; - case Const.T_DOUBLE: - return DOUBLE; - case Const.T_FLOAT: - return FLOAT; - default: - throw new ClassGenException("Invalid type: " + type); - } - } - - - /** @return a hash code value for the object. + /** + * @return true if both type objects refer to the same type */ @Override - public int hashCode() { - return super.getType(); + public boolean equals(final Object type) { + return type instanceof BasicType && ((BasicType) type).getType() == this.getType(); } - - /** @return true if both type objects refer to the same type + /** + * @return a hash code value for the object. */ @Override - public boolean equals( final Object _type ) { - return (_type instanceof BasicType) ? ((BasicType) _type).getType() == this.getType() : false; + public int hashCode() { + return super.getType(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java index d35800d4d96..91ab9ac5463 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java @@ -21,10 +21,8 @@ package com.sun.org.apache.bcel.internal.generic; /** - * BranchHandle is returned by specialized InstructionList.append() whenever a - * BranchInstruction is appended. This is useful when the target of this - * instruction is not known at time of creation and must be set later - * via setTarget(). + * BranchHandle is returned by specialized InstructionList.append() whenever a BranchInstruction is appended. This is + * useful when the target of this instruction is not known at time of creation and must be set later via setTarget(). * * @see InstructionHandle * @see Instruction @@ -32,83 +30,75 @@ */ public final class BranchHandle extends InstructionHandle { + /** + * Factory method. + */ + static BranchHandle getBranchHandle(final BranchInstruction i) { + return new BranchHandle(i); + } + // This is also a cache in case the InstructionHandle#swapInstruction() method is used // See BCEL-273 private BranchInstruction bi; // An alias in fact, but saves lots of casts - private BranchHandle(final BranchInstruction i) { super(i); bi = i; } - /** Factory method. - */ - static BranchHandle getBranchHandle( final BranchInstruction i ) { - return new BranchHandle(i); - } - - - /* Override InstructionHandle methods: delegate to branch instruction. - * Through this overriding all access to the private i_position field should - * be prevented. + /* + * Override InstructionHandle methods: delegate to branch instruction. Through this overriding all access to the private + * i_position field should be prevented. */ @Override public int getPosition() { return bi.getPosition(); } + /** + * @return target of instruction. + */ + public InstructionHandle getTarget() { + return bi.getTarget(); + } + + /** + * Set new contents. Old instruction is disposed and may not be used anymore. + */ + @Override // This is only done in order to apply the additional type check; could be merged with super impl. + public void setInstruction(final Instruction i) { // TODO could be package-protected? + super.setInstruction(i); + if (!(i instanceof BranchInstruction)) { + throw new ClassGenException("Assigning " + i + " to branch handle which is not a branch instruction"); + } + bi = (BranchInstruction) i; + } @Override - void setPosition( final int pos ) { + void setPosition(final int pos) { // Original code: i_position = bi.position = pos; bi.setPosition(pos); super.setPosition(pos); } - - @Override - protected int updatePosition( final int offset, final int max_offset ) { - final int x = bi.updatePosition(offset, max_offset); - super.setPosition(bi.getPosition()); - return x; - } - - /** * Pass new target to instruction. */ - public void setTarget( final InstructionHandle ih ) { + public void setTarget(final InstructionHandle ih) { bi.setTarget(ih); } - - /** - * Update target of instruction. - */ - public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) { - bi.updateTarget(old_ih, new_ih); - } - - - /** - * @return target of instruction. - */ - public InstructionHandle getTarget() { - return bi.getTarget(); + @Override + protected int updatePosition(final int offset, final int maxOffset) { + final int x = bi.updatePosition(offset, maxOffset); + super.setPosition(bi.getPosition()); + return x; } - /** - * Set new contents. Old instruction is disposed and may not be used anymore. + * Update target of instruction. */ - @Override // This is only done in order to apply the additional type check; could be merged with super impl. - public void setInstruction( final Instruction i ) { // TODO could be package-protected? - super.setInstruction(i); - if (!(i instanceof BranchInstruction)) { - throw new ClassGenException("Assigning " + i - + " to branch handle which is not a branch instruction"); - } - bi = (BranchInstruction) i; + public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) { + bi.updateTarget(oldIh, newIh); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java index e650bea8ec5..4aba9a97027 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -25,149 +25,94 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence; /** - * Abstract super class for branching instructions like GOTO, IFEQ, etc.. - * Branch instructions may have a variable length, namely GOTO, JSR, - * LOOKUPSWITCH and TABLESWITCH. + * Abstract super class for branching instructions like GOTO, IFEQ, etc.. Branch instructions may have a variable + * length, namely GOTO, JSR, LOOKUPSWITCH and TABLESWITCH. * * @see InstructionList - * @LastModified: July 2020 + * @LastModified: Feb 2023 */ public abstract class BranchInstruction extends Instruction implements InstructionTargeter { - private int index; // Branch target relative to this instruction - private InstructionHandle target; // Target object in instruction list - private int position; // Byte code offset - /** - * Empty constructor needed for the Class.newInstance() statement in - * Instruction.readInstruction(). Not to be used otherwise. + * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen, LineNumberGen */ - BranchInstruction() { + static void notifyTarget(final InstructionHandle oldIh, final InstructionHandle newIh, final InstructionTargeter t) { + if (oldIh != null) { + oldIh.removeTargeter(t); + } + if (newIh != null) { + newIh.addTargeter(t); + } } - - /** Common super constructor - * @param opcode Instruction opcode - * @param target instruction to branch to + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter */ - protected BranchInstruction(final short opcode, final InstructionHandle target) { - super(opcode, (short) 3); - setTarget(target); - } - + @Deprecated + protected int index; // Branch target relative to this instruction /** - * Dump instruction as byte code to stream out. - * @param out Output stream + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter */ - @Override - public void dump( final DataOutputStream out ) throws IOException { - out.writeByte(super.getOpcode()); - index = getTargetOffset(); - if (!isValidShort(index)) { - throw new ClassGenException("Branch target offset too large for short: " + index); - } - out.writeShort(index); // May be negative, i.e., point backwards - } - + @Deprecated + protected InstructionHandle target; // Target object in instruction list /** - * @param _target branch target - * @return the offset to `target' relative to this instruction + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter */ - protected int getTargetOffset( final InstructionHandle _target ) { - if (_target == null) { - throw new ClassGenException("Target of " + super.toString(true) - + " is invalid null handle"); - } - final int t = _target.getPosition(); - if (t < 0) { - throw new ClassGenException("Invalid branch target position offset for " - + super.toString(true) + ":" + t + ":" + _target); - } - return t - position; - } - + @Deprecated + protected int position; // Byte code offset /** - * @return the offset to this instruction's target + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ - protected int getTargetOffset() { - return getTargetOffset(target); + BranchInstruction() { } - /** - * Called by InstructionList.setPositions when setting the position for every - * instruction. In the presence of variable length instructions `setPositions' - * performs multiple passes over the instruction list to calculate the - * correct (byte) positions and offsets by calling this function. + * Common super constructor * - * @param offset additional offset caused by preceding (variable length) instructions - * @param max_offset the maximum offset that may be caused by these instructions - * @return additional offset caused by possible change of this instruction's length + * @param opcode Instruction opcode + * @param target instruction to branch to */ - protected int updatePosition( final int offset, final int max_offset ) { - position += offset; - return 0; + protected BranchInstruction(final short opcode, final InstructionHandle target) { + super(opcode, (short) 3); + setTarget(target); } - /** - * Long output format: - * - * <position in byte code> - * <name of opcode> "["<opcode number>"]" - * "("<length of instruction>")" - * "<"<target instruction>">" "@"<branch target offset> - * - * @param verbose long/short format switch - * @return mnemonic for instruction + * @return true, if ih is target of this instruction */ @Override - public String toString( final boolean verbose ) { - final String s = super.toString(verbose); - String t = "null"; - if (verbose) { - if (target != null) { - if (target.getInstruction() == this) { - t = ""; - } else if (target.getInstruction() == null) { - t = ""; - } else { - // I'm more interested in the address of the target then - // the instruction located there. - //t = target.getInstruction().toString(false); // Avoid circles - t = "" + target.getPosition(); - } - } - } else { - if (target != null) { - index = target.getPosition(); - // index = getTargetOffset(); crashes if positions haven't been set - // t = "" + (index + position); - t = "" + index; - } - } - return s + " -> " + t; + public boolean containsTarget(final InstructionHandle ih) { + return target == ih; } + /** + * Inform target that it's not targeted anymore. + */ + @Override + void dispose() { + setTarget(null); + index = -1; + position = -1; + } /** - * Read needed data (e.g. index) from file. Conversion to a InstructionHandle - * is done in InstructionList(byte[]). + * Dump instruction as byte code to stream out. * - * @param bytes input stream - * @param wide wide prefix? - * @see InstructionList + * @param out Output stream */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { - super.setLength(3); - index = bytes.readShort(); + public void dump(final DataOutputStream out) throws IOException { + out.writeByte(super.getOpcode()); + index = getTargetOffset(); + if (!isValidShort(index)) { + throw new ClassGenException("Branch target offset too large for short: " + index); + } + out.writeShort(index); // May be negative, i.e., point backwards } - /** * @return target offset in byte code */ @@ -175,6 +120,13 @@ public final int getIndex() { return index; } + /** + * @return the position + * @since 6.0 + */ + protected int getPosition() { + return position; + } /** * @return target of branch instruction @@ -183,51 +135,55 @@ public InstructionHandle getTarget() { return target; } - /** - * Set branch target - * @param target branch target + * @return the offset to this instruction's target */ - public void setTarget( final InstructionHandle target ) { - notifyTarget(this.target, target, this); - this.target = target; + protected int getTargetOffset() { + return getTargetOffset(target); } - /** - * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen, LineNumberGen + * @param target branch target + * @return the offset to 'target' relative to this instruction */ - static void notifyTarget( final InstructionHandle old_ih, final InstructionHandle new_ih, - final InstructionTargeter t ) { - if (old_ih != null) { - old_ih.removeTargeter(t); + protected int getTargetOffset(final InstructionHandle target) { + if (target == null) { + throw new ClassGenException("Target of " + super.toString(true) + " is invalid null handle"); } - if (new_ih != null) { - new_ih.addTargeter(t); + final int t = target.getPosition(); + if (t < 0) { + throw new ClassGenException("Invalid branch target position offset for " + super.toString(true) + ":" + t + ":" + target); } + return t - position; } - /** - * @param old_ih old target - * @param new_ih new target + * Read needed data (e.g. index) from file. Conversion to a InstructionHandle is done in InstructionList(byte[]). + * + * @param bytes input stream + * @param wide wide prefix? + * @see InstructionList */ @Override - public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) { - if (target == old_ih) { - setTarget(new_ih); - } else { - throw new ClassGenException("Not targeting " + old_ih + ", but " + target); - } + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { + super.setLength(3); + index = bytes.readShort(); } + /** + * @param index the index to set + * @since 6.0 + */ + protected void setIndex(final int index) { + this.index = index; + } /** - * @return true, if ih is target of this instruction + * @param position the position to set + * @since 6.0 */ - @Override - public boolean containsTarget( final InstructionHandle ih ) { - return target == ih; + protected void setPosition(final int position) { + this.position = position; } /** @@ -249,40 +205,74 @@ void setOpcode( final short opcode ) { } /** - * Inform target that it's not targeted anymore. + * Set branch target + * + * @param target branch target */ - @Override - void dispose() { - setTarget(null); - index = -1; - position = -1; + public void setTarget(final InstructionHandle target) { + notifyTarget(this.target, target, this); + this.target = target; } - /** - * @return the position - * @since 6.0 + * Long output format: + * + * <position in byte code> <name of opcode> "["<opcode number>"]" "("<length of instruction>")" + * "<"<target instruction>">" "@"<branch target offset> + * + * @param verbose long/short format switch + * @return mnemonic for instruction */ - protected int getPosition() { - return position; + @Override + public String toString(final boolean verbose) { + final String s = super.toString(verbose); + String t = "null"; + if (target != null) { + if (verbose) { + if (target.getInstruction() == this) { + t = ""; + } else if (target.getInstruction() == null) { + t = ""; + } else { + // I'm more interested in the address of the target then + // the instruction located there. + // t = target.getInstruction().toString(false); // Avoid circles + t = "" + target.getPosition(); + } + } else { + index = target.getPosition(); + // index = getTargetOffset(); crashes if positions haven't been set + // t = "" + (index + position); + t = "" + index; + } + } + return s + " -> " + t; } - /** - * @param position the position to set - * @since 6.0 + * Called by InstructionList.setPositions when setting the position for every instruction. In the presence of variable + * length instructions 'setPositions' performs multiple passes over the instruction list to calculate the correct (byte) + * positions and offsets by calling this function. + * + * @param offset additional offset caused by preceding (variable length) instructions + * @param maxOffset the maximum offset that may be caused by these instructions + * @return additional offset caused by possible change of this instruction's length */ - protected void setPosition(final int position) { - this.position = position; + protected int updatePosition(final int offset, final int maxOffset) { + position += offset; + return 0; } - /** - * @param index the index to set - * @since 6.0 + * @param oldIh old target + * @param newIh new target */ - protected void setIndex(final int index) { - this.index = index; + @Override + public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) { + if (target != oldIh) { + throw new ClassGenException("Not targeting " + oldIh + ", but " + target); + } + setTarget(newIh); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CALOAD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CALOAD.java index 750a6948bbc..02cc46df660 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CALOAD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CALOAD.java @@ -23,28 +23,28 @@ /** * CALOAD - Load char from array - *
    Stack: ..., arrayref, index -> ..., value
    * + *
    + * Stack: ..., arrayref, index -> ..., value
    + * 
    */ public class CALOAD extends ArrayInstruction implements StackProducer { - /** Load char from array + /** + * Load char from array */ public CALOAD() { super(com.sun.org.apache.bcel.internal.Const.CALOAD); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CASTORE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CASTORE.java index 499de83b9dd..ca4a4e1fe41 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CASTORE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CASTORE.java @@ -22,29 +22,29 @@ package com.sun.org.apache.bcel.internal.generic; /** - * CASTORE - Store into char array - *
    Stack: ..., arrayref, index, value -> ...
    + * CASTORE - Store into char array * + *
    + * Stack: ..., arrayref, index, value -> ...
    + * 
    */ public class CASTORE extends ArrayInstruction implements StackConsumer { - /** Store char into array + /** + * Store char into array */ public CASTORE() { super(com.sun.org.apache.bcel.internal.Const.CASTORE); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CHECKCAST.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CHECKCAST.java index a329f359f5f..6983350f646 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CHECKCAST.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CHECKCAST.java @@ -25,57 +25,36 @@ /** * CHECKCAST - Check whether object is of given type - *
    Stack: ..., objectref -> ..., objectref
    * + *
    + * Stack: ..., objectref -> ..., objectref
    + * 
    */ -public class CHECKCAST extends CPInstruction implements LoadClass, ExceptionThrower, StackProducer, - StackConsumer { +public class CHECKCAST extends CPInstruction implements LoadClass, ExceptionThrower, StackProducer, StackConsumer { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ CHECKCAST() { } - - /** Check whether object is of given type + /** + * Check whether object is of given type + * * @param index index to class in constant pool */ public CHECKCAST(final int index) { super(com.sun.org.apache.bcel.internal.Const.CHECKCAST, index); } - - /** @return exceptions this instruction may cause - */ - @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_CLASS_AND_INTERFACE_RESOLUTION, - ExceptionConst.CLASS_CAST_EXCEPTION); - } - - - @Override - public ObjectType getLoadClassType( final ConstantPoolGen cpg ) { - Type t = getType(cpg); - if (t instanceof ArrayType) { - t = ((ArrayType) t).getBasicType(); - } - return (t instanceof ObjectType) ? (ObjectType) t : null; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitLoadClass(this); v.visitExceptionThrower(this); v.visitStackProducer(this); @@ -84,4 +63,21 @@ public void accept( final Visitor v ) { v.visitCPInstruction(this); v.visitCHECKCAST(this); } + + /** + * @return exceptions this instruction may cause + */ + @Override + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_CLASS_AND_INTERFACE_RESOLUTION, ExceptionConst.CLASS_CAST_EXCEPTION); + } + + @Override + public ObjectType getLoadClassType(final ConstantPoolGen cpg) { + Type t = getType(cpg); + if (t instanceof ArrayType) { + t = ((ArrayType) t).getBasicType(); + } + return t instanceof ObjectType ? (ObjectType) t : null; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java index 5f904459751..1dfd244141a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java @@ -25,11 +25,11 @@ import com.sun.org.apache.bcel.internal.classfile.Constant; import com.sun.org.apache.bcel.internal.classfile.ConstantClass; import com.sun.org.apache.bcel.internal.classfile.ConstantPool; +import com.sun.org.apache.bcel.internal.classfile.Utility; import com.sun.org.apache.bcel.internal.util.ByteSequence; /** - * Abstract super class for instructions that use an index into the - * constant pool such as LDC, INVOKEVIRTUAL, etc. + * Abstract super class for instructions that use an index into the constant pool such as LDC, INVOKEVIRTUAL, etc. * * @see ConstantPoolGen * @see LDC @@ -37,20 +37,20 @@ * * @LastModified: Jan 2020 */ -public abstract class CPInstruction extends Instruction implements TypedInstruction, - IndexedInstruction { - - private int index; // index to constant pool +public abstract class CPInstruction extends Instruction implements TypedInstruction, IndexedInstruction { + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected int index; // index to constant pool /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ CPInstruction() { } - /** * @param index to constant pool */ @@ -59,90 +59,87 @@ protected CPInstruction(final short opcode, final int index) { setIndex(index); } - /** * Dump instruction as byte code to stream out. + * * @param out Output stream */ @Override - public void dump( final DataOutputStream out ) throws IOException { + public void dump(final DataOutputStream out) throws IOException { out.writeByte(super.getOpcode()); out.writeShort(index); } - /** - * Long output format: - * - * <name of opcode> "["<opcode number>"]" - * "("<length of instruction>")" "<"< constant pool index>">" - * - * @param verbose long/short format switch - * @return mnemonic for instruction + * @return index in constant pool referred by this instruction. */ @Override - public String toString( final boolean verbose ) { - return super.toString(verbose) + " " + index; + public final int getIndex() { + return index; } - /** - * @return mnemonic for instruction with symbolic references resolved + * @return type related with this instruction. */ @Override - public String toString( final ConstantPool cp ) { - final Constant c = cp.getConstant(index); - String str = cp.constantToString(c); - if (c instanceof ConstantClass) { - str = str.replace('.', '/'); + public Type getType(final ConstantPoolGen cpg) { + final ConstantPool cp = cpg.getConstantPool(); + String name = cp.getConstantString(index, com.sun.org.apache.bcel.internal.Const.CONSTANT_Class); + if (!name.startsWith("[")) { + name = "L" + name + ";"; } - return com.sun.org.apache.bcel.internal.Const.getOpcodeName(super.getOpcode()) + " " + str; + return Type.getType(name); } - /** * Read needed data (i.e., index) from file. + * * @param bytes input stream * @param wide wide prefix? */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { setIndex(bytes.readUnsignedShort()); super.setLength(3); } - - /** - * @return index in constant pool referred by this instruction. - */ - @Override - public final int getIndex() { - return index; - } - - /** * Set the index to constant pool. - * @param index in constant pool. + * + * @param index in constant pool. */ @Override - public void setIndex( final int index ) { // TODO could be package-protected? + public void setIndex(final int index) { // TODO could be package-protected? if (index < 0) { throw new ClassGenException("Negative index value: " + index); } this.index = index; } + /** + * Long output format: + * + * <name of opcode> "["<opcode number>"]" "("<length of instruction>")" "<"< constant pool + * index>">" + * + * @param verbose long/short format switch + * @return mnemonic for instruction + */ + @Override + public String toString(final boolean verbose) { + return super.toString(verbose) + " " + index; + } - /** @return type related with this instruction. + /** + * @return mnemonic for instruction with symbolic references resolved */ @Override - public Type getType( final ConstantPoolGen cpg ) { - final ConstantPool cp = cpg.getConstantPool(); - String name = cp.getConstantString(index, com.sun.org.apache.bcel.internal.Const.CONSTANT_Class); - if (!name.startsWith("[")) { - name = "L" + name + ";"; + public String toString(final ConstantPool cp) { + final Constant c = cp.getConstant(index); + String str = cp.constantToString(c); + if (c instanceof ConstantClass) { + str = Utility.packageToPath(str); } - return Type.getType(name); + return com.sun.org.apache.bcel.internal.Const.getOpcodeName(super.getOpcode()) + " " + str; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java index 249618f6122..1c1c032dbd5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java @@ -31,59 +31,40 @@ /** * @since 6.0 */ -public class ClassElementValueGen extends ElementValueGen -{ +public class ClassElementValueGen extends ElementValueGen { // For primitive types and string type, this points to the value entry in // the cpool // For 'class' this points to the class entry in the cpool - private int idx; + private final int idx; - protected ClassElementValueGen(final int typeIdx, final ConstantPoolGen cpool) - { + public ClassElementValueGen(final ClassElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) { + super(CLASS, cpool); + if (copyPoolEntries) { + // idx = cpool.addClass(value.getClassString()); + idx = cpool.addUtf8(value.getClassString()); + } else { + idx = value.getIndex(); + } + } + + protected ClassElementValueGen(final int typeIdx, final ConstantPoolGen cpool) { super(ElementValueGen.CLASS, cpool); this.idx = typeIdx; } - public ClassElementValueGen(final ObjectType t, final ConstantPoolGen cpool) - { + public ClassElementValueGen(final ObjectType t, final ConstantPoolGen cpool) { super(ElementValueGen.CLASS, cpool); // this.idx = cpool.addClass(t); idx = cpool.addUtf8(t.getSignature()); } - /** - * Return immutable variant of this ClassElementValueGen - */ @Override - public ElementValue getElementValue() - { - return new ClassElementValue(super.getElementValueType(), - idx, - getConstantPool().getConstantPool()); - } - - public ClassElementValueGen(final ClassElementValue value, final ConstantPoolGen cpool, - final boolean copyPoolEntries) - { - super(CLASS, cpool); - if (copyPoolEntries) - { - // idx = cpool.addClass(value.getClassString()); - idx = cpool.addUtf8(value.getClassString()); - } - else - { - idx = value.getIndex(); - } - } - - public int getIndex() - { - return idx; + public void dump(final DataOutputStream dos) throws IOException { + dos.writeByte(super.getElementValueType()); // u1 kind of value + dos.writeShort(idx); } - public String getClassString() - { + public String getClassString() { final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(idx); return cu8.getBytes(); // ConstantClass c = (ConstantClass)getConstantPool().getConstant(idx); @@ -92,16 +73,20 @@ public String getClassString() // return utf8.getBytes(); } + /** + * Return immutable variant of this ClassElementValueGen + */ @Override - public String stringifyValue() - { - return getClassString(); + public ElementValue getElementValue() { + return new ClassElementValue(super.getElementValueType(), idx, getConstantPool().getConstantPool()); + } + + public int getIndex() { + return idx; } @Override - public void dump(final DataOutputStream dos) throws IOException - { - dos.writeByte(super.getElementValueType()); // u1 kind of value - dos.writeShort(idx); + public String stringifyValue() { + return getClassString(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java index 04be4be622a..acaf4519567 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,12 +20,13 @@ package com.sun.org.apache.bcel.internal.generic; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Objects; import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.classfile.AccessFlags; -import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry; import com.sun.org.apache.bcel.internal.classfile.Annotations; import com.sun.org.apache.bcel.internal.classfile.Attribute; import com.sun.org.apache.bcel.internal.classfile.ConstantPool; @@ -35,106 +36,79 @@ import com.sun.org.apache.bcel.internal.classfile.RuntimeInvisibleAnnotations; import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleAnnotations; import com.sun.org.apache.bcel.internal.classfile.SourceFile; +import com.sun.org.apache.bcel.internal.classfile.Utility; import com.sun.org.apache.bcel.internal.util.BCELComparator; /** - * Template class for building up a java class. May be initialized with an - * existing java class (file). + * Template class for building up a java class. May be initialized with an existing java class (file). * * @see JavaClass - * @LastModified: May 2021 + * @LastModified: Feb 2023 */ public class ClassGen extends AccessFlags implements Cloneable { - /* Corresponds to the fields found in a JavaClass object. - */ - private String className; - private String superClassName; - private final String fileName; - private int classNameIndex = -1; - private int superclass_name_index = -1; - private int major = Const.MAJOR_1_1; - private int minor = Const.MINOR_1_1; - private ConstantPoolGen cp; // Template for building up constant pool - // ArrayLists instead of arrays to gather fields, methods, etc. - private final List fieldList = new ArrayList<>(); - private final List methodList = new ArrayList<>(); - private final List attributeList = new ArrayList<>(); - private final List interfaceList = new ArrayList<>(); - private final List annotationList = new ArrayList<>(); - private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals( final Object o1, final Object o2 ) { + public boolean equals(final Object o1, final Object o2) { final ClassGen THIS = (ClassGen) o1; final ClassGen THAT = (ClassGen) o2; return Objects.equals(THIS.getClassName(), THAT.getClassName()); } - @Override - public int hashCode( final Object o ) { + public int hashCode(final Object o) { final ClassGen THIS = (ClassGen) o; return THIS.getClassName().hashCode(); } }; - - /** Convenience constructor to set up some important values initially. - * - * @param className fully qualified class name - * @param superClassName fully qualified superclass name - * @param fileName source file name - * @param accessFlags access qualifiers - * @param interfaces implemented interfaces - * @param cp constant pool to use + /** + * @return Comparison strategy object */ - public ClassGen(final String className, final String superClassName, final String fileName, final int accessFlags, - final String[] interfaces, final ConstantPoolGen cp) { - super(accessFlags); - this.className = className; - this.superClassName = superClassName; - this.fileName = fileName; - this.cp = cp; - // Put everything needed by default into the constant pool and the vectors - if (fileName != null) { - addAttribute(new SourceFile(cp.addUtf8("SourceFile"), 2, cp.addUtf8(fileName), cp - .getConstantPool())); - } - classNameIndex = cp.addClass(className); - superclass_name_index = cp.addClass(superClassName); - if (interfaces != null) { - for (final String interface1 : interfaces) { - addInterface(interface1); - } - } + public static BCELComparator getComparator() { + return bcelComparator; } - - /** Convenience constructor to set up some important values initially. - * - * @param className fully qualified class name - * @param superClassName fully qualified superclass name - * @param fileName source file name - * @param accessFlags access qualifiers - * @param interfaces implemented interfaces + /** + * @param comparator Comparison strategy object */ - public ClassGen(final String className, final String superClassName, final String fileName, final int accessFlags, - final String[] interfaces) { - this(className, superClassName, fileName, accessFlags, interfaces, - new ConstantPoolGen()); + public static void setComparator(final BCELComparator comparator) { + bcelComparator = comparator; } + /* + * Corresponds to the fields found in a JavaClass object. + */ + private String className; + private String superClassName; + private final String fileName; + private int classNameIndex = -1; + private int superclassNameIndex = -1; + private int major = Const.MAJOR_1_1; + private int minor = Const.MINOR_1_1; + private ConstantPoolGen cp; // Template for building up constant pool + // ArrayLists instead of arrays to gather fields, methods, etc. + private final List fieldList = new ArrayList<>(); + private final List methodList = new ArrayList<>(); + + private final List attributeList = new ArrayList<>(); + + private final List interfaceList = new ArrayList<>(); + + private final List annotationList = new ArrayList<>(); + + private List observers; /** * Initialize with existing class. + * * @param clazz JavaClass object (e.g. read from file) */ public ClassGen(final JavaClass clazz) { super(clazz.getAccessFlags()); classNameIndex = clazz.getClassNameIndex(); - superclass_name_index = clazz.getSuperclassNameIndex(); + superclassNameIndex = clazz.getSuperclassNameIndex(); className = clazz.getClassName(); superClassName = clazz.getSuperclassName(); fileName = clazz.getSourceFileName(); @@ -144,189 +118,142 @@ public ClassGen(final JavaClass clazz) { final Attribute[] attributes = clazz.getAttributes(); // J5TODO: Could make unpacking lazy, done on first reference final AnnotationEntryGen[] annotations = unpackAnnotations(attributes); - final Method[] methods = clazz.getMethods(); - final Field[] fields = clazz.getFields(); - final String[] interfaces = clazz.getInterfaceNames(); - for (final String interface1 : interfaces) { - addInterface(interface1); - } + Collections.addAll(interfaceList, clazz.getInterfaceNames()); for (final Attribute attribute : attributes) { if (!(attribute instanceof Annotations)) { addAttribute(attribute); } } - for (final AnnotationEntryGen annotation : annotations) { - addAnnotationEntry(annotation); - } - for (final Method method : methods) { - addMethod(method); - } - for (final Field field : fields) { - addField(field); - } + Collections.addAll(annotationList, annotations); + Collections.addAll(methodList, clazz.getMethods()); + Collections.addAll(fieldList, clazz.getFields()); } /** - * Look for attributes representing annotations and unpack them. + * Convenience constructor to set up some important values initially. + * + * @param className fully qualified class name + * @param superClassName fully qualified superclass name + * @param fileName source file name + * @param accessFlags access qualifiers + * @param interfaces implemented interfaces */ - private AnnotationEntryGen[] unpackAnnotations(final Attribute[] attrs) - { - final List annotationGenObjs = new ArrayList<>(); - for (final Attribute attr : attrs) { - if (attr instanceof RuntimeVisibleAnnotations) - { - final RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr; - final AnnotationEntry[] annos = rva.getAnnotationEntries(); - for (final AnnotationEntry a : annos) { - annotationGenObjs.add(new AnnotationEntryGen(a, - getConstantPool(), false)); - } - } - else - if (attr instanceof RuntimeInvisibleAnnotations) - { - final RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr; - final AnnotationEntry[] annos = ria.getAnnotationEntries(); - for (final AnnotationEntry a : annos) { - annotationGenObjs.add(new AnnotationEntryGen(a, - getConstantPool(), false)); - } - } - } - return annotationGenObjs.toArray(new AnnotationEntryGen[annotationGenObjs.size()]); + public ClassGen(final String className, final String superClassName, final String fileName, final int accessFlags, final String[] interfaces) { + this(className, superClassName, fileName, accessFlags, interfaces, new ConstantPoolGen()); } - /** - * @return the (finally) built up Java class object. + * Convenience constructor to set up some important values initially. + * + * @param className fully qualified class name + * @param superClassName fully qualified superclass name + * @param fileName source file name + * @param accessFlags access qualifiers + * @param interfaces implemented interfaces + * @param cp constant pool to use */ - public JavaClass getJavaClass() { - final int[] interfaces = getInterfaces(); - final Field[] fields = getFields(); - final Method[] methods = getMethods(); - Attribute[] attributes = null; - if (annotationList.isEmpty()) { - attributes = getAttributes(); - } else { - // TODO: Sometime later, trash any attributes called 'RuntimeVisibleAnnotations' or 'RuntimeInvisibleAnnotations' - final Attribute[] annAttributes = AnnotationEntryGen.getAnnotationAttributes(cp, getAnnotationEntries()); - attributes = new Attribute[attributeList.size()+annAttributes.length]; - attributeList.toArray(attributes); - System.arraycopy(annAttributes,0,attributes,attributeList.size(),annAttributes.length); + public ClassGen(final String className, final String superClassName, final String fileName, final int accessFlags, final String[] interfaces, + final ConstantPoolGen cp) { + super(accessFlags); + this.className = className; + this.superClassName = superClassName; + this.fileName = fileName; + this.cp = cp; + // Put everything needed by default into the constant pool and the vectors + if (fileName != null) { + addAttribute(new SourceFile(cp.addUtf8("SourceFile"), 2, cp.addUtf8(fileName), cp.getConstantPool())); + } + classNameIndex = cp.addClass(className); + superclassNameIndex = cp.addClass(superClassName); + if (interfaces != null) { + Collections.addAll(interfaceList, interfaces); } - // Must be last since the above calls may still add something to it - final ConstantPool _cp = this.cp.getFinalConstantPool(); - return new JavaClass(classNameIndex, superclass_name_index, fileName, major, minor, - super.getAccessFlags(), _cp, interfaces, fields, methods, attributes); } - - /** - * Add an interface to this class, i.e., this class has to implement it. - * @param name interface to implement (fully qualified class name) - */ - public void addInterface( final String name ) { - interfaceList.add(name); + public void addAnnotationEntry(final AnnotationEntryGen a) { + annotationList.add(a); } - /** - * Remove an interface from this class. - * @param name interface to remove (fully qualified name) + * Add an attribute to this class. + * + * @param a attribute to add */ - public void removeInterface( final String name ) { - interfaceList.remove(name); + public void addAttribute(final Attribute a) { + attributeList.add(a); } - /** - * @return major version number of class file - */ - public int getMajor() { - return major; - } - - - /** Set major version number of class file, default value is 45 (JDK 1.1) - * @param major major version number - */ - public void setMajor( final int major ) { // TODO could be package-protected - only called by test code - this.major = major; - } - - - /** Set minor version number of class file, default value is 3 (JDK 1.1) - * @param minor minor version number + * Convenience method. + * + * Add an empty constructor to this class that does nothing but calling super(). + * + * @param accessFlags rights for constructor */ - public void setMinor( final int minor ) { // TODO could be package-protected - only called by test code - this.minor = minor; + public void addEmptyConstructor(final int accessFlags) { + final InstructionList il = new InstructionList(); + il.append(InstructionConst.THIS); // Push 'this' + il.append(new INVOKESPECIAL(cp.addMethodref(superClassName, Const.CONSTRUCTOR_NAME, "()V"))); + il.append(InstructionConst.RETURN); + final MethodGen mg = new MethodGen(accessFlags, Type.VOID, Type.NO_ARGS, null, Const.CONSTRUCTOR_NAME, className, il, cp); + mg.setMaxStack(1); + addMethod(mg.getMethod()); } /** - * @return minor version number of class file + * Add a field to this class. + * + * @param f field to add */ - public int getMinor() { - return minor; + public void addField(final Field f) { + fieldList.add(f); } - /** - * Add an attribute to this class. - * @param a attribute to add + * Add an interface to this class, i.e., this class has to implement it. + * + * @param name interface to implement (fully qualified class name) */ - public void addAttribute( final Attribute a ) { - attributeList.add(a); - } - - public void addAnnotationEntry(final AnnotationEntryGen a) { - annotationList.add(a); + public void addInterface(final String name) { + interfaceList.add(name); } - /** * Add a method to this class. + * * @param m method to add */ - public void addMethod( final Method m ) { + public void addMethod(final Method m) { methodList.add(m); } - /** - * Convenience method. - * - * Add an empty constructor to this class that does nothing but calling super(). - * @param access_flags rights for constructor + * Add observer for this object. */ - public void addEmptyConstructor( final int access_flags ) { - final InstructionList il = new InstructionList(); - il.append(InstructionConst.THIS); // Push `this' - il.append(new INVOKESPECIAL(cp.addMethodref(superClassName, "", "()V"))); - il.append(InstructionConst.RETURN); - final MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "", - className, il, cp); - mg.setMaxStack(1); - addMethod(mg.getMethod()); + public void addObserver(final ClassObserver o) { + if (observers == null) { + observers = new ArrayList<>(); + } + observers.add(o); } - - /** - * Add a field to this class. - * @param f field to add - */ - public void addField( final Field f ) { - fieldList.add(f); + @Override + public Object clone() { + try { + return super.clone(); + } catch (final CloneNotSupportedException e) { + throw new Error("Clone Not Supported"); // never happens + } } - - public boolean containsField( final Field f ) { + public boolean containsField(final Field f) { return fieldList.contains(f); } - - /** @return field object with given name, or null + /** + * @return field object with given name, or null */ - public Field containsField( final String name ) { + public Field containsField(final String name) { for (final Field f : fieldList) { if (f.getName().equals(name)) { return f; @@ -335,10 +262,10 @@ public Field containsField( final String name ) { return null; } - - /** @return method object with given name and signature, or null + /** + * @return method object with given name and signature, or null */ - public Method containsMethod( final String name, final String signature ) { + public Method containsMethod(final String name, final String signature) { for (final Method m : methodList) { if (m.getName().equals(name) && m.getSignature().equals(signature)) { return m; @@ -347,264 +274,272 @@ public Method containsMethod( final String name, final String signature ) { return null; } - /** - * Remove an attribute from this class. - * @param a attribute to remove - */ - public void removeAttribute( final Attribute a ) { - attributeList.remove(a); - } - - - /** - * Remove a method from this class. - * @param m method to remove - */ - public void removeMethod( final Method m ) { - methodList.remove(m); - } - - - /** Replace given method with new one. If the old one does not exist - * add the new_ method to the class anyway. + * Return value as defined by given BCELComparator strategy. By default two ClassGen objects are said to be equal when + * their class names are equal. + * + * @see Object#equals(Object) */ - public void replaceMethod( final Method old, final Method new_ ) { - if (new_ == null) { - throw new ClassGenException("Replacement method must not be null"); - } - final int i = methodList.indexOf(old); - if (i < 0) { - methodList.add(new_); - } else { - methodList.set(i, new_); - } + @Override + public boolean equals(final Object obj) { + return bcelComparator.equals(this, obj); } - - /** Replace given field with new one. If the old one does not exist - * add the new_ field to the class anyway. - */ - public void replaceField( final Field old, final Field new_ ) { - if (new_ == null) { - throw new ClassGenException("Replacement method must not be null"); - } - final int i = fieldList.indexOf(old); - if (i < 0) { - fieldList.add(new_); - } else { - fieldList.set(i, new_); - } + // J5TODO: Should we make calling unpackAnnotations() lazy and put it in here? + public AnnotationEntryGen[] getAnnotationEntries() { + return annotationList.toArray(AnnotationEntryGen.EMPTY_ARRAY); } - - /** - * Remove a field to this class. - * @param f field to remove - */ - public void removeField( final Field f ) { - fieldList.remove(f); + public Attribute[] getAttributes() { + return attributeList.toArray(Attribute.EMPTY_ARRAY); } - public String getClassName() { return className; } - - public String getSuperclassName() { - return superClassName; - } - - - public String getFileName() { - return fileName; - } - - - public void setClassName( final String name ) { - className = name.replace('/', '.'); - classNameIndex = cp.addClass(name); - } - - - public void setSuperclassName( final String name ) { - superClassName = name.replace('/', '.'); - superclass_name_index = cp.addClass(name); - } - - - public Method[] getMethods() { - return methodList.toArray(new Method[methodList.size()]); + public int getClassNameIndex() { + return classNameIndex; } - - public void setMethods( final Method[] methods ) { - methodList.clear(); - for (final Method method : methods) { - addMethod(method); - } + public ConstantPoolGen getConstantPool() { + return cp; } - - public void setMethodAt( final Method method, final int pos ) { - methodList.set(pos, method); + public Field[] getFields() { + return fieldList.toArray(Field.EMPTY_ARRAY); } - - public Method getMethodAt( final int pos ) { - return methodList.get(pos); + public String getFileName() { + return fileName; } - public String[] getInterfaceNames() { - final int size = interfaceList.size(); - final String[] interfaces = new String[size]; - interfaceList.toArray(interfaces); - return interfaces; + return interfaceList.toArray(Const.EMPTY_STRING_ARRAY); } - public int[] getInterfaces() { final int size = interfaceList.size(); final int[] interfaces = new int[size]; - for (int i = 0; i < size; i++) { - interfaces[i] = cp.addClass(interfaceList.get(i)); - } + Arrays.setAll(interfaces, i -> cp.addClass(interfaceList.get(i))); return interfaces; } - - public Field[] getFields() { - return fieldList.toArray(new Field[fieldList.size()]); - } - - - public Attribute[] getAttributes() { - return attributeList.toArray(new Attribute[attributeList.size()]); + /** + * @return the (finally) built up Java class object. + */ + public JavaClass getJavaClass() { + final int[] interfaces = getInterfaces(); + final Field[] fields = getFields(); + final Method[] methods = getMethods(); + Attribute[] attributes = null; + if (annotationList.isEmpty()) { + attributes = getAttributes(); + } else { + // TODO: Sometime later, trash any attributes called 'RuntimeVisibleAnnotations' or 'RuntimeInvisibleAnnotations' + final Attribute[] annAttributes = AnnotationEntryGen.getAnnotationAttributes(cp, getAnnotationEntries()); + attributes = new Attribute[attributeList.size() + annAttributes.length]; + attributeList.toArray(attributes); + System.arraycopy(annAttributes, 0, attributes, attributeList.size(), annAttributes.length); + } + // Must be last since the above calls may still add something to it + final ConstantPool cp = this.cp.getFinalConstantPool(); + return new JavaClass(classNameIndex, superclassNameIndex, fileName, major, minor, super.getAccessFlags(), cp, interfaces, fields, methods, + attributes); } - // J5TODO: Should we make calling unpackAnnotations() lazy and put it in here? - public AnnotationEntryGen[] getAnnotationEntries() { - return annotationList.toArray(new AnnotationEntryGen[annotationList.size()]); + /** + * @return major version number of class file + */ + public int getMajor() { + return major; } - - public ConstantPoolGen getConstantPool() { - return cp; + public Method getMethodAt(final int pos) { + return methodList.get(pos); } - - public void setConstantPool( final ConstantPoolGen constant_pool ) { - cp = constant_pool; + public Method[] getMethods() { + return methodList.toArray(Method.EMPTY_ARRAY); } - - public void setClassNameIndex( final int class_name_index ) { - this.classNameIndex = class_name_index; - className = cp.getConstantPool().getConstantString(class_name_index, - Const.CONSTANT_Class).replace('/', '.'); + /** + * @return minor version number of class file + */ + public int getMinor() { + return minor; } - - public void setSuperclassNameIndex( final int superclass_name_index ) { - this.superclass_name_index = superclass_name_index; - superClassName = cp.getConstantPool().getConstantString(superclass_name_index, - Const.CONSTANT_Class).replace('/', '.'); + public String getSuperclassName() { + return superClassName; } - public int getSuperclassNameIndex() { - return superclass_name_index; + return superclassNameIndex; } - - public int getClassNameIndex() { - return classNameIndex; + /** + * Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name. + * + * @see Object#hashCode() + */ + @Override + public int hashCode() { + return bcelComparator.hashCode(this); } - private List observers; + /** + * Remove an attribute from this class. + * + * @param a attribute to remove + */ + public void removeAttribute(final Attribute a) { + attributeList.remove(a); + } + /** + * Remove a field to this class. + * + * @param f field to remove + */ + public void removeField(final Field f) { + fieldList.remove(f); + } - /** Add observer for this object. + /** + * Remove an interface from this class. + * + * @param name interface to remove (fully qualified name) */ - public void addObserver( final ClassObserver o ) { - if (observers == null) { - observers = new ArrayList<>(); - } - observers.add(o); + public void removeInterface(final String name) { + interfaceList.remove(name); } + /** + * Remove a method from this class. + * + * @param m method to remove + */ + public void removeMethod(final Method m) { + methodList.remove(m); + } - /** Remove observer for this object. + /** + * Remove observer for this object. */ - public void removeObserver( final ClassObserver o ) { + public void removeObserver(final ClassObserver o) { if (observers != null) { observers.remove(o); } } + /** + * Replace given field with new one. If the old one does not exist add the new_ field to the class anyway. + */ + public void replaceField(final Field old, final Field newField) { + if (newField == null) { + throw new ClassGenException("Replacement method must not be null"); + } + final int i = fieldList.indexOf(old); + if (i < 0) { + fieldList.add(newField); + } else { + fieldList.set(i, newField); + } + } - /** Call notify() method on all observers. This method is not called - * automatically whenever the state has changed, but has to be - * called by the user after he has finished editing the object. + /** + * Replace given method with new one. If the old one does not exist add the newMethod method to the class anyway. */ - public void update() { - if (observers != null) { - for (final ClassObserver observer : observers) { - observer.notify(this); - } + public void replaceMethod(final Method old, final Method newMethod) { + if (newMethod == null) { + throw new ClassGenException("Replacement method must not be null"); + } + final int i = methodList.indexOf(old); + if (i < 0) { + methodList.add(newMethod); + } else { + methodList.set(i, newMethod); } } + public void setClassName(final String name) { + className = Utility.pathToPackage(name); + classNameIndex = cp.addClass(name); + } - @Override - public Object clone() { - try { - return super.clone(); - } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens - } + public void setClassNameIndex(final int classNameIndex) { + this.classNameIndex = classNameIndex; + this.className = Utility.pathToPackage(cp.getConstantPool().getConstantString(classNameIndex, Const.CONSTANT_Class)); } + public void setConstantPool(final ConstantPoolGen constantPool) { + cp = constantPool; + } /** - * @return Comparison strategy object + * Set major version number of class file, default value is 45 (JDK 1.1) + * + * @param major major version number */ - public static BCELComparator getComparator() { - return bcelComparator; + public void setMajor(final int major) { // TODO could be package-protected - only called by test code + this.major = major; } + public void setMethodAt(final Method method, final int pos) { + methodList.set(pos, method); + } + + public void setMethods(final Method[] methods) { + methodList.clear(); + Collections.addAll(methodList, methods); + } /** - * @param comparator Comparison strategy object + * Set minor version number of class file, default value is 3 (JDK 1.1) + * + * @param minor minor version number */ - public static void setComparator( final BCELComparator comparator ) { - bcelComparator = comparator; + public void setMinor(final int minor) { // TODO could be package-protected - only called by test code + this.minor = minor; } + public void setSuperclassName(final String name) { + superClassName = Utility.pathToPackage(name); + superclassNameIndex = cp.addClass(name); + } + + public void setSuperclassNameIndex(final int superclassNameIndex) { + this.superclassNameIndex = superclassNameIndex; + superClassName = Utility.pathToPackage(cp.getConstantPool().getConstantString(superclassNameIndex, Const.CONSTANT_Class)); + } /** - * Return value as defined by given BCELComparator strategy. - * By default two ClassGen objects are said to be equal when - * their class names are equal. - * - * @see java.lang.Object#equals(java.lang.Object) + * Look for attributes representing annotations and unpack them. */ - @Override - public boolean equals( final Object obj ) { - return bcelComparator.equals(this, obj); + private AnnotationEntryGen[] unpackAnnotations(final Attribute[] attrs) { + final List annotationGenObjs = new ArrayList<>(); + for (final Attribute attr : attrs) { + if (attr instanceof RuntimeVisibleAnnotations) { + final RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr; + rva.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false))); + } else if (attr instanceof RuntimeInvisibleAnnotations) { + final RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr; + ria.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false))); + } + } + return annotationGenObjs.toArray(AnnotationEntryGen.EMPTY_ARRAY); } - /** - * Return value as defined by given BCELComparator strategy. - * By default return the hashcode of the class name. - * - * @see java.lang.Object#hashCode() + * Call notify() method on all observers. This method is not called automatically whenever the state has changed, but + * has to be called by the user after they have finished editing the object. */ - @Override - public int hashCode() { - return bcelComparator.hashCode(this); + public void update() { + if (observers != null) { + for (final ClassObserver observer : observers) { + observer.notify(this); + } + } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGenException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGenException.java index 8fd54651af8..8dfbde810de 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGenException.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGenException.java @@ -22,19 +22,15 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Thrown on internal errors. Extends RuntimeException so it hasn't to be declared - * in the throws clause every time. - * + * Thrown on internal exceptions. */ public class ClassGenException extends RuntimeException { private static final long serialVersionUID = 7247369755051242791L; public ClassGenException() { - super(); } - public ClassGenException(final String s) { super(s); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassObserver.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassObserver.java index 62ec3139efe..64f2c44c41d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassObserver.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassObserver.java @@ -22,11 +22,10 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Implement this interface if you're interested in changes to a ClassGen object - * and register yourself with addObserver(). - * + * Implement this interface if you're interested in changes to a ClassGen object and register yourself with + * addObserver(). */ public interface ClassObserver { - void notify( ClassGen clazz ); + void notify(ClassGen clazz); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java index de1a31dd125..fa660954d15 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java @@ -23,167 +23,158 @@ import com.sun.org.apache.bcel.internal.classfile.CodeException; /** - * This class represents an exception handler, i.e., specifies the region where - * a handler is active and an instruction where the actual handling is done. - * pool as parameters. Opposed to the JVM specification the end of the handled - * region is set to be inclusive, i.e. all instructions between start and end - * are protected including the start and end instructions (handles) themselves. - * The end of the region is automatically mapped to be exclusive when calling + * This class represents an exception handler, i.e., specifies the region where a handler is active and an instruction + * where the actual handling is done. pool as parameters. Opposed to the JVM specification the end of the handled region + * is set to be inclusive, i.e. all instructions between start and end are protected including the start and end + * instructions (handles) themselves. The end of the region is automatically mapped to be exclusive when calling * getCodeException(), i.e., there is no difference semantically. * - * @see MethodGen - * @see CodeException - * @see InstructionHandle + * @see MethodGen + * @see CodeException + * @see InstructionHandle */ public final class CodeExceptionGen implements InstructionTargeter, Cloneable { + static final CodeExceptionGen[] EMPTY_ARRAY = {}; + private InstructionHandle startPc; private InstructionHandle endPc; private InstructionHandle handlerPc; private ObjectType catchType; - /** - * Add an exception handler, i.e., specify region where a handler is active and an - * instruction where the actual handling is done. + * Add an exception handler, i.e., specify region where a handler is active and an instruction where the actual handling + * is done. * * @param startPc Start of handled region (inclusive) * @param endPc End of handled region (inclusive) * @param handlerPc Where handling is done * @param catchType which exception is handled, null for ANY */ - public CodeExceptionGen(final InstructionHandle startPc, final InstructionHandle endPc, - final InstructionHandle handlerPc, final ObjectType catchType) { + public CodeExceptionGen(final InstructionHandle startPc, final InstructionHandle endPc, final InstructionHandle handlerPc, final ObjectType catchType) { setStartPC(startPc); setEndPC(endPc); setHandlerPC(handlerPc); this.catchType = catchType; } + @Override + public Object clone() { + try { + return super.clone(); + } catch (final CloneNotSupportedException e) { + throw new Error("Clone Not Supported"); // never happens + } + } /** - * Get CodeException object.
    - * - * This relies on that the instruction list has already been dumped - * to byte code or or that the `setPositions' methods has been - * called for the instruction list. - * - * @param cp constant pool + * @return true, if ih is target of this handler */ - public CodeException getCodeException( final ConstantPoolGen cp ) { - return new CodeException(startPc.getPosition(), endPc.getPosition() - + endPc.getInstruction().getLength(), handlerPc.getPosition(), - (catchType == null) ? 0 : cp.addClass(catchType)); + @Override + public boolean containsTarget(final InstructionHandle ih) { + return startPc == ih || endPc == ih || handlerPc == ih; } - - /* Set start of handler - * @param startPc Start of handled region (inclusive) - */ - public void setStartPC( final InstructionHandle start_pc ) { // TODO could be package-protected? - BranchInstruction.notifyTarget(this.startPc, start_pc, this); - this.startPc = start_pc; + /** Gets the type of the Exception to catch, 'null' for ANY. */ + public ObjectType getCatchType() { + return catchType; } - - /* Set end of handler - * @param endPc End of handled region (inclusive) + /** + * Get CodeException object.
    + * + * This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods + * has been called for the instruction list. + * + * @param cp constant pool */ - public void setEndPC( final InstructionHandle end_pc ) { // TODO could be package-protected? - BranchInstruction.notifyTarget(this.endPc, end_pc, this); - this.endPc = end_pc; + public CodeException getCodeException(final ConstantPoolGen cp) { + return new CodeException(startPc.getPosition(), endPc.getPosition() + endPc.getInstruction().getLength(), handlerPc.getPosition(), + catchType == null ? 0 : cp.addClass(catchType)); } - - /* Set handler code - * @param handlerPc Start of handler + /** + * @return end of handled region (inclusive) */ - public void setHandlerPC( final InstructionHandle handler_pc ) { // TODO could be package-protected? - BranchInstruction.notifyTarget(this.handlerPc, handler_pc, this); - this.handlerPc = handler_pc; + public InstructionHandle getEndPC() { + return endPc; } - /** - * @param old_ih old target, either start or end - * @param new_ih new target + * @return start of handler */ - @Override - public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) { - boolean targeted = false; - if (startPc == old_ih) { - targeted = true; - setStartPC(new_ih); - } - if (endPc == old_ih) { - targeted = true; - setEndPC(new_ih); - } - if (handlerPc == old_ih) { - targeted = true; - setHandlerPC(new_ih); - } - if (!targeted) { - throw new ClassGenException("Not targeting " + old_ih + ", but {" + startPc + ", " - + endPc + ", " + handlerPc + "}"); - } + public InstructionHandle getHandlerPC() { + return handlerPc; } - /** - * @return true, if ih is target of this handler + * @return start of handled region (inclusive) */ - @Override - public boolean containsTarget( final InstructionHandle ih ) { - return (startPc == ih) || (endPc == ih) || (handlerPc == ih); + public InstructionHandle getStartPC() { + return startPc; } - /** Sets the type of the Exception to catch. Set 'null' for ANY. */ - public void setCatchType( final ObjectType catchType ) { + public void setCatchType(final ObjectType catchType) { this.catchType = catchType; } - - /** Gets the type of the Exception to catch, 'null' for ANY. */ - public ObjectType getCatchType() { - return catchType; - } - - - /** @return start of handled region (inclusive) + /* + * Set end of handler + * + * @param endPc End of handled region (inclusive) */ - public InstructionHandle getStartPC() { - return startPc; + public void setEndPC(final InstructionHandle endPc) { // TODO could be package-protected? + BranchInstruction.notifyTarget(this.endPc, endPc, this); + this.endPc = endPc; } - - /** @return end of handled region (inclusive) + /* + * Set handler code + * + * @param handlerPc Start of handler */ - public InstructionHandle getEndPC() { - return endPc; + public void setHandlerPC(final InstructionHandle handlerPc) { // TODO could be package-protected? + BranchInstruction.notifyTarget(this.handlerPc, handlerPc, this); + this.handlerPc = handlerPc; } - - /** @return start of handler + /* + * Set start of handler + * + * @param startPc Start of handled region (inclusive) */ - public InstructionHandle getHandlerPC() { - return handlerPc; + public void setStartPC(final InstructionHandle startPc) { // TODO could be package-protected? + BranchInstruction.notifyTarget(this.startPc, startPc, this); + this.startPc = startPc; } - @Override public String toString() { return "CodeExceptionGen(" + startPc + ", " + endPc + ", " + handlerPc + ")"; } - + /** + * @param oldIh old target, either start or end + * @param newIh new target + */ @Override - public Object clone() { - try { - return super.clone(); - } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) { + boolean targeted = false; + if (startPc == oldIh) { + targeted = true; + setStartPC(newIh); + } + if (endPc == oldIh) { + targeted = true; + setEndPC(newIh); + } + if (handlerPc == oldIh) { + targeted = true; + setHandlerPC(newIh); + } + if (!targeted) { + throw new ClassGenException("Not targeting " + oldIh + ", but {" + startPc + ", " + endPc + ", " + handlerPc + "}"); } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CompoundInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CompoundInstruction.java index f487d51fcfd..40fc722d0d1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CompoundInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CompoundInstruction.java @@ -22,15 +22,12 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Wrapper class for `compound' operations, virtual instructions that - * don't exist as byte code, but give a useful meaning. For example, - * the (virtual) PUSH instruction takes an arbitray argument and produces the - * appropiate code at dump time (ICONST, LDC, BIPUSH, ...). Also you can use the - * SWITCH instruction as a useful template for either LOOKUPSWITCH or - * TABLESWITCH. + * Wrapper class for 'compound' operations, virtual instructions that don't exist as byte code, but give a useful + * meaning. For example, the (virtual) PUSH instruction takes an arbitrary argument and produces the appropriate code at + * dump time (ICONST, LDC, BIPUSH, ...). Also you can use the SWITCH instruction as a useful template for either + * LOOKUPSWITCH or TABLESWITCH. * - * The interface provides the possibilty for the user to write - * `templates' or `macros' for such reuseable code patterns. + * The interface provides the possibility for the user to write 'templates' or 'macros' for such reusable code patterns. * * @see PUSH * @see SWITCH diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConstantPoolGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConstantPoolGen.java index 622cdb1b7ac..b07fef8f901 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConstantPoolGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConstantPoolGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -19,6 +19,7 @@ */ package com.sun.org.apache.bcel.internal.generic; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -27,6 +28,7 @@ import com.sun.org.apache.bcel.internal.classfile.ConstantCP; import com.sun.org.apache.bcel.internal.classfile.ConstantClass; import com.sun.org.apache.bcel.internal.classfile.ConstantDouble; +import com.sun.org.apache.bcel.internal.classfile.ConstantDynamic; import com.sun.org.apache.bcel.internal.classfile.ConstantFieldref; import com.sun.org.apache.bcel.internal.classfile.ConstantFloat; import com.sun.org.apache.bcel.internal.classfile.ConstantInteger; @@ -38,45 +40,68 @@ import com.sun.org.apache.bcel.internal.classfile.ConstantPool; import com.sun.org.apache.bcel.internal.classfile.ConstantString; import com.sun.org.apache.bcel.internal.classfile.ConstantUtf8; +import com.sun.org.apache.bcel.internal.classfile.Utility; /** - * This class is used to build up a constant pool. The user adds - * constants via `addXXX' methods, `addString', `addClass', - * etc.. These methods return an index into the constant - * pool. Finally, `getFinalConstantPool()' returns the constant pool - * built up. Intermediate versions of the constant pool can be - * obtained with `getConstantPool()'. A constant pool has capacity for - * Constants.MAX_SHORT entries. Note that the first (0) is used by the - * JVM and that Double and Long constants need two slots. + * This class is used to build up a constant pool. The user adds constants via 'addXXX' methods, 'addString', + * 'addClass', etc.. These methods return an index into the constant pool. Finally, 'getFinalConstantPool()' returns the + * constant pool built up. Intermediate versions of the constant pool can be obtained with 'getConstantPool()'. A + * constant pool has capacity for Constants.MAX_SHORT entries. Note that the first (0) is used by the JVM and that + * Double and Long constants need two slots. * * @see Constant - * @LastModified: June 2022 + * @LastModified: Feb 2023 */ public class ConstantPoolGen { - public static final int CONSTANT_POOL_SIZE = 65535; + private static final int DEFAULT_BUFFER_SIZE = 256; - private int size; - private Constant[] constants; - private int index = 1; // First entry (0) used by JVM private static final String METHODREF_DELIM = ":"; + private static final String IMETHODREF_DELIM = "#"; + private static final String FIELDREF_DELIM = "&"; + private static final String NAT_DELIM = "%"; // Name and Type - private static class Index { + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected int size; - final int index; + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected Constant[] constants; + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getSize() + */ + @Deprecated + protected int index = 1; // First entry (0) used by JVM - Index(final int i) { - index = i; - } - } + private final Map stringTable = new HashMap<>(); + + private final Map classTable = new HashMap<>(); + + private final Map utf8Table = new HashMap<>(); + + private final Map natTable = new HashMap<>(); + private final Map cpTable = new HashMap<>(); /** - * Initialize with given array of constants. + * Constructs a new empty constant pool. + */ + public ConstantPoolGen() { + size = DEFAULT_BUFFER_SIZE; + constants = new Constant[size]; + } + + /** + * Constructs a new instance with the given array of constants. * * @param cs array of given constants, new ones will be appended */ @@ -88,15 +113,15 @@ public ConstantPoolGen(final Constant[] cs) { * This is however, not used by XSLT (or the java.xml implementation), * and only happens when BCELifier is called (see BCELifier). */ - if (cs.length > CONSTANT_POOL_SIZE) { - throw new RuntimeException("The number of constants " + cs.length + if (cs.length > Const.MAX_CP_ENTRIES) { + throw new IllegalStateException("The number of constants " + cs.length + " is over the size limit of the constant pool: " - + CONSTANT_POOL_SIZE); + + Const.MAX_CP_ENTRIES); } final StringBuilder sb = new StringBuilder(DEFAULT_BUFFER_SIZE); - size = Math.min(Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64), CONSTANT_POOL_SIZE); + size = Math.min(Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64), Const.MAX_CP_ENTRIES); constants = new Constant[size]; System.arraycopy(cs, 0, constants, 0, cs.length); @@ -104,7 +129,6 @@ public ConstantPoolGen(final Constant[] cs) { index = cs.length; } - for (int i = 1; i < index; i++) { final Constant c = constants[i]; if (c instanceof ConstantString) { @@ -112,56 +136,57 @@ public ConstantPoolGen(final Constant[] cs) { final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; final String key = u8.getBytes(); if (!stringTable.containsKey(key)) { - stringTable.put(key, new Index(i)); + stringTable.put(key, Integer.valueOf(i)); } } else if (c instanceof ConstantClass) { final ConstantClass s = (ConstantClass) c; final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; final String key = u8.getBytes(); if (!classTable.containsKey(key)) { - classTable.put(key, new Index(i)); + classTable.put(key, Integer.valueOf(i)); } } else if (c instanceof ConstantNameAndType) { final ConstantNameAndType n = (ConstantNameAndType) c; - final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; - final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; + final ConstantUtf8 u8NameIdx = (ConstantUtf8) constants[n.getNameIndex()]; + final ConstantUtf8 u8SigIdx = (ConstantUtf8) constants[n.getSignatureIndex()]; - sb.append(u8.getBytes()); + sb.append(u8NameIdx.getBytes()); sb.append(NAT_DELIM); - sb.append(u8_2.getBytes()); + sb.append(u8SigIdx.getBytes()); final String key = sb.toString(); sb.delete(0, sb.length()); if (!natTable.containsKey(key)) { - natTable.put(key, new Index(i)); + natTable.put(key, Integer.valueOf(i)); } } else if (c instanceof ConstantUtf8) { final ConstantUtf8 u = (ConstantUtf8) c; final String key = u.getBytes(); if (!utf8Table.containsKey(key)) { - utf8Table.put(key, new Index(i)); + utf8Table.put(key, Integer.valueOf(i)); } } else if (c instanceof ConstantCP) { final ConstantCP m = (ConstantCP) c; - String class_name; + String className; ConstantUtf8 u8; if (c instanceof ConstantInvokeDynamic) { - class_name = Integer.toString(((ConstantInvokeDynamic) m).getBootstrapMethodAttrIndex()); - // since name can't begin with digit, can use - // METHODREF_DELIM with out fear of duplicates. + className = Integer.toString(((ConstantInvokeDynamic) m).getBootstrapMethodAttrIndex()); + } else if (c instanceof ConstantDynamic) { + className = Integer.toString(((ConstantDynamic) m).getBootstrapMethodAttrIndex()); } else { - final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; + final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; - class_name = u8.getBytes().replace('/', '.'); + className = Utility.pathToPackage(u8.getBytes()); } final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; u8 = (ConstantUtf8) constants[n.getNameIndex()]; - final String method_name = u8.getBytes(); + final String methodName = u8.getBytes(); u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; final String signature = u8.getBytes(); + // Since name cannot begin with digit, we can use METHODREF_DELIM without fear of duplicates String delim = METHODREF_DELIM; if (c instanceof ConstantInterfaceMethodref) { delim = IMETHODREF_DELIM; @@ -169,245 +194,205 @@ public ConstantPoolGen(final Constant[] cs) { delim = FIELDREF_DELIM; } - sb.append(class_name); + sb.append(className); sb.append(delim); - sb.append(method_name); + sb.append(methodName); sb.append(delim); sb.append(signature); final String key = sb.toString(); sb.delete(0, sb.length()); if (!cpTable.containsKey(key)) { - cpTable.put(key, new Index(i)); + cpTable.put(key, Integer.valueOf(i)); } - } else if (c == null) { // entries may be null - // nothing to do - } else if (c instanceof ConstantInteger) { - // nothing to do - } else if (c instanceof ConstantLong) { - // nothing to do - } else if (c instanceof ConstantFloat) { - // nothing to do - } else if (c instanceof ConstantDouble) { - // nothing to do - } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantMethodType) { - // TODO should this be handled somehow? - } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantMethodHandle) { - // TODO should this be handled somehow? - } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantModule) { - // TODO should this be handled somehow? - } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantPackage) { - // TODO should this be handled somehow? - } else { - assert false : "Unexpected constant type: " + c.getClass().getName(); } +// else if (c == null) { // entries may be null +// // nothing to do +// } else if (c instanceof ConstantInteger) { +// // nothing to do +// } else if (c instanceof ConstantLong) { +// // nothing to do +// } else if (c instanceof ConstantFloat) { +// // nothing to do +// } else if (c instanceof ConstantDouble) { +// // nothing to do +// } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantMethodType) { +// // TODO should this be handled somehow? +// } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantMethodHandle) { +// // TODO should this be handled somehow? +// } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantModule) { +// // TODO should this be handled somehow? +// } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantPackage) { +// // TODO should this be handled somehow? +// } else { +// // Not helpful, should throw an exception. +// assert false : "Unexpected constant type: " + c.getClass().getName(); +// } } } - /** - * Initialize with given constant pool. + * Constructs a new instance with the given constant pool. + * + * @param cp the constant pool. */ public ConstantPoolGen(final ConstantPool cp) { this(cp.getConstantPool()); } - /** - * Create empty constant pool. - */ - public ConstantPoolGen() { - size = DEFAULT_BUFFER_SIZE; - constants = new Constant[size]; - } - - - /** Resize internal array of constants. - */ - protected void adjustSize() { - // 3 extra spaces are needed as some entries may take 3 slots - if (index + 3 >= CONSTANT_POOL_SIZE) { - throw new RuntimeException("The number of constants " + (index + 3) - + " is over the size limit of the constant pool: " - + CONSTANT_POOL_SIZE); - } - - if (index + 3 >= size) { - final Constant[] cs = constants; - size *= 2; - // the constant array shall not exceed the size of the constant pool - size = Math.min(size, CONSTANT_POOL_SIZE); - constants = new Constant[size]; - System.arraycopy(cs, 0, constants, 0, index); - } - } - - private final Map stringTable = new HashMap<>(); - - - /** - * Look for ConstantString in ConstantPool containing String `str'. + * Add a reference to an array class (e.g. String[][]) as needed by MULTIANEWARRAY instruction, e.g. to the + * ConstantPool. * - * @param str String to search for - * @return index on success, -1 otherwise + * @param type type of array class + * @return index of entry */ - public int lookupString( final String str ) { - final Index index = stringTable.get(str); - return (index != null) ? index.index : -1; + public int addArrayClass(final ArrayType type) { + return addClass_(type.getSignature()); } - /** - * Add a new String constant to the ConstantPool, if it is not already in there. + * Add a new Class reference to the ConstantPool for a given type. * - * @param str String to add + * @param type Class to add * @return index of entry */ - public int addString( final String str ) { - int ret; - if ((ret = lookupString(str)) != -1) { - return ret; // Already in CP - } - final int utf8 = addUtf8(str); - adjustSize(); - final ConstantString s = new ConstantString(utf8); - ret = index; - constants[index++] = s; - if (!stringTable.containsKey(str)) { - stringTable.put(str, new Index(ret)); - } - return ret; + public int addClass(final ObjectType type) { + return addClass(type.getClassName()); } - private final Map classTable = new HashMap<>(); - - /** - * Look for ConstantClass in ConstantPool named `str'. + * Add a new Class reference to the ConstantPool, if it is not already in there. * - * @param str String to search for - * @return index on success, -1 otherwise + * @param str Class to add + * @return index of entry */ - public int lookupClass( final String str ) { - final Index index = classTable.get(str.replace('.', '/')); - return (index != null) ? index.index : -1; + public int addClass(final String str) { + return addClass_(Utility.packageToPath(str)); } - - private int addClass_( final String clazz ) { - int ret; - if ((ret = lookupClass(clazz)) != -1) { - return ret; // Already in CP + private int addClass_(final String clazz) { + final int cpRet; + if ((cpRet = lookupClass(clazz)) != -1) { + return cpRet; // Already in CP } adjustSize(); final ConstantClass c = new ConstantClass(addUtf8(clazz)); - ret = index; + final int ret = index; constants[index++] = c; - if (!classTable.containsKey(clazz)) { - classTable.put(clazz, new Index(ret)); - } - return ret; - } - - - /** - * Add a new Class reference to the ConstantPool, if it is not already in there. - * - * @param str Class to add - * @return index of entry - */ - public int addClass( final String str ) { - return addClass_(str.replace('.', '/')); - } - - - /** - * Add a new Class reference to the ConstantPool for a given type. - * - * @param type Class to add - * @return index of entry - */ - public int addClass( final ObjectType type ) { - return addClass(type.getClassName()); + return computeIfAbsent(classTable, clazz, ret); } - /** - * Add a reference to an array class (e.g. String[][]) as needed by MULTIANEWARRAY - * instruction, e.g. to the ConstantPool. + * Adds a constant from another ConstantPool and returns the new index. * - * @param type type of array class + * @param constant The constant to add. + * @param cpGen Source pool. * @return index of entry */ - public int addArrayClass( final ArrayType type ) { - return addClass_(type.getSignature()); - } - - - /** - * Look for ConstantInteger in ConstantPool. - * - * @param n integer number to look for - * @return index on success, -1 otherwise - */ - public int lookupInteger( final int n ) { - for (int i = 1; i < index; i++) { - if (constants[i] instanceof ConstantInteger) { - final ConstantInteger c = (ConstantInteger) constants[i]; - if (c.getBytes() == n) { - return i; - } + public int addConstant(final Constant constant, final ConstantPoolGen cpGen) { + final Constant[] constants = cpGen.getConstantPool().getConstantPool(); + switch (constant.getTag()) { + case Const.CONSTANT_String: { + final ConstantString s = (ConstantString) constant; + final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; + return addString(u8.getBytes()); + } + case Const.CONSTANT_Class: { + final ConstantClass s = (ConstantClass) constant; + final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; + return addClass(u8.getBytes()); + } + case Const.CONSTANT_NameAndType: { + final ConstantNameAndType n = (ConstantNameAndType) constant; + final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; + final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; + return addNameAndType(u8.getBytes(), u8_2.getBytes()); + } + case Const.CONSTANT_Utf8: + return addUtf8(((ConstantUtf8) constant).getBytes()); + case Const.CONSTANT_Double: + return addDouble(((ConstantDouble) constant).getBytes()); + case Const.CONSTANT_Float: + return addFloat(((ConstantFloat) constant).getBytes()); + case Const.CONSTANT_Long: + return addLong(((ConstantLong) constant).getBytes()); + case Const.CONSTANT_Integer: + return addInteger(((ConstantInteger) constant).getBytes()); + case Const.CONSTANT_InterfaceMethodref: + case Const.CONSTANT_Methodref: + case Const.CONSTANT_Fieldref: { + final ConstantCP m = (ConstantCP) constant; + final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; + final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; + ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; + final String className = Utility.pathToPackage(u8.getBytes()); + u8 = (ConstantUtf8) constants[n.getNameIndex()]; + final String name = u8.getBytes(); + u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; + final String signature = u8.getBytes(); + switch (constant.getTag()) { + case Const.CONSTANT_InterfaceMethodref: + return addInterfaceMethodref(className, name, signature); + case Const.CONSTANT_Methodref: + return addMethodref(className, name, signature); + case Const.CONSTANT_Fieldref: + return addFieldref(className, name, signature); + default: // Never reached + throw new IllegalArgumentException("Unknown constant type " + constant); } } - return -1; + default: // Never reached + throw new IllegalArgumentException("Unknown constant type " + constant); + } } - /** - * Add a new Integer constant to the ConstantPool, if it is not already in there. + * Add a new double constant to the ConstantPool, if it is not already in there. * - * @param n integer number to add + * @param n Double number to add * @return index of entry */ - public int addInteger( final int n ) { + public int addDouble(final double n) { int ret; - if ((ret = lookupInteger(n)) != -1) { + if ((ret = lookupDouble(n)) != -1) { return ret; // Already in CP } adjustSize(); ret = index; - constants[index++] = new ConstantInteger(n); + constants[index] = new ConstantDouble(n); + index += 2; // Wastes one entry according to spec return ret; } - /** - * Look for ConstantFloat in ConstantPool. + * Add a new Fieldref constant to the ConstantPool, if it is not already in there. * - * @param n Float number to look for - * @return index on success, -1 otherwise + * @param className class name string to add + * @param fieldName field name string to add + * @param signature signature string to add + * @return index of entry */ - public int lookupFloat( final float n ) { - final int bits = Float.floatToIntBits(n); - for (int i = 1; i < index; i++) { - if (constants[i] instanceof ConstantFloat) { - final ConstantFloat c = (ConstantFloat) constants[i]; - if (Float.floatToIntBits(c.getBytes()) == bits) { - return i; - } - } + public int addFieldref(final String className, final String fieldName, final String signature) { + final int cpRet; + if ((cpRet = lookupFieldref(className, fieldName, signature)) != -1) { + return cpRet; // Already in CP } - return -1; + adjustSize(); + final int classIndex = addClass(className); + final int nameAndTypeIndex = addNameAndType(fieldName, signature); + final int ret = index; + constants[index++] = new ConstantFieldref(classIndex, nameAndTypeIndex); + return computeIfAbsent(cpTable, className + FIELDREF_DELIM + fieldName + FIELDREF_DELIM + signature, ret); } - /** * Add a new Float constant to the ConstantPool, if it is not already in there. * * @param n Float number to add * @return index of entry */ - public int addFloat( final float n ) { + public int addFloat(final float n) { int ret; if ((ret = lookupFloat(n)) != -1) { return ret; // Already in CP @@ -418,68 +403,55 @@ public int addFloat( final float n ) { return ret; } - private final Map utf8Table = new HashMap<>(); - - - /** - * Look for ConstantUtf8 in ConstantPool. - * - * @param n Utf8 string to look for - * @return index on success, -1 otherwise - */ - public int lookupUtf8( final String n ) { - final Index index = utf8Table.get(n); - return (index != null) ? index.index : -1; - } - - /** - * Add a new Utf8 constant to the ConstantPool, if it is not already in there. + * Add a new Integer constant to the ConstantPool, if it is not already in there. * - * @param n Utf8 string to add + * @param n integer number to add * @return index of entry */ - public int addUtf8( final String n ) { + public int addInteger(final int n) { int ret; - if ((ret = lookupUtf8(n)) != -1) { + if ((ret = lookupInteger(n)) != -1) { return ret; // Already in CP } adjustSize(); ret = index; - constants[index++] = new ConstantUtf8(n); - if (!utf8Table.containsKey(n)) { - utf8Table.put(n, new Index(ret)); - } + constants[index++] = new ConstantInteger(n); return ret; } + public int addInterfaceMethodref(final MethodGen method) { + return addInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); + } /** - * Look for ConstantLong in ConstantPool. + * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already in there. * - * @param n Long number to look for - * @return index on success, -1 otherwise + * @param className class name string to add + * @param methodName method name string to add + * @param signature signature string to add + * @return index of entry */ - public int lookupLong( final long n ) { - for (int i = 1; i < index; i++) { - if (constants[i] instanceof ConstantLong) { - final ConstantLong c = (ConstantLong) constants[i]; - if (c.getBytes() == n) { - return i; - } - } + public int addInterfaceMethodref(final String className, final String methodName, final String signature) { + final int cpRet; + if ((cpRet = lookupInterfaceMethodref(className, methodName, signature)) != -1) { + return cpRet; // Already in CP } - return -1; + adjustSize(); + final int classIndex = addClass(className); + final int nameAndTypeIndex = addNameAndType(methodName, signature); + final int ret = index; + constants[index++] = new ConstantInterfaceMethodref(classIndex, nameAndTypeIndex); + return computeIfAbsent(cpTable, className + IMETHODREF_DELIM + methodName + IMETHODREF_DELIM + signature, ret); } - /** * Add a new long constant to the ConstantPool, if it is not already in there. * * @param n Long number to add * @return index of entry */ - public int addLong( final long n ) { + public int addLong(final long n) { int ret; if ((ret = lookupLong(n)) != -1) { return ret; // Already in CP @@ -490,290 +462,317 @@ public int addLong( final long n ) { index += 2; // Wastes one entry according to spec return ret; } - + public int addMethodref(final MethodGen method) { + return addMethodref(method.getClassName(), method.getName(), method.getSignature()); + } /** - * Look for ConstantDouble in ConstantPool. + * Add a new Methodref constant to the ConstantPool, if it is not already in there. * - * @param n Double number to look for - * @return index on success, -1 otherwise + * @param className class name string to add + * @param methodName method name string to add + * @param signature method signature string to add + * @return index of entry */ - public int lookupDouble( final double n ) { - final long bits = Double.doubleToLongBits(n); - for (int i = 1; i < index; i++) { - if (constants[i] instanceof ConstantDouble) { - final ConstantDouble c = (ConstantDouble) constants[i]; - if (Double.doubleToLongBits(c.getBytes()) == bits) { - return i; - } - } + public int addMethodref(final String className, final String methodName, final String signature) { + final int cpRet; + if ((cpRet = lookupMethodref(className, methodName, signature)) != -1) { + return cpRet; // Already in CP } - return -1; + adjustSize(); + final int nameAndTypeIndex = addNameAndType(methodName, signature); + final int classIndex = addClass(className); + final int ret = index; + constants[index++] = new ConstantMethodref(classIndex, nameAndTypeIndex); + return computeIfAbsent(cpTable, className + METHODREF_DELIM + methodName + METHODREF_DELIM + signature, ret); } - /** - * Add a new double constant to the ConstantPool, if it is not already in there. + * Add a new NameAndType constant to the ConstantPool if it is not already in there. * - * @param n Double number to add + * @param name Name string to add + * @param signature signature string to add * @return index of entry */ - public int addDouble( final double n ) { + public int addNameAndType(final String name, final String signature) { int ret; - if ((ret = lookupDouble(n)) != -1) { + if ((ret = lookupNameAndType(name, signature)) != -1) { return ret; // Already in CP } adjustSize(); + final int nameIndex = addUtf8(name); + final int signatureIndex = addUtf8(signature); ret = index; - constants[index] = new ConstantDouble(n); - index += 2; // Wastes one entry according to spec - return ret; + constants[index++] = new ConstantNameAndType(nameIndex, signatureIndex); + return computeIfAbsent(natTable, name + NAT_DELIM + signature, ret); } - private final Map natTable = new HashMap<>(); - - /** - * Look for ConstantNameAndType in ConstantPool. + * Add a new String constant to the ConstantPool, if it is not already in there. * - * @param name of variable/method - * @param signature of variable/method - * @return index on success, -1 otherwise + * @param str String to add + * @return index of entry */ - public int lookupNameAndType( final String name, final String signature ) { - final Index _index = natTable.get(name + NAT_DELIM + signature); - return (_index != null) ? _index.index : -1; + public int addString(final String str) { + int ret; + if ((ret = lookupString(str)) != -1) { + return ret; // Already in CP + } + final int utf8 = addUtf8(str); + adjustSize(); + final ConstantString s = new ConstantString(utf8); + ret = index; + constants[index++] = s; + return computeIfAbsent(stringTable, str, ret); } - /** - * Add a new NameAndType constant to the ConstantPool if it is not already - * in there. + * Add a new Utf8 constant to the ConstantPool, if it is not already in there. * - * @param name Name string to add - * @param signature signature string to add + * @param n Utf8 string to add * @return index of entry */ - public int addNameAndType( final String name, final String signature ) { + public int addUtf8(final String n) { int ret; - int name_index; - int signature_index; - if ((ret = lookupNameAndType(name, signature)) != -1) { + if ((ret = lookupUtf8(n)) != -1) { return ret; // Already in CP } adjustSize(); - name_index = addUtf8(name); - signature_index = addUtf8(signature); ret = index; - constants[index++] = new ConstantNameAndType(name_index, signature_index); - final String key = name + NAT_DELIM + signature; - if (!natTable.containsKey(key)) { - natTable.put(key, new Index(ret)); + constants[index++] = new ConstantUtf8(n); + return computeIfAbsent(utf8Table, n, ret); + } + + /** + * Resize internal array of constants. + */ + protected void adjustSize() { + // 3 extra spaces are needed as some entries may take 3 slots + if (index + 3 >= Const.MAX_CP_ENTRIES) { + throw new IllegalStateException("The number of constants " + (index + 3) + + " is over the size limit of the constant pool: " + + Const.MAX_CP_ENTRIES); + } + + if (index + 3 >= size) { + final Constant[] cs = constants; + size *= 2; + // the constant array shall not exceed the size of the constant pool + size = Math.min(size, Const.MAX_CP_ENTRIES); + constants = new Constant[size]; + System.arraycopy(cs, 0, constants, 0, index); } - return ret; } - private final Map cpTable = new HashMap<>(); + private int computeIfAbsent(final Map map, final String key, final int value) { + return map.computeIfAbsent(key, k -> Integer.valueOf(value)); + } + /** + * @param i index in constant pool + * @return constant pool entry at index i + */ + public Constant getConstant(final int i) { + return constants[i]; + } /** - * Look for ConstantMethodref in ConstantPool. - * - * @param class_name Where to find method - * @param method_name Guess what - * @param signature return and argument types - * @return index on success, -1 otherwise + * @return intermediate constant pool */ - public int lookupMethodref( final String class_name, final String method_name, final String signature ) { - final Index index = cpTable.get(class_name + METHODREF_DELIM + method_name - + METHODREF_DELIM + signature); - return (index != null) ? index.index : -1; + public ConstantPool getConstantPool() { + return new ConstantPool(constants); } + /** + * @return constant pool with proper length + */ + public ConstantPool getFinalConstantPool() { + return new ConstantPool(Arrays.copyOf(constants, index)); + } - public int lookupMethodref( final MethodGen method ) { - return lookupMethodref(method.getClassName(), method.getName(), method.getSignature()); + private int getIndex(final Map map, final String key) { + return toIndex(map.get(key)); } + /** + * @return current size of constant pool + */ + public int getSize() { + return index; + } /** - * Add a new Methodref constant to the ConstantPool, if it is not already - * in there. + * Look for ConstantClass in ConstantPool named 'str'. * - * @param class_name class name string to add - * @param method_name method name string to add - * @param signature method signature string to add - * @return index of entry + * @param str String to search for + * @return index on success, -1 otherwise */ - public int addMethodref( final String class_name, final String method_name, final String signature ) { - int ret; - int class_index; - int name_and_type_index; - if ((ret = lookupMethodref(class_name, method_name, signature)) != -1) { - return ret; // Already in CP - } - adjustSize(); - name_and_type_index = addNameAndType(method_name, signature); - class_index = addClass(class_name); - ret = index; - constants[index++] = new ConstantMethodref(class_index, name_and_type_index); - final String key = class_name + METHODREF_DELIM + method_name + METHODREF_DELIM + signature; - if (!cpTable.containsKey(key)) { - cpTable.put(key, new Index(ret)); - } - return ret; + public int lookupClass(final String str) { + return getIndex(classTable, Utility.packageToPath(str)); } - - public int addMethodref( final MethodGen method ) { - return addMethodref(method.getClassName(), method.getName(), method.getSignature()); + /** + * Look for ConstantDouble in ConstantPool. + * + * @param n Double number to look for + * @return index on success, -1 otherwise + */ + public int lookupDouble(final double n) { + final long bits = Double.doubleToLongBits(n); + for (int i = 1; i < index; i++) { + if (constants[i] instanceof ConstantDouble) { + final ConstantDouble c = (ConstantDouble) constants[i]; + if (Double.doubleToLongBits(c.getBytes()) == bits) { + return i; + } + } + } + return -1; } - /** - * Look for ConstantInterfaceMethodref in ConstantPool. + * Look for ConstantFieldref in ConstantPool. * - * @param class_name Where to find method - * @param method_name Guess what + * @param className Where to find method + * @param fieldName Guess what * @param signature return and argument types * @return index on success, -1 otherwise */ - public int lookupInterfaceMethodref( final String class_name, final String method_name, final String signature ) { - final Index index = cpTable.get(class_name + IMETHODREF_DELIM + method_name - + IMETHODREF_DELIM + signature); - return (index != null) ? index.index : -1; + public int lookupFieldref(final String className, final String fieldName, final String signature) { + return getIndex(cpTable, className + FIELDREF_DELIM + fieldName + FIELDREF_DELIM + signature); } - - public int lookupInterfaceMethodref( final MethodGen method ) { - return lookupInterfaceMethodref(method.getClassName(), method.getName(), method - .getSignature()); + /** + * Look for ConstantFloat in ConstantPool. + * + * @param n Float number to look for + * @return index on success, -1 otherwise + */ + public int lookupFloat(final float n) { + final int bits = Float.floatToIntBits(n); + for (int i = 1; i < index; i++) { + if (constants[i] instanceof ConstantFloat) { + final ConstantFloat c = (ConstantFloat) constants[i]; + if (Float.floatToIntBits(c.getBytes()) == bits) { + return i; + } + } + } + return -1; } - /** - * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already - * in there. + * Look for ConstantInteger in ConstantPool. * - * @param class_name class name string to add - * @param method_name method name string to add - * @param signature signature string to add - * @return index of entry + * @param n integer number to look for + * @return index on success, -1 otherwise */ - public int addInterfaceMethodref( final String class_name, final String method_name, final String signature ) { - int ret; - int class_index; - int name_and_type_index; - if ((ret = lookupInterfaceMethodref(class_name, method_name, signature)) != -1) { - return ret; // Already in CP - } - adjustSize(); - class_index = addClass(class_name); - name_and_type_index = addNameAndType(method_name, signature); - ret = index; - constants[index++] = new ConstantInterfaceMethodref(class_index, name_and_type_index); - final String key = class_name + IMETHODREF_DELIM + method_name + IMETHODREF_DELIM + signature; - if (!cpTable.containsKey(key)) { - cpTable.put(key, new Index(ret)); + public int lookupInteger(final int n) { + for (int i = 1; i < index; i++) { + if (constants[i] instanceof ConstantInteger) { + final ConstantInteger c = (ConstantInteger) constants[i]; + if (c.getBytes() == n) { + return i; + } + } } - return ret; + return -1; } - - public int addInterfaceMethodref( final MethodGen method ) { - return addInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); + public int lookupInterfaceMethodref(final MethodGen method) { + return lookupInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); } - /** - * Look for ConstantFieldref in ConstantPool. + * Look for ConstantInterfaceMethodref in ConstantPool. * - * @param class_name Where to find method - * @param field_name Guess what + * @param className Where to find method + * @param methodName Guess what * @param signature return and argument types * @return index on success, -1 otherwise */ - public int lookupFieldref( final String class_name, final String field_name, final String signature ) { - final Index index = cpTable.get(class_name + FIELDREF_DELIM + field_name - + FIELDREF_DELIM + signature); - return (index != null) ? index.index : -1; + public int lookupInterfaceMethodref(final String className, final String methodName, final String signature) { + return getIndex(cpTable, className + IMETHODREF_DELIM + methodName + IMETHODREF_DELIM + signature); } - /** - * Add a new Fieldref constant to the ConstantPool, if it is not already - * in there. + * Look for ConstantLong in ConstantPool. * - * @param class_name class name string to add - * @param field_name field name string to add - * @param signature signature string to add - * @return index of entry + * @param n Long number to look for + * @return index on success, -1 otherwise */ - public int addFieldref( final String class_name, final String field_name, final String signature ) { - int ret; - int class_index; - int name_and_type_index; - if ((ret = lookupFieldref(class_name, field_name, signature)) != -1) { - return ret; // Already in CP - } - adjustSize(); - class_index = addClass(class_name); - name_and_type_index = addNameAndType(field_name, signature); - ret = index; - constants[index++] = new ConstantFieldref(class_index, name_and_type_index); - final String key = class_name + FIELDREF_DELIM + field_name + FIELDREF_DELIM + signature; - if (!cpTable.containsKey(key)) { - cpTable.put(key, new Index(ret)); + public int lookupLong(final long n) { + for (int i = 1; i < index; i++) { + if (constants[i] instanceof ConstantLong) { + final ConstantLong c = (ConstantLong) constants[i]; + if (c.getBytes() == n) { + return i; + } + } } - return ret; + return -1; } + public int lookupMethodref(final MethodGen method) { + return lookupMethodref(method.getClassName(), method.getName(), method.getSignature()); + } /** - * @param i index in constant pool - * @return constant pool entry at index i + * Look for ConstantMethodref in ConstantPool. + * + * @param className Where to find method + * @param methodName Guess what + * @param signature return and argument types + * @return index on success, -1 otherwise */ - public Constant getConstant( final int i ) { - return constants[i]; + public int lookupMethodref(final String className, final String methodName, final String signature) { + return getIndex(cpTable, className + METHODREF_DELIM + methodName + METHODREF_DELIM + signature); } - /** - * Use with care! + * Look for ConstantNameAndType in ConstantPool. * - * @param i index in constant pool - * @param c new constant pool entry at index i + * @param name of variable/method + * @param signature of variable/method + * @return index on success, -1 otherwise */ - public void setConstant( final int i, final Constant c ) { - constants[i] = c; + public int lookupNameAndType(final String name, final String signature) { + return getIndex(natTable, name + NAT_DELIM + signature); } - /** - * @return intermediate constant pool + * Look for ConstantString in ConstantPool containing String 'str'. + * + * @param str String to search for + * @return index on success, -1 otherwise */ - public ConstantPool getConstantPool() { - return new ConstantPool(constants); + public int lookupString(final String str) { + return getIndex(stringTable, str); } - /** - * @return current size of constant pool + * Look for ConstantUtf8 in ConstantPool. + * + * @param n Utf8 string to look for + * @return index on success, -1 otherwise */ - public int getSize() { - return index; + public int lookupUtf8(final String n) { + return getIndex(utf8Table, n); } - /** - * @return constant pool with proper length + * Use with care! + * + * @param i index in constant pool + * @param c new constant pool entry at index i */ - public ConstantPool getFinalConstantPool() { - final Constant[] cs = new Constant[index]; - System.arraycopy(constants, 0, cs, 0, index); - return new ConstantPool(cs); + public void setConstant(final int i, final Constant c) { + constants[i] = c; } + private int toIndex(final Integer index) { + return index != null ? index.intValue() : -1; + } /** * @return String representation. @@ -786,64 +785,4 @@ public String toString() { } return buf.toString(); } - - - /** Import constant from another ConstantPool and return new index. - */ - public int addConstant( final Constant c, final ConstantPoolGen cp ) { - final Constant[] constants = cp.getConstantPool().getConstantPool(); - switch (c.getTag()) { - case Const.CONSTANT_String: { - final ConstantString s = (ConstantString) c; - final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; - return addString(u8.getBytes()); - } - case Const.CONSTANT_Class: { - final ConstantClass s = (ConstantClass) c; - final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; - return addClass(u8.getBytes()); - } - case Const.CONSTANT_NameAndType: { - final ConstantNameAndType n = (ConstantNameAndType) c; - final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; - final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; - return addNameAndType(u8.getBytes(), u8_2.getBytes()); - } - case Const.CONSTANT_Utf8: - return addUtf8(((ConstantUtf8) c).getBytes()); - case Const.CONSTANT_Double: - return addDouble(((ConstantDouble) c).getBytes()); - case Const.CONSTANT_Float: - return addFloat(((ConstantFloat) c).getBytes()); - case Const.CONSTANT_Long: - return addLong(((ConstantLong) c).getBytes()); - case Const.CONSTANT_Integer: - return addInteger(((ConstantInteger) c).getBytes()); - case Const.CONSTANT_InterfaceMethodref: - case Const.CONSTANT_Methodref: - case Const.CONSTANT_Fieldref: { - final ConstantCP m = (ConstantCP) c; - final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; - final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; - ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; - final String class_name = u8.getBytes().replace('/', '.'); - u8 = (ConstantUtf8) constants[n.getNameIndex()]; - final String name = u8.getBytes(); - u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; - final String signature = u8.getBytes(); - switch (c.getTag()) { - case Const.CONSTANT_InterfaceMethodref: - return addInterfaceMethodref(class_name, name, signature); - case Const.CONSTANT_Methodref: - return addMethodref(class_name, name, signature); - case Const.CONSTANT_Fieldref: - return addFieldref(class_name, name, signature); - default: // Never reached - throw new IllegalArgumentException("Unknown constant type " + c); - } - } - default: // Never reached - throw new IllegalArgumentException("Unknown constant type " + c); - } - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConstantPushInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConstantPushInstruction.java index 3d752246a59..69114bf4628 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConstantPushInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConstantPushInstruction.java @@ -22,10 +22,9 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Denotes a push instruction that produces a literal on the stack - * such as SIPUSH, BIPUSH, ICONST, etc. + * Denotes a push instruction that produces a literal on the stack such as SIPUSH, BIPUSH, ICONST, etc. + * * - * @see ICONST * @see SIPUSH */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConversionInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConversionInstruction.java index 20750fefb54..7937bbe46bc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConversionInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConversionInstruction.java @@ -25,19 +25,15 @@ /** * Super class for the x2y family of instructions. - * */ -public abstract class ConversionInstruction extends Instruction implements TypedInstruction, - StackProducer, StackConsumer { +public abstract class ConversionInstruction extends Instruction implements TypedInstruction, StackProducer, StackConsumer { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ ConversionInstruction() { } - /** * @param opcode opcode of instruction */ @@ -45,37 +41,37 @@ protected ConversionInstruction(final short opcode) { super(opcode, (short) 1); } - - /** @return type associated with the instruction + /** + * @return type associated with the instruction */ @Override - public Type getType( final ConstantPoolGen cp ) { - final short _opcode = super.getOpcode(); - switch (_opcode) { - case Const.D2I: - case Const.F2I: - case Const.L2I: - return Type.INT; - case Const.D2F: - case Const.I2F: - case Const.L2F: - return Type.FLOAT; - case Const.D2L: - case Const.F2L: - case Const.I2L: - return Type.LONG; - case Const.F2D: - case Const.I2D: - case Const.L2D: - return Type.DOUBLE; - case Const.I2B: - return Type.BYTE; - case Const.I2C: - return Type.CHAR; - case Const.I2S: - return Type.SHORT; - default: // Never reached - throw new ClassGenException("Unknown type " + _opcode); + public Type getType(final ConstantPoolGen cp) { + final short opcode = super.getOpcode(); + switch (opcode) { + case Const.D2I: + case Const.F2I: + case Const.L2I: + return Type.INT; + case Const.D2F: + case Const.I2F: + case Const.L2F: + return Type.FLOAT; + case Const.D2L: + case Const.F2L: + case Const.I2L: + return Type.LONG; + case Const.F2D: + case Const.I2D: + case Const.L2D: + return Type.DOUBLE; + case Const.I2B: + return Type.BYTE; + case Const.I2C: + return Type.CHAR; + case Const.I2S: + return Type.SHORT; + default: // Never reached + throw new ClassGenException("Unknown type " + opcode); } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/D2F.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/D2F.java index e857a41f5ee..45ee7158c3c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/D2F.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/D2F.java @@ -23,28 +23,28 @@ /** * D2F - Convert double to float - *
    Stack: ..., value.word1, value.word2 -> ..., result
    * + *
    + * Stack: ..., value.word1, value.word2 -> ..., result
    + * 
    */ public class D2F extends ConversionInstruction { - /** Convert double to float + /** + * Convert double to float */ public D2F() { super(com.sun.org.apache.bcel.internal.Const.D2F); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/D2I.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/D2I.java index 97519bb5f8a..343076d7159 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/D2I.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/D2I.java @@ -23,28 +23,28 @@ /** * D2I - Convert double to int - *
    Stack: ..., value.word1, value.word2 -> ..., result
    * + *
    + * Stack: ..., value.word1, value.word2 -> ..., result
    + * 
    */ public class D2I extends ConversionInstruction { - /** Convert double to int + /** + * Convert double to int */ public D2I() { super(com.sun.org.apache.bcel.internal.Const.D2I); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/D2L.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/D2L.java index 975eec6a39d..0a8b09c1d93 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/D2L.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/D2L.java @@ -23,28 +23,28 @@ /** * D2L - Convert double to long - *
    Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2
    * + *
    + * Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2
    + * 
    */ public class D2L extends ConversionInstruction { - /** Convert double to long + /** + * Convert double to long */ public D2L() { super(com.sun.org.apache.bcel.internal.Const.D2L); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DADD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DADD.java index 8c787b60b66..55c6e05fe5a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DADD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DADD.java @@ -23,29 +23,30 @@ /** * DADD - Add doubles - *
    Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    - * ..., result.word1, result1.word2 * + *
    + * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    + * 
    + * + * ..., result.word1, result1.word2 */ public class DADD extends ArithmeticInstruction { - /** Add doubles + /** + * Add doubles */ public DADD() { super(com.sun.org.apache.bcel.internal.Const.DADD); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DALOAD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DALOAD.java index 3f901b335d3..e875b35171b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DALOAD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DALOAD.java @@ -23,28 +23,28 @@ /** * DALOAD - Load double from array - *
    Stack: ..., arrayref, index -> ..., result.word1, result.word2
    * + *
    + * Stack: ..., arrayref, index -> ..., result.word1, result.word2
    + * 
    */ public class DALOAD extends ArrayInstruction implements StackProducer { - /** Load double from array + /** + * Load double from array */ public DALOAD() { super(com.sun.org.apache.bcel.internal.Const.DALOAD); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DASTORE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DASTORE.java index 53178fc3108..63a855900e1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DASTORE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DASTORE.java @@ -22,29 +22,29 @@ package com.sun.org.apache.bcel.internal.generic; /** - * DASTORE - Store into double array - *
    Stack: ..., arrayref, index, value.word1, value.word2 -> ...
    + * DASTORE - Store into double array * + *
    + * Stack: ..., arrayref, index, value.word1, value.word2 -> ...
    + * 
    */ public class DASTORE extends ArrayInstruction implements StackConsumer { - /** Store double into array + /** + * Store double into array */ public DASTORE() { super(com.sun.org.apache.bcel.internal.Const.DASTORE); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCMPG.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCMPG.java index 338c5906d6a..aa1353ef569 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCMPG.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCMPG.java @@ -23,8 +23,10 @@ /** * DCMPG - Compare doubles: value1 > value2 - *
    Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -> ..., result
    * + *
    + * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -> ..., result
    + * 
    */ public class DCMPG extends Instruction implements TypedInstruction, StackProducer, StackConsumer { @@ -32,26 +34,25 @@ public DCMPG() { super(com.sun.org.apache.bcel.internal.Const.DCMPG, (short) 1); } - /** @return Type.DOUBLE - */ - @Override - public Type getType( final ConstantPoolGen cp ) { - return Type.DOUBLE; - } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); v.visitDCMPG(this); } + + /** + * @return Type.DOUBLE + */ + @Override + public Type getType(final ConstantPoolGen cp) { + return Type.DOUBLE; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCMPL.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCMPL.java index e654310fe99..b43380bdbf8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCMPL.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCMPL.java @@ -23,8 +23,10 @@ /** * DCMPL - Compare doubles: value1 < value2 - *
    Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -> ..., result
    * + *
    + * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -> ..., result
    + * 
    */ public class DCMPL extends Instruction implements TypedInstruction, StackProducer, StackConsumer { @@ -32,26 +34,25 @@ public DCMPL() { super(com.sun.org.apache.bcel.internal.Const.DCMPL, (short) 1); } - /** @return Type.DOUBLE - */ - @Override - public Type getType( final ConstantPoolGen cp ) { - return Type.DOUBLE; - } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); v.visitDCMPL(this); } + + /** + * @return Type.DOUBLE + */ + @Override + public Type getType(final ConstantPoolGen cp) { + return Type.DOUBLE; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCONST.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCONST.java index 39375bd5a89..313277185fe 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCONST.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCONST.java @@ -23,23 +23,22 @@ /** * DCONST - Push 0.0 or 1.0, other values cause an exception * - *
    Stack: ... -> ..., 
    - * + *
    + * Stack: ... -> ...,
    + * 
    * @LastModified: Jan 2020 */ public class DCONST extends Instruction implements ConstantPushInstruction { - private double value; - + private final double value; /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ DCONST() { + this(0); } - public DCONST(final double f) { super(com.sun.org.apache.bcel.internal.Const.DCONST_0, (short) 1); if (f == 0.0) { @@ -52,35 +51,31 @@ public DCONST(final double f) { value = f; } - - @Override - public Number getValue() { - return value; - } - - - /** @return Type.DOUBLE - */ - @Override - public Type getType( final ConstantPoolGen cp ) { - return Type.DOUBLE; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitPushInstruction(this); v.visitStackProducer(this); v.visitTypedInstruction(this); v.visitConstantPushInstruction(this); v.visitDCONST(this); } + + /** + * @return Type.DOUBLE + */ + @Override + public Type getType(final ConstantPoolGen cp) { + return Type.DOUBLE; + } + + @Override + public Number getValue() { + return Double.valueOf(value); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DDIV.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DDIV.java index ae43ba11ace..29c008e7ccb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DDIV.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DDIV.java @@ -22,30 +22,31 @@ package com.sun.org.apache.bcel.internal.generic; /** - * DDIV - Divide doubles - *
    Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    - * ..., result.word1, result.word2 + * DDIV - Divide doubles * + *
    + * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    + * 
    + * + * ..., result.word1, result.word2 */ public class DDIV extends ArithmeticInstruction { - /** Divide doubles + /** + * Divide doubles */ public DDIV() { super(com.sun.org.apache.bcel.internal.Const.DDIV); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DLOAD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DLOAD.java index e13896bb009..9b61fd6697c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DLOAD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DLOAD.java @@ -23,38 +23,37 @@ /** * DLOAD - Load double from local variable - *
    Stack ... -> ..., result.word1, result.word2
    * + *
    + * Stack ... -> ..., result.word1, result.word2
    + * 
    */ public class DLOAD extends LoadInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ DLOAD() { super(com.sun.org.apache.bcel.internal.Const.DLOAD, com.sun.org.apache.bcel.internal.Const.DLOAD_0); } - - /** Load double from local variable + /** + * Load double from local variable + * * @param n index of local variable */ public DLOAD(final int n) { super(com.sun.org.apache.bcel.internal.Const.DLOAD, com.sun.org.apache.bcel.internal.Const.DLOAD_0, n); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { super.accept(v); v.visitDLOAD(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DMUL.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DMUL.java index 98ee17fad47..6dc65ffa082 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DMUL.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DMUL.java @@ -23,29 +23,30 @@ /** * DMUL - Multiply doubles - *
    Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    - * ..., result.word1, result.word2 * + *
    + * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    + * 
    + * + * ..., result.word1, result.word2 */ public class DMUL extends ArithmeticInstruction { - /** Multiply doubles + /** + * Multiply doubles */ public DMUL() { super(com.sun.org.apache.bcel.internal.Const.DMUL); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DNEG.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DNEG.java index 42043492537..8999f6fbaa3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DNEG.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DNEG.java @@ -23,8 +23,10 @@ /** * DNEG - Negate double - *
    Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2
    * + *
    + * Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2
    + * 
    */ public class DNEG extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public DNEG() { super(com.sun.org.apache.bcel.internal.Const.DNEG); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DREM.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DREM.java index 41ad3be2165..b478f6ca94a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DREM.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DREM.java @@ -23,29 +23,30 @@ /** * DREM - Remainder of doubles - *
    Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    - * ..., result.word1, result.word2 * + *
    + * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    + * 
    + * + * ..., result.word1, result.word2 */ public class DREM extends ArithmeticInstruction { - /** Remainder of doubles + /** + * Remainder of doubles */ public DREM() { super(com.sun.org.apache.bcel.internal.Const.DREM); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DRETURN.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DRETURN.java index 929ba33ef5f..749d92246dd 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DRETURN.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DRETURN.java @@ -22,29 +22,29 @@ package com.sun.org.apache.bcel.internal.generic; /** - * DRETURN - Return double from method - *
    Stack: ..., value.word1, value.word2 -> <empty>
    + * DRETURN - Return double from method * + *
    + * Stack: ..., value.word1, value.word2 -> <empty>
    + * 
    */ public class DRETURN extends ReturnInstruction { - /** Return double from method + /** + * Return double from method */ public DRETURN() { super(com.sun.org.apache.bcel.internal.Const.DRETURN); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DSTORE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DSTORE.java index aad12e19aeb..bd4e130c7e8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DSTORE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DSTORE.java @@ -23,38 +23,37 @@ /** * DSTORE - Store double into local variable - *
    Stack: ..., value.word1, value.word2 -> ... 
    * + *
    + * Stack: ..., value.word1, value.word2 -> ...
    + * 
    */ public class DSTORE extends StoreInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ DSTORE() { super(com.sun.org.apache.bcel.internal.Const.DSTORE, com.sun.org.apache.bcel.internal.Const.DSTORE_0); } - - /** Store double into local variable + /** + * Store double into local variable + * * @param n index of local variable */ public DSTORE(final int n) { super(com.sun.org.apache.bcel.internal.Const.DSTORE, com.sun.org.apache.bcel.internal.Const.DSTORE_0, n); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { super.accept(v); v.visitDSTORE(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DSUB.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DSUB.java index efe66fb3b43..080a325d743 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DSUB.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DSUB.java @@ -23,29 +23,30 @@ /** * DSUB - Substract doubles - *
    Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    - * ..., result.word1, result.word2 * + *
    + * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    + * 
    + * + * ..., result.word1, result.word2 */ public class DSUB extends ArithmeticInstruction { - /** Substract doubles + /** + * Substract doubles */ public DSUB() { super(com.sun.org.apache.bcel.internal.Const.DSUB); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP.java index 8f697a29d73..30cc6821c28 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP.java @@ -23,8 +23,10 @@ /** * DUP - Duplicate top operand stack word - *
    Stack: ..., word -> ..., word, word
    * + *
    + * Stack: ..., word -> ..., word, word
    + * 
    */ public class DUP extends StackInstruction implements PushInstruction { @@ -32,17 +34,14 @@ public DUP() { super(com.sun.org.apache.bcel.internal.Const.DUP); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitPushInstruction(this); v.visitStackInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP2.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP2.java index c3560979377..8b01a0606a0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP2.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP2.java @@ -23,8 +23,10 @@ /** * DUP2 - Duplicate two top operand stack words - *
    Stack: ..., word2, word1 -> ..., word2, word1, word2, word1
    * + *
    + * Stack: ..., word2, word1 -> ..., word2, word1, word2, word1
    + * 
    */ public class DUP2 extends StackInstruction implements PushInstruction { @@ -32,17 +34,14 @@ public DUP2() { super(com.sun.org.apache.bcel.internal.Const.DUP2); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitPushInstruction(this); v.visitStackInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP2_X1.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP2_X1.java index b2c90b428b1..69043ab87dc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP2_X1.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP2_X1.java @@ -23,8 +23,10 @@ /** * DUP2_X1 - Duplicate two top operand stack words and put three down - *
    Stack: ..., word3, word2, word1 -> ..., word2, word1, word3, word2, word1
    * + *
    + * Stack: ..., word3, word2, word1 -> ..., word2, word1, word3, word2, word1
    + * 
    */ public class DUP2_X1 extends StackInstruction { @@ -32,17 +34,14 @@ public DUP2_X1() { super(com.sun.org.apache.bcel.internal.Const.DUP2_X1); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackInstruction(this); v.visitDUP2_X1(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP2_X2.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP2_X2.java index 74ed06ef58b..e9b807ffc30 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP2_X2.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP2_X2.java @@ -23,8 +23,10 @@ /** * DUP2_X2 - Duplicate two top operand stack words and put four down - *
    Stack: ..., word4, word3, word2, word1 -> ..., word2, word1, word4, word3, word2, word1
    * + *
    + * Stack: ..., word4, word3, word2, word1 -> ..., word2, word1, word4, word3, word2, word1
    + * 
    */ public class DUP2_X2 extends StackInstruction { @@ -32,17 +34,14 @@ public DUP2_X2() { super(com.sun.org.apache.bcel.internal.Const.DUP2_X2); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackInstruction(this); v.visitDUP2_X2(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP_X1.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP_X1.java index 81b1e01f0db..ce2316baa88 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP_X1.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP_X1.java @@ -23,8 +23,10 @@ /** * DUP_X1 - Duplicate top operand stack word and put two down - *
    Stack: ..., word2, word1 -> ..., word1, word2, word1
    * + *
    + * Stack: ..., word2, word1 -> ..., word1, word2, word1
    + * 
    */ public class DUP_X1 extends StackInstruction { @@ -32,17 +34,14 @@ public DUP_X1() { super(com.sun.org.apache.bcel.internal.Const.DUP_X1); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackInstruction(this); v.visitDUP_X1(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP_X2.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP_X2.java index 344f0068e2f..735437e1f80 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP_X2.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DUP_X2.java @@ -23,8 +23,10 @@ /** * DUP_X2 - Duplicate top operand stack word and put three down - *
    Stack: ..., word3, word2, word1 -> ..., word1, word3, word2, word1
    * + *
    + * Stack: ..., word3, word2, word1 -> ..., word1, word3, word2, word1
    + * 
    */ public class DUP_X2 extends StackInstruction { @@ -32,17 +34,14 @@ public DUP_X2() { super(com.sun.org.apache.bcel.internal.Const.DUP_X2); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackInstruction(this); v.visitDUP_X2(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValueGen.java index cebc7c45bd2..11b6b014a05 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValueGen.java @@ -36,31 +36,7 @@ * @since 6.0 * @LastModified: May 2021 */ -public abstract class ElementValueGen -{ - private final int type; - private final ConstantPoolGen cpGen; - - protected ElementValueGen(final int type, final ConstantPoolGen cpGen) - { - this.type = type; - this.cpGen = cpGen; - } - - /** - * Subtypes return an immutable variant of the ElementValueGen - */ - public abstract ElementValue getElementValue(); - - public int getElementValueType() - { - return type; - } - - public abstract String stringifyValue(); - - public abstract void dump(DataOutputStream dos) throws IOException; - +public abstract class ElementValueGen { public static final int STRING = 's'; public static final int ENUM_CONSTANT = 'e'; @@ -87,57 +63,69 @@ public int getElementValueType() public static final int PRIMITIVE_BOOLEAN = 'Z'; - public static ElementValueGen readElementValue(final DataInput dis, - final ConstantPoolGen cpGen) throws IOException - { + /** + * Creates an (modifiable) ElementValueGen copy of an (immutable) ElementValue - constant pool is assumed correct. + */ + public static ElementValueGen copy(final ElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) { + switch (value.getElementValueType()) { + case 'B': // byte + case 'C': // char + case 'D': // double + case 'F': // float + case 'I': // int + case 'J': // long + case 'S': // short + case 'Z': // boolean + case 's': // String + return new SimpleElementValueGen((SimpleElementValue) value, cpool, copyPoolEntries); + case 'e': // Enum constant + return new EnumElementValueGen((EnumElementValue) value, cpool, copyPoolEntries); + case '@': // Annotation + return new AnnotationElementValueGen((AnnotationElementValue) value, cpool, copyPoolEntries); + case '[': // Array + return new ArrayElementValueGen((ArrayElementValue) value, cpool, copyPoolEntries); + case 'c': // Class + return new ClassElementValueGen((ClassElementValue) value, cpool, copyPoolEntries); + default: + throw new UnsupportedOperationException("Not implemented yet! (" + value.getElementValueType() + ")"); + } + } + + public static ElementValueGen readElementValue(final DataInput dis, final ConstantPoolGen cpGen) throws IOException { final int type = dis.readUnsignedByte(); - switch (type) - { + switch (type) { case 'B': // byte - return new SimpleElementValueGen(PRIMITIVE_BYTE, dis - .readUnsignedShort(), cpGen); + return new SimpleElementValueGen(PRIMITIVE_BYTE, dis.readUnsignedShort(), cpGen); case 'C': // char - return new SimpleElementValueGen(PRIMITIVE_CHAR, dis - .readUnsignedShort(), cpGen); + return new SimpleElementValueGen(PRIMITIVE_CHAR, dis.readUnsignedShort(), cpGen); case 'D': // double - return new SimpleElementValueGen(PRIMITIVE_DOUBLE, dis - .readUnsignedShort(), cpGen); + return new SimpleElementValueGen(PRIMITIVE_DOUBLE, dis.readUnsignedShort(), cpGen); case 'F': // float - return new SimpleElementValueGen(PRIMITIVE_FLOAT, dis - .readUnsignedShort(), cpGen); + return new SimpleElementValueGen(PRIMITIVE_FLOAT, dis.readUnsignedShort(), cpGen); case 'I': // int - return new SimpleElementValueGen(PRIMITIVE_INT, dis - .readUnsignedShort(), cpGen); + return new SimpleElementValueGen(PRIMITIVE_INT, dis.readUnsignedShort(), cpGen); case 'J': // long - return new SimpleElementValueGen(PRIMITIVE_LONG, dis - .readUnsignedShort(), cpGen); + return new SimpleElementValueGen(PRIMITIVE_LONG, dis.readUnsignedShort(), cpGen); case 'S': // short - return new SimpleElementValueGen(PRIMITIVE_SHORT, dis - .readUnsignedShort(), cpGen); + return new SimpleElementValueGen(PRIMITIVE_SHORT, dis.readUnsignedShort(), cpGen); case 'Z': // boolean - return new SimpleElementValueGen(PRIMITIVE_BOOLEAN, dis - .readUnsignedShort(), cpGen); + return new SimpleElementValueGen(PRIMITIVE_BOOLEAN, dis.readUnsignedShort(), cpGen); case 's': // String - return new SimpleElementValueGen(STRING, dis.readUnsignedShort(), - cpGen); + return new SimpleElementValueGen(STRING, dis.readUnsignedShort(), cpGen); case 'e': // Enum constant - return new EnumElementValueGen(dis.readUnsignedShort(), dis - .readUnsignedShort(), cpGen); + return new EnumElementValueGen(dis.readUnsignedShort(), dis.readUnsignedShort(), cpGen); case 'c': // Class return new ClassElementValueGen(dis.readUnsignedShort(), cpGen); case '@': // Annotation // TODO: isRuntimeVisible ?????????? // FIXME - return new AnnotationElementValueGen(ANNOTATION, - new AnnotationEntryGen(AnnotationEntry.read(dis, cpGen - .getConstantPool(), true), cpGen, false), cpGen); + return new AnnotationElementValueGen(ANNOTATION, new AnnotationEntryGen(AnnotationEntry.read(dis, cpGen.getConstantPool(), true), cpGen, false), + cpGen); case '[': // Array final int numArrayVals = dis.readUnsignedShort(); final ElementValue[] evalues = new ElementValue[numArrayVals]; - for (int j = 0; j < numArrayVals; j++) - { - evalues[j] = ElementValue.readElementValue(dis, cpGen - .getConstantPool()); + for (int j = 0; j < numArrayVals; j++) { + evalues[j] = ElementValue.readElementValue(dis, cpGen.getConstantPool()); } return new ArrayElementValueGen(ARRAY, evalues, cpGen); default: @@ -145,45 +133,37 @@ public static ElementValueGen readElementValue(final DataInput dis, } } - protected ConstantPoolGen getConstantPool() - { + /** + * @deprecated (since 6.0) will be made private and final; do not access directly, use getter + */ + @Deprecated + protected int type; + + /** + * @deprecated (since 6.0) will be made private and final; do not access directly, use getter + */ + @Deprecated + protected ConstantPoolGen cpGen; + + protected ElementValueGen(final int type, final ConstantPoolGen cpGen) { + this.type = type; + this.cpGen = cpGen; + } + + public abstract void dump(DataOutputStream dos) throws IOException; + + protected ConstantPoolGen getConstantPool() { return cpGen; } /** - * Creates an (modifiable) ElementValueGen copy of an (immutable) - * ElementValue - constant pool is assumed correct. + * Subtypes return an immutable variant of the ElementValueGen */ - public static ElementValueGen copy(final ElementValue value, - final ConstantPoolGen cpool, final boolean copyPoolEntries) - { - switch (value.getElementValueType()) - { - case 'B': // byte - case 'C': // char - case 'D': // double - case 'F': // float - case 'I': // int - case 'J': // long - case 'S': // short - case 'Z': // boolean - case 's': // String - return new SimpleElementValueGen((SimpleElementValue) value, cpool, - copyPoolEntries); - case 'e': // Enum constant - return new EnumElementValueGen((EnumElementValue) value, cpool, - copyPoolEntries); - case '@': // Annotation - return new AnnotationElementValueGen( - (AnnotationElementValue) value, cpool, copyPoolEntries); - case '[': // Array - return new ArrayElementValueGen((ArrayElementValue) value, cpool, - copyPoolEntries); - case 'c': // Class - return new ClassElementValueGen((ClassElementValue) value, cpool, - copyPoolEntries); - default: - throw new UnsupportedOperationException("Not implemented yet! (" + value.getElementValueType() + ")"); - } + public abstract ElementValue getElementValue(); + + public int getElementValueType() { + return type; } + + public abstract String stringifyValue(); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java index 218ea89cae0..bdc9c517a86 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java @@ -31,17 +31,14 @@ /** * @since 6.0 */ -public class ElementValuePairGen -{ - private int nameIdx; +public class ElementValuePairGen { + private final int nameIdx; private final ElementValueGen value; private final ConstantPoolGen constantPoolGen; - public ElementValuePairGen(final ElementValuePair nvp, final ConstantPoolGen cpool, - final boolean copyPoolEntries) - { + public ElementValuePairGen(final ElementValuePair nvp, final ConstantPoolGen cpool, final boolean copyPoolEntries) { this.constantPoolGen = cpool; // J5ASSERT: // Could assert nvp.getNameString() points to the same thing as @@ -51,69 +48,54 @@ public ElementValuePairGen(final ElementValuePair nvp, final ConstantPoolGen cpo // { // throw new IllegalArgumentException("envp buggered"); // } - if (copyPoolEntries) - { + if (copyPoolEntries) { nameIdx = cpool.addUtf8(nvp.getNameString()); - } - else - { + } else { nameIdx = nvp.getNameIndex(); } value = ElementValueGen.copy(nvp.getValue(), cpool, copyPoolEntries); } - /** - * Retrieve an immutable version of this ElementNameValuePairGen - */ - public ElementValuePair getElementNameValuePair() - { - final ElementValue immutableValue = value.getElementValue(); - return new ElementValuePair(nameIdx, immutableValue, constantPoolGen - .getConstantPool()); - } - - protected ElementValuePairGen(final int idx, final ElementValueGen value, - final ConstantPoolGen cpool) - { + protected ElementValuePairGen(final int idx, final ElementValueGen value, final ConstantPoolGen cpool) { this.nameIdx = idx; this.value = value; this.constantPoolGen = cpool; } - public ElementValuePairGen(final String name, final ElementValueGen value, - final ConstantPoolGen cpool) - { + public ElementValuePairGen(final String name, final ElementValueGen value, final ConstantPoolGen cpool) { this.nameIdx = cpool.addUtf8(name); this.value = value; this.constantPoolGen = cpool; } - protected void dump(final DataOutputStream dos) throws IOException - { + protected void dump(final DataOutputStream dos) throws IOException { dos.writeShort(nameIdx); // u2 name of the element value.dump(dos); } - public int getNameIndex() - { + /** + * Retrieve an immutable version of this ElementNameValuePairGen + */ + public ElementValuePair getElementNameValuePair() { + final ElementValue immutableValue = value.getElementValue(); + return new ElementValuePair(nameIdx, immutableValue, constantPoolGen.getConstantPool()); + } + + public int getNameIndex() { return nameIdx; } - public final String getNameString() - { + public final String getNameString() { // ConstantString cu8 = (ConstantString)constantPoolGen.getConstant(nameIdx); return ((ConstantUtf8) constantPoolGen.getConstant(nameIdx)).getBytes(); } - public final ElementValueGen getValue() - { + public final ElementValueGen getValue() { return value; } @Override - public String toString() - { - return "ElementValuePair:[" + getNameString() + "=" - + value.stringifyValue() + "]"; + public String toString() { + return "ElementValuePair:[" + getNameString() + "=" + value.stringifyValue() + "]"; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EmptyVisitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EmptyVisitor.java index 5ae39f2d4ad..b76944416cb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EmptyVisitor.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EmptyVisitor.java @@ -23,913 +23,733 @@ /** * Supplies empty method bodies to be overridden by subclasses. - * */ public abstract class EmptyVisitor implements Visitor { @Override - public void visitStackInstruction( final StackInstruction obj ) { + public void visitAALOAD(final AALOAD obj) { } - @Override - public void visitLocalVariableInstruction( final LocalVariableInstruction obj ) { + public void visitAASTORE(final AASTORE obj) { } - @Override - public void visitBranchInstruction( final BranchInstruction obj ) { + public void visitACONST_NULL(final ACONST_NULL obj) { } - @Override - public void visitLoadClass( final LoadClass obj ) { + public void visitAllocationInstruction(final AllocationInstruction obj) { } - @Override - public void visitFieldInstruction( final FieldInstruction obj ) { + public void visitALOAD(final ALOAD obj) { } - @Override - public void visitIfInstruction( final IfInstruction obj ) { + public void visitANEWARRAY(final ANEWARRAY obj) { } - @Override - public void visitConversionInstruction( final ConversionInstruction obj ) { + public void visitARETURN(final ARETURN obj) { } - @Override - public void visitPopInstruction( final PopInstruction obj ) { + public void visitArithmeticInstruction(final ArithmeticInstruction obj) { } - @Override - public void visitJsrInstruction( final JsrInstruction obj ) { + public void visitArrayInstruction(final ArrayInstruction obj) { } - @Override - public void visitGotoInstruction( final GotoInstruction obj ) { + public void visitARRAYLENGTH(final ARRAYLENGTH obj) { } - @Override - public void visitStoreInstruction( final StoreInstruction obj ) { + public void visitASTORE(final ASTORE obj) { } - @Override - public void visitTypedInstruction( final TypedInstruction obj ) { + public void visitATHROW(final ATHROW obj) { } - @Override - public void visitSelect( final Select obj ) { + public void visitBALOAD(final BALOAD obj) { } - @Override - public void visitUnconditionalBranch( final UnconditionalBranch obj ) { + public void visitBASTORE(final BASTORE obj) { } - @Override - public void visitPushInstruction( final PushInstruction obj ) { + public void visitBIPUSH(final BIPUSH obj) { } - @Override - public void visitArithmeticInstruction( final ArithmeticInstruction obj ) { + public void visitBranchInstruction(final BranchInstruction obj) { } - @Override - public void visitCPInstruction( final CPInstruction obj ) { + public void visitBREAKPOINT(final BREAKPOINT obj) { } - @Override - public void visitInvokeInstruction( final InvokeInstruction obj ) { + public void visitCALOAD(final CALOAD obj) { } - @Override - public void visitArrayInstruction( final ArrayInstruction obj ) { + public void visitCASTORE(final CASTORE obj) { } - @Override - public void visitAllocationInstruction( final AllocationInstruction obj ) { + public void visitCHECKCAST(final CHECKCAST obj) { } - @Override - public void visitReturnInstruction( final ReturnInstruction obj ) { + public void visitConstantPushInstruction(final ConstantPushInstruction obj) { } - @Override - public void visitFieldOrMethod( final FieldOrMethod obj ) { + public void visitConversionInstruction(final ConversionInstruction obj) { } - @Override - public void visitConstantPushInstruction( final ConstantPushInstruction obj ) { + public void visitCPInstruction(final CPInstruction obj) { } - @Override - public void visitExceptionThrower( final ExceptionThrower obj ) { + public void visitD2F(final D2F obj) { } - @Override - public void visitLoadInstruction( final LoadInstruction obj ) { + public void visitD2I(final D2I obj) { } - @Override - public void visitVariableLengthInstruction( final VariableLengthInstruction obj ) { + public void visitD2L(final D2L obj) { } - @Override - public void visitStackProducer( final StackProducer obj ) { + public void visitDADD(final DADD obj) { } - @Override - public void visitStackConsumer( final StackConsumer obj ) { + public void visitDALOAD(final DALOAD obj) { } - @Override - public void visitACONST_NULL( final ACONST_NULL obj ) { + public void visitDASTORE(final DASTORE obj) { } - @Override - public void visitGETSTATIC( final GETSTATIC obj ) { + public void visitDCMPG(final DCMPG obj) { } - @Override - public void visitIF_ICMPLT( final IF_ICMPLT obj ) { + public void visitDCMPL(final DCMPL obj) { } - @Override - public void visitMONITOREXIT( final MONITOREXIT obj ) { + public void visitDCONST(final DCONST obj) { } - @Override - public void visitIFLT( final IFLT obj ) { + public void visitDDIV(final DDIV obj) { } - @Override - public void visitLSTORE( final LSTORE obj ) { + public void visitDLOAD(final DLOAD obj) { } - @Override - public void visitPOP2( final POP2 obj ) { + public void visitDMUL(final DMUL obj) { } - @Override - public void visitBASTORE( final BASTORE obj ) { + public void visitDNEG(final DNEG obj) { } - @Override - public void visitISTORE( final ISTORE obj ) { + public void visitDREM(final DREM obj) { } - @Override - public void visitCHECKCAST( final CHECKCAST obj ) { + public void visitDRETURN(final DRETURN obj) { } - @Override - public void visitFCMPG( final FCMPG obj ) { + public void visitDSTORE(final DSTORE obj) { } - @Override - public void visitI2F( final I2F obj ) { + public void visitDSUB(final DSUB obj) { } - @Override - public void visitATHROW( final ATHROW obj ) { + public void visitDUP(final DUP obj) { } - @Override - public void visitDCMPL( final DCMPL obj ) { + public void visitDUP_X1(final DUP_X1 obj) { } - @Override - public void visitARRAYLENGTH( final ARRAYLENGTH obj ) { + public void visitDUP_X2(final DUP_X2 obj) { } - @Override - public void visitDUP( final DUP obj ) { + public void visitDUP2(final DUP2 obj) { } - @Override - public void visitINVOKESTATIC( final INVOKESTATIC obj ) { + public void visitDUP2_X1(final DUP2_X1 obj) { } - @Override - public void visitLCONST( final LCONST obj ) { + public void visitDUP2_X2(final DUP2_X2 obj) { } - @Override - public void visitDREM( final DREM obj ) { + public void visitExceptionThrower(final ExceptionThrower obj) { } - @Override - public void visitIFGE( final IFGE obj ) { + public void visitF2D(final F2D obj) { } - @Override - public void visitCALOAD( final CALOAD obj ) { + public void visitF2I(final F2I obj) { } - @Override - public void visitLASTORE( final LASTORE obj ) { + public void visitF2L(final F2L obj) { } - @Override - public void visitI2D( final I2D obj ) { + public void visitFADD(final FADD obj) { } - @Override - public void visitDADD( final DADD obj ) { + public void visitFALOAD(final FALOAD obj) { } - @Override - public void visitINVOKESPECIAL( final INVOKESPECIAL obj ) { + public void visitFASTORE(final FASTORE obj) { } - @Override - public void visitIAND( final IAND obj ) { + public void visitFCMPG(final FCMPG obj) { } - @Override - public void visitPUTFIELD( final PUTFIELD obj ) { + public void visitFCMPL(final FCMPL obj) { } - @Override - public void visitILOAD( final ILOAD obj ) { + public void visitFCONST(final FCONST obj) { } - @Override - public void visitDLOAD( final DLOAD obj ) { + public void visitFDIV(final FDIV obj) { } - @Override - public void visitDCONST( final DCONST obj ) { + public void visitFieldInstruction(final FieldInstruction obj) { } - @Override - public void visitNEW( final NEW obj ) { + public void visitFieldOrMethod(final FieldOrMethod obj) { } - @Override - public void visitIFNULL( final IFNULL obj ) { + public void visitFLOAD(final FLOAD obj) { } - @Override - public void visitLSUB( final LSUB obj ) { + public void visitFMUL(final FMUL obj) { } - @Override - public void visitL2I( final L2I obj ) { + public void visitFNEG(final FNEG obj) { } - @Override - public void visitISHR( final ISHR obj ) { + public void visitFREM(final FREM obj) { } - @Override - public void visitTABLESWITCH( final TABLESWITCH obj ) { + public void visitFRETURN(final FRETURN obj) { } - @Override - public void visitIINC( final IINC obj ) { + public void visitFSTORE(final FSTORE obj) { } - @Override - public void visitDRETURN( final DRETURN obj ) { + public void visitFSUB(final FSUB obj) { } - @Override - public void visitFSTORE( final FSTORE obj ) { + public void visitGETFIELD(final GETFIELD obj) { } - @Override - public void visitDASTORE( final DASTORE obj ) { + public void visitGETSTATIC(final GETSTATIC obj) { } - @Override - public void visitIALOAD( final IALOAD obj ) { + public void visitGOTO(final GOTO obj) { } - @Override - public void visitDDIV( final DDIV obj ) { + public void visitGOTO_W(final GOTO_W obj) { } - @Override - public void visitIF_ICMPGE( final IF_ICMPGE obj ) { + public void visitGotoInstruction(final GotoInstruction obj) { } - @Override - public void visitLAND( final LAND obj ) { + public void visitI2B(final I2B obj) { } - @Override - public void visitIDIV( final IDIV obj ) { + public void visitI2C(final I2C obj) { } - @Override - public void visitLOR( final LOR obj ) { + public void visitI2D(final I2D obj) { } - @Override - public void visitCASTORE( final CASTORE obj ) { + public void visitI2F(final I2F obj) { } - @Override - public void visitFREM( final FREM obj ) { + public void visitI2L(final I2L obj) { } - @Override - public void visitLDC( final LDC obj ) { + public void visitI2S(final I2S obj) { } - @Override - public void visitBIPUSH( final BIPUSH obj ) { + public void visitIADD(final IADD obj) { } - @Override - public void visitDSTORE( final DSTORE obj ) { + public void visitIALOAD(final IALOAD obj) { } - @Override - public void visitF2L( final F2L obj ) { + public void visitIAND(final IAND obj) { } - @Override - public void visitFMUL( final FMUL obj ) { + public void visitIASTORE(final IASTORE obj) { } - @Override - public void visitLLOAD( final LLOAD obj ) { + public void visitICONST(final ICONST obj) { } - @Override - public void visitJSR( final JSR obj ) { + public void visitIDIV(final IDIV obj) { } - @Override - public void visitFSUB( final FSUB obj ) { + public void visitIF_ACMPEQ(final IF_ACMPEQ obj) { } - @Override - public void visitSASTORE( final SASTORE obj ) { + public void visitIF_ACMPNE(final IF_ACMPNE obj) { } - @Override - public void visitALOAD( final ALOAD obj ) { + public void visitIF_ICMPEQ(final IF_ICMPEQ obj) { } - @Override - public void visitDUP2_X2( final DUP2_X2 obj ) { + public void visitIF_ICMPGE(final IF_ICMPGE obj) { } - @Override - public void visitRETURN( final RETURN obj ) { + public void visitIF_ICMPGT(final IF_ICMPGT obj) { } - @Override - public void visitDALOAD( final DALOAD obj ) { + public void visitIF_ICMPLE(final IF_ICMPLE obj) { } - @Override - public void visitSIPUSH( final SIPUSH obj ) { + public void visitIF_ICMPLT(final IF_ICMPLT obj) { } - @Override - public void visitDSUB( final DSUB obj ) { + public void visitIF_ICMPNE(final IF_ICMPNE obj) { } - @Override - public void visitL2F( final L2F obj ) { + public void visitIFEQ(final IFEQ obj) { } - @Override - public void visitIF_ICMPGT( final IF_ICMPGT obj ) { + public void visitIFGE(final IFGE obj) { } - @Override - public void visitF2D( final F2D obj ) { + public void visitIFGT(final IFGT obj) { } - @Override - public void visitI2L( final I2L obj ) { + public void visitIfInstruction(final IfInstruction obj) { } - @Override - public void visitIF_ACMPNE( final IF_ACMPNE obj ) { + public void visitIFLE(final IFLE obj) { } - @Override - public void visitPOP( final POP obj ) { + public void visitIFLT(final IFLT obj) { } - @Override - public void visitI2S( final I2S obj ) { + public void visitIFNE(final IFNE obj) { } - @Override - public void visitIFEQ( final IFEQ obj ) { + public void visitIFNONNULL(final IFNONNULL obj) { } - @Override - public void visitSWAP( final SWAP obj ) { + public void visitIFNULL(final IFNULL obj) { } - @Override - public void visitIOR( final IOR obj ) { + public void visitIINC(final IINC obj) { } - @Override - public void visitIREM( final IREM obj ) { + public void visitILOAD(final ILOAD obj) { } - @Override - public void visitIASTORE( final IASTORE obj ) { + public void visitIMPDEP1(final IMPDEP1 obj) { } - @Override - public void visitNEWARRAY( final NEWARRAY obj ) { + public void visitIMPDEP2(final IMPDEP2 obj) { } - @Override - public void visitINVOKEINTERFACE( final INVOKEINTERFACE obj ) { + public void visitIMUL(final IMUL obj) { } - @Override - public void visitINEG( final INEG obj ) { + public void visitINEG(final INEG obj) { } - @Override - public void visitLCMP( final LCMP obj ) { + public void visitINSTANCEOF(final INSTANCEOF obj) { } - + /** + * @since 6.0 + */ @Override - public void visitJSR_W( final JSR_W obj ) { + public void visitINVOKEDYNAMIC(final INVOKEDYNAMIC obj) { } - @Override - public void visitMULTIANEWARRAY( final MULTIANEWARRAY obj ) { + public void visitInvokeInstruction(final InvokeInstruction obj) { } - @Override - public void visitDUP_X2( final DUP_X2 obj ) { + public void visitINVOKEINTERFACE(final INVOKEINTERFACE obj) { } - @Override - public void visitSALOAD( final SALOAD obj ) { + public void visitINVOKESPECIAL(final INVOKESPECIAL obj) { } - @Override - public void visitIFNONNULL( final IFNONNULL obj ) { + public void visitINVOKESTATIC(final INVOKESTATIC obj) { } - @Override - public void visitDMUL( final DMUL obj ) { + public void visitINVOKEVIRTUAL(final INVOKEVIRTUAL obj) { } - @Override - public void visitIFNE( final IFNE obj ) { + public void visitIOR(final IOR obj) { } - @Override - public void visitIF_ICMPLE( final IF_ICMPLE obj ) { + public void visitIREM(final IREM obj) { } - @Override - public void visitLDC2_W( final LDC2_W obj ) { + public void visitIRETURN(final IRETURN obj) { } - @Override - public void visitGETFIELD( final GETFIELD obj ) { + public void visitISHL(final ISHL obj) { } - @Override - public void visitLADD( final LADD obj ) { + public void visitISHR(final ISHR obj) { } - @Override - public void visitNOP( final NOP obj ) { + public void visitISTORE(final ISTORE obj) { } - @Override - public void visitFALOAD( final FALOAD obj ) { + public void visitISUB(final ISUB obj) { } - @Override - public void visitINSTANCEOF( final INSTANCEOF obj ) { + public void visitIUSHR(final IUSHR obj) { } - @Override - public void visitIFLE( final IFLE obj ) { + public void visitIXOR(final IXOR obj) { } - @Override - public void visitLXOR( final LXOR obj ) { + public void visitJSR(final JSR obj) { } - @Override - public void visitLRETURN( final LRETURN obj ) { + public void visitJSR_W(final JSR_W obj) { } - @Override - public void visitFCONST( final FCONST obj ) { + public void visitJsrInstruction(final JsrInstruction obj) { } - @Override - public void visitIUSHR( final IUSHR obj ) { + public void visitL2D(final L2D obj) { } - @Override - public void visitBALOAD( final BALOAD obj ) { + public void visitL2F(final L2F obj) { } - @Override - public void visitDUP2( final DUP2 obj ) { + public void visitL2I(final L2I obj) { } - @Override - public void visitIF_ACMPEQ( final IF_ACMPEQ obj ) { + public void visitLADD(final LADD obj) { } - @Override - public void visitIMPDEP1( final IMPDEP1 obj ) { + public void visitLALOAD(final LALOAD obj) { } - @Override - public void visitMONITORENTER( final MONITORENTER obj ) { + public void visitLAND(final LAND obj) { } - @Override - public void visitLSHL( final LSHL obj ) { + public void visitLASTORE(final LASTORE obj) { } - @Override - public void visitDCMPG( final DCMPG obj ) { + public void visitLCMP(final LCMP obj) { } - @Override - public void visitD2L( final D2L obj ) { + public void visitLCONST(final LCONST obj) { } - @Override - public void visitIMPDEP2( final IMPDEP2 obj ) { + public void visitLDC(final LDC obj) { } - @Override - public void visitL2D( final L2D obj ) { + public void visitLDC2_W(final LDC2_W obj) { } - @Override - public void visitRET( final RET obj ) { + public void visitLDIV(final LDIV obj) { } - @Override - public void visitIFGT( final IFGT obj ) { + public void visitLLOAD(final LLOAD obj) { } - @Override - public void visitIXOR( final IXOR obj ) { + public void visitLMUL(final LMUL obj) { } - @Override - public void visitINVOKEVIRTUAL( final INVOKEVIRTUAL obj ) { + public void visitLNEG(final LNEG obj) { } - @Override - public void visitFASTORE( final FASTORE obj ) { + public void visitLoadClass(final LoadClass obj) { } - @Override - public void visitIRETURN( final IRETURN obj ) { + public void visitLoadInstruction(final LoadInstruction obj) { } - @Override - public void visitIF_ICMPNE( final IF_ICMPNE obj ) { + public void visitLocalVariableInstruction(final LocalVariableInstruction obj) { } - @Override - public void visitFLOAD( final FLOAD obj ) { + public void visitLOOKUPSWITCH(final LOOKUPSWITCH obj) { } - @Override - public void visitLDIV( final LDIV obj ) { + public void visitLOR(final LOR obj) { } - @Override - public void visitPUTSTATIC( final PUTSTATIC obj ) { + public void visitLREM(final LREM obj) { } - @Override - public void visitAALOAD( final AALOAD obj ) { + public void visitLRETURN(final LRETURN obj) { } - @Override - public void visitD2I( final D2I obj ) { + public void visitLSHL(final LSHL obj) { } - @Override - public void visitIF_ICMPEQ( final IF_ICMPEQ obj ) { + public void visitLSHR(final LSHR obj) { } - @Override - public void visitAASTORE( final AASTORE obj ) { + public void visitLSTORE(final LSTORE obj) { } - @Override - public void visitARETURN( final ARETURN obj ) { + public void visitLSUB(final LSUB obj) { } - @Override - public void visitDUP2_X1( final DUP2_X1 obj ) { + public void visitLUSHR(final LUSHR obj) { } - @Override - public void visitFNEG( final FNEG obj ) { + public void visitLXOR(final LXOR obj) { } - @Override - public void visitGOTO_W( final GOTO_W obj ) { + public void visitMONITORENTER(final MONITORENTER obj) { } - @Override - public void visitD2F( final D2F obj ) { + public void visitMONITOREXIT(final MONITOREXIT obj) { } - @Override - public void visitGOTO( final GOTO obj ) { + public void visitMULTIANEWARRAY(final MULTIANEWARRAY obj) { } - @Override - public void visitISUB( final ISUB obj ) { + public void visitNEW(final NEW obj) { } - @Override - public void visitF2I( final F2I obj ) { + public void visitNEWARRAY(final NEWARRAY obj) { } - @Override - public void visitDNEG( final DNEG obj ) { + public void visitNOP(final NOP obj) { } - @Override - public void visitICONST( final ICONST obj ) { + public void visitPOP(final POP obj) { } - @Override - public void visitFDIV( final FDIV obj ) { + public void visitPOP2(final POP2 obj) { } - @Override - public void visitI2B( final I2B obj ) { + public void visitPopInstruction(final PopInstruction obj) { } - @Override - public void visitLNEG( final LNEG obj ) { + public void visitPushInstruction(final PushInstruction obj) { } - @Override - public void visitLREM( final LREM obj ) { + public void visitPUTFIELD(final PUTFIELD obj) { } - @Override - public void visitIMUL( final IMUL obj ) { + public void visitPUTSTATIC(final PUTSTATIC obj) { } - @Override - public void visitIADD( final IADD obj ) { + public void visitRET(final RET obj) { } - @Override - public void visitLSHR( final LSHR obj ) { + public void visitRETURN(final RETURN obj) { } - @Override - public void visitLOOKUPSWITCH( final LOOKUPSWITCH obj ) { + public void visitReturnInstruction(final ReturnInstruction obj) { } - @Override - public void visitDUP_X1( final DUP_X1 obj ) { + public void visitSALOAD(final SALOAD obj) { } - @Override - public void visitFCMPL( final FCMPL obj ) { + public void visitSASTORE(final SASTORE obj) { } - @Override - public void visitI2C( final I2C obj ) { + public void visitSelect(final Select obj) { } - @Override - public void visitLMUL( final LMUL obj ) { + public void visitSIPUSH(final SIPUSH obj) { } - @Override - public void visitLUSHR( final LUSHR obj ) { + public void visitStackConsumer(final StackConsumer obj) { } - @Override - public void visitISHL( final ISHL obj ) { + public void visitStackInstruction(final StackInstruction obj) { } - @Override - public void visitLALOAD( final LALOAD obj ) { + public void visitStackProducer(final StackProducer obj) { } - @Override - public void visitASTORE( final ASTORE obj ) { + public void visitStoreInstruction(final StoreInstruction obj) { } - @Override - public void visitANEWARRAY( final ANEWARRAY obj ) { + public void visitSWAP(final SWAP obj) { } - @Override - public void visitFRETURN( final FRETURN obj ) { + public void visitTABLESWITCH(final TABLESWITCH obj) { } - @Override - public void visitFADD( final FADD obj ) { + public void visitTypedInstruction(final TypedInstruction obj) { } - @Override - public void visitBREAKPOINT( final BREAKPOINT obj ) { + public void visitUnconditionalBranch(final UnconditionalBranch obj) { } - /** - * @since 6.0 - */ @Override - public void visitINVOKEDYNAMIC(final INVOKEDYNAMIC obj) { + public void visitVariableLengthInstruction(final VariableLengthInstruction obj) { } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java index 13958521398..95ac794f2d7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java @@ -31,103 +31,73 @@ /** * @since 6.0 */ -public class EnumElementValueGen extends ElementValueGen -{ +public class EnumElementValueGen extends ElementValueGen { // For enum types, these two indices point to the type and value - private int typeIdx; + private final int typeIdx; - private int valueIdx; + private final int valueIdx; + + public EnumElementValueGen(final EnumElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) { + super(ENUM_CONSTANT, cpool); + if (copyPoolEntries) { + typeIdx = cpool.addUtf8(value.getEnumTypeString());// was + // addClass(value.getEnumTypeString()); + valueIdx = cpool.addUtf8(value.getEnumValueString()); // was + // addString(value.getEnumValueString()); + } else { + typeIdx = value.getTypeIndex(); + valueIdx = value.getValueIndex(); + } + } /** - * This ctor assumes the constant pool already contains the right type and - * value - as indicated by typeIdx and valueIdx. This ctor is used for - * deserialization + * This ctor assumes the constant pool already contains the right type and value - as indicated by typeIdx and valueIdx. + * This ctor is used for deserialization */ - protected EnumElementValueGen(final int typeIdx, final int valueIdx, - final ConstantPoolGen cpool) - { + protected EnumElementValueGen(final int typeIdx, final int valueIdx, final ConstantPoolGen cpool) { super(ElementValueGen.ENUM_CONSTANT, cpool); if (super.getElementValueType() != ENUM_CONSTANT) { - throw new IllegalArgumentException( - "Only element values of type enum can be built with this ctor - type specified: " - + super.getElementValueType()); + throw new IllegalArgumentException("Only element values of type enum can be built with this ctor - type specified: " + super.getElementValueType()); } this.typeIdx = typeIdx; this.valueIdx = valueIdx; } - /** - * Return immutable variant of this EnumElementValue - */ - @Override - public ElementValue getElementValue() - { - System.err.println("Duplicating value: " + getEnumTypeString() + ":" - + getEnumValueString()); - return new EnumElementValue(super.getElementValueType(), typeIdx, valueIdx, - getConstantPool().getConstantPool()); - } - - public EnumElementValueGen(final ObjectType t, final String value, final ConstantPoolGen cpool) - { + public EnumElementValueGen(final ObjectType t, final String value, final ConstantPoolGen cpool) { super(ElementValueGen.ENUM_CONSTANT, cpool); typeIdx = cpool.addUtf8(t.getSignature());// was addClass(t); valueIdx = cpool.addUtf8(value);// was addString(value); } - public EnumElementValueGen(final EnumElementValue value, final ConstantPoolGen cpool, - final boolean copyPoolEntries) - { - super(ENUM_CONSTANT, cpool); - if (copyPoolEntries) - { - typeIdx = cpool.addUtf8(value.getEnumTypeString());// was - // addClass(value.getEnumTypeString()); - valueIdx = cpool.addUtf8(value.getEnumValueString()); // was - // addString(value.getEnumValueString()); - } - else - { - typeIdx = value.getTypeIndex(); - valueIdx = value.getValueIndex(); - } - } - @Override - public void dump(final DataOutputStream dos) throws IOException - { + public void dump(final DataOutputStream dos) throws IOException { dos.writeByte(super.getElementValueType()); // u1 type of value (ENUM_CONSTANT == 'e') dos.writeShort(typeIdx); // u2 dos.writeShort(valueIdx); // u2 } + /** + * Return immutable variant of this EnumElementValue + */ @Override - public String stringifyValue() - { - final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(valueIdx); - return cu8.getBytes(); - // ConstantString cu8 = - // (ConstantString)getConstantPool().getConstant(valueIdx); - // return - // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); + public ElementValue getElementValue() { + System.err.println("Duplicating value: " + getEnumTypeString() + ":" + getEnumValueString()); + return new EnumElementValue(super.getElementValueType(), typeIdx, valueIdx, getConstantPool().getConstantPool()); } // BCELBUG: Should we need to call utility.signatureToString() on the output // here? - public String getEnumTypeString() - { + public String getEnumTypeString() { // Constant cc = getConstantPool().getConstant(typeIdx); // ConstantClass cu8 = // (ConstantClass)getConstantPool().getConstant(typeIdx); // return // ((ConstantUtf8)getConstantPool().getConstant(cu8.getNameIndex())).getBytes(); - return ((ConstantUtf8) getConstantPool().getConstant(typeIdx)) - .getBytes(); + return ((ConstantUtf8) getConstantPool().getConstant(typeIdx)).getBytes(); // return Utility.signatureToString(cu8.getBytes()); } - public String getEnumValueString() - { + public String getEnumValueString() { return ((ConstantUtf8) getConstantPool().getConstant(valueIdx)).getBytes(); // ConstantString cu8 = // (ConstantString)getConstantPool().getConstant(valueIdx); @@ -135,13 +105,21 @@ public String getEnumValueString() // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); } - public int getValueIndex() - { + public int getTypeIndex() { + return typeIdx; + } + + public int getValueIndex() { return valueIdx; } - public int getTypeIndex() - { - return typeIdx; + @Override + public String stringifyValue() { + final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(valueIdx); + return cu8.getBytes(); + // ConstantString cu8 = + // (ConstantString)getConstantPool().getConstant(valueIdx); + // return + // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java index 9d6adb4e6c3..86a0cad256c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java @@ -22,24 +22,17 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Denote an instruction that may throw a run-time or a linking - * exception (or both) during execution. This is not quite the truth - * as such; because all instructions may throw an - * java.lang.VirtualMachineError. These exceptions are omitted. + * Denote an instruction that may throw a run-time or a linking exception (or both) during execution. This is not quite + * the truth as such; because all instructions may throw an java.lang.VirtualMachineError. These exceptions are omitted. * - * The Lava Language Specification specifies exactly which - * RUN-TIME and which LINKING exceptions each - * instruction may throw which is reflected by the implementers. Due - * to the structure of the JVM specification, it may be possible that - * an Instruction implementing this interface returns a Class[] of - * size 0. - * - * Please note that we speak of an "exception" here when we mean any - * "Throwable" object; so this term is equally used for "Exception" - * and "Error" objects. + * The Lava Language Specification specifies exactly which RUN-TIME and which LINKING exceptions each + * instruction may throw which is reflected by the implementers. Due to the structure of the JVM specification, it may + * be possible that an Instruction implementing this interface returns a Class[] of size 0. * + * Please note that we speak of an "exception" here when we mean any "Throwable" object; so this term is equally used + * for "Exception" and "Error" objects. */ public interface ExceptionThrower { - java.lang.Class[] getExceptions(); + Class[] getExceptions(); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/F2D.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/F2D.java index a49d9bb7b18..3697ae379d5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/F2D.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/F2D.java @@ -23,28 +23,28 @@ /** * F2D - Convert float to double - *
    Stack: ..., value -> ..., result.word1, result.word2
    * + *
    + * Stack: ..., value -> ..., result.word1, result.word2
    + * 
    */ public class F2D extends ConversionInstruction { - /** Convert float to double + /** + * Convert float to double */ public F2D() { super(com.sun.org.apache.bcel.internal.Const.F2D); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/F2I.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/F2I.java index f3bd65485ef..552ab176a29 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/F2I.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/F2I.java @@ -23,28 +23,28 @@ /** * F2I - Convert float to int - *
    Stack: ..., value -> ..., result
    * + *
    + * Stack: ..., value -> ..., result
    + * 
    */ public class F2I extends ConversionInstruction { - /** Convert float to int + /** + * Convert float to int */ public F2I() { super(com.sun.org.apache.bcel.internal.Const.F2I); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/F2L.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/F2L.java index 8d0ed680c1b..73b4edf7a2c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/F2L.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/F2L.java @@ -23,28 +23,28 @@ /** * F2L - Convert float to long - *
    Stack: ..., value -> ..., result.word1, result.word2
    * + *
    + * Stack: ..., value -> ..., result.word1, result.word2
    + * 
    */ public class F2L extends ConversionInstruction { - /** Convert float to long + /** + * Convert float to long */ public F2L() { super(com.sun.org.apache.bcel.internal.Const.F2L); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FADD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FADD.java index e89d1a4f6e6..a1e4e466b15 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FADD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FADD.java @@ -23,28 +23,28 @@ /** * FADD - Add floats - *
    Stack: ..., value1, value2 -> result
    * + *
    + * Stack: ..., value1, value2 -> result
    + * 
    */ public class FADD extends ArithmeticInstruction { - /** Add floats + /** + * Add floats */ public FADD() { super(com.sun.org.apache.bcel.internal.Const.FADD); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FALOAD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FALOAD.java index be3b8f07ab7..7d00b4c5764 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FALOAD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FALOAD.java @@ -23,28 +23,28 @@ /** * FALOAD - Load float from array - *
    Stack: ..., arrayref, index -> ..., value
    * + *
    + * Stack: ..., arrayref, index -> ..., value
    + * 
    */ public class FALOAD extends ArrayInstruction implements StackProducer { - /** Load float from array + /** + * Load float from array */ public FALOAD() { super(com.sun.org.apache.bcel.internal.Const.FALOAD); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FASTORE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FASTORE.java index 9d0c0685c02..0215fd74bef 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FASTORE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FASTORE.java @@ -22,29 +22,29 @@ package com.sun.org.apache.bcel.internal.generic; /** - * FASTORE - Store into float array - *
    Stack: ..., arrayref, index, value -> ...
    + * FASTORE - Store into float array * + *
    + * Stack: ..., arrayref, index, value -> ...
    + * 
    */ public class FASTORE extends ArrayInstruction implements StackConsumer { - /** Store float into array + /** + * Store float into array */ public FASTORE() { super(com.sun.org.apache.bcel.internal.Const.FASTORE); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCMPG.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCMPG.java index 24b2655f05f..bbeb1e2ed23 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCMPG.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCMPG.java @@ -23,8 +23,10 @@ /** * FCMPG - Compare floats: value1 > value2 - *
    Stack: ..., value1, value2 -> ..., result
    * + *
    + * Stack: ..., value1, value2 -> ..., result
    + * 
    */ public class FCMPG extends Instruction implements TypedInstruction, StackProducer, StackConsumer { @@ -32,28 +34,25 @@ public FCMPG() { super(com.sun.org.apache.bcel.internal.Const.FCMPG, (short) 1); } - - /** @return Type.FLOAT - */ - @Override - public Type getType( final ConstantPoolGen cp ) { - return Type.FLOAT; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); v.visitFCMPG(this); } + + /** + * @return Type.FLOAT + */ + @Override + public Type getType(final ConstantPoolGen cp) { + return Type.FLOAT; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCMPL.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCMPL.java index 5d4cf811e83..0b7cec09388 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCMPL.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCMPL.java @@ -23,8 +23,10 @@ /** * FCMPL - Compare floats: value1 < value2 - *
    Stack: ..., value1, value2 -> ..., result
    * + *
    + * Stack: ..., value1, value2 -> ..., result
    + * 
    */ public class FCMPL extends Instruction implements TypedInstruction, StackProducer, StackConsumer { @@ -32,28 +34,25 @@ public FCMPL() { super(com.sun.org.apache.bcel.internal.Const.FCMPL, (short) 1); } - - /** @return Type.FLOAT - */ - @Override - public Type getType( final ConstantPoolGen cp ) { - return Type.FLOAT; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); v.visitFCMPL(this); } + + /** + * @return Type.FLOAT + */ + @Override + public Type getType(final ConstantPoolGen cp) { + return Type.FLOAT; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCONST.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCONST.java index 717ace5abfb..7c8116e8cbf 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCONST.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCONST.java @@ -23,23 +23,22 @@ /** * FCONST - Push 0.0, 1.0 or 2.0, other values cause an exception * - *
    Stack: ... -> ..., 
    - * + *
    + * Stack: ... -> ...,
    + * 
    * @LastModified: Jan 2020 */ public class FCONST extends Instruction implements ConstantPushInstruction { - private float value; - + private final float value; /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ FCONST() { + this(0); } - public FCONST(final float f) { super(com.sun.org.apache.bcel.internal.Const.FCONST_0, (short) 1); if (f == 0.0) { @@ -54,35 +53,31 @@ public FCONST(final float f) { value = f; } - - @Override - public Number getValue() { - return value; - } - - - /** @return Type.FLOAT - */ - @Override - public Type getType( final ConstantPoolGen cp ) { - return Type.FLOAT; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitPushInstruction(this); v.visitStackProducer(this); v.visitTypedInstruction(this); v.visitConstantPushInstruction(this); v.visitFCONST(this); } + + /** + * @return Type.FLOAT + */ + @Override + public Type getType(final ConstantPoolGen cp) { + return Type.FLOAT; + } + + @Override + public Number getValue() { + return Float.valueOf(value); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FDIV.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FDIV.java index 720709b47a4..010c9d9960a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FDIV.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FDIV.java @@ -23,28 +23,28 @@ /** * FDIV - Divide floats - *
    Stack: ..., value1, value2 -> result
    * + *
    + * Stack: ..., value1, value2 -> result
    + * 
    */ public class FDIV extends ArithmeticInstruction { - /** Divide floats + /** + * Divide floats */ public FDIV() { super(com.sun.org.apache.bcel.internal.Const.FDIV); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FLOAD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FLOAD.java index 8fecdd219ce..e8abc13d642 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FLOAD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FLOAD.java @@ -23,38 +23,37 @@ /** * FLOAD - Load float from local variable - *
    Stack ... -> ..., result
    * + *
    + * Stack ... -> ..., result
    + * 
    */ public class FLOAD extends LoadInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ FLOAD() { super(com.sun.org.apache.bcel.internal.Const.FLOAD, com.sun.org.apache.bcel.internal.Const.FLOAD_0); } - - /** Load float from local variable + /** + * Load float from local variable + * * @param n index of local variable */ public FLOAD(final int n) { super(com.sun.org.apache.bcel.internal.Const.FLOAD, com.sun.org.apache.bcel.internal.Const.FLOAD_0, n); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { super.accept(v); v.visitFLOAD(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FMUL.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FMUL.java index e6c7cbcc9a4..a1d67147755 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FMUL.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FMUL.java @@ -23,28 +23,28 @@ /** * FMUL - Multiply floats - *
    Stack: ..., value1, value2 -> result
    * + *
    + * Stack: ..., value1, value2 -> result
    + * 
    */ public class FMUL extends ArithmeticInstruction { - /** Multiply floats + /** + * Multiply floats */ public FMUL() { super(com.sun.org.apache.bcel.internal.Const.FMUL); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FNEG.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FNEG.java index 55311300005..eb134d9940f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FNEG.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FNEG.java @@ -23,8 +23,10 @@ /** * FNEG - Negate float - *
    Stack: ..., value -> ..., result
    * + *
    + * Stack: ..., value -> ..., result
    + * 
    */ public class FNEG extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public FNEG() { super(com.sun.org.apache.bcel.internal.Const.FNEG); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FREM.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FREM.java index aa65abb8aef..39e0740cfbc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FREM.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FREM.java @@ -23,28 +23,28 @@ /** * FREM - Remainder of floats - *
    Stack: ..., value1, value2 -> result
    * + *
    + * Stack: ..., value1, value2 -> result
    + * 
    */ public class FREM extends ArithmeticInstruction { - /** Remainder of floats + /** + * Remainder of floats */ public FREM() { super(com.sun.org.apache.bcel.internal.Const.FREM); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FRETURN.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FRETURN.java index d232625f7cb..3f7ba0c9a75 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FRETURN.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FRETURN.java @@ -22,29 +22,29 @@ package com.sun.org.apache.bcel.internal.generic; /** - * FRETURN - Return float from method - *
    Stack: ..., value -> <empty>
    + * FRETURN - Return float from method * + *
    + * Stack: ..., value -> <empty>
    + * 
    */ public class FRETURN extends ReturnInstruction { - /** Return float from method + /** + * Return float from method */ public FRETURN() { super(com.sun.org.apache.bcel.internal.Const.FRETURN); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FSTORE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FSTORE.java index eb366e3a203..868f9211f03 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FSTORE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FSTORE.java @@ -23,38 +23,37 @@ /** * FSTORE - Store float into local variable - *
    Stack: ..., value -> ... 
    * + *
    + * Stack: ..., value -> ...
    + * 
    */ public class FSTORE extends StoreInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ FSTORE() { super(com.sun.org.apache.bcel.internal.Const.FSTORE, com.sun.org.apache.bcel.internal.Const.FSTORE_0); } - - /** Store float into local variable + /** + * Store float into local variable + * * @param n index of local variable */ public FSTORE(final int n) { super(com.sun.org.apache.bcel.internal.Const.FSTORE, com.sun.org.apache.bcel.internal.Const.FSTORE_0, n); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { super.accept(v); v.visitFSTORE(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FSUB.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FSUB.java index ecb791b4398..9f2a3607a3d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FSUB.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FSUB.java @@ -23,28 +23,28 @@ /** * FSUB - Substract floats - *
    Stack: ..., value1, value2 -> result
    * + *
    + * Stack: ..., value1, value2 -> result
    + * 
    */ public class FSUB extends ArithmeticInstruction { - /** Substract floats + /** + * Substract floats */ public FSUB() { super(com.sun.org.apache.bcel.internal.Const.FSUB); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java index 78af8b698e0..9d1f4d41d93 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java @@ -22,9 +22,9 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.stream.Stream; import com.sun.org.apache.bcel.internal.Const; -import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry; import com.sun.org.apache.bcel.internal.classfile.Annotations; import com.sun.org.apache.bcel.internal.classfile.Attribute; import com.sun.org.apache.bcel.internal.classfile.Constant; @@ -36,52 +36,47 @@ import com.sun.org.apache.bcel.internal.util.BCELComparator; /** - * Template class for building up a field. The only extraordinary thing - * one can do is to add a constant value attribute to a field (which must of - * course be compatible with to the declared type). + * Template class for building up a field. The only extraordinary thing one can do is to add a constant value attribute + * to a field (which must of course be compatible with to the declared type). * * @see Field * @LastModified: May 2021 */ public class FieldGen extends FieldGenOrMethodGen { - private Object value = null; private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals( final Object o1, final Object o2 ) { + public boolean equals(final Object o1, final Object o2) { final FieldGen THIS = (FieldGen) o1; final FieldGen THAT = (FieldGen) o2; - return Objects.equals(THIS.getName(), THAT.getName()) - && Objects.equals(THIS.getSignature(), THAT.getSignature()); + return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature()); } - @Override - public int hashCode( final Object o ) { + public int hashCode(final Object o) { final FieldGen THIS = (FieldGen) o; return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); } }; + /** + * @return Comparison strategy object + */ + public static BCELComparator getComparator() { + return bcelComparator; + } /** - * Declare a field. If it is static (isStatic() == true) and has a - * basic type like int or String it may have an initial value - * associated with it as defined by setInitValue(). - * - * @param access_flags access qualifiers - * @param type field type - * @param name field name - * @param cp constant pool + * @param comparator Comparison strategy object */ - public FieldGen(final int access_flags, final Type type, final String name, final ConstantPoolGen cp) { - super(access_flags); - setType(type); - setName(name); - setConstantPool(cp); + public static void setComparator(final BCELComparator comparator) { + bcelComparator = comparator; } + private Object value; + + private List observers; /** * Instantiate from existing field. @@ -96,109 +91,73 @@ public FieldGen(final Field field, final ConstantPoolGen cp) { if (attr instanceof ConstantValue) { setValue(((ConstantValue) attr).getConstantValueIndex()); } else if (attr instanceof Annotations) { - final Annotations runtimeAnnotations = (Annotations)attr; - final AnnotationEntry[] annotationEntries = runtimeAnnotations.getAnnotationEntries(); - for (final AnnotationEntry element : annotationEntries) { - addAnnotationEntry(new AnnotationEntryGen(element,cp,false)); - } + final Annotations runtimeAnnotations = (Annotations) attr; + runtimeAnnotations.forEach(element -> addAnnotationEntry(new AnnotationEntryGen(element, cp, false))); } else { addAttribute(attr); } } } - - private void setValue( final int index ) { - final ConstantPool cp = super.getConstantPool().getConstantPool(); - final Constant c = cp.getConstant(index); - value = ((ConstantObject) c).getConstantValue(cp); - } - - /** - * Set (optional) initial value of field, otherwise it will be set to null/0/false - * by the JVM automatically. + * Declare a field. If it is static (isStatic() == true) and has a basic type like int or String it may have an initial + * value associated with it as defined by setInitValue(). + * + * @param accessFlags access qualifiers + * @param type field type + * @param name field name + * @param cp constant pool */ - public void setInitValue( final String str ) { - checkType( ObjectType.getInstance("java.lang.String")); - if (str != null) { - value = str; - } - } - - - public void setInitValue( final long l ) { - checkType(Type.LONG); - if (l != 0L) { - value = Long.valueOf(l); - } - } - - - public void setInitValue( final int i ) { - checkType(Type.INT); - if (i != 0) { - value = Integer.valueOf(i); - } - } - - - public void setInitValue( final short s ) { - checkType(Type.SHORT); - if (s != 0) { - value = Integer.valueOf(s); - } - } - - - public void setInitValue( final char c ) { - checkType(Type.CHAR); - if (c != 0) { - value = Integer.valueOf(c); - } - } - - - public void setInitValue( final byte b ) { - checkType(Type.BYTE); - if (b != 0) { - value = Integer.valueOf(b); - } + public FieldGen(final int accessFlags, final Type type, final String name, final ConstantPoolGen cp) { + super(accessFlags); + setType(type); + setName(name); + setConstantPool(cp); } - - public void setInitValue( final boolean b ) { - checkType(Type.BOOLEAN); - if (b) { - value = Integer.valueOf(1); - } + private void addAnnotationsAsAttribute(final ConstantPoolGen cp) { + Stream.of(AnnotationEntryGen.getAnnotationAttributes(cp, super.getAnnotationEntries())).forEach(this::addAttribute); } - - public void setInitValue( final float f ) { - checkType(Type.FLOAT); - if (f != 0.0) { - value = f; + private int addConstant() { + switch (super.getType().getType()) { // sic + case Const.T_INT: + case Const.T_CHAR: + case Const.T_BYTE: + case Const.T_BOOLEAN: + case Const.T_SHORT: + return super.getConstantPool().addInteger(((Integer) value).intValue()); + case Const.T_FLOAT: + return super.getConstantPool().addFloat(((Float) value).floatValue()); + case Const.T_DOUBLE: + return super.getConstantPool().addDouble(((Double) value).doubleValue()); + case Const.T_LONG: + return super.getConstantPool().addLong(((Long) value).longValue()); + case Const.T_REFERENCE: + return super.getConstantPool().addString((String) value); + default: + throw new IllegalStateException("Unhandled : " + super.getType().getType()); // sic } } - - public void setInitValue( final double d ) { - checkType(Type.DOUBLE); - if (d != 0.0) { - value = d; + /** + * Add observer for this object. + */ + public void addObserver(final FieldObserver o) { + if (observers == null) { + observers = new ArrayList<>(); } + observers.add(o); } - - /** Remove any initial value. + /** + * Remove any initial value. */ public void cancelInitValue() { value = null; } - - private void checkType( final Type atype ) { + private void checkType(final Type atype) { final Type superType = super.getType(); if (superType == null) { throw new ClassGenException("You haven't defined the type of the field yet"); @@ -211,106 +170,148 @@ private void checkType( final Type atype ) { } } + /** + * @return deep copy of this field + */ + public FieldGen copy(final ConstantPoolGen cp) { + final FieldGen fg = (FieldGen) clone(); + fg.setConstantPool(cp); + return fg; + } + + /** + * Return value as defined by given BCELComparator strategy. By default two FieldGen objects are said to be equal when + * their names and signatures are equal. + * + * @see Object#equals(Object) + */ + @Override + public boolean equals(final Object obj) { + return bcelComparator.equals(this, obj); + } /** * Get field object after having set up all necessary values. */ public Field getField() { final String signature = getSignature(); - final int name_index = super.getConstantPool().addUtf8(super.getName()); - final int signature_index = super.getConstantPool().addUtf8(signature); + final int nameIndex = super.getConstantPool().addUtf8(super.getName()); + final int signatureIndex = super.getConstantPool().addUtf8(signature); if (value != null) { checkType(super.getType()); final int index = addConstant(); - addAttribute(new ConstantValue(super.getConstantPool().addUtf8("ConstantValue"), 2, index, - super.getConstantPool().getConstantPool())); // sic + addAttribute(new ConstantValue(super.getConstantPool().addUtf8("ConstantValue"), 2, index, super.getConstantPool().getConstantPool())); // sic } addAnnotationsAsAttribute(super.getConstantPool()); - return new Field(super.getAccessFlags(), name_index, signature_index, getAttributes(), - super.getConstantPool().getConstantPool()); // sic + return new Field(super.getAccessFlags(), nameIndex, signatureIndex, getAttributes(), super.getConstantPool().getConstantPool()); // sic } - private void addAnnotationsAsAttribute(final ConstantPoolGen cp) { - final Attribute[] attrs = AnnotationEntryGen.getAnnotationAttributes(cp, super.getAnnotationEntries()); - for (final Attribute attr : attrs) { - addAttribute(attr); - } - } - - - private int addConstant() { - switch (super.getType().getType()) { // sic - case Const.T_INT: - case Const.T_CHAR: - case Const.T_BYTE: - case Const.T_BOOLEAN: - case Const.T_SHORT: - return super.getConstantPool().addInteger(((Integer) value)); - case Const.T_FLOAT: - return super.getConstantPool().addFloat(((Float) value)); - case Const.T_DOUBLE: - return super.getConstantPool().addDouble(((Double) value)); - case Const.T_LONG: - return super.getConstantPool().addLong(((Long) value)); - case Const.T_REFERENCE: - return super.getConstantPool().addString((String) value); - default: - throw new IllegalStateException("Unhandled : " + super.getType().getType()); // sic + public String getInitValue() { + if (value != null) { + return value.toString(); } + return null; } - @Override public String getSignature() { return super.getType().getSignature(); } - private List observers; - - - /** Add observer for this object. + /** + * Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR + * signature. + * + * @see Object#hashCode() */ - public void addObserver( final FieldObserver o ) { - if (observers == null) { - observers = new ArrayList<>(); - } - observers.add(o); + @Override + public int hashCode() { + return bcelComparator.hashCode(this); } - - /** Remove observer for this object. + /** + * Remove observer for this object. */ - public void removeObserver( final FieldObserver o ) { + public void removeObserver(final FieldObserver o) { if (observers != null) { observers.remove(o); } } + public void setInitValue(final boolean b) { + checkType(Type.BOOLEAN); + if (b) { + value = Integer.valueOf(1); + } + } - /** Call notify() method on all observers. This method is not called - * automatically whenever the state has changed, but has to be - * called by the user after he has finished editing the object. - */ - public void update() { - if (observers != null) { - for (final FieldObserver observer : observers ) { - observer.notify(this); - } + public void setInitValue(final byte b) { + checkType(Type.BYTE); + if (b != 0) { + value = Integer.valueOf(b); } } + public void setInitValue(final char c) { + checkType(Type.CHAR); + if (c != 0) { + value = Integer.valueOf(c); + } + } - public String getInitValue() { - if (value != null) { - return value.toString(); + public void setInitValue(final double d) { + checkType(Type.DOUBLE); + if (d != 0.0) { + value = Double.valueOf(d); + } + } + + public void setInitValue(final float f) { + checkType(Type.FLOAT); + if (f != 0.0) { + value = Float.valueOf(f); + } + } + + public void setInitValue(final int i) { + checkType(Type.INT); + if (i != 0) { + value = Integer.valueOf(i); + } + } + + public void setInitValue(final long l) { + checkType(Type.LONG); + if (l != 0L) { + value = Long.valueOf(l); + } + } + + public void setInitValue(final short s) { + checkType(Type.SHORT); + if (s != 0) { + value = Integer.valueOf(s); } - return null; } + /** + * Set (optional) initial value of field, otherwise it will be set to null/0/false by the JVM automatically. + */ + public void setInitValue(final String str) { + checkType(ObjectType.getInstance("java.lang.String")); + if (str != null) { + value = str; + } + } + + private void setValue(final int index) { + final ConstantPool cp = super.getConstantPool().getConstantPool(); + final Constant c = cp.getConstant(index); + value = ((ConstantObject) c).getConstantValue(cp); + } /** - * Return string representation close to declaration format, - * `public static final short MAX = 100', e.g.. + * Return string representation close to declaration format, 'public static final short MAX = 100', e.g.. * * @return String representation of field */ @@ -320,7 +321,7 @@ public final String toString() { String signature; String access; // Short cuts to constant pool access = Utility.accessToString(super.getAccessFlags()); - access = access.isEmpty() ? "" : (access + " "); + access = access.isEmpty() ? "" : access + " "; signature = super.getType().toString(); name = getName(); final StringBuilder buf = new StringBuilder(32); // CHECKSTYLE IGNORE MagicNumber @@ -332,53 +333,15 @@ public final String toString() { return buf.toString(); } - - /** @return deep copy of this field - */ - public FieldGen copy( final ConstantPoolGen cp ) { - final FieldGen fg = (FieldGen) clone(); - fg.setConstantPool(cp); - return fg; - } - - /** - * @return Comparison strategy object + * Call notify() method on all observers. This method is not called automatically whenever the state has changed, but + * has to be called by the user after they have finished editing the object. */ - public static BCELComparator getComparator() { - return bcelComparator; - } - - - /** - * @param comparator Comparison strategy object - */ - public static void setComparator( final BCELComparator comparator ) { - bcelComparator = comparator; - } - - - /** - * Return value as defined by given BCELComparator strategy. - * By default two FieldGen objects are said to be equal when - * their names and signatures are equal. - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals( final Object obj ) { - return bcelComparator.equals(this, obj); - } - - - /** - * Return value as defined by given BCELComparator strategy. - * By default return the hashcode of the field's name XOR signature. - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - return bcelComparator.hashCode(this); + public void update() { + if (observers != null) { + for (final FieldObserver observer : observers) { + observer.notify(this); + } + } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java index 1c2e37f7d8b..6555392e9d4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java @@ -20,6 +20,7 @@ package com.sun.org.apache.bcel.internal.generic; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import com.sun.org.apache.bcel.internal.Const; @@ -27,109 +28,128 @@ import com.sun.org.apache.bcel.internal.classfile.Attribute; /** - * Super class for FieldGen and MethodGen objects, since they have - * some methods in common! + * Super class for FieldGen and MethodGen objects, since they have some methods in common! * * @LastModified: May 2021 */ public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAndTyped, Cloneable { - private String name; - private Type type; - private ConstantPoolGen cp; + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected String name; + + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected Type type; + + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected ConstantPoolGen cp; private final List attributeList = new ArrayList<>(); // @since 6.0 private final List annotationList = new ArrayList<>(); - protected FieldGenOrMethodGen() { } - /** * @since 6.0 */ - protected FieldGenOrMethodGen(final int access_flags) { // TODO could this be package protected? - super(access_flags); + protected FieldGenOrMethodGen(final int accessFlags) { // TODO could this be package protected? + super(accessFlags); } - @Override - public void setType( final Type type ) { // TODO could be package-protected? - if (type.getType() == Const.T_ADDRESS) { - throw new IllegalArgumentException("Type can not be " + type); - } - this.type = type; + protected void addAll(final Attribute[] attrs) { + Collections.addAll(attributeList, attrs); } - - @Override - public Type getType() { - return type; + /** + * @since 6.0 + */ + public void addAnnotationEntry(final AnnotationEntryGen ag) { + annotationList.add(ag); } - - /** @return name of method/field. + /** + * Add an attribute to this method. Currently, the JVM knows about the 'Code', 'ConstantValue', 'Synthetic' and + * 'Exceptions' attributes. Other attributes will be ignored by the JVM but do no harm. + * + * @param a attribute to be added */ - @Override - public String getName() { - return name; + public void addAttribute(final Attribute a) { + attributeList.add(a); } - @Override - public void setName( final String name ) { // TODO could be package-protected? - this.name = name; + public Object clone() { + try { + return super.clone(); + } catch (final CloneNotSupportedException e) { + throw new Error("Clone Not Supported"); // never happens + } } - - public ConstantPoolGen getConstantPool() { - return cp; + public AnnotationEntryGen[] getAnnotationEntries() { + return annotationList.toArray(AnnotationEntryGen.EMPTY_ARRAY); } - - public void setConstantPool( final ConstantPoolGen cp ) { // TODO could be package-protected? - this.cp = cp; + /** + * @return all attributes of this method. + */ + public Attribute[] getAttributes() { + return attributeList.toArray(Attribute.EMPTY_ARRAY); } + public ConstantPoolGen getConstantPool() { + return cp; + } /** - * Add an attribute to this method. Currently, the JVM knows about - * the `Code', `ConstantValue', `Synthetic' and `Exceptions' - * attributes. Other attributes will be ignored by the JVM but do no - * harm. - * - * @param a attribute to be added + * @return name of method/field. */ - public void addAttribute( final Attribute a ) { - attributeList.add(a); + @Override + public String getName() { + return name; } /** - * @since 6.0 + * @return signature of method/field. */ - public void addAnnotationEntry(final AnnotationEntryGen ag) - { - annotationList.add(ag); - } + public abstract String getSignature(); + @Override + public Type getType() { + return type; + } /** - * Remove an attribute. + * @since 6.0 */ - public void removeAttribute( final Attribute a ) { - attributeList.remove(a); + public void removeAnnotationEntries() { + annotationList.clear(); } /** * @since 6.0 */ - public void removeAnnotationEntry(final AnnotationEntryGen ag) - { + public void removeAnnotationEntry(final AnnotationEntryGen ag) { annotationList.remove(ag); } + /** + * Remove an attribute. + */ + public void removeAttribute(final Attribute a) { + attributeList.remove(a); + } /** * Remove all attributes. @@ -138,38 +158,20 @@ public void removeAttributes() { attributeList.clear(); } - /** - * @since 6.0 - */ - public void removeAnnotationEntries() - { - annotationList.clear(); + public void setConstantPool(final ConstantPoolGen cp) { // TODO could be package-protected? + this.cp = cp; } - - /** - * @return all attributes of this method. - */ - public Attribute[] getAttributes() { - return attributeList.toArray(new Attribute[0]); + @Override + public void setName(final String name) { // TODO could be package-protected? + this.name = name; } - public AnnotationEntryGen[] getAnnotationEntries() { - return annotationList.toArray(new AnnotationEntryGen[0]); - } - - - /** @return signature of method/field. - */ - public abstract String getSignature(); - - @Override - public Object clone() { - try { - return super.clone(); - } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + public void setType(final Type type) { // TODO could be package-protected? + if (type.getType() == Const.T_ADDRESS) { + throw new IllegalArgumentException("Type can not be " + type); } + this.type = type; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldInstruction.java index 604a47ca330..368d07ec99f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldInstruction.java @@ -25,18 +25,15 @@ /** * Super class for the GET/PUTxxx family of instructions. - * */ public abstract class FieldInstruction extends FieldOrMethod { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ FieldInstruction() { } - /** * @param index to constant pool */ @@ -44,42 +41,40 @@ protected FieldInstruction(final short opcode, final int index) { super(opcode, index); } - /** - * @return mnemonic for instruction with symbolic references resolved + * @return name of referenced field. */ - @Override - public String toString( final ConstantPool cp ) { - return com.sun.org.apache.bcel.internal.Const.getOpcodeName(super.getOpcode()) + " " - + cp.constantToString(super.getIndex(), com.sun.org.apache.bcel.internal.Const.CONSTANT_Fieldref); + public String getFieldName(final ConstantPoolGen cpg) { + return getName(cpg); } - - /** @return size of field (1 or 2) + /** + * @return size of field (1 or 2) */ - protected int getFieldSize( final ConstantPoolGen cpg ) { + protected int getFieldSize(final ConstantPoolGen cpg) { return Type.size(Type.getTypeSize(getSignature(cpg))); } - - /** @return return type of referenced field + /** + * @return type of field */ - @Override - public Type getType( final ConstantPoolGen cpg ) { - return getFieldType(cpg); + public Type getFieldType(final ConstantPoolGen cpg) { + return Type.getType(getSignature(cpg)); } - - /** @return type of field + /** + * @return return type of referenced field */ - public Type getFieldType( final ConstantPoolGen cpg ) { - return Type.getType(getSignature(cpg)); + @Override + public Type getType(final ConstantPoolGen cpg) { + return getFieldType(cpg); } - - /** @return name of referenced field. + /** + * @return mnemonic for instruction with symbolic references resolved */ - public String getFieldName( final ConstantPoolGen cpg ) { - return getName(cpg); + @Override + public String toString(final ConstantPool cp) { + return com.sun.org.apache.bcel.internal.Const.getOpcodeName(super.getOpcode()) + " " + cp.constantToString(super.getIndex(), com.sun.org.apache.bcel.internal.Const.CONSTANT_Fieldref); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldObserver.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldObserver.java index 4bcbee8d922..a207a098522 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldObserver.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldObserver.java @@ -22,11 +22,10 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Imnplement this interface if you're interested in changes to a FieldGen object - * and register yourself with addObserver(). - * + * Imnplement this interface if you're interested in changes to a FieldGen object and register yourself with + * addObserver(). */ public interface FieldObserver { - void notify( FieldGen field ); + void notify(FieldGen field); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java index 182c3972601..1c646f48292 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java @@ -26,23 +26,20 @@ import com.sun.org.apache.bcel.internal.classfile.ConstantNameAndType; import com.sun.org.apache.bcel.internal.classfile.ConstantPool; import com.sun.org.apache.bcel.internal.classfile.ConstantUtf8; +import com.sun.org.apache.bcel.internal.classfile.Utility; /** - * Super class for InvokeInstruction and FieldInstruction, since they have - * some methods in common! - * + * Super class for InvokeInstruction and FieldInstruction, since they have some methods in common! */ public abstract class FieldOrMethod extends CPInstruction implements LoadClass { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ FieldOrMethod() { // no init } - /** * @param index to constant pool */ @@ -50,36 +47,12 @@ protected FieldOrMethod(final short opcode, final int index) { super(opcode, index); } - - /** @return signature of referenced method/field. - */ - public String getSignature(final ConstantPoolGen cpg) { - final ConstantPool cp = cpg.getConstantPool(); - final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); - final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); - return ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getBytes(); - } - - - /** @return name of referenced method/field. - */ - public String getName(final ConstantPoolGen cpg) { - final ConstantPool cp = cpg.getConstantPool(); - final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); - final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); - return ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getBytes(); - } - - /** * @return name of the referenced class/interface - * @deprecated If the instruction references an array class, - * this method will return "java.lang.Object". - * For code generated by Java 1.5, this answer is - * sometimes wrong (e.g., if the "clone()" method is - * called on an array). A better idea is to use - * the {@link #getReferenceType(ConstantPoolGen)} method, which correctly distinguishes - * between class types and array types. + * @deprecated If the instruction references an array class, this method will return "java.lang.Object". For code + * generated by Java 1.5, this answer is sometimes wrong (e.g., if the "clone()" method is called on an + * array). A better idea is to use the {@link #getReferenceType(ConstantPoolGen)} method, which correctly + * distinguishes between class types and array types. * */ @Deprecated @@ -91,28 +64,50 @@ public String getClassName(final ConstantPoolGen cpg) { // Turn array classes into java.lang.Object. return "java.lang.Object"; } - return className.replace('/', '.'); + return Utility.pathToPackage(className); } - - /** @return type of the referenced class/interface - * @deprecated If the instruction references an array class, - * the ObjectType returned will be invalid. Use - * getReferenceType() instead. + /** + * @return type of the referenced class/interface + * @deprecated If the instruction references an array class, the ObjectType returned will be invalid. Use + * getReferenceType() instead. */ @Deprecated public ObjectType getClassType(final ConstantPoolGen cpg) { return ObjectType.getInstance(getClassName(cpg)); } + /** + * Gets the ObjectType of the method return or field. + * + * @return type of the referenced class/interface + * @throws ClassGenException when the field is (or method returns) an array, + */ + @Override + public ObjectType getLoadClassType(final ConstantPoolGen cpg) { + final ReferenceType rt = getReferenceType(cpg); + if (rt instanceof ObjectType) { + return (ObjectType) rt; + } + throw new ClassGenException(rt.getClass().getCanonicalName() + " " + rt.getSignature() + " does not represent an ObjectType"); + } + + /** + * @return name of referenced method/field. + */ + public String getName(final ConstantPoolGen cpg) { + final ConstantPool cp = cpg.getConstantPool(); + final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); + final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); + return ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getBytes(); + } /** - * Gets the reference type representing the class, interface, - * or array class referenced by the instruction. + * Gets the reference type representing the class, interface, or array class referenced by the instruction. + * * @param cpg the ConstantPoolGen used to create the instruction - * @return an ObjectType (if the referenced class type is a class - * or interface), or an ArrayType (if the referenced class - * type is an array class) + * @return an ObjectType (if the referenced class type is a class or interface), or an ArrayType (if the referenced + * class type is an array class) */ public ReferenceType getReferenceType(final ConstantPoolGen cpg) { final ConstantPool cp = cpg.getConstantPool(); @@ -121,24 +116,17 @@ public ReferenceType getReferenceType(final ConstantPoolGen cpg) { if (className.startsWith("[")) { return (ArrayType) Type.getType(className); } - className = className.replace('/', '.'); + className = Utility.pathToPackage(className); return ObjectType.getInstance(className); } - /** - * Gets the ObjectType of the method return or field. - * - * @return type of the referenced class/interface - * @throws ClassGenException when the field is (or method returns) an array, + * @return signature of referenced method/field. */ - @Override - public ObjectType getLoadClassType(final ConstantPoolGen cpg) { - final ReferenceType rt = getReferenceType(cpg); - if (rt instanceof ObjectType) { - return (ObjectType) rt; - } - throw new ClassGenException(rt.getClass().getCanonicalName() + " " + - rt.getSignature() + " does not represent an ObjectType"); + public String getSignature(final ConstantPoolGen cpg) { + final ConstantPool cp = cpg.getConstantPool(); + final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); + final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); + return ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getBytes(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GETFIELD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GETFIELD.java index 1e1a652daec..bc4e5b11674 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GETFIELD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GETFIELD.java @@ -25,51 +25,37 @@ /** * GETFIELD - Fetch field from object - *
    Stack: ..., objectref -> ..., value
    + * + *
    + * Stack: ..., objectref -> ..., value
    + * 
    + * * OR - *
    Stack: ..., objectref -> ..., value.word1, value.word2
    * + *
    + * Stack: ..., objectref -> ..., value.word1, value.word2
    + * 
    */ -public class GETFIELD extends FieldInstruction implements ExceptionThrower, StackConsumer, - StackProducer { +public class GETFIELD extends FieldInstruction implements ExceptionThrower, StackConsumer, StackProducer { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ GETFIELD() { } - public GETFIELD(final int index) { super(Const.GETFIELD, index); } - - @Override - public int produceStack( final ConstantPoolGen cpg ) { - return getFieldSize(cpg); - } - - - @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, - ExceptionConst.NULL_POINTER_EXCEPTION, - ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitStackConsumer(this); v.visitStackProducer(this); @@ -80,4 +66,15 @@ public void accept( final Visitor v ) { v.visitFieldInstruction(this); v.visitGETFIELD(this); } + + @Override + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, ExceptionConst.NULL_POINTER_EXCEPTION, + ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); + } + + @Override + public int produceStack(final ConstantPoolGen cpg) { + return getFieldSize(cpg); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GETSTATIC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GETSTATIC.java index a8ff0989fbb..b8c4a4a3560 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GETSTATIC.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GETSTATIC.java @@ -26,49 +26,37 @@ /** * GETSTATIC - Fetch static field from class - *
    Stack: ..., -> ..., value
    + * + *
    + * Stack: ..., -> ..., value
    + * 
    + * * OR - *
    Stack: ..., -> ..., value.word1, value.word2
    * + *
    + * Stack: ..., -> ..., value.word1, value.word2
    + * 
    */ public class GETSTATIC extends FieldInstruction implements PushInstruction, ExceptionThrower { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ GETSTATIC() { } - public GETSTATIC(final int index) { super(Const.GETSTATIC, index); } - - @Override - public int produceStack( final ConstantPoolGen cpg ) { - return getFieldSize(cpg); - } - - - @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, - ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitPushInstruction(this); v.visitExceptionThrower(this); @@ -79,4 +67,14 @@ public void accept( final Visitor v ) { v.visitFieldInstruction(this); v.visitGETSTATIC(this); } + + @Override + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); + } + + @Override + public int produceStack(final ConstantPoolGen cpg) { + return getFieldSize(cpg); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GOTO.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GOTO.java index 64b7de98d62..cd76aae7981 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GOTO.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GOTO.java @@ -26,77 +26,70 @@ /** * GOTO - Branch always (to relative offset, not absolute address) - * */ public class GOTO extends GotoInstruction implements VariableLengthInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ GOTO() { } - public GOTO(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.GOTO, target); } + /** + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitVariableLengthInstruction(this); + v.visitUnconditionalBranch(this); + v.visitBranchInstruction(this); + v.visitGotoInstruction(this); + v.visitGOTO(this); + } /** * Dump instruction as byte code to stream out. + * * @param out Output stream */ @Override - public void dump( final DataOutputStream out ) throws IOException { + public void dump(final DataOutputStream out) throws IOException { super.setIndex(getTargetOffset()); - final short _opcode = getOpcode(); - if (_opcode == com.sun.org.apache.bcel.internal.Const.GOTO) { + final short opcode = getOpcode(); + if (opcode == com.sun.org.apache.bcel.internal.Const.GOTO) { super.dump(out); } else { // GOTO_W super.setIndex(getTargetOffset()); - out.writeByte(_opcode); + out.writeByte(opcode); out.writeInt(super.getIndex()); } } - /** - * Called in pass 2 of InstructionList.setPositions() in order to update - * the branch target, that may shift due to variable length instructions. + * Called in pass 2 of InstructionList.setPositions() in order to update the branch target, that may shift due to + * variable length instructions. * * @param offset additional offset caused by preceding (variable length) instructions - * @param max_offset the maximum offset that may be caused by these instructions + * @param maxOffset the maximum offset that may be caused by these instructions * @return additional offset caused by possible change of this instruction's length */ @Override - protected int updatePosition( final int offset, final int max_offset ) { + protected int updatePosition(final int offset, final int maxOffset) { final int i = getTargetOffset(); // Depending on old position value setPosition(getPosition() + offset); // Position may be shifted by preceding expansions - if (Math.abs(i) >= (Short.MAX_VALUE - max_offset)) { // to large for short (estimate) + if (Math.abs(i) >= Short.MAX_VALUE - maxOffset) { // to large for short (estimate) super.setOpcode(com.sun.org.apache.bcel.internal.Const.GOTO_W); - final short old_length = (short) super.getLength(); + final short oldLength = (short) super.getLength(); super.setLength(5); - return super.getLength() - old_length; + return super.getLength() - oldLength; } return 0; } - - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. - * - * @param v Visitor object - */ - @Override - public void accept( final Visitor v ) { - v.visitVariableLengthInstruction(this); - v.visitUnconditionalBranch(this); - v.visitBranchInstruction(this); - v.visitGotoInstruction(this); - v.visitGOTO(this); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GOTO_W.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GOTO_W.java index 5c97a0c9d55..df4c06be09a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GOTO_W.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GOTO_W.java @@ -28,59 +28,52 @@ /** * GOTO_W - Branch always (to relative offset, not absolute address) - * */ public class GOTO_W extends GotoInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ GOTO_W() { } - public GOTO_W(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.GOTO_W, target); super.setLength(5); } + /** + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitUnconditionalBranch(this); + v.visitBranchInstruction(this); + v.visitGotoInstruction(this); + v.visitGOTO_W(this); + } /** * Dump instruction as byte code to stream out. + * * @param out Output stream */ @Override - public void dump( final DataOutputStream out ) throws IOException { + public void dump(final DataOutputStream out) throws IOException { super.setIndex(getTargetOffset()); out.writeByte(super.getOpcode()); out.writeInt(super.getIndex()); } - /** * Read needed data (e.g. index) from file. */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { super.setIndex(bytes.readInt()); super.setLength(5); } - - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. - * - * @param v Visitor object - */ - @Override - public void accept( final Visitor v ) { - v.visitUnconditionalBranch(this); - v.visitBranchInstruction(this); - v.visitGotoInstruction(this); - v.visitGOTO_W(this); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GotoInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GotoInstruction.java index 766f68a95f1..b261ca584b6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GotoInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/GotoInstruction.java @@ -23,19 +23,16 @@ /** * Super class for GOTO - * */ public abstract class GotoInstruction extends BranchInstruction implements UnconditionalBranch { - GotoInstruction(final short opcode, final InstructionHandle target) { - super(opcode, target); - } - - /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ GotoInstruction() { } + + GotoInstruction(final short opcode, final InstructionHandle target) { + super(opcode, target); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2B.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2B.java index 0daab14fccb..0b8c9dd529e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2B.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2B.java @@ -23,28 +23,28 @@ /** * I2B - Convert int to byte - *
    Stack: ..., value -> ..., result
    * + *
    + * Stack: ..., value -> ..., result
    + * 
    */ public class I2B extends ConversionInstruction { - /** Convert int to byte + /** + * Convert int to byte */ public I2B() { super(com.sun.org.apache.bcel.internal.Const.I2B); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2C.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2C.java index 1222026e4ff..b5c6532a592 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2C.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2C.java @@ -23,28 +23,28 @@ /** * I2C - Convert int to char - *
    Stack: ..., value -> ..., result
    * + *
    + * Stack: ..., value -> ..., result
    + * 
    */ public class I2C extends ConversionInstruction { - /** Convert int to char + /** + * Convert int to char */ public I2C() { super(com.sun.org.apache.bcel.internal.Const.I2C); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2D.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2D.java index 70c83845e69..e73270a5874 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2D.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2D.java @@ -23,28 +23,28 @@ /** * I2D - Convert int to double - *
    Stack: ..., value -> ..., result.word1, result.word2
    * + *
    + * Stack: ..., value -> ..., result.word1, result.word2
    + * 
    */ public class I2D extends ConversionInstruction { - /** Convert int to double + /** + * Convert int to double */ public I2D() { super(com.sun.org.apache.bcel.internal.Const.I2D); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2F.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2F.java index f4b10e91d27..dc7df8c6d48 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2F.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2F.java @@ -23,28 +23,28 @@ /** * I2F - Convert int to float - *
    Stack: ..., value -> ..., result
    * + *
    + * Stack: ..., value -> ..., result
    + * 
    */ public class I2F extends ConversionInstruction { - /** Convert int to float + /** + * Convert int to float */ public I2F() { super(com.sun.org.apache.bcel.internal.Const.I2F); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2L.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2L.java index 0ab03dd8413..e0a8e81e1cd 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2L.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2L.java @@ -23,28 +23,28 @@ /** * I2L - Convert int to long - *
    Stack: ..., value -> ..., result.word1, result.word2
    * + *
    + * Stack: ..., value -> ..., result.word1, result.word2
    + * 
    */ public class I2L extends ConversionInstruction { - /** Convert int to long + /** + * Convert int to long */ public I2L() { super(com.sun.org.apache.bcel.internal.Const.I2L); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2S.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2S.java index 7fc76358385..04fa0e62a06 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2S.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/I2S.java @@ -23,8 +23,10 @@ /** * I2S - Convert int to short - *
    Stack: ..., value -> ..., result
    * + *
    + * Stack: ..., value -> ..., result
    + * 
    */ public class I2S extends ConversionInstruction { @@ -32,17 +34,14 @@ public I2S() { super(com.sun.org.apache.bcel.internal.Const.I2S); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IADD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IADD.java index 2e454f30c6b..ad5e109af8c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IADD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IADD.java @@ -23,28 +23,28 @@ /** * IADD - Add ints - *
    Stack: ..., value1, value2 -> result
    * + *
    + * Stack: ..., value1, value2 -> result
    + * 
    */ public class IADD extends ArithmeticInstruction { - /** Add ints + /** + * Add ints */ public IADD() { super(com.sun.org.apache.bcel.internal.Const.IADD); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IALOAD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IALOAD.java index 79b6a66deb1..b9f39c13d51 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IALOAD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IALOAD.java @@ -23,8 +23,10 @@ /** * IALOAD - Load int from array - *
    Stack: ..., arrayref, index -> ..., value
    * + *
    + * Stack: ..., arrayref, index -> ..., value
    + * 
    */ public class IALOAD extends ArrayInstruction implements StackProducer { @@ -35,17 +37,14 @@ public IALOAD() { super(com.sun.org.apache.bcel.internal.Const.IALOAD); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IAND.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IAND.java index be4420e4f43..4fe036cc550 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IAND.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IAND.java @@ -23,8 +23,10 @@ /** * IAND - Bitwise AND int - *
    Stack: ..., value1, value2 -> ..., result
    * + *
    + * Stack: ..., value1, value2 -> ..., result
    + * 
    */ public class IAND extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public IAND() { super(com.sun.org.apache.bcel.internal.Const.IAND); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IASTORE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IASTORE.java index ff954de48ed..62cded23fe4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IASTORE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IASTORE.java @@ -22,9 +22,11 @@ package com.sun.org.apache.bcel.internal.generic; /** - * IASTORE - Store into int array - *
    Stack: ..., arrayref, index, value -> ...
    + * IASTORE - Store into int array * + *
    + * Stack: ..., arrayref, index, value -> ...
    + * 
    */ public class IASTORE extends ArrayInstruction implements StackConsumer { @@ -35,17 +37,14 @@ public IASTORE() { super(com.sun.org.apache.bcel.internal.Const.IASTORE); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java index 4c00097cb69..5effd7edcd9 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java @@ -22,61 +22,56 @@ /** * ICONST - Push value between -1, ..., 5, other values cause an exception * - *
    Stack: ... -> ..., 
    + *
    + * Stack: ... -> ...,
    + * 
    * */ public class ICONST extends Instruction implements ConstantPushInstruction { - private int value; - + private final int value; /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ ICONST() { + this(0); } - public ICONST(final int i) { super(com.sun.org.apache.bcel.internal.Const.ICONST_0, (short) 1); - if ((i >= -1) && (i <= 5)) { - super.setOpcode((short) (com.sun.org.apache.bcel.internal.Const.ICONST_0 + i)); // Even works for i == -1 - } else { + if (i < -1 || i > 5) { throw new ClassGenException("ICONST can be used only for value between -1 and 5: " + i); } + super.setOpcode((short) (com.sun.org.apache.bcel.internal.Const.ICONST_0 + i)); // Even works for i == -1 value = i; } - - @Override - public Number getValue() { - return Integer.valueOf(value); - } - - - /** @return Type.INT - */ - @Override - public Type getType( final ConstantPoolGen cp ) { - return Type.INT; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitPushInstruction(this); v.visitStackProducer(this); v.visitTypedInstruction(this); v.visitConstantPushInstruction(this); v.visitICONST(this); } + + /** + * @return Type.INT + */ + @Override + public Type getType(final ConstantPoolGen cp) { + return Type.INT; + } + + @Override + public Number getValue() { + return Integer.valueOf(value); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IDIV.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IDIV.java index 078eefe1113..e23968c9ae3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IDIV.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IDIV.java @@ -24,39 +24,29 @@ /** * IDIV - Divide ints - *
    Stack: ..., value1, value2 -> result
    * + *
    + * Stack: ..., value1, value2 -> result
    + * 
    * @LastModified: Jan 2020 */ public class IDIV extends ArithmeticInstruction implements ExceptionThrower { - /** Divide ints + /** + * Divide ints */ public IDIV() { super(com.sun.org.apache.bcel.internal.Const.IDIV); } - - /** @return exceptions this instruction may cause - */ - @Override - public Class[] getExceptions() { - return new Class[] { - ExceptionConst.ARITHMETIC_EXCEPTION - }; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackProducer(this); @@ -64,4 +54,12 @@ public void accept( final Visitor v ) { v.visitArithmeticInstruction(this); v.visitIDIV(this); } + + /** + * @return exceptions this instruction may cause + */ + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConst.ARITHMETIC_EXCEPTION}; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFEQ.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFEQ.java index 7518c24ee31..c44d0f57dfe 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFEQ.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFEQ.java @@ -24,46 +24,41 @@ /** * IFEQ - Branch if int comparison with zero succeeds * - *
    Stack: ..., value -> ...
    - * + *
    + * Stack: ..., value -> ...
    + * 
    */ public class IFEQ extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IFEQ() { } - public IFEQ(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IFEQ, target); } - - /** - * @return negation of instruction, e.g. IFEQ.negate() == IFNE - */ - @Override - public IfInstruction negate() { - return new IFNE(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIFEQ(this); } + + /** + * @return negation of instruction, e.g. IFEQ.negate() == IFNE + */ + @Override + public IfInstruction negate() { + return new IFNE(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFGE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFGE.java index ed5337de2ba..53e32a57ba3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFGE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFGE.java @@ -24,46 +24,41 @@ /** * IFGE - Branch if int comparison with zero succeeds * - *
    Stack: ..., value -> ...
    - * + *
    + * Stack: ..., value -> ...
    + * 
    */ public class IFGE extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IFGE() { } - public IFGE(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IFGE, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IFLT(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIFGE(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IFLT(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFGT.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFGT.java index 08a9788779b..23ab44754f6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFGT.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFGT.java @@ -24,46 +24,41 @@ /** * IFGT - Branch if int comparison with zero succeeds * - *
    Stack: ..., value -> ...
    - * + *
    + * Stack: ..., value -> ...
    + * 
    */ public class IFGT extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IFGT() { } - public IFGT(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IFGT, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IFLE(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIFGT(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IFLE(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFLE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFLE.java index 3eeced2aa4f..0bd68bd1be7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFLE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFLE.java @@ -24,46 +24,41 @@ /** * IFLE - Branch if int comparison with zero succeeds * - *
    Stack: ..., value -> ...
    - * + *
    + * Stack: ..., value -> ...
    + * 
    */ public class IFLE extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IFLE() { } - public IFLE(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IFLE, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IFGT(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIFLE(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IFGT(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFLT.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFLT.java index 36d086093fc..0c1589e95b8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFLT.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFLT.java @@ -24,46 +24,41 @@ /** * IFLT - Branch if int comparison with zero succeeds * - *
    Stack: ..., value -> ...
    - * + *
    + * Stack: ..., value -> ...
    + * 
    */ public class IFLT extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IFLT() { } - public IFLT(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IFLT, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IFGE(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIFLT(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IFGE(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFNE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFNE.java index 46a4ed659fa..91075bc66d8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFNE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFNE.java @@ -24,46 +24,41 @@ /** * IFNE - Branch if int comparison with zero succeeds * - *
    Stack: ..., value -> ...
    - * + *
    + * Stack: ..., value -> ...
    + * 
    */ public class IFNE extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IFNE() { } - public IFNE(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IFNE, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IFEQ(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIFNE(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IFEQ(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFNONNULL.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFNONNULL.java index 221ef55f1d1..342779a9b4f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFNONNULL.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFNONNULL.java @@ -24,46 +24,41 @@ /** * IFNONNULL - Branch if reference is not null * - *
    Stack: ..., reference -> ...
    - * + *
    + * Stack: ..., reference -> ...
    + * 
    */ public class IFNONNULL extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IFNONNULL() { } - public IFNONNULL(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IFNONNULL, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IFNULL(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIFNONNULL(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IFNULL(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFNULL.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFNULL.java index c5d01005c19..b680033096d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFNULL.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IFNULL.java @@ -24,46 +24,41 @@ /** * IFNULL - Branch if reference is not null * - *
    Stack: ..., reference -> ...
    - * + *
    + * Stack: ..., reference -> ...
    + * 
    */ public class IFNULL extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IFNULL() { } - public IFNULL(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IFNULL, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IFNONNULL(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIFNULL(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IFNONNULL(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ACMPEQ.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ACMPEQ.java index a01749f90d1..9f14fb58909 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ACMPEQ.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ACMPEQ.java @@ -24,46 +24,41 @@ /** * IF_ACMPEQ - Branch if reference comparison succeeds * - *
    Stack: ..., value1, value2 -> ...
    - * + *
    + * Stack: ..., value1, value2 -> ...
    + * 
    */ public class IF_ACMPEQ extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IF_ACMPEQ() { } - public IF_ACMPEQ(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IF_ACMPEQ, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IF_ACMPNE(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIF_ACMPEQ(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IF_ACMPNE(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ACMPNE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ACMPNE.java index 3115e4f70ee..536abe40d64 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ACMPNE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ACMPNE.java @@ -24,46 +24,41 @@ /** * IF_ACMPNE - Branch if reference comparison doesn't succeed * - *
    Stack: ..., value1, value2 -> ...
    - * + *
    + * Stack: ..., value1, value2 -> ...
    + * 
    */ public class IF_ACMPNE extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IF_ACMPNE() { } - public IF_ACMPNE(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IF_ACMPNE, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IF_ACMPEQ(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIF_ACMPNE(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IF_ACMPEQ(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPEQ.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPEQ.java index e9850f886c9..a3fa883dfb2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPEQ.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPEQ.java @@ -24,46 +24,41 @@ /** * IF_ICMPEQ - Branch if int comparison succeeds * - *
    Stack: ..., value1, value2 -> ...
    - * + *
    + * Stack: ..., value1, value2 -> ...
    + * 
    */ public class IF_ICMPEQ extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IF_ICMPEQ() { } - public IF_ICMPEQ(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IF_ICMPEQ, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IF_ICMPNE(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIF_ICMPEQ(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IF_ICMPNE(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPGE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPGE.java index 59fb4e1c089..8848da01b49 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPGE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPGE.java @@ -24,46 +24,41 @@ /** * IF_ICMPGE - Branch if int comparison succeeds * - *
    Stack: ..., value1, value2 -> ...
    - * + *
    + * Stack: ..., value1, value2 -> ...
    + * 
    */ public class IF_ICMPGE extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IF_ICMPGE() { } - public IF_ICMPGE(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IF_ICMPGE, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IF_ICMPLT(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIF_ICMPGE(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IF_ICMPLT(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPGT.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPGT.java index b9e4b379e6f..b1145cc9491 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPGT.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPGT.java @@ -24,46 +24,41 @@ /** * IF_ICMPGT - Branch if int comparison succeeds * - *
    Stack: ..., value1, value2 -> ...
    - * + *
    + * Stack: ..., value1, value2 -> ...
    + * 
    */ public class IF_ICMPGT extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IF_ICMPGT() { } - public IF_ICMPGT(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IF_ICMPGT, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IF_ICMPLE(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIF_ICMPGT(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IF_ICMPLE(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPLE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPLE.java index 8227630a88f..54eed61742d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPLE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPLE.java @@ -24,46 +24,41 @@ /** * IF_ICMPLE - Branch if int comparison succeeds * - *
    Stack: ..., value1, value2 -> ...
    - * + *
    + * Stack: ..., value1, value2 -> ...
    + * 
    */ public class IF_ICMPLE extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IF_ICMPLE() { } - public IF_ICMPLE(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IF_ICMPLE, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IF_ICMPGT(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIF_ICMPLE(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IF_ICMPGT(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPLT.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPLT.java index 92800955831..7c159f4b56a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPLT.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPLT.java @@ -24,46 +24,41 @@ /** * IF_ICMPLT - Branch if int comparison succeeds * - *
    Stack: ..., value1, value2 -> ...
    - * + *
    + * Stack: ..., value1, value2 -> ...
    + * 
    */ public class IF_ICMPLT extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IF_ICMPLT() { } - public IF_ICMPLT(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IF_ICMPLT, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IF_ICMPGE(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIF_ICMPLT(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IF_ICMPGE(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPNE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPNE.java index e1de79ab77e..1c1f9800a47 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPNE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IF_ICMPNE.java @@ -24,46 +24,41 @@ /** * IF_ICMPNE - Branch if int comparison doesn't succeed * - *
    Stack: ..., value1, value2 -> ...
    - * + *
    + * Stack: ..., value1, value2 -> ...
    + * 
    */ public class IF_ICMPNE extends IfInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IF_ICMPNE() { } - public IF_ICMPNE(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.IF_ICMPNE, target); } - - /** - * @return negation of instruction - */ - @Override - public IfInstruction negate() { - return new IF_ICMPEQ(super.getTarget()); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitBranchInstruction(this); v.visitIfInstruction(this); v.visitIF_ICMPNE(this); } + + /** + * @return negation of instruction + */ + @Override + public IfInstruction negate() { + return new IF_ICMPEQ(super.getTarget()); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IINC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IINC.java index 7b4e80c274c..aeaa2d8cdd2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IINC.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IINC.java @@ -24,47 +24,56 @@ import java.io.DataOutputStream; import java.io.IOException; +import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.util.ByteSequence; /** * IINC - Increment local variable by constant - * */ public class IINC extends LocalVariableInstruction { private boolean wide; private int c; - /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IINC() { } - /** * @param n index of local variable * @param c increment factor */ public IINC(final int n, final int c) { - super(); // Default behavior of LocalVariableInstruction causes error - super.setOpcode(com.sun.org.apache.bcel.internal.Const.IINC); + // Default behavior of LocalVariableInstruction causes error + super.setOpcode(Const.IINC); super.setLength((short) 3); setIndex(n); // May set wide as side effect setIncrement(c); } + /** + * Calls corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitLocalVariableInstruction(this); + v.visitIINC(this); + } /** - * Dump instruction as byte code to stream out. + * Dumps instruction as byte code to stream out. + * * @param out Output stream */ @Override - public void dump( final DataOutputStream out ) throws IOException { + public void dump(final DataOutputStream out) throws IOException { if (wide) { - out.writeByte(com.sun.org.apache.bcel.internal.Const.WIDE); + out.writeByte(Const.WIDE); } out.writeByte(super.getOpcode()); if (wide) { @@ -76,27 +85,26 @@ public void dump( final DataOutputStream out ) throws IOException { } } - - private void setWide() { - wide = super.getIndex() > com.sun.org.apache.bcel.internal.Const.MAX_BYTE; - if (c > 0) { - wide = wide || (c > Byte.MAX_VALUE); - } else { - wide = wide || (c < Byte.MIN_VALUE); - } - if (wide) { - super.setLength(6); // wide byte included - } else { - super.setLength(3); - } + /** + * @return increment factor + */ + public final int getIncrement() { + return c; } + /** + * @return int type + */ + @Override + public Type getType(final ConstantPoolGen cp) { + return Type.INT; + } /** - * Read needed data (e.g. index) from file. + * Reads needed data (e.g. index) from file. */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { this.wide = wide; if (wide) { super.setLength(6); @@ -109,21 +117,19 @@ protected void initFromFile( final ByteSequence bytes, final boolean wide ) thro } } - /** - * @return mnemonic for instruction + * Sets increment factor. */ - @Override - public String toString( final boolean verbose ) { - return super.toString(verbose) + " " + c; + public final void setIncrement(final int c) { + this.c = c; + setWide(); } - /** - * Set index of local variable. + * Sets index of local variable. */ @Override - public final void setIndex( final int n ) { + public final void setIndex(final int n) { if (n < 0) { throw new ClassGenException("Negative index value: " + n); } @@ -131,43 +137,27 @@ public final void setIndex( final int n ) { setWide(); } - - /** - * @return increment factor - */ - public final int getIncrement() { - return c; - } - - - /** - * Set increment factor. - */ - public final void setIncrement( final int c ) { - this.c = c; - setWide(); - } - - - /** @return int type - */ - @Override - public Type getType( final ConstantPoolGen cp ) { - return Type.INT; + private void setWide() { + wide = super.getIndex() > Const.MAX_BYTE; + if (c > 0) { + wide = wide || c > Byte.MAX_VALUE; + } else { + wide = wide || c < Byte.MIN_VALUE; + } + if (wide) { + super.setLength(6); // wide byte included + } else { + super.setLength(3); + } } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Returns mnemonic for instruction. * - * @param v Visitor object + * @return mnemonic for instruction. */ @Override - public void accept( final Visitor v ) { - v.visitLocalVariableInstruction(this); - v.visitIINC(this); + public String toString(final boolean verbose) { + return super.toString(verbose) + " " + c; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ILOAD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ILOAD.java index 55f9c29fbbd..1ecc3aae4cc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ILOAD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ILOAD.java @@ -23,38 +23,37 @@ /** * ILOAD - Load int from local variable onto stack - *
    Stack: ... -> ..., result
    * + *
    + * Stack: ... -> ..., result
    + * 
    */ public class ILOAD extends LoadInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ ILOAD() { super(com.sun.org.apache.bcel.internal.Const.ILOAD, com.sun.org.apache.bcel.internal.Const.ILOAD_0); } - - /** Load int from local variable + /** + * Load int from local variable + * * @param n index of local variable */ public ILOAD(final int n) { super(com.sun.org.apache.bcel.internal.Const.ILOAD, com.sun.org.apache.bcel.internal.Const.ILOAD_0, n); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { super.accept(v); v.visitILOAD(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IMPDEP1.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IMPDEP1.java index a93c1808017..62fc89299a9 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IMPDEP1.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IMPDEP1.java @@ -23,7 +23,6 @@ /** * IMPDEP1 - Implementation dependent - * */ public class IMPDEP1 extends Instruction { @@ -31,17 +30,14 @@ public IMPDEP1() { super(com.sun.org.apache.bcel.internal.Const.IMPDEP1, (short) 1); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitIMPDEP1(this); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IMPDEP2.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IMPDEP2.java index e77c250531c..cef4e08c794 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IMPDEP2.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IMPDEP2.java @@ -23,7 +23,6 @@ /** * IMPDEP2 - Implementation dependent - * */ public class IMPDEP2 extends Instruction { @@ -31,17 +30,14 @@ public IMPDEP2() { super(com.sun.org.apache.bcel.internal.Const.IMPDEP2, (short) 1); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitIMPDEP2(this); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IMUL.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IMUL.java index f8fa6a18792..9f7ff3dbf6c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IMUL.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IMUL.java @@ -23,28 +23,28 @@ /** * IMUL - Multiply ints - *
    Stack: ..., value1, value2 -> result
    * + *
    + * Stack: ..., value1, value2 -> result
    + * 
    */ public class IMUL extends ArithmeticInstruction { - /** Multiply ints + /** + * Multiply ints */ public IMUL() { super(com.sun.org.apache.bcel.internal.Const.IMUL); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INEG.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INEG.java index 1acc2886718..d881260b66e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INEG.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INEG.java @@ -23,8 +23,10 @@ /** * INEG - Negate int - *
    Stack: ..., value -> ..., result
    * + *
    + * Stack: ..., value -> ..., result
    + * 
    */ public class INEG extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public INEG() { super(com.sun.org.apache.bcel.internal.Const.INEG); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INSTANCEOF.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INSTANCEOF.java index 48500a4744b..10d5f2c0f65 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INSTANCEOF.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INSTANCEOF.java @@ -25,51 +25,31 @@ /** * INSTANCEOF - Determine if object is of given type - *
    Stack: ..., objectref -> ..., result
    * + *
    + * Stack: ..., objectref -> ..., result
    + * 
    */ -public class INSTANCEOF extends CPInstruction implements LoadClass, ExceptionThrower, - StackProducer, StackConsumer { +public class INSTANCEOF extends CPInstruction implements LoadClass, ExceptionThrower, StackProducer, StackConsumer { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ INSTANCEOF() { } - public INSTANCEOF(final int index) { super(com.sun.org.apache.bcel.internal.Const.INSTANCEOF, index); } - - @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_CLASS_AND_INTERFACE_RESOLUTION); - } - - - @Override - public ObjectType getLoadClassType( final ConstantPoolGen cpg ) { - Type t = getType(cpg); - if (t instanceof ArrayType) { - t = ((ArrayType) t).getBasicType(); - } - return (t instanceof ObjectType) ? (ObjectType) t : null; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitLoadClass(this); v.visitExceptionThrower(this); v.visitStackProducer(this); @@ -78,4 +58,18 @@ public void accept( final Visitor v ) { v.visitCPInstruction(this); v.visitINSTANCEOF(this); } + + @Override + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_CLASS_AND_INTERFACE_RESOLUTION); + } + + @Override + public ObjectType getLoadClassType(final ConstantPoolGen cpg) { + Type t = getType(cpg); + if (t instanceof ArrayType) { + t = ((ArrayType) t).getBasicType(); + } + return t instanceof ObjectType ? (ObjectType) t : null; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java index d6bac98f036..2865a158de2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,85 +31,34 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence; /** - * Class for INVOKEDYNAMIC. Not an instance of InvokeInstruction, since that class - * expects to be able to get the class of the method. Ignores the bootstrap - * mechanism entirely. + * Class for INVOKEDYNAMIC. Not an instance of InvokeInstruction, since that class expects to be able to get the class + * of the method. Ignores the bootstrap mechanism entirely. * - * @see - * - * The invokedynamic instruction in The Java Virtual Machine Specification + * @see The + * invokedynamic instruction in The Java Virtual Machine Specification * @since 6.0 - * @LastModified: May 2021 + * @LastModified: Feb 2023 */ public class INVOKEDYNAMIC extends InvokeInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ INVOKEDYNAMIC() { } - public INVOKEDYNAMIC(final int index) { super(Const.INVOKEDYNAMIC, index); } - - /** - * Dump instruction as byte code to stream out. - * @param out Output stream - */ - @Override - public void dump( final DataOutputStream out ) throws IOException { - out.writeByte(super.getOpcode()); - out.writeShort(super.getIndex()); - out.writeByte(0); - out.writeByte(0); - } - - - /** - * Read needed data (i.e., index) from file. - */ - @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { - super.initFromFile(bytes, wide); - super.setLength(5); - bytes.readByte(); // Skip 0 byte - bytes.readByte(); // Skip 0 byte - } - - - /** - * @return mnemonic for instruction with symbolic references resolved - */ - @Override - public String toString( final ConstantPool cp ) { - return super.toString(cp); - } - - - @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_INTERFACE_METHOD_RESOLUTION, - ExceptionConst.UNSATISFIED_LINK_ERROR, - ExceptionConst.ABSTRACT_METHOD_ERROR, - ExceptionConst.ILLEGAL_ACCESS_ERROR, - ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackConsumer(this); @@ -122,28 +71,43 @@ public void accept( final Visitor v ) { } /** - * Override the parent method because our classname is held elsewhere. + * Dump instruction as byte code to stream out. * - * @param cpg the ConstantPool generator - * @deprecated in FieldOrMethod + * @param out Output stream + */ + @Override + public void dump(final DataOutputStream out) throws IOException { + out.writeByte(super.getOpcode()); + out.writeShort(super.getIndex()); + out.writeByte(0); + out.writeByte(0); + } + + /** + * Override the parent method because our class name is held elsewhere. * - * @return name of the referenced class/interface + * Note: Contrary to this method's name it does not return the class name of the invoke target; rather it returns the + * name of the method that will be used to invoke the Lambda method generated by this invoke dynamic instruction. */ @Override @Deprecated public String getClassName( final ConstantPoolGen cpg ) { final ConstantPool cp = cpg.getConstantPool(); - final ConstantInvokeDynamic cid = (ConstantInvokeDynamic) cp.getConstant(super.getIndex(), Const.CONSTANT_InvokeDynamic); - return ((ConstantNameAndType) cp.getConstant(cid.getNameAndTypeIndex())).getName(cp); + final ConstantInvokeDynamic cid = cp.getConstant(super.getIndex(), Const.CONSTANT_InvokeDynamic, ConstantInvokeDynamic.class); + return cp.getConstant(cid.getNameAndTypeIndex(), ConstantNameAndType.class).getName(cp); } + @Override + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_INTERFACE_METHOD_RESOLUTION, ExceptionConst.UNSATISFIED_LINK_ERROR, + ExceptionConst.ABSTRACT_METHOD_ERROR, ExceptionConst.ILLEGAL_ACCESS_ERROR, ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); + } /** - * Since InvokeDynamic doesn't refer to a reference type, just return java.lang.Object, - * as that is the only type we can say for sure the reference will be. + * Since InvokeDynamic doesn't refer to a reference type, just return java.lang.Object, as that is the only type we can + * say for sure the reference will be. * - * @param cpg - * the ConstantPoolGen used to create the instruction + * @param cpg the ConstantPoolGen used to create the instruction * @return an ObjectType for java.lang.Object * @since 6.1 */ @@ -151,4 +115,16 @@ public String getClassName( final ConstantPoolGen cpg ) { public ReferenceType getReferenceType(final ConstantPoolGen cpg) { return new ObjectType(Object.class.getName()); } + + /** + * Read needed data (i.e., index) from file. + */ + @Override + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { + super.initFromFile(bytes, wide); + super.setLength(5); + bytes.readByte(); // Skip 0 byte + bytes.readByte(); // Skip 0 byte + } + } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEINTERFACE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEINTERFACE.java index 4953abda34b..7f1858c5766 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEINTERFACE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEINTERFACE.java @@ -31,25 +31,24 @@ /** * INVOKEINTERFACE - Invoke interface method - *
    Stack: ..., objectref, [arg1, [arg2 ...]] -> ...
    * - * @see - * - * The invokeinterface instruction in The Java Virtual Machine Specification + *
    + * Stack: ..., objectref, [arg1, [arg2 ...]] -> ...
    + * 
    + * + * @see The + * invokeinterface instruction in The Java Virtual Machine Specification */ public final class INVOKEINTERFACE extends InvokeInstruction { private int nargs; // Number of arguments on stack (number of stack slots), called "count" in vmspec2 - /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ INVOKEINTERFACE() { } - public INVOKEINTERFACE(final int index, final int nargs) { super(Const.INVOKEINTERFACE, index); super.setLength(5); @@ -59,84 +58,72 @@ public INVOKEINTERFACE(final int index, final int nargs) { this.nargs = nargs; } + /** + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackConsumer(this); + v.visitStackProducer(this); + v.visitLoadClass(this); + v.visitCPInstruction(this); + v.visitFieldOrMethod(this); + v.visitInvokeInstruction(this); + v.visitINVOKEINTERFACE(this); + } + + @Override + public int consumeStack(final ConstantPoolGen cpg) { // nargs is given in byte-code + return nargs; // nargs includes this reference + } /** * Dump instruction as byte code to stream out. + * * @param out Output stream */ @Override - public void dump( final DataOutputStream out ) throws IOException { + public void dump(final DataOutputStream out) throws IOException { out.writeByte(super.getOpcode()); out.writeShort(super.getIndex()); out.writeByte(nargs); out.writeByte(0); } - /** - * The count argument according to the Java Language Specification, - * Second Edition. + * The count argument according to the Java Language Specification, Second Edition. */ public int getCount() { return nargs; } + @Override + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_INTERFACE_METHOD_RESOLUTION, ExceptionConst.UNSATISFIED_LINK_ERROR, + ExceptionConst.ABSTRACT_METHOD_ERROR, ExceptionConst.ILLEGAL_ACCESS_ERROR, ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); + } /** * Read needed data (i.e., index) from file. */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { super.initFromFile(bytes, wide); super.setLength(5); nargs = bytes.readUnsignedByte(); bytes.readByte(); // Skip 0 byte } - /** * @return mnemonic for instruction with symbolic references resolved */ @Override - public String toString( final ConstantPool cp ) { + public String toString(final ConstantPool cp) { return super.toString(cp) + " " + nargs; } - - - @Override - public int consumeStack( final ConstantPoolGen cpg ) { // nargs is given in byte-code - return nargs; // nargs includes this reference - } - - - @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_INTERFACE_METHOD_RESOLUTION, - ExceptionConst.UNSATISFIED_LINK_ERROR, - ExceptionConst.ABSTRACT_METHOD_ERROR, - ExceptionConst.ILLEGAL_ACCESS_ERROR, - ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); - } - - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. - * - * @param v Visitor object - */ - @Override - public void accept( final Visitor v ) { - v.visitExceptionThrower(this); - v.visitTypedInstruction(this); - v.visitStackConsumer(this); - v.visitStackProducer(this); - v.visitLoadClass(this); - v.visitCPInstruction(this); - v.visitFieldOrMethod(this); - v.visitInvokeInstruction(this); - v.visitINVOKEINTERFACE(this); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKESPECIAL.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKESPECIAL.java index ce27d07fd20..4fdff394241 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKESPECIAL.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKESPECIAL.java @@ -28,60 +28,36 @@ import com.sun.org.apache.bcel.internal.ExceptionConst; /** - * INVOKESPECIAL - Invoke instance method; special handling for superclass, private - * and instance initialization method invocations + * INVOKESPECIAL - Invoke instance method; special handling for superclass, private and instance initialization method + * invocations * - *
    Stack: ..., objectref, [arg1, [arg2 ...]] -> ...
    + *
    + * Stack: ..., objectref, [arg1, [arg2 ...]] -> ...
    + * 
    * - * @see - * - * The invokespecial instruction in The Java Virtual Machine Specification + * @see The + * invokespecial instruction in The Java Virtual Machine Specification */ public class INVOKESPECIAL extends InvokeInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ INVOKESPECIAL() { } - public INVOKESPECIAL(final int index) { super(Const.INVOKESPECIAL, index); } - - /** - * Dump instruction as byte code to stream out. - * @param out Output stream - */ - @Override - public void dump( final DataOutputStream out ) throws IOException { - out.writeByte(super.getOpcode()); - out.writeShort(super.getIndex()); - } - - @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, - ExceptionConst.NULL_POINTER_EXCEPTION, - ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR, - ExceptionConst.ABSTRACT_METHOD_ERROR, - ExceptionConst.UNSATISFIED_LINK_ERROR); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackConsumer(this); @@ -92,4 +68,21 @@ public void accept( final Visitor v ) { v.visitInvokeInstruction(this); v.visitINVOKESPECIAL(this); } + + /** + * Dump instruction as byte code to stream out. + * + * @param out Output stream + */ + @Override + public void dump(final DataOutputStream out) throws IOException { + out.writeByte(super.getOpcode()); + out.writeShort(super.getIndex()); + } + + @Override + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, ExceptionConst.NULL_POINTER_EXCEPTION, + ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR, ExceptionConst.ABSTRACT_METHOD_ERROR, ExceptionConst.UNSATISFIED_LINK_ERROR); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKESTATIC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKESTATIC.java index a89702514a2..c9c7dcdab63 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKESTATIC.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKESTATIC.java @@ -30,55 +30,33 @@ /** * INVOKESTATIC - Invoke a class (static) method * - *
    Stack: ..., [arg1, [arg2 ...]] -> ...
    + *
    + * Stack: ..., [arg1, [arg2 ...]] -> ...
    + * 
    * - * @see - * - * The invokestatic instruction in The Java Virtual Machine Specification + * @see The invokestatic + * instruction in The Java Virtual Machine Specification */ public class INVOKESTATIC extends InvokeInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ INVOKESTATIC() { } - public INVOKESTATIC(final int index) { super(Const.INVOKESTATIC, index); } - - /** - * Dump instruction as byte code to stream out. - * @param out Output stream - */ - @Override - public void dump( final DataOutputStream out ) throws IOException { - out.writeByte(super.getOpcode()); - out.writeShort(super.getIndex()); - } - - @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, - ExceptionConst.UNSATISFIED_LINK_ERROR, - ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackConsumer(this); @@ -89,4 +67,21 @@ public void accept( final Visitor v ) { v.visitInvokeInstruction(this); v.visitINVOKESTATIC(this); } + + /** + * Dump instruction as byte code to stream out. + * + * @param out Output stream + */ + @Override + public void dump(final DataOutputStream out) throws IOException { + out.writeByte(super.getOpcode()); + out.writeShort(super.getIndex()); + } + + @Override + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, ExceptionConst.UNSATISFIED_LINK_ERROR, + ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEVIRTUAL.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEVIRTUAL.java index bd5a2b5fd07..09961236e2d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEVIRTUAL.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEVIRTUAL.java @@ -30,57 +30,33 @@ /** * INVOKEVIRTUAL - Invoke instance method; dispatch based on class * - *
    Stack: ..., objectref, [arg1, [arg2 ...]] -> ...
    + *
    + * Stack: ..., objectref, [arg1, [arg2 ...]] -> ...
    + * 
    * - * @see - * - * The invokevirtual instruction in The Java Virtual Machine Specification + * @see The + * invokevirtual instruction in The Java Virtual Machine Specification */ public class INVOKEVIRTUAL extends InvokeInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ INVOKEVIRTUAL() { } - public INVOKEVIRTUAL(final int index) { super(Const.INVOKEVIRTUAL, index); } - - /** - * Dump instruction as byte code to stream out. - * @param out Output stream - */ - @Override - public void dump( final DataOutputStream out ) throws IOException { - out.writeByte(super.getOpcode()); - out.writeShort(super.getIndex()); - } - - @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, - ExceptionConst.NULL_POINTER_EXCEPTION, - ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR, - ExceptionConst.ABSTRACT_METHOD_ERROR, - ExceptionConst.UNSATISFIED_LINK_ERROR); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackConsumer(this); @@ -91,4 +67,21 @@ public void accept( final Visitor v ) { v.visitInvokeInstruction(this); v.visitINVOKEVIRTUAL(this); } + + /** + * Dump instruction as byte code to stream out. + * + * @param out Output stream + */ + @Override + public void dump(final DataOutputStream out) throws IOException { + out.writeByte(super.getOpcode()); + out.writeShort(super.getIndex()); + } + + @Override + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, ExceptionConst.NULL_POINTER_EXCEPTION, + ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR, ExceptionConst.ABSTRACT_METHOD_ERROR, ExceptionConst.UNSATISFIED_LINK_ERROR); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IOR.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IOR.java index 0589c4b8297..9f9ee094e2d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IOR.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IOR.java @@ -23,8 +23,10 @@ /** * IOR - Bitwise OR int - *
    Stack: ..., value1, value2 -> ..., result
    * + *
    + * Stack: ..., value1, value2 -> ..., result
    + * 
    */ public class IOR extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public IOR() { super(com.sun.org.apache.bcel.internal.Const.IOR); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IREM.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IREM.java index 984cf31fcf7..34b11f42d0e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IREM.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IREM.java @@ -24,39 +24,29 @@ /** * IREM - Remainder of int - *
    Stack: ..., value1, value2 -> result
    * + *
    + * Stack: ..., value1, value2 -> result
    + * 
    * @LastModified: Jan 2020 */ public class IREM extends ArithmeticInstruction implements ExceptionThrower { - /** Remainder of ints + /** + * Remainder of ints */ public IREM() { super(com.sun.org.apache.bcel.internal.Const.IREM); } - - /** @return exceptions this instruction may cause - */ - @Override - public Class[] getExceptions() { - return new Class[] { - ExceptionConst.ARITHMETIC_EXCEPTION - }; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackProducer(this); @@ -64,4 +54,12 @@ public void accept( final Visitor v ) { v.visitArithmeticInstruction(this); v.visitIREM(this); } + + /** + * @return exceptions this instruction may cause + */ + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConst.ARITHMETIC_EXCEPTION}; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IRETURN.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IRETURN.java index 894738ffe4a..80c3bfba744 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IRETURN.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IRETURN.java @@ -22,29 +22,29 @@ package com.sun.org.apache.bcel.internal.generic; /** - * IRETURN - Return int from method - *
    Stack: ..., value -> <empty>
    + * IRETURN - Return int from method * + *
    + * Stack: ..., value -> <empty>
    + * 
    */ public class IRETURN extends ReturnInstruction { - /** Return int from method + /** + * Return int from method */ public IRETURN() { super(com.sun.org.apache.bcel.internal.Const.IRETURN); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISHL.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISHL.java index 67482bf7633..2e762db8969 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISHL.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISHL.java @@ -23,8 +23,10 @@ /** * ISHL - Arithmetic shift left int - *
    Stack: ..., value1, value2 -> ..., result
    * + *
    + * Stack: ..., value1, value2 -> ..., result
    + * 
    */ public class ISHL extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public ISHL() { super(com.sun.org.apache.bcel.internal.Const.ISHL); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISHR.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISHR.java index 1729abb7ecd..c5e3906173a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISHR.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISHR.java @@ -23,8 +23,10 @@ /** * ISHR - Arithmetic shift right int - *
    Stack: ..., value1, value2 -> ..., result
    * + *
    + * Stack: ..., value1, value2 -> ..., result
    + * 
    */ public class ISHR extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public ISHR() { super(com.sun.org.apache.bcel.internal.Const.ISHR); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISTORE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISTORE.java index d27b087dc30..76d8f930f8d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISTORE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISTORE.java @@ -23,38 +23,37 @@ /** * ISTORE - Store int from stack into local variable - *
    Stack: ..., value -> ... 
    * + *
    + * Stack: ..., value -> ...
    + * 
    */ public class ISTORE extends StoreInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ ISTORE() { super(com.sun.org.apache.bcel.internal.Const.ISTORE, com.sun.org.apache.bcel.internal.Const.ISTORE_0); } - - /** Store int into local variable + /** + * Store int into local variable + * * @param n index of local variable */ public ISTORE(final int n) { super(com.sun.org.apache.bcel.internal.Const.ISTORE, com.sun.org.apache.bcel.internal.Const.ISTORE_0, n); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { super.accept(v); v.visitISTORE(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISUB.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISUB.java index 60d67a47e25..571751ce33e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISUB.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ISUB.java @@ -23,28 +23,28 @@ /** * ISUB - Substract ints - *
    Stack: ..., value1, value2 -> result
    * + *
    + * Stack: ..., value1, value2 -> result
    + * 
    */ public class ISUB extends ArithmeticInstruction { - /** Substract ints + /** + * Substract ints */ public ISUB() { super(com.sun.org.apache.bcel.internal.Const.ISUB); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IUSHR.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IUSHR.java index 0434d28889c..89236a0afa9 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IUSHR.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IUSHR.java @@ -23,8 +23,10 @@ /** * IUSHR - Logical shift right int - *
    Stack: ..., value1, value2 -> ..., result
    * + *
    + * Stack: ..., value1, value2 -> ..., result
    + * 
    */ public class IUSHR extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public IUSHR() { super(com.sun.org.apache.bcel.internal.Const.IUSHR); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IXOR.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IXOR.java index 5aae103fd61..1006f3d3841 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IXOR.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IXOR.java @@ -23,8 +23,10 @@ /** * IXOR - Bitwise XOR int - *
    Stack: ..., value1, value2 -> ..., result
    * + *
    + * Stack: ..., value1, value2 -> ..., result
    + * 
    */ public class IXOR extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public IXOR() { super(com.sun.org.apache.bcel.internal.Const.IXOR); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IfInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IfInstruction.java index be02b847107..b4be83ebdc2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IfInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IfInstruction.java @@ -23,18 +23,15 @@ /** * Super class for the IFxxx family of instructions. - * */ public abstract class IfInstruction extends BranchInstruction implements StackConsumer { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ IfInstruction() { } - /** * @param opcode opcode of instruction * @param target Target instruction to branch to @@ -43,7 +40,6 @@ protected IfInstruction(final short opcode, final InstructionHandle target) { super(opcode, target); } - /** * @return negation of instruction, e.g. IFEQ.negate() == IFNE */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IndexedInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IndexedInstruction.java index f84d2839d30..f9846297614 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IndexedInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/IndexedInstruction.java @@ -22,14 +22,11 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Denote entity that refers to an index, e.g. local variable instructions, - * RET, CPInstruction, etc. - * + * Denote entity that refers to an index, e.g. local variable instructions, RET, CPInstruction, etc. */ public interface IndexedInstruction { int getIndex(); - - void setIndex( int index ); + void setIndex(int index); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java index 20188a9f16a..16c8e2444b4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -29,127 +29,59 @@ /** * Abstract super class for all Java byte codes. * - * @LastModified: July 2020 + * @LastModified: Feb 2023 */ public abstract class Instruction implements Cloneable { - private short length = 1; // Length of instruction in bytes - private short opcode = -1; // Opcode number + static final Instruction[] EMPTY_ARRAY = {}; private static InstructionComparator cmp = InstructionComparator.DEFAULT; - /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. - */ - Instruction() { - } - - - public Instruction(final short opcode, final short length) { - this.length = length; - this.opcode = opcode; - } - - - /** - * Dump instruction as byte code to stream out. - * @param out Output stream - */ - public void dump( final DataOutputStream out ) throws IOException { - out.writeByte(opcode); // Common for all instructions - } - - - /** @return name of instruction, i.e., opcode name - */ - public String getName() { - return Const.getOpcodeName(opcode); - } - - - /** - * Long output format: - * - * <name of opcode> "["<opcode number>"]" - * "("<length of instruction>")" + * Gets Comparator object used in the equals() method to determine equality of instructions. * - * @param verbose long/short format switch - * @return mnemonic for instruction - */ - public String toString( final boolean verbose ) { - if (verbose) { - return getName() + "[" + opcode + "](" + length + ")"; - } - return getName(); - } - - - /** - * @return mnemonic for instruction in verbose format - */ - @Override - public String toString() { - return toString(true); - } - - - /** - * @return mnemonic for instruction with sumbolic references resolved + * @return currently used comparator for equals() + * @deprecated (6.0) use the built in comparator, or wrap this class in another object that implements these methods */ - public String toString( final ConstantPool cp ) { - return toString(false); + @Deprecated + public static InstructionComparator getComparator() { + return cmp; } - /** - * Use with caution, since `BranchInstruction's have a `target' reference which - * is not copied correctly (only basic types are). This also applies for - * `Select' instructions with their multiple branch targets. + * Tests if the value can fit in a byte (signed) * - * @see BranchInstruction - * @return (shallow) copy of an instruction + * @param value the value to check + * @return true if the value is in range + * @since 6.0 */ - public Instruction copy() { - Instruction i = null; - // "Constant" instruction, no need to duplicate - if (InstructionConst.getInstruction(this.getOpcode()) != null) { - i = this; - } else { - try { - i = (Instruction) clone(); - } catch (final CloneNotSupportedException e) { - System.err.println(e); - } - } - return i; + public static boolean isValidByte(final int value) { + return value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE; } - /** - * Read needed data (e.g. index) from file. + * Tests if the value can fit in a short (signed) * - * @param bytes byte sequence to read from - * @param wide "wide" instruction flag - * @throws IOException may be thrown if the implementation needs to read data from the file + * @param value the value to check + * @return true if the value is in range + * @since 6.0 */ - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { + public static boolean isValidShort(final int value) { + return value >= Short.MIN_VALUE && value <= Short.MAX_VALUE; } - /** - * Read an instruction from (byte code) input stream and return the - * appropiate object. + * Reads an instruction from (byte code) input stream and return the appropriate object. *

    - * If the Instruction is defined in {@link InstructionConst}, then the - * singleton instance is returned. + * If the Instruction is defined in {@link InstructionConst}, then the singleton instance is returned. + *

    * @param bytes input stream bytes * @return instruction object being read + * @throws IOException Thrown when an I/O exception of some sort has occurred. * @see InstructionConst#getInstruction(int) */ // @since 6.0 no longer final - public static Instruction readInstruction( final ByteSequence bytes ) throws IOException { + public static Instruction readInstruction(final ByteSequence bytes) throws IOException { boolean wide = false; short opcode = (short) bytes.readUnsignedByte(); Instruction obj = null; @@ -163,304 +95,303 @@ public static Instruction readInstruction( final ByteSequence bytes ) throws IOE } switch (opcode) { - case Const.BIPUSH: - obj = new BIPUSH(); - break; - case Const.SIPUSH: - obj = new SIPUSH(); - break; - case Const.LDC: - obj = new LDC(); - break; - case Const.LDC_W: - obj = new LDC_W(); - break; - case Const.LDC2_W: - obj = new LDC2_W(); - break; - case Const.ILOAD: - obj = new ILOAD(); - break; - case Const.LLOAD: - obj = new LLOAD(); - break; - case Const.FLOAD: - obj = new FLOAD(); - break; - case Const.DLOAD: - obj = new DLOAD(); - break; - case Const.ALOAD: - obj = new ALOAD(); - break; - case Const.ILOAD_0: - obj = new ILOAD(0); - break; - case Const.ILOAD_1: - obj = new ILOAD(1); - break; - case Const.ILOAD_2: - obj = new ILOAD(2); - break; - case Const.ILOAD_3: - obj = new ILOAD(3); - break; - case Const.LLOAD_0: - obj = new LLOAD(0); - break; - case Const.LLOAD_1: - obj = new LLOAD(1); - break; - case Const.LLOAD_2: - obj = new LLOAD(2); - break; - case Const.LLOAD_3: - obj = new LLOAD(3); - break; - case Const.FLOAD_0: - obj = new FLOAD(0); - break; - case Const.FLOAD_1: - obj = new FLOAD(1); - break; - case Const.FLOAD_2: - obj = new FLOAD(2); - break; - case Const.FLOAD_3: - obj = new FLOAD(3); - break; - case Const.DLOAD_0: - obj = new DLOAD(0); - break; - case Const.DLOAD_1: - obj = new DLOAD(1); - break; - case Const.DLOAD_2: - obj = new DLOAD(2); - break; - case Const.DLOAD_3: - obj = new DLOAD(3); - break; - case Const.ALOAD_0: - obj = new ALOAD(0); - break; - case Const.ALOAD_1: - obj = new ALOAD(1); - break; - case Const.ALOAD_2: - obj = new ALOAD(2); - break; - case Const.ALOAD_3: - obj = new ALOAD(3); - break; - case Const.ISTORE: - obj = new ISTORE(); - break; - case Const.LSTORE: - obj = new LSTORE(); - break; - case Const.FSTORE: - obj = new FSTORE(); - break; - case Const.DSTORE: - obj = new DSTORE(); - break; - case Const.ASTORE: - obj = new ASTORE(); - break; - case Const.ISTORE_0: - obj = new ISTORE(0); - break; - case Const.ISTORE_1: - obj = new ISTORE(1); - break; - case Const.ISTORE_2: - obj = new ISTORE(2); - break; - case Const.ISTORE_3: - obj = new ISTORE(3); - break; - case Const.LSTORE_0: - obj = new LSTORE(0); - break; - case Const.LSTORE_1: - obj = new LSTORE(1); - break; - case Const.LSTORE_2: - obj = new LSTORE(2); - break; - case Const.LSTORE_3: - obj = new LSTORE(3); - break; - case Const.FSTORE_0: - obj = new FSTORE(0); - break; - case Const.FSTORE_1: - obj = new FSTORE(1); - break; - case Const.FSTORE_2: - obj = new FSTORE(2); - break; - case Const.FSTORE_3: - obj = new FSTORE(3); - break; - case Const.DSTORE_0: - obj = new DSTORE(0); - break; - case Const.DSTORE_1: - obj = new DSTORE(1); - break; - case Const.DSTORE_2: - obj = new DSTORE(2); - break; - case Const.DSTORE_3: - obj = new DSTORE(3); - break; - case Const.ASTORE_0: - obj = new ASTORE(0); - break; - case Const.ASTORE_1: - obj = new ASTORE(1); - break; - case Const.ASTORE_2: - obj = new ASTORE(2); - break; - case Const.ASTORE_3: - obj = new ASTORE(3); - break; - case Const.IINC: - obj = new IINC(); - break; - case Const.IFEQ: - obj = new IFEQ(); - break; - case Const.IFNE: - obj = new IFNE(); - break; - case Const.IFLT: - obj = new IFLT(); - break; - case Const.IFGE: - obj = new IFGE(); - break; - case Const.IFGT: - obj = new IFGT(); - break; - case Const.IFLE: - obj = new IFLE(); - break; - case Const.IF_ICMPEQ: - obj = new IF_ICMPEQ(); - break; - case Const.IF_ICMPNE: - obj = new IF_ICMPNE(); - break; - case Const.IF_ICMPLT: - obj = new IF_ICMPLT(); - break; - case Const.IF_ICMPGE: - obj = new IF_ICMPGE(); - break; - case Const.IF_ICMPGT: - obj = new IF_ICMPGT(); - break; - case Const.IF_ICMPLE: - obj = new IF_ICMPLE(); - break; - case Const.IF_ACMPEQ: - obj = new IF_ACMPEQ(); - break; - case Const.IF_ACMPNE: - obj = new IF_ACMPNE(); - break; - case Const.GOTO: - obj = new GOTO(); - break; - case Const.JSR: - obj = new JSR(); - break; - case Const.RET: - obj = new RET(); - break; - case Const.TABLESWITCH: - obj = new TABLESWITCH(); - break; - case Const.LOOKUPSWITCH: - obj = new LOOKUPSWITCH(); - break; - case Const.GETSTATIC: - obj = new GETSTATIC(); - break; - case Const.PUTSTATIC: - obj = new PUTSTATIC(); - break; - case Const.GETFIELD: - obj = new GETFIELD(); - break; - case Const.PUTFIELD: - obj = new PUTFIELD(); - break; - case Const.INVOKEVIRTUAL: - obj = new INVOKEVIRTUAL(); - break; - case Const.INVOKESPECIAL: - obj = new INVOKESPECIAL(); - break; - case Const.INVOKESTATIC: - obj = new INVOKESTATIC(); - break; - case Const.INVOKEINTERFACE: - obj = new INVOKEINTERFACE(); - break; - case Const.INVOKEDYNAMIC: - obj = new INVOKEDYNAMIC(); - break; - case Const.NEW: - obj = new NEW(); - break; - case Const.NEWARRAY: - obj = new NEWARRAY(); - break; - case Const.ANEWARRAY: - obj = new ANEWARRAY(); - break; - case Const.CHECKCAST: - obj = new CHECKCAST(); - break; - case Const.INSTANCEOF: - obj = new INSTANCEOF(); - break; - case Const.MULTIANEWARRAY: - obj = new MULTIANEWARRAY(); - break; - case Const.IFNULL: - obj = new IFNULL(); - break; - case Const.IFNONNULL: - obj = new IFNONNULL(); - break; - case Const.GOTO_W: - obj = new GOTO_W(); - break; - case Const.JSR_W: - obj = new JSR_W(); - break; - case Const.BREAKPOINT: - obj = new BREAKPOINT(); - break; - case Const.IMPDEP1: - obj = new IMPDEP1(); - break; - case Const.IMPDEP2: - obj = new IMPDEP2(); - break; - default: - throw new ClassGenException("Illegal opcode detected: " + opcode); + case Const.BIPUSH: + obj = new BIPUSH(); + break; + case Const.SIPUSH: + obj = new SIPUSH(); + break; + case Const.LDC: + obj = new LDC(); + break; + case Const.LDC_W: + obj = new LDC_W(); + break; + case Const.LDC2_W: + obj = new LDC2_W(); + break; + case Const.ILOAD: + obj = new ILOAD(); + break; + case Const.LLOAD: + obj = new LLOAD(); + break; + case Const.FLOAD: + obj = new FLOAD(); + break; + case Const.DLOAD: + obj = new DLOAD(); + break; + case Const.ALOAD: + obj = new ALOAD(); + break; + case Const.ILOAD_0: + obj = new ILOAD(0); + break; + case Const.ILOAD_1: + obj = new ILOAD(1); + break; + case Const.ILOAD_2: + obj = new ILOAD(2); + break; + case Const.ILOAD_3: + obj = new ILOAD(3); + break; + case Const.LLOAD_0: + obj = new LLOAD(0); + break; + case Const.LLOAD_1: + obj = new LLOAD(1); + break; + case Const.LLOAD_2: + obj = new LLOAD(2); + break; + case Const.LLOAD_3: + obj = new LLOAD(3); + break; + case Const.FLOAD_0: + obj = new FLOAD(0); + break; + case Const.FLOAD_1: + obj = new FLOAD(1); + break; + case Const.FLOAD_2: + obj = new FLOAD(2); + break; + case Const.FLOAD_3: + obj = new FLOAD(3); + break; + case Const.DLOAD_0: + obj = new DLOAD(0); + break; + case Const.DLOAD_1: + obj = new DLOAD(1); + break; + case Const.DLOAD_2: + obj = new DLOAD(2); + break; + case Const.DLOAD_3: + obj = new DLOAD(3); + break; + case Const.ALOAD_0: + obj = new ALOAD(0); + break; + case Const.ALOAD_1: + obj = new ALOAD(1); + break; + case Const.ALOAD_2: + obj = new ALOAD(2); + break; + case Const.ALOAD_3: + obj = new ALOAD(3); + break; + case Const.ISTORE: + obj = new ISTORE(); + break; + case Const.LSTORE: + obj = new LSTORE(); + break; + case Const.FSTORE: + obj = new FSTORE(); + break; + case Const.DSTORE: + obj = new DSTORE(); + break; + case Const.ASTORE: + obj = new ASTORE(); + break; + case Const.ISTORE_0: + obj = new ISTORE(0); + break; + case Const.ISTORE_1: + obj = new ISTORE(1); + break; + case Const.ISTORE_2: + obj = new ISTORE(2); + break; + case Const.ISTORE_3: + obj = new ISTORE(3); + break; + case Const.LSTORE_0: + obj = new LSTORE(0); + break; + case Const.LSTORE_1: + obj = new LSTORE(1); + break; + case Const.LSTORE_2: + obj = new LSTORE(2); + break; + case Const.LSTORE_3: + obj = new LSTORE(3); + break; + case Const.FSTORE_0: + obj = new FSTORE(0); + break; + case Const.FSTORE_1: + obj = new FSTORE(1); + break; + case Const.FSTORE_2: + obj = new FSTORE(2); + break; + case Const.FSTORE_3: + obj = new FSTORE(3); + break; + case Const.DSTORE_0: + obj = new DSTORE(0); + break; + case Const.DSTORE_1: + obj = new DSTORE(1); + break; + case Const.DSTORE_2: + obj = new DSTORE(2); + break; + case Const.DSTORE_3: + obj = new DSTORE(3); + break; + case Const.ASTORE_0: + obj = new ASTORE(0); + break; + case Const.ASTORE_1: + obj = new ASTORE(1); + break; + case Const.ASTORE_2: + obj = new ASTORE(2); + break; + case Const.ASTORE_3: + obj = new ASTORE(3); + break; + case Const.IINC: + obj = new IINC(); + break; + case Const.IFEQ: + obj = new IFEQ(); + break; + case Const.IFNE: + obj = new IFNE(); + break; + case Const.IFLT: + obj = new IFLT(); + break; + case Const.IFGE: + obj = new IFGE(); + break; + case Const.IFGT: + obj = new IFGT(); + break; + case Const.IFLE: + obj = new IFLE(); + break; + case Const.IF_ICMPEQ: + obj = new IF_ICMPEQ(); + break; + case Const.IF_ICMPNE: + obj = new IF_ICMPNE(); + break; + case Const.IF_ICMPLT: + obj = new IF_ICMPLT(); + break; + case Const.IF_ICMPGE: + obj = new IF_ICMPGE(); + break; + case Const.IF_ICMPGT: + obj = new IF_ICMPGT(); + break; + case Const.IF_ICMPLE: + obj = new IF_ICMPLE(); + break; + case Const.IF_ACMPEQ: + obj = new IF_ACMPEQ(); + break; + case Const.IF_ACMPNE: + obj = new IF_ACMPNE(); + break; + case Const.GOTO: + obj = new GOTO(); + break; + case Const.JSR: + obj = new JSR(); + break; + case Const.RET: + obj = new RET(); + break; + case Const.TABLESWITCH: + obj = new TABLESWITCH(); + break; + case Const.LOOKUPSWITCH: + obj = new LOOKUPSWITCH(); + break; + case Const.GETSTATIC: + obj = new GETSTATIC(); + break; + case Const.PUTSTATIC: + obj = new PUTSTATIC(); + break; + case Const.GETFIELD: + obj = new GETFIELD(); + break; + case Const.PUTFIELD: + obj = new PUTFIELD(); + break; + case Const.INVOKEVIRTUAL: + obj = new INVOKEVIRTUAL(); + break; + case Const.INVOKESPECIAL: + obj = new INVOKESPECIAL(); + break; + case Const.INVOKESTATIC: + obj = new INVOKESTATIC(); + break; + case Const.INVOKEINTERFACE: + obj = new INVOKEINTERFACE(); + break; + case Const.INVOKEDYNAMIC: + obj = new INVOKEDYNAMIC(); + break; + case Const.NEW: + obj = new NEW(); + break; + case Const.NEWARRAY: + obj = new NEWARRAY(); + break; + case Const.ANEWARRAY: + obj = new ANEWARRAY(); + break; + case Const.CHECKCAST: + obj = new CHECKCAST(); + break; + case Const.INSTANCEOF: + obj = new INSTANCEOF(); + break; + case Const.MULTIANEWARRAY: + obj = new MULTIANEWARRAY(); + break; + case Const.IFNULL: + obj = new IFNULL(); + break; + case Const.IFNONNULL: + obj = new IFNONNULL(); + break; + case Const.GOTO_W: + obj = new GOTO_W(); + break; + case Const.JSR_W: + obj = new JSR_W(); + break; + case Const.BREAKPOINT: + obj = new BREAKPOINT(); + break; + case Const.IMPDEP1: + obj = new IMPDEP1(); + break; + case Const.IMPDEP2: + obj = new IMPDEP2(); + break; + default: + throw new ClassGenException("Illegal opcode detected: " + opcode); } - if (wide - && !((obj instanceof LocalVariableInstruction) || (obj instanceof IINC) || (obj instanceof RET))) { + if (wide && !(obj instanceof LocalVariableInstruction || obj instanceof RET)) { throw new ClassGenException("Illegal opcode after wide: " + opcode); } obj.setOpcode(opcode); @@ -469,109 +400,129 @@ public static Instruction readInstruction( final ByteSequence bytes ) throws IOE } /** - * This method also gives right results for instructions whose - * effect on the stack depends on the constant pool entry they - * reference. - * @return Number of words consumed from stack by this instruction, - * or Constants.UNPREDICTABLE, if this can not be computed statically + * Sets comparator to be used for equals(). + * + * @deprecated (6.0) use the built in comparator, or wrap this class in another object that implements these methods */ - public int consumeStack( final ConstantPoolGen cpg ) { - return Const.getConsumeStack(opcode); + @Deprecated + public static void setComparator(final InstructionComparator c) { + cmp = c; } - /** - * This method also gives right results for instructions whose - * effect on the stack depends on the constant pool entry they - * reference. - * @return Number of words produced onto stack by this instruction, - * or Constants.UNPREDICTABLE, if this can not be computed statically + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter */ - public int produceStack( final ConstantPoolGen cpg ) { - return Const.getProduceStack(opcode); - } + @Deprecated + protected short length = 1; // Length of instruction in bytes + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected short opcode = -1; // Opcode number /** - * @return this instructions opcode + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ - public short getOpcode() { - return opcode; + Instruction() { } + public Instruction(final short opcode, final short length) { + this.length = length; + this.opcode = opcode; + } /** - * @return length (in bytes) of instruction + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object */ - public int getLength() { - return length; - } - + public abstract void accept(Visitor v); /** - * Needed in readInstruction and subclasses in this package + * This method also gives right results for instructions whose effect on the stack depends on the constant pool entry + * they reference. + * + * @return Number of words consumed from stack by this instruction, or Constants.UNPREDICTABLE, if this can not be + * computed statically */ - void setOpcode( final short opcode ) { - this.opcode = opcode; + public int consumeStack(final ConstantPoolGen cpg) { + return Const.getConsumeStack(opcode); } - /** - * Needed in readInstruction and subclasses in this package - * @since 6.0 + * Use with caution, since 'BranchInstruction's have a 'target' reference which is not copied correctly (only basic + * types are). This also applies for 'Select' instructions with their multiple branch targets. + * + * @see BranchInstruction + * @return (shallow) copy of an instruction */ - final void setLength( final int length ) { - this.length = (short) length; // TODO check range? + public Instruction copy() { + Instruction i = null; + // "Constant" instruction, no need to duplicate + if (InstructionConst.getInstruction(this.getOpcode()) != null) { + i = this; + } else { + try { + i = (Instruction) clone(); + } catch (final CloneNotSupportedException e) { + System.err.println(e); + } + } + return i; } - - /** Some instructions may be reused, so don't do anything by default. + /** + * Some instructions may be reused, so don't do anything by default. */ void dispose() { } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Dumps instruction as byte code to stream out. * - * @param v Visitor object + * @param out Output stream + * @throws IOException Thrown when an I/O exception of some sort has occurred. */ - public abstract void accept( Visitor v ); - + public void dump(final DataOutputStream out) throws IOException { + out.writeByte(opcode); // Common for all instructions + } - /** Get Comparator object used in the equals() method to determine - * equality of instructions. + /** + * Tests for equality, delegated to comparator * - * @return currently used comparator for equals() - * @deprecated (6.0) use the built in comparator, or wrap this class in another object that implements these methods + * @return true if that is an Instruction and has the same opcode */ - @Deprecated - public static InstructionComparator getComparator() { - return cmp; + @Override + public boolean equals(final Object that) { + return that instanceof Instruction && cmp.equals(this, (Instruction) that); } - - /** Set comparator to be used for equals(). - * @deprecated (6.0) use the built in comparator, or wrap this class in another object that implements these methods + /** + * @return length (in bytes) of instruction */ - @Deprecated - public static void setComparator( final InstructionComparator c ) { - cmp = c; + public int getLength() { + return length; } + /** + * @return name of instruction, i.e., opcode name + */ + public String getName() { + return Const.getOpcodeName(opcode); + } - /** Check for equality, delegated to comparator - * @return true if that is an Instruction and has the same opcode + /** + * @return this instructions opcode */ - @Override - public boolean equals( final Object that ) { - return (that instanceof Instruction) ? cmp.equals(this, (Instruction) that) : false; + public short getOpcode() { + return opcode; } - /** calculate the hashCode of this object + /** + * Gets the hashCode of this object. + * * @return the hashCode * @since 6.0 */ @@ -581,22 +532,70 @@ public int hashCode() { } /** - * Check if the value can fit in a byte (signed) - * @param value the value to check - * @return true if the value is in range - * @since 6.0 + * Reads needed data (e.g. index) from file. + * + * @param bytes byte sequence to read from + * @param wide "wide" instruction flag + * @throws IOException may be thrown if the implementation needs to read data from the file */ - public static boolean isValidByte(final int value) { - return value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE; + @SuppressWarnings("unused") // thrown by subclasses + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { } /** - * Check if the value can fit in a short (signed) - * @param value the value to check - * @return true if the value is in range + * This method also gives right results for instructions whose effect on the stack depends on the constant pool entry + * they reference. + * + * @return Number of words produced onto stack by this instruction, or Constants.UNPREDICTABLE, if this can not be + * computed statically + */ + public int produceStack(final ConstantPoolGen cpg) { + return Const.getProduceStack(opcode); + } + + /** + * Needed in readInstruction and subclasses in this package + * * @since 6.0 */ - public static boolean isValidShort(final int value) { - return value >= Short.MIN_VALUE && value <= Short.MAX_VALUE; + final void setLength(final int length) { + this.length = (short) length; // TODO check range? + } + + /** + * Needed in readInstruction and subclasses in this package + */ + void setOpcode(final short opcode) { + this.opcode = opcode; + } + + /** + * @return mnemonic for instruction in verbose format + */ + @Override + public String toString() { + return toString(true); + } + + /** + * Long output format: + * + * <name of opcode> "["<opcode number>"]" "("<length of instruction>")" + * + * @param verbose long/short format switch + * @return mnemonic for instruction + */ + public String toString(final boolean verbose) { + if (verbose) { + return getName() + "[" + opcode + "](" + length + ")"; + } + return getName(); + } + + /** + * @return mnemonic for instruction with sumbolic references resolved + */ + public String toString(final ConstantPool cp) { + return toString(false); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionComparator.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionComparator.java index a3f3c2d45e9..9f806a2d3d7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionComparator.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionComparator.java @@ -22,15 +22,12 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Equality of instructions isn't clearly to be defined. You might - * wish, for example, to compare whether instructions have the same - * meaning. E.g., whether two INVOKEVIRTUALs describe the same - * call. + * Equality of instructions isn't clearly to be defined. You might wish, for example, to compare whether instructions + * have the same meaning. E.g., whether two INVOKEVIRTUALs describe the same call. *

    - * The DEFAULT comparator however, considers two instructions - * to be equal if they have same opcode and point to the same indexes - * (if any) in the constant pool or the same local variable index. Branch - * instructions must have the same target. + * The DEFAULT comparator however, considers two instructions to be equal if they have same opcode and point to the same + * indexes (if any) in the constant pool or the same local variable index. Branch instructions must have the same + * target. *

    * * @see Instruction @@ -40,25 +37,24 @@ public interface InstructionComparator { InstructionComparator DEFAULT = (i1, i2) -> { if (i1.getOpcode() == i2.getOpcode()) { if (i1 instanceof BranchInstruction) { - // BIs are never equal to make targeters work correctly (BCEL-195) + // BIs are never equal to make targeters work correctly (BCEL-195) return false; // } else if (i1 == i2) { TODO consider adding this shortcut // return true; // this must be AFTER the BI test - } else if (i1 instanceof ConstantPushInstruction) { - return ((ConstantPushInstruction) i1).getValue().equals( - ((ConstantPushInstruction) i2).getValue()); - } else if (i1 instanceof IndexedInstruction) { - return ((IndexedInstruction) i1).getIndex() == ((IndexedInstruction) i2) - .getIndex(); - } else if (i1 instanceof NEWARRAY) { + } + if (i1 instanceof ConstantPushInstruction) { + return ((ConstantPushInstruction) i1).getValue().equals(((ConstantPushInstruction) i2).getValue()); + } + if (i1 instanceof IndexedInstruction) { + return ((IndexedInstruction) i1).getIndex() == ((IndexedInstruction) i2).getIndex(); + } + if (i1 instanceof NEWARRAY) { return ((NEWARRAY) i1).getTypecode() == ((NEWARRAY) i2).getTypecode(); - } else { - return true; } + return true; } return false; }; - - boolean equals( Instruction i1, Instruction i2 ); + boolean equals(Instruction i1, Instruction i2); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java index fece96b10ca..439268e35eb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java @@ -24,28 +24,24 @@ import com.sun.org.apache.bcel.internal.Const; /** - * This interface contains shareable instruction objects. - * - * In order to save memory you can use some instructions multiply, - * since they have an immutable state and are directly derived from - * Instruction. I.e. they have no instance fields that could be - * changed. Since some of these instructions like ICONST_0 occur - * very frequently this can save a lot of time and space. This - * feature is an adaptation of the FlyWeight design pattern, we - * just use an array instead of a factory. - * - * The Instructions can also accessed directly under their names, so - * it's possible to write il.append(Instruction.ICONST_0); - * + * Contains shareable instruction objects. + *

    + * In order to save memory you can use some instructions multiply, since they have an immutable state and are directly + * derived from Instruction. I.e. they have no instance fields that could be changed. Since some of these instructions + * like ICONST_0 occur very frequently this can save a lot of time and space. This feature is an adaptation of the + * FlyWeight design pattern, we just use an array instead of a factory. + *

    + *

    + * The Instructions can also accessed directly under their names, so it's possible to write + * il.append(Instruction.ICONST_0); + *

    */ public final class InstructionConst { /** - * Predefined instruction objects - */ - /* - * NOTE these are not currently immutable, because Instruction - * has mutable protected fields opcode and length. + * Predefined instruction objects. + * + * NOTE these are not currently immutable, because Instruction has mutable protected fields opcode and length. */ public static final Instruction NOP = new NOP(); public static final Instruction ACONST_NULL = new ACONST_NULL(); @@ -155,8 +151,9 @@ public final class InstructionConst { public static final Instruction MONITORENTER = new MONITORENTER(); public static final Instruction MONITOREXIT = new MONITOREXIT(); - /** You can use these constants in multiple places safely, if you can guarantee - * that you will never alter their internal values, e.g. call setIndex(). + /** + * You can use these constants in multiple places safely, if you can guarantee that you will never alter their internal + * values, e.g. call setIndex(). */ public static final LocalVariableInstruction THIS = new ALOAD(0); public static final LocalVariableInstruction ALOAD_0 = THIS; @@ -172,10 +169,10 @@ public final class InstructionConst { public static final LocalVariableInstruction ISTORE_1 = new ISTORE(1); public static final LocalVariableInstruction ISTORE_2 = new ISTORE(2); - /** Get object via its opcode, for immutable instructions like - * branch instructions entries are set to null. + /** + * Get object via its opcode, for immutable instructions like branch instructions entries are set to null. */ - private static final Instruction[] INSTRUCTIONS = new Instruction[256]; + static final Instruction[] INSTRUCTIONS = new Instruction[256]; static { INSTRUCTIONS[Const.NOP] = NOP; @@ -287,14 +284,16 @@ public final class InstructionConst { INSTRUCTIONS[Const.MONITOREXIT] = MONITOREXIT; } - private InstructionConst() { } // non-instantiable - /** * Gets the Instruction. + * * @param index the index, e.g. {@link Const#RETURN} * @return the entry from the private INSTRUCTIONS table */ public static Instruction getInstruction(final int index) { return INSTRUCTIONS[index]; } + + private InstructionConst() { + } // non-instantiable } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java index d2ec08ed678..5e9220354c3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -22,672 +22,673 @@ import com.sun.org.apache.bcel.internal.Const; /** - * Instances of this class may be used, e.g., to generate typed - * versions of instructions. Its main purpose is to be used as the - * byte code generating backend of a compiler. You can subclass it to - * add your own create methods. + * Instances of this class may be used, e.g., to generate typed versions of instructions. Its main purpose is to be used + * as the byte code generating backend of a compiler. You can subclass it to add your own create methods. *

    - * Note: The static createXXX methods return singleton instances - * from the {@link InstructionConst} class. + * Note: The static createXXX methods return singleton instances from the {@link InstructionConst} class. + *

    * * @see Const * @see InstructionConst - * @LastModified: May 2021 + * @LastModified: Feb 2023 */ public class InstructionFactory { - // N.N. These must agree with the order of Constants.T_CHAR through T_LONG - private static final String[] short_names = { - "C", "F", "D", "B", "S", "I", "L" - }; - - private ClassGen cg; - private ConstantPoolGen cp; - - public InstructionFactory(final ClassGen cg, final ConstantPoolGen cp) { - this.cg = cg; - this.cp = cp; - } + private static class MethodObject { + final Type[] argTypes; + final Type resultType; + final String className; + final String name; - /** Initialize with ClassGen object - */ - public InstructionFactory(final ClassGen cg) { - this(cg, cg.getConstantPool()); + MethodObject(final String c, final String n, final Type r, final Type[] a) { + this.className = c; + this.name = n; + this.resultType = r; + this.argTypes = a; + } } + private static final String APPEND = "append"; - /** Initialize just with ConstantPoolGen object - */ - public InstructionFactory(final ConstantPoolGen cp) { - this(null, cp); - } - + private static final String FQCN_STRING_BUFFER = "java.lang.StringBuffer"; - /** Create an invoke instruction. (Except for invokedynamic.) - * - * @param class_name name of the called class - * @param name name of the called method - * @param ret_type return type of method - * @param arg_types argument types of method - * @param kind how to invoke, i.e., INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL, - * or INVOKESPECIAL - * @see Const - */ - public InvokeInstruction createInvoke( final String class_name, final String name, - final Type ret_type, final Type[] arg_types, final short kind ) { - return createInvoke(class_name, name, ret_type, arg_types, kind, kind == Const.INVOKEINTERFACE); - } + // N.N. These must agree with the order of Constants.T_CHAR through T_LONG + private static final String[] shortNames = {"C", "F", "D", "B", "S", "I", "L"}; + + private static final MethodObject[] appendMethodObjects = { + new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.STRING }), + new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.OBJECT }), null, null, // indices 2, 3 + new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.BOOLEAN }), + new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.CHAR }), + new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.FLOAT }), + new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.DOUBLE }), + new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.INT }), + new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.INT }), // No append(byte) + new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.INT }), // No append(short) + new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.LONG })}; /** - * Creates an invoke instruction. (Except for invokedynamic.) - * - * @param class_name name of the called class - * @param name name of the called method - * @param ret_type return type of method - * @param arg_types argument types of method - * @param kind how to invoke: INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL, or INVOKESPECIAL - * @param use_interface force use of InterfaceMethodref - * @return A new InvokeInstruction. - * @since 6.5.0 + * @param type type of elements of array, i.e., array.getElementType() */ - public InvokeInstruction createInvoke( final String class_name, final String name, final Type ret_type, - final Type[] arg_types, final short kind, final boolean use_interface) { - if (kind != Const.INVOKESPECIAL && kind != Const.INVOKEVIRTUAL && kind != Const.INVOKESTATIC - && kind != Const.INVOKEINTERFACE && kind != Const.INVOKEDYNAMIC) { - throw new IllegalArgumentException("Unknown invoke kind: " + kind); - } - int index; - int nargs = 0; - final String signature = Type.getMethodSignature(ret_type, arg_types); - for (final Type arg_type : arg_types) { - nargs += arg_type.getSize(); - } - if (use_interface) { - index = cp.addInterfaceMethodref(class_name, name, signature); - } else { - index = cp.addMethodref(class_name, name, signature); - } - switch (kind) { - case Const.INVOKESPECIAL: - return new INVOKESPECIAL(index); - case Const.INVOKEVIRTUAL: - return new INVOKEVIRTUAL(index); - case Const.INVOKESTATIC: - return new INVOKESTATIC(index); - case Const.INVOKEINTERFACE: - return new INVOKEINTERFACE(index, nargs + 1); - case Const.INVOKEDYNAMIC: - return new INVOKEDYNAMIC(index); + public static ArrayInstruction createArrayLoad(final Type type) { + switch (type.getType()) { + case Const.T_BOOLEAN: + case Const.T_BYTE: + return InstructionConst.BALOAD; + case Const.T_CHAR: + return InstructionConst.CALOAD; + case Const.T_SHORT: + return InstructionConst.SALOAD; + case Const.T_INT: + return InstructionConst.IALOAD; + case Const.T_FLOAT: + return InstructionConst.FALOAD; + case Const.T_DOUBLE: + return InstructionConst.DALOAD; + case Const.T_LONG: + return InstructionConst.LALOAD; + case Const.T_ARRAY: + case Const.T_OBJECT: + return InstructionConst.AALOAD; default: - // Can't happen - throw new IllegalStateException("Unknown invoke kind: " + kind); + throw new IllegalArgumentException("Invalid type " + type); } } - /** Create an invokedynamic instruction. - * - * @param bootstrap_index index into the bootstrap_methods array - * @param name name of the called method - * @param ret_type return type of method - * @param arg_types argument types of method - * @see Constants + /** + * @param type type of elements of array, i.e., array.getElementType() */ -/* - * createInvokeDynamic only needed if instrumention code wants to generate - * a new invokedynamic instruction. I don't think we need. (markro) - * - public InvokeInstruction createInvokeDynamic( int bootstrap_index, String name, Type ret_type, - Type[] arg_types) { - int index; - int nargs = 0; - String signature = Type.getMethodSignature(ret_type, arg_types); - for (int i = 0; i < arg_types.length; i++) { - nargs += arg_types[i].getSize(); + public static ArrayInstruction createArrayStore(final Type type) { + switch (type.getType()) { + case Const.T_BOOLEAN: + case Const.T_BYTE: + return InstructionConst.BASTORE; + case Const.T_CHAR: + return InstructionConst.CASTORE; + case Const.T_SHORT: + return InstructionConst.SASTORE; + case Const.T_INT: + return InstructionConst.IASTORE; + case Const.T_FLOAT: + return InstructionConst.FASTORE; + case Const.T_DOUBLE: + return InstructionConst.DASTORE; + case Const.T_LONG: + return InstructionConst.LASTORE; + case Const.T_ARRAY: + case Const.T_OBJECT: + return InstructionConst.AASTORE; + default: + throw new IllegalArgumentException("Invalid type " + type); } - // UNDONE - needs to be added to ConstantPoolGen - //index = cp.addInvokeDynamic(bootstrap_index, name, signature); - index = 0; - return new INVOKEDYNAMIC(index); - } - */ - - /** Create a call to the most popular System.out.println() method. - * - * @param s the string to print - */ - public InstructionList createPrintln( final String s ) { - final InstructionList il = new InstructionList(); - final int out = cp.addFieldref("java.lang.System", "out", "Ljava/io/PrintStream;"); - final int println = cp.addMethodref("java.io.PrintStream", "println", "(Ljava/lang/String;)V"); - il.append(new GETSTATIC(out)); - il.append(new PUSH(cp, s)); - il.append(new INVOKEVIRTUAL(println)); - return il; } - - /** Uses PUSH to push a constant value onto the stack. - * @param value must be of type Number, Boolean, Character or String - */ - public Instruction createConstant( final Object value ) { - PUSH push; - if (value instanceof Number) { - push = new PUSH(cp, (Number) value); - } else if (value instanceof String) { - push = new PUSH(cp, (String) value); - } else if (value instanceof Boolean) { - push = new PUSH(cp, (Boolean) value); - } else if (value instanceof Character) { - push = new PUSH(cp, (Character) value); - } else { - throw new ClassGenException("Illegal type: " + value.getClass()); + private static ArithmeticInstruction createBinaryDoubleOp(final char op) { + switch (op) { + case '-': + return InstructionConst.DSUB; + case '+': + return InstructionConst.DADD; + case '*': + return InstructionConst.DMUL; + case '/': + return InstructionConst.DDIV; + case '%': + return InstructionConst.DREM; + default: + throw new IllegalArgumentException("Invalid operand " + op); } - return push.getInstruction(); } - private static class MethodObject { - - final Type[] arg_types; - final Type result_type; - final String class_name; - final String name; - - - MethodObject(final String c, final String n, final Type r, final Type[] a) { - class_name = c; - name = n; - result_type = r; - arg_types = a; + private static ArithmeticInstruction createBinaryFloatOp(final char op) { + switch (op) { + case '-': + return InstructionConst.FSUB; + case '+': + return InstructionConst.FADD; + case '*': + return InstructionConst.FMUL; + case '/': + return InstructionConst.FDIV; + case '%': + return InstructionConst.FREM; + default: + throw new IllegalArgumentException("Invalid operand " + op); } } - - private InvokeInstruction createInvoke( final MethodObject m, final short kind ) { - return createInvoke(m.class_name, m.name, m.result_type, m.arg_types, kind); - } - - private static final MethodObject[] append_mos = { - new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { - Type.STRING - }), - new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { - Type.OBJECT - }), - null, - null, // indices 2, 3 - new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { - Type.BOOLEAN - }), - new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { - Type.CHAR - }), - new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { - Type.FLOAT - }), - new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { - Type.DOUBLE - }), - new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { - Type.INT - }), - new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(byte) - new Type[] { - Type.INT - }), - new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(short) - new Type[] { - Type.INT - }), - new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { - Type.LONG - }) - }; - - - private static boolean isString( final Type type ) { - return (type instanceof ObjectType) && - ((ObjectType) type).getClassName().equals("java.lang.String"); - } - - - public Instruction createAppend( final Type type ) { - final byte t = type.getType(); - if (isString(type)) { - return createInvoke(append_mos[0], Const.INVOKEVIRTUAL); - } - switch (t) { - case Const.T_BOOLEAN: - case Const.T_CHAR: - case Const.T_FLOAT: - case Const.T_DOUBLE: - case Const.T_BYTE: - case Const.T_SHORT: - case Const.T_INT: - case Const.T_LONG: - return createInvoke(append_mos[t], Const.INVOKEVIRTUAL); - case Const.T_ARRAY: - case Const.T_OBJECT: - return createInvoke(append_mos[1], Const.INVOKEVIRTUAL); - default: - throw new IllegalArgumentException("No append for this type? " + type); + private static ArithmeticInstruction createBinaryIntOp(final char first, final String op) { + switch (first) { + case '-': + return InstructionConst.ISUB; + case '+': + return InstructionConst.IADD; + case '%': + return InstructionConst.IREM; + case '*': + return InstructionConst.IMUL; + case '/': + return InstructionConst.IDIV; + case '&': + return InstructionConst.IAND; + case '|': + return InstructionConst.IOR; + case '^': + return InstructionConst.IXOR; + case '<': + return InstructionConst.ISHL; + case '>': + return op.equals(">>>") ? InstructionConst.IUSHR : InstructionConst.ISHR; + default: + throw new IllegalArgumentException("Invalid operand " + op); } } - - /** Create a field instruction. + /** + * Create an invokedynamic instruction. * - * @param class_name name of the accessed class - * @param name name of the referenced field - * @param type type of field - * @param kind how to access, i.e., GETFIELD, PUTFIELD, GETSTATIC, PUTSTATIC + * @param bootstrap_index index into the bootstrap_methods array + * @param name name of the called method + * @param ret_type return type of method + * @param argTypes argument types of method * @see Const */ - public FieldInstruction createFieldAccess( final String class_name, - final String name, final Type type, final short kind ) { - int index; - final String signature = type.getSignature(); - index = cp.addFieldref(class_name, name, signature); - switch (kind) { - case Const.GETFIELD: - return new GETFIELD(index); - case Const.PUTFIELD: - return new PUTFIELD(index); - case Const.GETSTATIC: - return new GETSTATIC(index); - case Const.PUTSTATIC: - return new PUTSTATIC(index); - default: - throw new IllegalArgumentException("Unknown getfield kind:" + kind); - } - } - - - /** Create reference to `this' - */ - public static Instruction createThis() { - return new ALOAD(0); - } - - /** Create typed return + /* + * createInvokeDynamic only needed if instrumentation code wants to generate a new invokedynamic instruction. I don't + * think we need. + * + * public InvokeInstruction createInvokeDynamic( int bootstrap_index, String name, Type ret_type, Type[] argTypes) { + * int index; int nargs = 0; String signature = Type.getMethodSignature(ret_type, argTypes); for (int i = 0; i < + * argTypes.length; i++) { nargs += argTypes[i].getSize(); } // UNDONE - needs to be added to ConstantPoolGen //index + * = cp.addInvokeDynamic(bootstrap_index, name, signature); index = 0; return new INVOKEDYNAMIC(index); } */ - public static ReturnInstruction createReturn( final Type type ) { - switch (type.getType()) { - case Const.T_ARRAY: - case Const.T_OBJECT: - return InstructionConst.ARETURN; - case Const.T_INT: - case Const.T_SHORT: - case Const.T_BOOLEAN: - case Const.T_CHAR: - case Const.T_BYTE: - return InstructionConst.IRETURN; - case Const.T_FLOAT: - return InstructionConst.FRETURN; - case Const.T_DOUBLE: - return InstructionConst.DRETURN; - case Const.T_LONG: - return InstructionConst.LRETURN; - case Const.T_VOID: - return InstructionConst.RETURN; - default: - throw new IllegalArgumentException("Invalid type: " + type); - } - } - - private static ArithmeticInstruction createBinaryIntOp( final char first, final String op ) { + private static ArithmeticInstruction createBinaryLongOp(final char first, final String op) { switch (first) { - case '-': - return InstructionConst.ISUB; - case '+': - return InstructionConst.IADD; - case '%': - return InstructionConst.IREM; - case '*': - return InstructionConst.IMUL; - case '/': - return InstructionConst.IDIV; - case '&': - return InstructionConst.IAND; - case '|': - return InstructionConst.IOR; - case '^': - return InstructionConst.IXOR; - case '<': - return InstructionConst.ISHL; - case '>': - return op.equals(">>>") ? InstructionConst.IUSHR : InstructionConst.ISHR; - default: - throw new IllegalArgumentException("Invalid operand " + op); - } - } - - - private static ArithmeticInstruction createBinaryLongOp( final char first, final String op ) { - switch (first) { - case '-': - return InstructionConst.LSUB; - case '+': - return InstructionConst.LADD; - case '%': - return InstructionConst.LREM; - case '*': - return InstructionConst.LMUL; - case '/': - return InstructionConst.LDIV; - case '&': - return InstructionConst.LAND; - case '|': - return InstructionConst.LOR; - case '^': - return InstructionConst.LXOR; - case '<': - return InstructionConst.LSHL; - case '>': - return op.equals(">>>") ? InstructionConst.LUSHR : InstructionConst.LSHR; - default: - throw new IllegalArgumentException("Invalid operand " + op); - } - } - - - private static ArithmeticInstruction createBinaryFloatOp( final char op ) { - switch (op) { - case '-': - return InstructionConst.FSUB; - case '+': - return InstructionConst.FADD; - case '*': - return InstructionConst.FMUL; - case '/': - return InstructionConst.FDIV; - case '%': - return InstructionConst.FREM; - default: - throw new IllegalArgumentException("Invalid operand " + op); - } - } - - - private static ArithmeticInstruction createBinaryDoubleOp( final char op ) { - switch (op) { - case '-': - return InstructionConst.DSUB; - case '+': - return InstructionConst.DADD; - case '*': - return InstructionConst.DMUL; - case '/': - return InstructionConst.DDIV; - case '%': - return InstructionConst.DREM; - default: - throw new IllegalArgumentException("Invalid operand " + op); + case '-': + return InstructionConst.LSUB; + case '+': + return InstructionConst.LADD; + case '%': + return InstructionConst.LREM; + case '*': + return InstructionConst.LMUL; + case '/': + return InstructionConst.LDIV; + case '&': + return InstructionConst.LAND; + case '|': + return InstructionConst.LOR; + case '^': + return InstructionConst.LXOR; + case '<': + return InstructionConst.LSHL; + case '>': + return op.equals(">>>") ? InstructionConst.LUSHR : InstructionConst.LSHR; + default: + throw new IllegalArgumentException("Invalid operand " + op); } } - /** * Create binary operation for simple basic types, such as int and float. * * @param op operation, such as "+", "*", "<<", etc. */ - public static ArithmeticInstruction createBinaryOperation( final String op, final Type type ) { + public static ArithmeticInstruction createBinaryOperation(final String op, final Type type) { final char first = op.charAt(0); switch (type.getType()) { - case Const.T_BYTE: - case Const.T_SHORT: - case Const.T_INT: - case Const.T_CHAR: - return createBinaryIntOp(first, op); - case Const.T_LONG: - return createBinaryLongOp(first, op); - case Const.T_FLOAT: - return createBinaryFloatOp(first); - case Const.T_DOUBLE: - return createBinaryDoubleOp(first); - default: - throw new IllegalArgumentException("Invalid type " + type); + case Const.T_BYTE: + case Const.T_SHORT: + case Const.T_INT: + case Const.T_CHAR: + return createBinaryIntOp(first, op); + case Const.T_LONG: + return createBinaryLongOp(first, op); + case Const.T_FLOAT: + return createBinaryFloatOp(first); + case Const.T_DOUBLE: + return createBinaryDoubleOp(first); + default: + throw new IllegalArgumentException("Invalid type " + type); } } + /** + * Create branch instruction by given opcode, except LOOKUPSWITCH and TABLESWITCH. For those you should use the SWITCH + * compound instruction. + */ + public static BranchInstruction createBranchInstruction(final short opcode, final InstructionHandle target) { + switch (opcode) { + case Const.IFEQ: + return new IFEQ(target); + case Const.IFNE: + return new IFNE(target); + case Const.IFLT: + return new IFLT(target); + case Const.IFGE: + return new IFGE(target); + case Const.IFGT: + return new IFGT(target); + case Const.IFLE: + return new IFLE(target); + case Const.IF_ICMPEQ: + return new IF_ICMPEQ(target); + case Const.IF_ICMPNE: + return new IF_ICMPNE(target); + case Const.IF_ICMPLT: + return new IF_ICMPLT(target); + case Const.IF_ICMPGE: + return new IF_ICMPGE(target); + case Const.IF_ICMPGT: + return new IF_ICMPGT(target); + case Const.IF_ICMPLE: + return new IF_ICMPLE(target); + case Const.IF_ACMPEQ: + return new IF_ACMPEQ(target); + case Const.IF_ACMPNE: + return new IF_ACMPNE(target); + case Const.GOTO: + return new GOTO(target); + case Const.JSR: + return new JSR(target); + case Const.IFNULL: + return new IFNULL(target); + case Const.IFNONNULL: + return new IFNONNULL(target); + case Const.GOTO_W: + return new GOTO_W(target); + case Const.JSR_W: + return new JSR_W(target); + default: + throw new IllegalArgumentException("Invalid opcode: " + opcode); + } + } /** * @param size size of operand, either 1 (int, e.g.) or 2 (double) */ - public static StackInstruction createPop( final int size ) { - return (size == 2) ? InstructionConst.POP2 : InstructionConst.POP; + public static StackInstruction createDup(final int size) { + return size == 2 ? InstructionConst.DUP2 : InstructionConst.DUP; } - /** * @param size size of operand, either 1 (int, e.g.) or 2 (double) */ - public static StackInstruction createDup( final int size ) { - return (size == 2) ? InstructionConst.DUP2 : InstructionConst.DUP; + public static StackInstruction createDup_1(final int size) { + return size == 2 ? InstructionConst.DUP2_X1 : InstructionConst.DUP_X1; } - /** * @param size size of operand, either 1 (int, e.g.) or 2 (double) */ - public static StackInstruction createDup_2( final int size ) { - return (size == 2) ? InstructionConst.DUP2_X2 : InstructionConst.DUP_X2; + public static StackInstruction createDup_2(final int size) { + return size == 2 ? InstructionConst.DUP2_X2 : InstructionConst.DUP_X2; } + /** + * @param index index of local variable + */ + public static LocalVariableInstruction createLoad(final Type type, final int index) { + switch (type.getType()) { + case Const.T_BOOLEAN: + case Const.T_CHAR: + case Const.T_BYTE: + case Const.T_SHORT: + case Const.T_INT: + return new ILOAD(index); + case Const.T_FLOAT: + return new FLOAD(index); + case Const.T_DOUBLE: + return new DLOAD(index); + case Const.T_LONG: + return new LLOAD(index); + case Const.T_ARRAY: + case Const.T_OBJECT: + return new ALOAD(index); + default: + throw new IllegalArgumentException("Invalid type " + type); + } + } /** - * @param size size of operand, either 1 (int, e.g.) or 2 (double) + * Create "null" value for reference types, 0 for basic types like int */ - public static StackInstruction createDup_1( final int size ) { - return (size == 2) ? InstructionConst.DUP2_X1 : InstructionConst.DUP_X1; + public static Instruction createNull(final Type type) { + switch (type.getType()) { + case Const.T_ARRAY: + case Const.T_OBJECT: + return InstructionConst.ACONST_NULL; + case Const.T_INT: + case Const.T_SHORT: + case Const.T_BOOLEAN: + case Const.T_CHAR: + case Const.T_BYTE: + return InstructionConst.ICONST_0; + case Const.T_FLOAT: + return InstructionConst.FCONST_0; + case Const.T_DOUBLE: + return InstructionConst.DCONST_0; + case Const.T_LONG: + return InstructionConst.LCONST_0; + case Const.T_VOID: + return InstructionConst.NOP; + default: + throw new IllegalArgumentException("Invalid type: " + type); + } } + /** + * @param size size of operand, either 1 (int, e.g.) or 2 (double) + */ + public static StackInstruction createPop(final int size) { + return size == 2 ? InstructionConst.POP2 : InstructionConst.POP; + } /** - * @param index index of local variable + * Create typed return */ - public static LocalVariableInstruction createStore( final Type type, final int index ) { + public static ReturnInstruction createReturn(final Type type) { switch (type.getType()) { - case Const.T_BOOLEAN: - case Const.T_CHAR: - case Const.T_BYTE: - case Const.T_SHORT: - case Const.T_INT: - return new ISTORE(index); - case Const.T_FLOAT: - return new FSTORE(index); - case Const.T_DOUBLE: - return new DSTORE(index); - case Const.T_LONG: - return new LSTORE(index); - case Const.T_ARRAY: - case Const.T_OBJECT: - return new ASTORE(index); - default: - throw new IllegalArgumentException("Invalid type " + type); + case Const.T_ARRAY: + case Const.T_OBJECT: + return InstructionConst.ARETURN; + case Const.T_INT: + case Const.T_SHORT: + case Const.T_BOOLEAN: + case Const.T_CHAR: + case Const.T_BYTE: + return InstructionConst.IRETURN; + case Const.T_FLOAT: + return InstructionConst.FRETURN; + case Const.T_DOUBLE: + return InstructionConst.DRETURN; + case Const.T_LONG: + return InstructionConst.LRETURN; + case Const.T_VOID: + return InstructionConst.RETURN; + default: + throw new IllegalArgumentException("Invalid type: " + type); } } - /** * @param index index of local variable */ - public static LocalVariableInstruction createLoad( final Type type, final int index ) { + public static LocalVariableInstruction createStore(final Type type, final int index) { switch (type.getType()) { - case Const.T_BOOLEAN: - case Const.T_CHAR: - case Const.T_BYTE: - case Const.T_SHORT: - case Const.T_INT: - return new ILOAD(index); - case Const.T_FLOAT: - return new FLOAD(index); - case Const.T_DOUBLE: - return new DLOAD(index); - case Const.T_LONG: - return new LLOAD(index); - case Const.T_ARRAY: - case Const.T_OBJECT: - return new ALOAD(index); - default: - throw new IllegalArgumentException("Invalid type " + type); + case Const.T_BOOLEAN: + case Const.T_CHAR: + case Const.T_BYTE: + case Const.T_SHORT: + case Const.T_INT: + return new ISTORE(index); + case Const.T_FLOAT: + return new FSTORE(index); + case Const.T_DOUBLE: + return new DSTORE(index); + case Const.T_LONG: + return new LSTORE(index); + case Const.T_ARRAY: + case Const.T_OBJECT: + return new ASTORE(index); + default: + throw new IllegalArgumentException("Invalid type " + type); } } + /** + * Create reference to 'this' + */ + public static Instruction createThis() { + return new ALOAD(0); + } + + private static boolean isString(final Type type) { + return type instanceof ObjectType && ((ObjectType) type).getClassName().equals("java.lang.String"); + } /** - * @param type type of elements of array, i.e., array.getElementType() + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter */ - public static ArrayInstruction createArrayLoad( final Type type ) { - switch (type.getType()) { - case Const.T_BOOLEAN: - case Const.T_BYTE: - return InstructionConst.BALOAD; - case Const.T_CHAR: - return InstructionConst.CALOAD; - case Const.T_SHORT: - return InstructionConst.SALOAD; - case Const.T_INT: - return InstructionConst.IALOAD; - case Const.T_FLOAT: - return InstructionConst.FALOAD; - case Const.T_DOUBLE: - return InstructionConst.DALOAD; - case Const.T_LONG: - return InstructionConst.LALOAD; - case Const.T_ARRAY: - case Const.T_OBJECT: - return InstructionConst.AALOAD; - default: - throw new IllegalArgumentException("Invalid type " + type); - } + @Deprecated + protected ClassGen cg; + + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected ConstantPoolGen cp; + + /** + * Initialize with ClassGen object + */ + public InstructionFactory(final ClassGen cg) { + this(cg, cg.getConstantPool()); } + public InstructionFactory(final ClassGen cg, final ConstantPoolGen cp) { + this.cg = cg; + this.cp = cp; + } /** - * @param type type of elements of array, i.e., array.getElementType() + * Initialize just with ConstantPoolGen object */ - public static ArrayInstruction createArrayStore( final Type type ) { - switch (type.getType()) { - case Const.T_BOOLEAN: - case Const.T_BYTE: - return InstructionConst.BASTORE; - case Const.T_CHAR: - return InstructionConst.CASTORE; - case Const.T_SHORT: - return InstructionConst.SASTORE; - case Const.T_INT: - return InstructionConst.IASTORE; - case Const.T_FLOAT: - return InstructionConst.FASTORE; - case Const.T_DOUBLE: - return InstructionConst.DASTORE; - case Const.T_LONG: - return InstructionConst.LASTORE; - case Const.T_ARRAY: - case Const.T_OBJECT: - return InstructionConst.AASTORE; - default: - throw new IllegalArgumentException("Invalid type " + type); + public InstructionFactory(final ConstantPoolGen cp) { + this(null, cp); + } + + public Instruction createAppend(final Type type) { + final byte t = type.getType(); + if (isString(type)) { + return createInvoke(appendMethodObjects[0], Const.INVOKEVIRTUAL); + } + switch (t) { + case Const.T_BOOLEAN: + case Const.T_CHAR: + case Const.T_FLOAT: + case Const.T_DOUBLE: + case Const.T_BYTE: + case Const.T_SHORT: + case Const.T_INT: + case Const.T_LONG: + return createInvoke(appendMethodObjects[t], Const.INVOKEVIRTUAL); + case Const.T_ARRAY: + case Const.T_OBJECT: + return createInvoke(appendMethodObjects[1], Const.INVOKEVIRTUAL); + default: + throw new IllegalArgumentException("No append for this type? " + type); } } /** - * Create conversion operation for two stack operands, this may be an I2C, - * instruction, e.g., if the operands are basic types and CHECKCAST if they - * are reference types. + * Create conversion operation for two stack operands, this may be an I2C, instruction, e.g., if the operands are basic + * types and CHECKCAST if they are reference types. */ - public Instruction createCast( final Type src_type, final Type dest_type ) { - if ((src_type instanceof BasicType) && (dest_type instanceof BasicType)) { - final byte dest = dest_type.getType(); - byte src = src_type.getType(); - if (dest == Const.T_LONG - && (src == Const.T_CHAR || src == Const.T_BYTE || src == Const.T_SHORT)) { + public Instruction createCast(final Type srcType, final Type destType) { + if (srcType instanceof BasicType && destType instanceof BasicType) { + final byte dest = destType.getType(); + byte src = srcType.getType(); + if (dest == Const.T_LONG && (src == Const.T_CHAR || src == Const.T_BYTE || src == Const.T_SHORT)) { src = Const.T_INT; } - final String name = "com.sun.org.apache.bcel.internal.generic." + short_names[src - Const.T_CHAR] + "2" - + short_names[dest - Const.T_CHAR]; + final String name = "com.sun.org.apache.bcel.internal.generic." + shortNames[src - Const.T_CHAR] + "2" + shortNames[dest - Const.T_CHAR]; Instruction i = null; try { - i = (Instruction) java.lang.Class.forName(name).getDeclaredConstructor().newInstance(); + i = (Instruction) Class.forName(name).getDeclaredConstructor().newInstance();; } catch (final Exception e) { throw new IllegalArgumentException("Could not find instruction: " + name, e); } return i; - } else if ((src_type instanceof ReferenceType) && (dest_type instanceof ReferenceType)) { - if (dest_type instanceof ArrayType) { - return new CHECKCAST(cp.addArrayClass((ArrayType) dest_type)); - } - return new CHECKCAST(cp.addClass(((ObjectType) dest_type).getClassName())); - } else { - throw new IllegalArgumentException("Cannot cast " + src_type + " to " + dest_type); } + if (!(srcType instanceof ReferenceType) || !(destType instanceof ReferenceType)) { + throw new IllegalArgumentException("Cannot cast " + srcType + " to " + destType); + } + if (destType instanceof ArrayType) { + return new CHECKCAST(cp.addArrayClass((ArrayType) destType)); + } + return new CHECKCAST(cp.addClass(((ObjectType) destType).getClassName())); } - - public GETFIELD createGetField( final String class_name, final String name, final Type t ) { - return new GETFIELD(cp.addFieldref(class_name, name, t.getSignature())); + public CHECKCAST createCheckCast(final ReferenceType t) { + if (t instanceof ArrayType) { + return new CHECKCAST(cp.addArrayClass((ArrayType) t)); + } + return new CHECKCAST(cp.addClass((ObjectType) t)); } - - public GETSTATIC createGetStatic( final String class_name, final String name, final Type t ) { - return new GETSTATIC(cp.addFieldref(class_name, name, t.getSignature())); + /** + * Uses PUSH to push a constant value onto the stack. + * + * @param value must be of type Number, Boolean, Character or String + */ + public Instruction createConstant(final Object value) { + PUSH push; + if (value instanceof Number) { + push = new PUSH(cp, (Number) value); + } else if (value instanceof String) { + push = new PUSH(cp, (String) value); + } else if (value instanceof Boolean) { + push = new PUSH(cp, (Boolean) value); + } else if (value instanceof Character) { + push = new PUSH(cp, (Character) value); + } else { + throw new ClassGenException("Illegal type: " + value.getClass()); + } + return push.getInstruction(); } - - public PUTFIELD createPutField( final String class_name, final String name, final Type t ) { - return new PUTFIELD(cp.addFieldref(class_name, name, t.getSignature())); + /** + * Create a field instruction. + * + * @param className name of the accessed class + * @param name name of the referenced field + * @param type type of field + * @param kind how to access, i.e., GETFIELD, PUTFIELD, GETSTATIC, PUTSTATIC + * @see Const + */ + public FieldInstruction createFieldAccess(final String className, final String name, final Type type, final short kind) { + int index; + final String signature = type.getSignature(); + index = cp.addFieldref(className, name, signature); + switch (kind) { + case Const.GETFIELD: + return new GETFIELD(index); + case Const.PUTFIELD: + return new PUTFIELD(index); + case Const.GETSTATIC: + return new GETSTATIC(index); + case Const.PUTSTATIC: + return new PUTSTATIC(index); + default: + throw new IllegalArgumentException("Unknown getfield kind:" + kind); + } } - - public PUTSTATIC createPutStatic( final String class_name, final String name, final Type t ) { - return new PUTSTATIC(cp.addFieldref(class_name, name, t.getSignature())); + public GETFIELD createGetField(final String className, final String name, final Type t) { + return new GETFIELD(cp.addFieldref(className, name, t.getSignature())); } - - public CHECKCAST createCheckCast( final ReferenceType t ) { - if (t instanceof ArrayType) { - return new CHECKCAST(cp.addArrayClass((ArrayType) t)); - } - return new CHECKCAST(cp.addClass((ObjectType) t)); + public GETSTATIC createGetStatic(final String className, final String name, final Type t) { + return new GETSTATIC(cp.addFieldref(className, name, t.getSignature())); } - - public INSTANCEOF createInstanceOf( final ReferenceType t ) { + public INSTANCEOF createInstanceOf(final ReferenceType t) { if (t instanceof ArrayType) { return new INSTANCEOF(cp.addArrayClass((ArrayType) t)); } return new INSTANCEOF(cp.addClass((ObjectType) t)); } + private InvokeInstruction createInvoke(final MethodObject m, final short kind) { + return createInvoke(m.className, m.name, m.resultType, m.argTypes, kind); + } - public NEW createNew( final ObjectType t ) { - return new NEW(cp.addClass(t)); + /** + * Create an invoke instruction. (Except for invokedynamic.) + * + * @param className name of the called class + * @param name name of the called method + * @param retType return type of method + * @param argTypes argument types of method + * @param kind how to invoke, i.e., INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL, or INVOKESPECIAL + * @see Const + */ + public InvokeInstruction createInvoke(final String className, final String name, final Type retType, final Type[] argTypes, final short kind) { + return createInvoke(className, name, retType, argTypes, kind, kind == Const.INVOKEINTERFACE); + } + + /** + * Create an invoke instruction. (Except for invokedynamic.) + * + * @param className name of the called class + * @param name name of the called method + * @param retType return type of method + * @param argTypes argument types of method + * @param kind how to invoke: INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL, or INVOKESPECIAL + * @param useInterface force use of InterfaceMethodref + * @return A new InvokeInstruction. + * @since 6.5.0 + */ + public InvokeInstruction createInvoke(final String className, final String name, final Type retType, final Type[] argTypes, final short kind, + final boolean useInterface) { + if (kind != Const.INVOKESPECIAL && kind != Const.INVOKEVIRTUAL && kind != Const.INVOKESTATIC && kind != Const.INVOKEINTERFACE + && kind != Const.INVOKEDYNAMIC) { + throw new IllegalArgumentException("Unknown invoke kind: " + kind); + } + int index; + int nargs = 0; + final String signature = Type.getMethodSignature(retType, argTypes); + for (final Type argType : argTypes) { + nargs += argType.getSize(); + } + if (useInterface) { + index = cp.addInterfaceMethodref(className, name, signature); + } else { + index = cp.addMethodref(className, name, signature); + } + switch (kind) { + case Const.INVOKESPECIAL: + return new INVOKESPECIAL(index); + case Const.INVOKEVIRTUAL: + return new INVOKEVIRTUAL(index); + case Const.INVOKESTATIC: + return new INVOKESTATIC(index); + case Const.INVOKEINTERFACE: + return new INVOKEINTERFACE(index, nargs + 1); + case Const.INVOKEDYNAMIC: + return new INVOKEDYNAMIC(index); + default: + // Can't happen + throw new IllegalStateException("Unknown invoke kind: " + kind); + } } + public NEW createNew(final ObjectType t) { + return new NEW(cp.addClass(t)); + } - public NEW createNew( final String s ) { + public NEW createNew(final String s) { return createNew(ObjectType.getInstance(s)); } /** * Create new array of given size and type. * - * @return an instruction that creates the corresponding array at runtime, - * i.e. is an AllocationInstruction + * @return an instruction that creates the corresponding array at runtime, i.e. is an AllocationInstruction */ - public Instruction createNewArray( final Type t, final short dim ) { + public Instruction createNewArray(final Type t, final short dim) { if (dim == 1) { if (t instanceof ObjectType) { return new ANEWARRAY(cp.addClass((ObjectType) t)); - } else if (t instanceof ArrayType) { + } + if (t instanceof ArrayType) { return new ANEWARRAY(cp.addArrayClass((ArrayType) t)); - } else { - return new NEWARRAY(t.getType()); } + return new NEWARRAY(t.getType()); } ArrayType at; if (t instanceof ArrayType) { @@ -699,101 +700,40 @@ public Instruction createNewArray( final Type t, final short dim ) { } /** - * Create "null" value for reference types, 0 for basic types like int + * Create a call to the most popular System.out.println() method. + * + * @param s the string to print */ - public static Instruction createNull( final Type type ) { - switch (type.getType()) { - case Const.T_ARRAY: - case Const.T_OBJECT: - return InstructionConst.ACONST_NULL; - case Const.T_INT: - case Const.T_SHORT: - case Const.T_BOOLEAN: - case Const.T_CHAR: - case Const.T_BYTE: - return InstructionConst.ICONST_0; - case Const.T_FLOAT: - return InstructionConst.FCONST_0; - case Const.T_DOUBLE: - return InstructionConst.DCONST_0; - case Const.T_LONG: - return InstructionConst.LCONST_0; - case Const.T_VOID: - return InstructionConst.NOP; - default: - throw new IllegalArgumentException("Invalid type: " + type); - } + public InstructionList createPrintln(final String s) { + final InstructionList il = new InstructionList(); + il.append(createGetStatic("java.lang.System", "out", Type.getType("Ljava/io/PrintStream;"))); + il.append(new PUSH(cp, s)); + final MethodObject methodObject = new MethodObject("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.getType("Ljava/lang/String;") }); + il.append(createInvoke(methodObject, Const.INVOKEVIRTUAL)); + return il; } - /** - * Create branch instruction by given opcode, except LOOKUPSWITCH and - * TABLESWITCH. For those you should use the SWITCH compound instruction. - */ - public static BranchInstruction createBranchInstruction( final short opcode, - final InstructionHandle target ) { - switch (opcode) { - case Const.IFEQ: - return new IFEQ(target); - case Const.IFNE: - return new IFNE(target); - case Const.IFLT: - return new IFLT(target); - case Const.IFGE: - return new IFGE(target); - case Const.IFGT: - return new IFGT(target); - case Const.IFLE: - return new IFLE(target); - case Const.IF_ICMPEQ: - return new IF_ICMPEQ(target); - case Const.IF_ICMPNE: - return new IF_ICMPNE(target); - case Const.IF_ICMPLT: - return new IF_ICMPLT(target); - case Const.IF_ICMPGE: - return new IF_ICMPGE(target); - case Const.IF_ICMPGT: - return new IF_ICMPGT(target); - case Const.IF_ICMPLE: - return new IF_ICMPLE(target); - case Const.IF_ACMPEQ: - return new IF_ACMPEQ(target); - case Const.IF_ACMPNE: - return new IF_ACMPNE(target); - case Const.GOTO: - return new GOTO(target); - case Const.JSR: - return new JSR(target); - case Const.IFNULL: - return new IFNULL(target); - case Const.IFNONNULL: - return new IFNONNULL(target); - case Const.GOTO_W: - return new GOTO_W(target); - case Const.JSR_W: - return new JSR_W(target); - default: - throw new IllegalArgumentException("Invalid opcode: " + opcode); - } + public PUTFIELD createPutField(final String className, final String name, final Type t) { + return new PUTFIELD(cp.addFieldref(className, name, t.getSignature())); } - - public void setClassGen( final ClassGen c ) { - cg = c; + public PUTSTATIC createPutStatic(final String className, final String name, final Type t) { + return new PUTSTATIC(cp.addFieldref(className, name, t.getSignature())); } - public ClassGen getClassGen() { return cg; } - - public void setConstantPool( final ConstantPoolGen c ) { - cp = c; + public ConstantPoolGen getConstantPool() { + return cp; } + public void setClassGen(final ClassGen c) { + cg = c; + } - public ConstantPoolGen getConstantPool() { - return cp; + public void setConstantPool(final ConstantPoolGen c) { + cp = c; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java index bdf78029537..5e962354d16 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java @@ -28,16 +28,12 @@ import com.sun.org.apache.bcel.internal.classfile.Utility; /** - * Instances of this class give users a handle to the instructions contained in - * an InstructionList. Instruction objects may be used more than once within a - * list, this is useful because it saves memory and may be much faster. + * Instances of this class give users a handle to the instructions contained in an InstructionList. Instruction objects + * may be used more than once within a list, this is useful because it saves memory and may be much faster. * - * Within an InstructionList an InstructionHandle object is wrapped - * around all instructions, i.e., it implements a cell in a - * doubly-linked list. From the outside only the next and the - * previous instruction (handle) are accessible. One - * can traverse the list via an Enumeration returned by - * InstructionList.elements(). + * Within an InstructionList an InstructionHandle object is wrapped around all instructions, i.e., it implements a cell + * in a doubly-linked list. From the outside only the next and the previous instruction (handle) are accessible. One can + * traverse the list via an Enumeration returned by InstructionList.elements(). * * @see Instruction * @see BranchHandle @@ -46,121 +42,86 @@ */ public class InstructionHandle { - private InstructionHandle next; - private InstructionHandle prev; - private Instruction instruction; - - private int i_position = -1; // byte code offset of instruction - - private Set targeters; - private Map attributes; - - /** - * Does nothing. + * Empty array. * - * @deprecated Does nothing as of 6.3.1. + * @since 6.6.0 */ - @Deprecated - protected void addHandle() { - // noop - } - - public final InstructionHandle getNext() { - return next; - } - - - public final InstructionHandle getPrev() { - return prev; - } - - - public final Instruction getInstruction() { - return instruction; - } + public static final InstructionHandle[] EMPTY_ARRAY = {}; + /** + * Empty array. + */ + static final InstructionTargeter[] EMPTY_INSTRUCTION_TARGETER_ARRAY = {}; /** - * Replace current instruction contained in this handle. - * Old instruction is disposed using Instruction.dispose(). + * Factory method. */ - public void setInstruction( final Instruction i ) { // Overridden in BranchHandle TODO could be package-protected? - if (i == null) { - throw new ClassGenException("Assigning null to handle"); - } - if ((this.getClass() != BranchHandle.class) && (i instanceof BranchInstruction)) { - throw new ClassGenException("Assigning branch instruction " + i + " to plain handle"); - } - if (instruction != null) { - instruction.dispose(); - } - instruction = i; + static InstructionHandle getInstructionHandle(final Instruction i) { + return new InstructionHandle(i); } + private InstructionHandle next; + private InstructionHandle prev; + + private Instruction instruction; /** - * Temporarily swap the current instruction, without disturbing - * anything. Meant to be used by a debugger, implementing - * breakpoints. Current instruction is returned. - *

    - * Warning: if this is used on a BranchHandle then some methods such as - * getPosition() will still refer to the original cached instruction, whereas - * other BH methods may affect the cache and the replacement instruction. + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter */ - // See BCEL-273 - // TODO remove this method in any redesign of BCEL - public Instruction swapInstruction( final Instruction i ) { - final Instruction oldInstruction = instruction; - instruction = i; - return oldInstruction; - } + @Deprecated + protected int i_position = -1; // byte code offset of instruction + private Set targeters; + private Map attributes; - /*private*/protected InstructionHandle(final Instruction i) { + protected InstructionHandle(final Instruction i) { setInstruction(i); } - /** Factory method. + /** + * Convenience method, simply calls accept() on the contained instruction. + * + * @param v Visitor object */ - static InstructionHandle getInstructionHandle( final Instruction i ) { - return new InstructionHandle(i); + public void accept(final Visitor v) { + instruction.accept(v); } - /** - * Called by InstructionList.setPositions when setting the position for every - * instruction. In the presence of variable length instructions `setPositions()' - * performs multiple passes over the instruction list to calculate the - * correct (byte) positions and offsets by calling this function. + * Add an attribute to an instruction handle. * - * @param offset additional offset caused by preceding (variable length) instructions - * @param max_offset the maximum offset that may be caused by these instructions - * @return additional offset caused by possible change of this instruction's length + * @param key the key object to store/retrieve the attribute + * @param attr the attribute to associate with this handle */ - protected int updatePosition( final int offset, final int max_offset ) { - i_position += offset; - return 0; + public void addAttribute(final Object key, final Object attr) { + if (attributes == null) { + attributes = new HashMap<>(3); + } + attributes.put(key, attr); } - - /** @return the position, i.e., the byte code offset of the contained - * instruction. This is accurate only after - * InstructionList.setPositions() has been called. + /** + * Does nothing. + * + * @deprecated Does nothing as of 6.3.1. */ - public int getPosition() { - return i_position; + @Deprecated + protected void addHandle() { + // noop } - - /** Set the position, i.e., the byte code offset of the contained - * instruction. + /** + * Denote this handle is being referenced by t. */ - void setPosition( final int pos ) { - i_position = pos; + public void addTargeter(final InstructionTargeter t) { + if (targeters == null) { + targeters = new HashSet<>(); + } + // if(!targeters.contains(t)) + targeters.add(t); } - /** * Delete contents, i.e., remove user access. */ @@ -173,126 +134,109 @@ void dispose() { removeAllTargeters(); } - - /** Remove all targeters, if any. + /** + * Get attribute of an instruction handle. + * + * @param key the key object to store/retrieve the attribute */ - public void removeAllTargeters() { - if (targeters != null) { - targeters.clear(); + public Object getAttribute(final Object key) { + if (attributes != null) { + return attributes.get(key); } + return null; } - /** - * Denote this handle isn't referenced anymore by t. + * @return all attributes associated with this handle */ - public void removeTargeter( final InstructionTargeter t ) { - if (targeters != null) { - targeters.remove(t); + public Collection getAttributes() { + if (attributes == null) { + attributes = new HashMap<>(3); } + return attributes.values(); + } + + public final Instruction getInstruction() { + return instruction; } + public final InstructionHandle getNext() { + return next; + } /** - * Denote this handle is being referenced by t. + * @return the position, i.e., the byte code offset of the contained instruction. This is accurate only after + * InstructionList.setPositions() has been called. */ - public void addTargeter( final InstructionTargeter t ) { - if (targeters == null) { - targeters = new HashSet<>(); - } - //if(!targeters.contains(t)) - targeters.add(t); + public int getPosition() { + return i_position; } - - public boolean hasTargeters() { - return (targeters != null) && (targeters.size() > 0); + public final InstructionHandle getPrev() { + return prev; } - /** * @return null, if there are no targeters */ public InstructionTargeter[] getTargeters() { if (!hasTargeters()) { - return new InstructionTargeter[0]; + return EMPTY_INSTRUCTION_TARGETER_ARRAY; } final InstructionTargeter[] t = new InstructionTargeter[targeters.size()]; targeters.toArray(t); return t; } - - /** @return a (verbose) string representation of the contained instruction. - */ - public String toString( final boolean verbose ) { - return Utility.format(i_position, 4, false, ' ') + ": " + instruction.toString(verbose); - } - - - /** @return a string representation of the contained instruction. - */ - @Override - public String toString() { - return toString(true); + public boolean hasTargeters() { + return targeters != null && !targeters.isEmpty(); } - - /** Add an attribute to an instruction handle. - * - * @param key the key object to store/retrieve the attribute - * @param attr the attribute to associate with this handle + /** + * Remove all targeters, if any. */ - public void addAttribute( final Object key, final Object attr ) { - if (attributes == null) { - attributes = new HashMap<>(3); + public void removeAllTargeters() { + if (targeters != null) { + targeters.clear(); } - attributes.put(key, attr); } - - /** Delete an attribute of an instruction handle. + /** + * Delete an attribute of an instruction handle. * * @param key the key object to retrieve the attribute */ - public void removeAttribute( final Object key ) { + public void removeAttribute(final Object key) { if (attributes != null) { attributes.remove(key); } } - - /** Get attribute of an instruction handle. - * - * @param key the key object to store/retrieve the attribute + /** + * Denote this handle isn't referenced anymore by t. */ - public Object getAttribute( final Object key ) { - if (attributes != null) { - return attributes.get(key); + public void removeTargeter(final InstructionTargeter t) { + if (targeters != null) { + targeters.remove(t); } - return null; } - - /** @return all attributes associated with this handle + /** + * Replace current instruction contained in this handle. Old instruction is disposed using Instruction.dispose(). */ - public Collection getAttributes() { - if (attributes == null) { - attributes = new HashMap<>(3); + public void setInstruction(final Instruction i) { // Overridden in BranchHandle TODO could be package-protected? + if (i == null) { + throw new ClassGenException("Assigning null to handle"); } - return attributes.values(); - } - - - /** Convenience method, simply calls accept() on the contained instruction. - * - * @param v Visitor object - */ - public void accept( final Visitor v ) { - instruction.accept(v); + if (this.getClass() != BranchHandle.class && i instanceof BranchInstruction) { + throw new ClassGenException("Assigning branch instruction " + i + " to plain handle"); + } + if (instruction != null) { + instruction.dispose(); + } + instruction = i; } - /** * @param next the next to set * @since 6.0 @@ -302,6 +246,12 @@ final InstructionHandle setNext(final InstructionHandle next) { return next; } + /** + * Set the position, i.e., the byte code offset of the contained instruction. + */ + void setPosition(final int pos) { + i_position = pos; + } /** * @param prev the prev to set @@ -311,4 +261,48 @@ final InstructionHandle setPrev(final InstructionHandle prev) { this.prev = prev; return prev; } + + /** + * Temporarily swap the current instruction, without disturbing anything. Meant to be used by a debugger, implementing + * breakpoints. Current instruction is returned. + *

    + * Warning: if this is used on a BranchHandle then some methods such as getPosition() will still refer to the original + * cached instruction, whereas other BH methods may affect the cache and the replacement instruction. + */ + // See BCEL-273 + // TODO remove this method in any redesign of BCEL + public Instruction swapInstruction(final Instruction i) { + final Instruction oldInstruction = instruction; + instruction = i; + return oldInstruction; + } + + /** + * @return a string representation of the contained instruction. + */ + @Override + public String toString() { + return toString(true); + } + + /** + * @return a (verbose) string representation of the contained instruction. + */ + public String toString(final boolean verbose) { + return Utility.format(i_position, 4, false, ' ') + ": " + instruction.toString(verbose); + } + + /** + * Called by InstructionList.setPositions when setting the position for every instruction. In the presence of variable + * length instructions 'setPositions()' performs multiple passes over the instruction list to calculate the correct + * (byte) positions and offsets by calling this function. + * + * @param offset additional offset caused by preceding (variable length) instructions + * @param maxOffset the maximum offset that may be caused by these instructions + * @return additional offset caused by possible change of this instruction's length + */ + protected int updatePosition(final int offset, final int maxOffset) { + i_position += offset; + return 0; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java index 28c53220444..7ffc3a8228e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -19,114 +19,59 @@ */ package com.sun.org.apache.bcel.internal.generic; -import com.sun.org.apache.bcel.internal.Const; -import com.sun.org.apache.bcel.internal.classfile.Constant; -import com.sun.org.apache.bcel.internal.util.ByteSequence; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; +import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.classfile.Constant; +import com.sun.org.apache.bcel.internal.util.ByteSequence; + /** - * This class is a container for a list of Instruction objects. Instructions can be + * This class is a container for a list of Instruction objects. Instructions can be * appended, inserted, moved, deleted, etc.. Instructions are being wrapped into - * InstructionHandles objects that are - * returned upon append/insert operations. They give the user (read only) access - * to the list structure, such that it can be traversed and manipulated in a - * controlled way. + * InstructionHandles objects that are returned upon append/insert operations. They + * give the user (read only) access to the list structure, such that it can be traversed and manipulated in a controlled + * way. * - * A list is finally dumped to a byte code array with getByteCode. + * A list is finally dumped to a byte code array with getByteCode. * * @see Instruction * @see InstructionHandle * @see BranchHandle - * @LastModified: May 2021 + * @LastModified: Feb 2023 */ public class InstructionList implements Iterable { - private InstructionHandle start = null; - private InstructionHandle end = null; - private int length = 0; // number of elements in list - private int[] bytePositions; // byte code offsets corresponding to instructions - - /** - * Create (empty) instruction list. - */ - public InstructionList() { - } - - /** - * Create instruction list containing one instruction. - * - * @param i - * initial instruction - */ - public InstructionList(final Instruction i) { - append(i); - } - - /** - * Create instruction list containing one instruction. - * - * @param i - * initial instruction - */ - public InstructionList(final BranchInstruction i) { - append(i); - } - - /** - * Initialize list with (nonnull) compound instruction. Consumes argument - * list, i.e., it becomes empty. - * - * @param c - * compound instruction (list) - */ - public InstructionList(final CompoundInstruction c) { - append(c.getInstructionList()); - } - - /** - * Test for empty list. - */ - public boolean isEmpty() { - return start == null; - } // && end == null - /** - * Find the target instruction (handle) that corresponds to the given target - * position (byte code offset). + * Find the target instruction (handle) that corresponds to the given target position (byte code offset). * - * @param ihs - * array of instruction handles, i.e. il.getInstructionHandles() - * @param pos - * array of positions corresponding to ihs, i.e. il.getInstructionPositions() - * @param count - * length of arrays - * @param target - * target position to search for + * @param ihs array of instruction handles, i.e. il.getInstructionHandles() + * @param pos array of positions corresponding to ihs, i.e. il.getInstructionPositions() + * @param count length of arrays + * @param target target position to search for * @return target position's instruction handle if available */ - public static InstructionHandle findHandle(final InstructionHandle[] ihs, - final int[] pos, final int count, final int target) { + public static InstructionHandle findHandle(final InstructionHandle[] ihs, final int[] pos, final int count, final int target) { int l = 0; int r = count - 1; /* * Do a binary search since the pos array is orderd. */ do { - final int i = (l + r) >>> 1; + final int i = l + r >>> 1; final int j = pos[i]; if (j == target) { return ihs[i]; - } else if (target < j) { + } + if (target < j) { r = i - 1; } else { l = i + 1; @@ -135,32 +80,33 @@ public static InstructionHandle findHandle(final InstructionHandle[] ihs, return null; } + private InstructionHandle start; + private InstructionHandle end; + private int length; // number of elements in list + + private int[] bytePositions; // byte code offsets corresponding to instructions + + private List observers; + + /** + * Create (empty) instruction list. + */ + public InstructionList() { + } + /** - * Get instruction handle for instruction at byte code position pos. This - * only works properly, if the list is freshly initialized from a byte array - * or setPositions() has been called before this method. + * Create instruction list containing one instruction. * - * @param pos - * byte code position to search for - * @return target position's instruction handle if available + * @param i initial instruction */ - public InstructionHandle findHandle(final int pos) { - final int[] positions = bytePositions; - InstructionHandle ih = start; - for (int i = 0; i < length; i++) { - if (positions[i] == pos) { - return ih; - } - ih = ih.getNext(); - } - return null; + public InstructionList(final BranchInstruction i) { + append(i); } /** * Initialize instruction list from byte array. * - * @param code - * byte array containing the instructions + * @param code byte array containing the instructions */ public InstructionList(final byte[] code) { int count = 0; // Contains actual length @@ -193,18 +139,16 @@ public InstructionList(final byte[] code) { } catch (final IOException e) { throw new ClassGenException(e.toString(), e); } - bytePositions = new int[count]; // Trim to proper size - System.arraycopy(pos, 0, bytePositions, 0, count); + bytePositions = Arrays.copyOf(pos, count); // Trim to proper size /* * Pass 2: Look for BranchInstruction and update their targets, i.e., convert offsets to instruction handles. */ for (int i = 0; i < count; i++) { if (ihs[i] instanceof BranchHandle) { final BranchInstruction bi = (BranchInstruction) ihs[i].getInstruction(); - int target = bi.getPosition() + bi.getIndex(); - /* - * Byte code position: relative -> absolute. - */ + int target = bi.getPosition() + bi.getIndex(); /* + * Byte code position: relative -> absolute. + */ // Search for target position InstructionHandle ih = findHandle(ihs, pos, count, target); if (ih == null) { @@ -229,104 +173,59 @@ public InstructionList(final byte[] code) { } /** - * Append another list after instruction (handle) ih contained in this list. - * Consumes argument list, i.e., it becomes empty. + * Initialize list with (nonnull) compound instruction. Consumes argument list, i.e., it becomes empty. * - * @param ih - * where to append the instruction list - * @param il - * Instruction list to append to this one - * @return instruction handle pointing to the first appended instruction + * @param c compound instruction (list) */ - public InstructionHandle append(final InstructionHandle ih, final InstructionList il) { - if (il == null) { - throw new ClassGenException("Appending null InstructionList"); - } - if (il.isEmpty()) { - return ih; - } - final InstructionHandle next = ih.getNext(); - final InstructionHandle ret = il.start; - ih.setNext(il.start); - il.start.setPrev(ih); - il.end.setNext(next); - if (next != null) { - next.setPrev(il.end); - } else { - end = il.end; // Update end ... - } - length += il.length; // Update length - il.clear(); - return ret; + public InstructionList(final CompoundInstruction c) { + append(c.getInstructionList()); } /** - * Append another list after instruction i contained in this list. Consumes - * argument list, i.e., it becomes empty. + * Create instruction list containing one instruction. * - * @param i - * where to append the instruction list - * @param il - * Instruction list to append to this one - * @return instruction handle pointing to the first appended instruction + * @param i initial instruction */ - public InstructionHandle append(final Instruction i, final InstructionList il) { - InstructionHandle ih; - if ((ih = findInstruction2(i)) == null) { - throw new ClassGenException("Instruction " + i + " is not contained in this list."); + public InstructionList(final Instruction i) { + append(i); + } + + /** + * Add observer for this object. + */ + public void addObserver(final InstructionListObserver o) { + if (observers == null) { + observers = new ArrayList<>(); } - return append(ih, il); + observers.add(o); } /** - * Append another list to this one. Consumes argument list, i.e., it becomes - * empty. + * Append a branch instruction to the end of this list. * - * @param il - * list to append to end of this list - * @return instruction handle of the first appended instruction + * @param i branch instruction to append + * @return branch instruction handle of the appended instruction */ - public InstructionHandle append(final InstructionList il) { - if (il == null) { - throw new ClassGenException("Appending null InstructionList"); - } - if (il.isEmpty()) { - return null; - } - if (isEmpty()) { - start = il.start; - end = il.end; - length = il.length; - il.clear(); - return start; - } - return append(end, il); // was end.instruction + public BranchHandle append(final BranchInstruction i) { + final BranchHandle ih = BranchHandle.getBranchHandle(i); + append(ih); + return ih; } /** - * Append an instruction to the end of this list. + * Append a compound instruction. * - * @param ih - * instruction to append + * @param c The composite instruction (containing an InstructionList) + * @return instruction handle of the first appended instruction */ - private void append(final InstructionHandle ih) { - if (isEmpty()) { - start = end = ih; - ih.setNext(ih.setPrev(null)); - } else { - end.setNext(ih); - ih.setPrev(end); - ih.setNext(null); - end = ih; - } - length++; // Update length + public InstructionHandle append(final CompoundInstruction c) { + return append(c.getInstructionList()); } /** * Append an instruction to the end of this list. * - * @param i - * instruction to append + * @param i instruction to append * @return instruction handle of the appended instruction */ public InstructionHandle append(final Instruction i) { @@ -336,26 +235,21 @@ public InstructionHandle append(final Instruction i) { } /** - * Append a branch instruction to the end of this list. + * Append a compound instruction, after instruction i. * - * @param i - * branch instruction to append - * @return branch instruction handle of the appended instruction + * @param i Instruction in list + * @param c The composite instruction (containing an InstructionList) + * @return instruction handle of the first appended instruction */ - public BranchHandle append(final BranchInstruction i) { - final BranchHandle ih = BranchHandle.getBranchHandle(i); - append(ih); - return ih; + public InstructionHandle append(final Instruction i, final CompoundInstruction c) { + return append(i, c.getInstructionList()); } /** - * Append a single instruction j after another instruction i, which must be - * in this list of course! + * Append a single instruction j after another instruction i, which must be in this list of course! * - * @param i - * Instruction in list - * @param j - * Instruction to append after i in list + * @param i Instruction in list + * @param j Instruction to append after i in list * @return instruction handle of the first appended instruction */ public InstructionHandle append(final Instruction i, final Instruction j) { @@ -363,36 +257,58 @@ public InstructionHandle append(final Instruction i, final Instruction j) { } /** - * Append a compound instruction, after instruction i. + * Append another list after instruction i contained in this list. Consumes argument list, i.e., it becomes empty. * - * @param i - * Instruction in list - * @param c - * The composite instruction (containing an InstructionList) - * @return instruction handle of the first appended instruction + * @param i where to append the instruction list + * @param il Instruction list to append to this one + * @return instruction handle pointing to the first appended instruction */ - public InstructionHandle append(final Instruction i, final CompoundInstruction c) { - return append(i, c.getInstructionList()); + public InstructionHandle append(final Instruction i, final InstructionList il) { + InstructionHandle ih; + if ((ih = findInstruction2(i)) == null) { + throw new ClassGenException("Instruction " + i + " is not contained in this list."); + } + return append(ih, il); } /** - * Append a compound instruction. + * Append an instruction to the end of this list. * - * @param c - * The composite instruction (containing an InstructionList) - * @return instruction handle of the first appended instruction + * @param ih instruction to append */ - public InstructionHandle append(final CompoundInstruction c) { - return append(c.getInstructionList()); + private void append(final InstructionHandle ih) { + if (isEmpty()) { + start = end = ih; + ih.setNext(ih.setPrev(null)); + } else { + end.setNext(ih); + ih.setPrev(end); + ih.setNext(null); + end = ih; + } + length++; // Update length + } + + /** + * Append an instruction after instruction (handle) ih contained in this list. + * + * @param ih where to append the instruction list + * @param i Instruction to append + * @return instruction handle pointing to the first appended instruction + */ + public BranchHandle append(final InstructionHandle ih, final BranchInstruction i) { + final BranchHandle bh = BranchHandle.getBranchHandle(i); + final InstructionList il = new InstructionList(); + il.append(bh); + append(ih, il); + return bh; } /** * Append a compound instruction. * - * @param ih - * where to append the instruction list - * @param c - * The composite instruction (containing an InstructionList) + * @param ih where to append the instruction list + * @param c The composite instruction (containing an InstructionList) * @return instruction handle of the first appended instruction */ public InstructionHandle append(final InstructionHandle ih, final CompoundInstruction c) { @@ -402,10 +318,8 @@ public InstructionHandle append(final InstructionHandle ih, final CompoundInstru /** * Append an instruction after instruction (handle) ih contained in this list. * - * @param ih - * where to append the instruction list - * @param i - * Instruction to append + * @param ih where to append the instruction list + * @param i Instruction to append * @return instruction handle pointing to the first appended instruction */ public InstructionHandle append(final InstructionHandle ih, final Instruction i) { @@ -413,48 +327,29 @@ public InstructionHandle append(final InstructionHandle ih, final Instruction i) } /** - * Append an instruction after instruction (handle) ih contained in this list. + * Append another list after instruction (handle) ih contained in this list. Consumes argument list, i.e., it becomes + * empty. * - * @param ih - * where to append the instruction list - * @param i - * Instruction to append + * @param ih where to append the instruction list + * @param il Instruction list to append to this one * @return instruction handle pointing to the first appended instruction */ - public BranchHandle append(final InstructionHandle ih, final BranchInstruction i) { - final BranchHandle bh = BranchHandle.getBranchHandle(i); - final InstructionList il = new InstructionList(); - il.append(bh); - append(ih, il); - return bh; - } - - /** - * Insert another list before Instruction handle ih contained in this list. - * Consumes argument list, i.e., it becomes empty. - * - * @param ih - * where to append the instruction list - * @param il - * Instruction list to insert - * @return instruction handle of the first inserted instruction - */ - public InstructionHandle insert(final InstructionHandle ih, final InstructionList il) { + public InstructionHandle append(final InstructionHandle ih, final InstructionList il) { if (il == null) { - throw new ClassGenException("Inserting null InstructionList"); + throw new ClassGenException("Appending null InstructionList"); } if (il.isEmpty()) { return ih; } - final InstructionHandle prev = ih.getPrev(); + final InstructionHandle next = ih.getNext(); final InstructionHandle ret = il.start; - ih.setPrev(il.end); - il.end.setNext(ih); - il.start.setPrev(prev); - if (prev != null) { - prev.setNext(il.start); + ih.setNext(il.start); + il.start.setPrev(ih); + il.end.setNext(next); + if (next != null) { + next.setPrev(il.end); } else { - start = il.start; // Update start ... + end = il.end; // Update end ... } length += il.length; // Update length il.clear(); @@ -462,75 +357,296 @@ public InstructionHandle insert(final InstructionHandle ih, final InstructionLis } /** - * Insert another list. + * Append another list to this one. Consumes argument list, i.e., it becomes empty. * - * @param il - * list to insert before start of this list - * @return instruction handle of the first inserted instruction + * @param il list to append to end of this list + * @return instruction handle of the first appended instruction */ - public InstructionHandle insert(final InstructionList il) { + public InstructionHandle append(final InstructionList il) { + if (il == null) { + throw new ClassGenException("Appending null InstructionList"); + } + if (il.isEmpty()) { + return null; + } if (isEmpty()) { - append(il); // Code is identical for this case + start = il.start; + end = il.end; + length = il.length; + il.clear(); return start; } - return insert(start, il); + return append(end, il); // was end.instruction } - /** - * Insert an instruction at start of this list. - * - * @param ih - * instruction to insert + private void clear() { + start = end = null; + length = 0; + } + + public boolean contains(final Instruction i) { + return findInstruction1(i) != null; + } + + public boolean contains(final InstructionHandle i) { + if (i == null) { + return false; + } + for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { + if (ih == i) { + return true; + } + } + return false; + } + + /** + * @return complete, i.e., deep copy of this list */ - private void insert(final InstructionHandle ih) { - if (isEmpty()) { - start = end = ih; - ih.setNext(ih.setPrev(null)); - } else { - start.setPrev(ih); - ih.setNext(start); - ih.setPrev(null); - start = ih; + public InstructionList copy() { + final Map map = new HashMap<>(); + final InstructionList il = new InstructionList(); + /* + * Pass 1: Make copies of all instructions, append them to the new list and associate old instruction references with + * the new ones, i.e., a 1:1 mapping. + */ + for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { + final Instruction i = ih.getInstruction(); + final Instruction c = i.copy(); // Use clone for shallow copy + if (c instanceof BranchInstruction) { + map.put(ih, il.append((BranchInstruction) c)); + } else { + map.put(ih, il.append(c)); + } } - length++; + /* + * Pass 2: Update branch targets. + */ + InstructionHandle ih = start; + InstructionHandle ch = il.start; + while (ih != null) { + final Instruction i = ih.getInstruction(); + final Instruction c = ch.getInstruction(); + if (i instanceof BranchInstruction) { + final BranchInstruction bi = (BranchInstruction) i; + final BranchInstruction bc = (BranchInstruction) c; + final InstructionHandle itarget = bi.getTarget(); // old target + // New target is in hash map + bc.setTarget(map.get(itarget)); + if (bi instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH + final InstructionHandle[] itargets = ((Select) bi).getTargets(); + final InstructionHandle[] ctargets = ((Select) bc).getTargets(); + for (int j = 0; j < itargets.length; j++) { // Update all targets + ctargets[j] = map.get(itargets[j]); + } + } + } + ih = ih.getNext(); + ch = ch.getNext(); + } + return il; } /** - * Insert another list before Instruction i contained in this list. Consumes - * argument list, i.e., it becomes empty. + * Remove instruction from this list. The corresponding Instruction handles must not be reused! * - * @param i - * where to append the instruction list - * @param il - * Instruction list to insert - * @return instruction handle pointing to the first inserted instruction, i.e., il.getStart() + * @param i instruction to remove */ - public InstructionHandle insert(final Instruction i, final InstructionList il) { + public void delete(final Instruction i) throws TargetLostException { InstructionHandle ih; if ((ih = findInstruction1(i)) == null) { throw new ClassGenException("Instruction " + i + " is not contained in this list."); } - return insert(ih, il); + delete(ih); } /** - * Insert an instruction at start of this list. + * Remove instructions from instruction 'from' to instruction 'to' contained in this list. The user must ensure that + * 'from' is an instruction before 'to', or risk havoc. The corresponding Instruction handles must not be reused! * - * @param i - * instruction to insert - * @return instruction handle of the inserted instruction + * @param from where to start deleting (inclusive) + * @param to where to end deleting (inclusive) */ - public InstructionHandle insert(final Instruction i) { - final InstructionHandle ih = InstructionHandle.getInstructionHandle(i); - insert(ih); - return ih; + public void delete(final Instruction from, final Instruction to) throws TargetLostException { + InstructionHandle fromIh; + InstructionHandle toIh; + if ((fromIh = findInstruction1(from)) == null) { + throw new ClassGenException("Instruction " + from + " is not contained in this list."); + } + if ((toIh = findInstruction2(to)) == null) { + throw new ClassGenException("Instruction " + to + " is not contained in this list."); + } + delete(fromIh, toIh); + } + + /** + * Remove instruction from this list. The corresponding Instruction handles must not be reused! + * + * @param ih instruction (handle) to remove + */ + public void delete(final InstructionHandle ih) throws TargetLostException { + remove(ih.getPrev(), ih.getNext()); + } + + /** + * Remove instructions from instruction 'from' to instruction 'to' contained in this list. The user must ensure that + * 'from' is an instruction before 'to', or risk havoc. The corresponding Instruction handles must not be reused! + * + * @param from where to start deleting (inclusive) + * @param to where to end deleting (inclusive) + */ + public void delete(final InstructionHandle from, final InstructionHandle to) throws TargetLostException { + remove(from.getPrev(), to.getNext()); + } + + /** + * Delete contents of list. Provides better memory utilization, because the system then may reuse the instruction + * handles. This method is typically called right after {@link MethodGen#getMethod()}. + */ + public void dispose() { + // Traverse in reverse order, because ih.next is overwritten + for (InstructionHandle ih = end; ih != null; ih = ih.getPrev()) { + // Causes BranchInstructions to release target and targeters, because it calls dispose() on the contained instruction. + ih.dispose(); + } + clear(); + } + + /** + * Get instruction handle for instruction at byte code position pos. This only works properly, if the list is freshly + * initialized from a byte array or setPositions() has been called before this method. + * + * @param pos byte code position to search for + * @return target position's instruction handle if available + */ + public InstructionHandle findHandle(final int pos) { + final int[] positions = bytePositions; + InstructionHandle ih = start; + for (int i = 0; i < length; i++) { + if (positions[i] == pos) { + return ih; + } + ih = ih.getNext(); + } + return null; + } + + /** + * Search for given Instruction reference, start at beginning of list. + * + * @param i instruction to search for + * @return instruction found on success, null otherwise + */ + private InstructionHandle findInstruction1(final Instruction i) { + for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { + if (ih.getInstruction() == i) { + return ih; + } + } + return null; + } + + /** + * Search for given Instruction reference, start at end of list + * + * @param i instruction to search for + * @return instruction found on success, null otherwise + */ + private InstructionHandle findInstruction2(final Instruction i) { + for (InstructionHandle ih = end; ih != null; ih = ih.getPrev()) { + if (ih.getInstruction() == i) { + return ih; + } + } + return null; + } + + /** + * When everything is finished, use this method to convert the instruction list into an array of bytes. + * + * @return the byte code ready to be dumped + */ + public byte[] getByteCode() { + // Update position indices of instructions + setPositions(); + final ByteArrayOutputStream b = new ByteArrayOutputStream(); + final DataOutputStream out = new DataOutputStream(b); + try { + for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { + final Instruction i = ih.getInstruction(); + i.dump(out); // Traverse list + } + out.flush(); + } catch (final IOException e) { + System.err.println(e); + return Const.EMPTY_BYTE_ARRAY; + } + return b.toByteArray(); + } + + /** + * @return end of list + */ + public InstructionHandle getEnd() { + return end; + } + + /** + * @return array containing all instructions (handles) + */ + public InstructionHandle[] getInstructionHandles() { + final InstructionHandle[] ihs = new InstructionHandle[length]; + InstructionHandle ih = start; + for (int i = 0; i < length; i++) { + ihs[i] = ih; + ih = ih.getNext(); + } + return ihs; + } + + /** + * Get positions (offsets) of all instructions in the list. This relies on that the list has been freshly created from + * an byte code array, or that setPositions() has been called. Otherwise this may be inaccurate. + * + * @return array containing all instruction's offset in byte code + */ + public int[] getInstructionPositions() { + return bytePositions; + } + + /** + * @return an array of instructions without target information for branch instructions. + */ + public Instruction[] getInstructions() { + final List instructions = new ArrayList<>(); + try (ByteSequence bytes = new ByteSequence(getByteCode())) { + while (bytes.available() > 0) { + instructions.add(Instruction.readInstruction(bytes)); + } + } catch (final IOException e) { + throw new ClassGenException(e.toString(), e); + } + return instructions.toArray(Instruction.EMPTY_ARRAY); + } + + /** + * @return length of list (Number of instructions, not bytes) + */ + public int getLength() { + return length; + } + + /** + * @return start of list + */ + public InstructionHandle getStart() { + return start; } /** * Insert a branch instruction at start of this list. * - * @param i - * branch instruction to insert + * @param i branch instruction to insert * @return branch instruction handle of the appended instruction */ public BranchHandle insert(final BranchInstruction i) { @@ -540,26 +656,32 @@ public BranchHandle insert(final BranchInstruction i) { } /** - * Insert a single instruction j before another instruction i, which must be - * in this list of course! + * Insert a compound instruction. * - * @param i - * Instruction in list - * @param j - * Instruction to insert before i in list + * @param c The composite instruction (containing an InstructionList) * @return instruction handle of the first inserted instruction */ - public InstructionHandle insert(final Instruction i, final Instruction j) { - return insert(i, new InstructionList(j)); + public InstructionHandle insert(final CompoundInstruction c) { + return insert(c.getInstructionList()); + } + + /** + * Insert an instruction at start of this list. + * + * @param i instruction to insert + * @return instruction handle of the inserted instruction + */ + public InstructionHandle insert(final Instruction i) { + final InstructionHandle ih = InstructionHandle.getInstructionHandle(i); + insert(ih); + return ih; } /** * Insert a compound instruction before instruction i. * - * @param i - * Instruction in list - * @param c - * The composite instruction (containing an InstructionList) + * @param i Instruction in list + * @param c The composite instruction (containing an InstructionList) * @return instruction handle of the first inserted instruction */ public InstructionHandle insert(final Instruction i, final CompoundInstruction c) { @@ -567,49 +689,54 @@ public InstructionHandle insert(final Instruction i, final CompoundInstruction c } /** - * Insert a compound instruction. + * Insert a single instruction j before another instruction i, which must be in this list of course! * - * @param c - * The composite instruction (containing an InstructionList) + * @param i Instruction in list + * @param j Instruction to insert before i in list * @return instruction handle of the first inserted instruction */ - public InstructionHandle insert(final CompoundInstruction c) { - return insert(c.getInstructionList()); + public InstructionHandle insert(final Instruction i, final Instruction j) { + return insert(i, new InstructionList(j)); } /** - * Insert an instruction before instruction (handle) ih contained in this list. + * Insert another list before Instruction i contained in this list. Consumes argument list, i.e., it becomes empty. * - * @param ih - * where to insert to the instruction list - * @param i - * Instruction to insert - * @return instruction handle of the first inserted instruction + * @param i where to append the instruction list + * @param il Instruction list to insert + * @return instruction handle pointing to the first inserted instruction, i.e., il.getStart() */ - public InstructionHandle insert(final InstructionHandle ih, final Instruction i) { - return insert(ih, new InstructionList(i)); + public InstructionHandle insert(final Instruction i, final InstructionList il) { + InstructionHandle ih; + if ((ih = findInstruction1(i)) == null) { + throw new ClassGenException("Instruction " + i + " is not contained in this list."); + } + return insert(ih, il); } /** - * Insert a compound instruction. + * Insert an instruction at start of this list. * - * @param ih - * where to insert the instruction list - * @param c - * The composite instruction (containing an InstructionList) - * @return instruction handle of the first inserted instruction + * @param ih instruction to insert */ - public InstructionHandle insert(final InstructionHandle ih, final CompoundInstruction c) { - return insert(ih, c.getInstructionList()); + private void insert(final InstructionHandle ih) { + if (isEmpty()) { + start = end = ih; + ih.setNext(ih.setPrev(null)); + } else { + start.setPrev(ih); + ih.setNext(start); + ih.setPrev(null); + start = ih; + } + length++; } /** * Insert an instruction before instruction (handle) ih contained in this list. * - * @param ih - * where to insert to the instruction list - * @param i - * Instruction to insert + * @param ih where to insert to the instruction list + * @param i Instruction to insert * @return instruction handle of the first inserted instruction */ public BranchHandle insert(final InstructionHandle ih, final BranchInstruction i) { @@ -621,33 +748,144 @@ public BranchHandle insert(final InstructionHandle ih, final BranchInstruction i } /** - * Take all instructions (handles) from "start" to "end" and append them - * after the new location "target". Of course, "end" must be after "start" - * and target must not be located within this range. If you want to move - * something to the start of the list use null as value for target. + * Insert a compound instruction. + * + * @param ih where to insert the instruction list + * @param c The composite instruction (containing an InstructionList) + * @return instruction handle of the first inserted instruction + */ + public InstructionHandle insert(final InstructionHandle ih, final CompoundInstruction c) { + return insert(ih, c.getInstructionList()); + } + + /** + * Insert an instruction before instruction (handle) ih contained in this list. + * + * @param ih where to insert to the instruction list + * @param i Instruction to insert + * @return instruction handle of the first inserted instruction + */ + public InstructionHandle insert(final InstructionHandle ih, final Instruction i) { + return insert(ih, new InstructionList(i)); + } + + /** + * Insert another list before Instruction handle ih contained in this list. Consumes argument list, i.e., it becomes + * empty. + * + * @param ih where to append the instruction list + * @param il Instruction list to insert + * @return instruction handle of the first inserted instruction + */ + public InstructionHandle insert(final InstructionHandle ih, final InstructionList il) { + if (il == null) { + throw new ClassGenException("Inserting null InstructionList"); + } + if (il.isEmpty()) { + return ih; + } + final InstructionHandle prev = ih.getPrev(); + final InstructionHandle ret = il.start; + ih.setPrev(il.end); + il.end.setNext(ih); + il.start.setPrev(prev); + if (prev != null) { + prev.setNext(il.start); + } else { + start = il.start; // Update start ... + } + length += il.length; // Update length + il.clear(); + return ret; + } + + /** + * Insert another list. + * + * @param il list to insert before start of this list + * @return instruction handle of the first inserted instruction + */ + public InstructionHandle insert(final InstructionList il) { + if (isEmpty()) { + append(il); // Code is identical for this case + return start; + } + return insert(start, il); + } + + /** + * Test for empty list. + */ + public boolean isEmpty() { + return start == null; + } // && end == null + + /** + * @return iterator that lists all instructions (handles) + */ + @Override + public Iterator iterator() { + return new Iterator() { + + private InstructionHandle ih = start; + + @Override + public boolean hasNext() { + return ih != null; + } + + @Override + public InstructionHandle next() throws NoSuchElementException { + if (ih == null) { + throw new NoSuchElementException(); + } + final InstructionHandle i = ih; + ih = ih.getNext(); + return i; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + /** + * Move a single instruction (handle) to a new location. + * + * @param ih moved instruction + * @param target new location of moved instruction + */ + public void move(final InstructionHandle ih, final InstructionHandle target) { + move(ih, ih, target); + } + + /** + * Take all instructions (handles) from "start" to "end" and append them after the new location "target". Of course, + * "end" must be after "start" and target must not be located withing this range. If you want to move something to the + * start of the list use null as value for target. *

    - * Any instruction targeters pointing to handles within the block, keep - * their targets. + * Any instruction targeters pointing to handles within the block, keep their targets. + *

    * - * @param start - * of moved block - * @param end - * of moved block - * @param target - * of moved block + * @param start of moved block + * @param end of moved block + * @param target of moved block */ public void move(final InstructionHandle start, final InstructionHandle end, final InstructionHandle target) { // Step 1: Check constraints - if ((start == null) || (end == null)) { + if (start == null || end == null) { throw new ClassGenException("Invalid null handle: From " + start + " to " + end); } - if ((target == start) || (target == end)) { + if (target == start || target == end) { throw new ClassGenException("Invalid range: From " + start + " to " + end + " contains target " + target); } for (InstructionHandle ih = start; ih != end.getNext(); ih = ih.getNext()) { if (ih == null) { throw new ClassGenException("Invalid range: From " + start + " to " + end); - } else if (ih == target) { + } + if (ih == target) { throw new ClassGenException("Invalid range: From " + start + " to " + end + " contains target " + target); } } @@ -686,31 +924,86 @@ public void move(final InstructionHandle start, final InstructionHandle end, fin } /** - * Move a single instruction (handle) to a new location. + * Redirect all references from oldTarget to newTarget, i.e., update targets of branch instructions. * - * @param ih - * moved instruction - * @param target - * new location of moved instruction + * @param oldTarget the old target instruction handle + * @param newTarget the new target instruction handle */ - public void move(final InstructionHandle ih, final InstructionHandle target) { - move(ih, ih, target); + public void redirectBranches(final InstructionHandle oldTarget, final InstructionHandle newTarget) { + for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { + final Instruction i = ih.getInstruction(); + if (i instanceof BranchInstruction) { + final BranchInstruction b = (BranchInstruction) i; + final InstructionHandle target = b.getTarget(); + if (target == oldTarget) { + b.setTarget(newTarget); + } + if (b instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH + final InstructionHandle[] targets = ((Select) b).getTargets(); + for (int j = 0; j < targets.length; j++) { + if (targets[j] == oldTarget) { + ((Select) b).setTarget(j, newTarget); + } + } + } + } + } + } + + /** + * Redirect all references of exception handlers from oldTarget to newTarget. + * + * @param exceptions array of exception handlers + * @param oldTarget the old target instruction handle + * @param newTarget the new target instruction handle + * @see MethodGen + */ + public void redirectExceptionHandlers(final CodeExceptionGen[] exceptions, final InstructionHandle oldTarget, final InstructionHandle newTarget) { + for (final CodeExceptionGen exception : exceptions) { + if (exception.getStartPC() == oldTarget) { + exception.setStartPC(newTarget); + } + if (exception.getEndPC() == oldTarget) { + exception.setEndPC(newTarget); + } + if (exception.getHandlerPC() == oldTarget) { + exception.setHandlerPC(newTarget); + } + } } /** - * Remove from instruction `prev' to instruction `next' both contained in - * this list. Throws TargetLostException when one of the removed instruction - * handles is still being targeted. + * Redirect all references of local variables from oldTarget to newTarget. * - * @param prev - * where to start deleting (predecessor, exclusive) - * @param next - * where to end deleting (successor, exclusive) + * @param lg array of local variables + * @param oldTarget the old target instruction handle + * @param newTarget the new target instruction handle + * @see MethodGen + */ + public void redirectLocalVariables(final LocalVariableGen[] lg, final InstructionHandle oldTarget, final InstructionHandle newTarget) { + for (final LocalVariableGen element : lg) { + final InstructionHandle start = element.getStart(); + final InstructionHandle end = element.getEnd(); + if (start == oldTarget) { + element.setStart(newTarget); + } + if (end == oldTarget) { + element.setEnd(newTarget); + } + } + } + + /** + * Remove from instruction 'prev' to instruction 'next' both contained in this list. Throws TargetLostException when one + * of the removed instruction handles is still being targeted. + * + * @param prev where to start deleting (predecessor, exclusive) + * @param next where to end deleting (successor, exclusive) */ private void remove(final InstructionHandle prev, InstructionHandle next) throws TargetLostException { InstructionHandle first; InstructionHandle last; // First and last deleted instruction - if ((prev == null) && (next == null)) { + if (prev == null && next == null) { first = start; last = end; start = end = null; @@ -732,7 +1025,7 @@ private void remove(final InstructionHandle prev, InstructionHandle next) throws } first.setPrev(null); // Completely separated from rest of list last.setNext(null); - final List target_vec = new ArrayList<>(); + final List targetList = new ArrayList<>(); for (InstructionHandle ih = first; ih != null; ih = ih.getNext()) { ih.getInstruction().dispose(); // e.g. BranchInstructions release their targets } @@ -741,7 +1034,7 @@ private void remove(final InstructionHandle prev, InstructionHandle next) throws next = ih.getNext(); length--; if (ih.hasTargeters()) { // Still got targeters? - target_vec.add(ih); + targetList.add(ih); buf.append(ih.toString(true)).append(" "); ih.setNext(ih.setPrev(null)); } else { @@ -749,120 +1042,32 @@ private void remove(final InstructionHandle prev, InstructionHandle next) throws } } buf.append("}"); - if (!target_vec.isEmpty()) { - final InstructionHandle[] targeted = new InstructionHandle[target_vec.size()]; - target_vec.toArray(targeted); - throw new TargetLostException(targeted, buf.toString()); - } - } - - /** - * Remove instruction from this list. The corresponding Instruction handles - * must not be reused! - * - * @param ih - * instruction (handle) to remove - */ - public void delete(final InstructionHandle ih) throws TargetLostException { - remove(ih.getPrev(), ih.getNext()); - } - - /** - * Remove instruction from this list. The corresponding Instruction handles must not be reused! - * - * @param i - * instruction to remove - */ - public void delete(final Instruction i) throws TargetLostException { - InstructionHandle ih; - if ((ih = findInstruction1(i)) == null) { - throw new ClassGenException("Instruction " + i + " is not contained in this list."); + if (!targetList.isEmpty()) { + throw new TargetLostException(targetList.toArray(InstructionHandle.EMPTY_ARRAY), buf.toString()); } - delete(ih); } /** - * Remove instructions from instruction `from' to instruction `to' contained - * in this list. The user must ensure that `from' is an instruction before - * `to', or risk havoc. The corresponding Instruction handles must not be - * reused! - * - * @param from - * where to start deleting (inclusive) - * @param to - * where to end deleting (inclusive) - */ - public void delete(final InstructionHandle from, final InstructionHandle to) throws TargetLostException { - remove(from.getPrev(), to.getNext()); - } - - /** - * Remove instructions from instruction `from' to instruction `to' contained in this list. The user must ensure that `from' is an instruction before `to', - * or risk havoc. The corresponding Instruction handles must not be reused! - * - * @param from - * where to start deleting (inclusive) - * @param to - * where to end deleting (inclusive) - */ - public void delete(final Instruction from, final Instruction to) throws TargetLostException { - InstructionHandle from_ih; - InstructionHandle to_ih; - if ((from_ih = findInstruction1(from)) == null) { - throw new ClassGenException("Instruction " + from + " is not contained in this list."); - } - if ((to_ih = findInstruction2(to)) == null) { - throw new ClassGenException("Instruction " + to + " is not contained in this list."); - } - delete(from_ih, to_ih); - } - - /** - * Search for given Instruction reference, start at beginning of list. - * - * @param i - * instruction to search for - * @return instruction found on success, null otherwise + * Remove observer for this object. */ - private InstructionHandle findInstruction1(final Instruction i) { - for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { - if (ih.getInstruction() == i) { - return ih; - } + public void removeObserver(final InstructionListObserver o) { + if (observers != null) { + observers.remove(o); } - return null; } /** - * Search for given Instruction reference, start at end of list - * - * @param i - * instruction to search for - * @return instruction found on success, null otherwise + * Replace all references to the old constant pool with references to the new constant pool */ - private InstructionHandle findInstruction2(final Instruction i) { - for (InstructionHandle ih = end; ih != null; ih = ih.getPrev()) { - if (ih.getInstruction() == i) { - return ih; - } - } - return null; - } - - public boolean contains(final InstructionHandle i) { - if (i == null) { - return false; - } + public void replaceConstantPool(final ConstantPoolGen oldCp, final ConstantPoolGen newCp) { for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { - if (ih == i) { - return true; + final Instruction i = ih.getInstruction(); + if (i instanceof CPInstruction) { + final CPInstruction ci = (CPInstruction) i; + final Constant c = oldCp.getConstant(ci.getIndex()); + ci.setIndex(newCp.addConstant(c, oldCp)); } } - return false; - } - - public boolean contains(final Instruction i) { - return findInstruction1(i) != null; } public void setPositions() { // TODO could be package-protected? (some test code would need to be repackaged) @@ -870,15 +1075,13 @@ public void setPositions() { // TODO could be package-protected? (some test code } /** - * Give all instructions their position number (offset in byte stream), - * i.e., make the list ready to be dumped. + * Give all instructions their position number (offset in byte stream), i.e., make the list ready to be dumped. * - * @param check - * Perform sanity checks, e.g. if all targeted instructions really belong to this list + * @param check Perform sanity checks, e.g. if all targeted instructions really belong to this list */ public void setPositions(final boolean check) { // called by code in other packages - int max_additional_bytes = 0; - int additional_bytes = 0; + int maxAdditionalBytes = 0; + int additionalBytes = 0; int index = 0; int count = 0; final int[] pos = new int[length]; @@ -891,26 +1094,20 @@ public void setPositions(final boolean check) { // called by code in other packa if (i instanceof BranchInstruction) { // target instruction within list? Instruction inst = ((BranchInstruction) i).getTarget().getInstruction(); if (!contains(inst)) { - throw new ClassGenException("Branch target of " - + Const.getOpcodeName(i.getOpcode()) + ":" - + inst + " not in instruction list"); + throw new ClassGenException("Branch target of " + Const.getOpcodeName(i.getOpcode()) + ":" + inst + " not in instruction list"); } if (i instanceof Select) { final InstructionHandle[] targets = ((Select) i).getTargets(); for (final InstructionHandle target : targets) { inst = target.getInstruction(); if (!contains(inst)) { - throw new ClassGenException("Branch target of " - + Const.getOpcodeName(i.getOpcode()) + ":" - + inst + " not in instruction list"); + throw new ClassGenException("Branch target of " + Const.getOpcodeName(i.getOpcode()) + ":" + inst + " not in instruction list"); } } } if (!(ih instanceof BranchHandle)) { throw new ClassGenException( - "Branch instruction " - + Const.getOpcodeName(i.getOpcode()) + ":" - + inst + " not contained in BranchHandle."); + "Branch instruction " + Const.getOpcodeName(i.getOpcode()) + ":" + inst + " not contained in BranchHandle."); } } } @@ -923,33 +1120,30 @@ public void setPositions(final boolean check) { // called by code in other packa ih.setPosition(index); pos[count++] = index; /* - * Get an estimate about how many additional bytes may be added, - * because BranchInstructions may have variable length depending on the target offset - * (short vs. int) or alignment issues (TABLESWITCH and LOOKUPSWITCH). + * Get an estimate about how many additional bytes may be added, because BranchInstructions may have variable length + * depending on the target offset (short vs. int) or alignment issues (TABLESWITCH and LOOKUPSWITCH). */ switch (i.getOpcode()) { - case Const.JSR: - case Const.GOTO: - max_additional_bytes += 2; + case Const.JSR: + case Const.GOTO: + maxAdditionalBytes += 2; break; - case Const.TABLESWITCH: - case Const.LOOKUPSWITCH: - max_additional_bytes += 3; + case Const.TABLESWITCH: + case Const.LOOKUPSWITCH: + maxAdditionalBytes += 3; break; } index += i.getLength(); } - - /* Pass 2: Expand the variable-length (Branch)Instructions depending on - * the target offset (short or int) and ensure that branch targets are - * within this list. + /* + * Pass 2: Expand the variable-length (Branch)Instructions depending on the target offset (short or int) and ensure that + * branch targets are within this list. */ for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { - additional_bytes += ih.updatePosition(additional_bytes, max_additional_bytes); + additionalBytes += ih.updatePosition(additionalBytes, maxAdditionalBytes); } /* - * Pass 3: Update position numbers (which may have changed due to the - * preceding expansions), like pass 1. + * Pass 3: Update position numbers (which may have changed due to the preceding expansions), like pass 1. */ index = count = 0; for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { @@ -963,43 +1157,10 @@ public void setPositions(final boolean check) { // called by code in other packa } /** - * When everything is finished, use this method to convert the instruction - * list into an array of bytes. - * - * @return the byte code ready to be dumped - */ - public byte[] getByteCode() { - // Update position indices of instructions - setPositions(); - final ByteArrayOutputStream b = new ByteArrayOutputStream(); - final DataOutputStream out = new DataOutputStream(b); - try { - for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { - final Instruction i = ih.getInstruction(); - i.dump(out); // Traverse list - } - out.flush(); - } catch (final IOException e) { - System.err.println(e); - return new byte[0]; - } - return b.toByteArray(); - } - - /** - * @return an array of instructions without target information for branch - * instructions. + * @return length of list (Number of instructions, not bytes) */ - public Instruction[] getInstructions() { - final List instructions = new ArrayList<>(); - try (ByteSequence bytes = new ByteSequence(getByteCode())) { - while (bytes.available() > 0) { - instructions.add(Instruction.readInstruction(bytes)); - } - } catch (final IOException e) { - throw new ClassGenException(e.toString(), e); - } - return instructions.toArray(new Instruction[instructions.size()]); + public int size() { + return length; } @Override @@ -1008,8 +1169,7 @@ public String toString() { } /** - * @param verbose - * toggle output format + * @param verbose toggle output format * @return String containing all instructions in this list. */ public String toString(final boolean verbose) { @@ -1021,277 +1181,8 @@ public String toString(final boolean verbose) { } /** - * @return iterator that lists all instructions (handles) - */ - @Override - public Iterator iterator() { - return new Iterator() { - - private InstructionHandle ih = start; - - @Override - public InstructionHandle next() throws NoSuchElementException { - if (ih == null) { - throw new NoSuchElementException(); - } - final InstructionHandle i = ih; - ih = ih.getNext(); - return i; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean hasNext() { - return ih != null; - } - }; - } - - /** - * @return array containing all instructions (handles) - */ - public InstructionHandle[] getInstructionHandles() { - final InstructionHandle[] ihs = new InstructionHandle[length]; - InstructionHandle ih = start; - for (int i = 0; i < length; i++) { - ihs[i] = ih; - ih = ih.getNext(); - } - return ihs; - } - - /** - * Get positions (offsets) of all instructions in the list. This relies on - * that the list has been freshly created from an byte code array, or that - * setPositions() has been called. Otherwise this may be inaccurate. - * - * @return array containing all instruction's offset in byte code - */ - public int[] getInstructionPositions() { - return bytePositions; - } - - /** - * @return complete, i.e., deep copy of this list - */ - public InstructionList copy() { - final Map map = new HashMap<>(); - final InstructionList il = new InstructionList(); - /* - * Pass 1: Make copies of all instructions, append them to the new list - * and associate old instruction references with the new ones, i.e., a 1:1 mapping. - */ - for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { - final Instruction i = ih.getInstruction(); - final Instruction c = i.copy(); // Use clone for shallow copy - if (c instanceof BranchInstruction) { - map.put(ih, il.append((BranchInstruction) c)); - } else { - map.put(ih, il.append(c)); - } - } - /* - * Pass 2: Update branch targets. - */ - InstructionHandle ih = start; - InstructionHandle ch = il.start; - while (ih != null) { - final Instruction i = ih.getInstruction(); - final Instruction c = ch.getInstruction(); - if (i instanceof BranchInstruction) { - final BranchInstruction bi = (BranchInstruction) i; - final BranchInstruction bc = (BranchInstruction) c; - final InstructionHandle itarget = bi.getTarget(); // old target - // New target is in hash map - bc.setTarget(map.get(itarget)); - if (bi instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH - final InstructionHandle[] itargets = ((Select) bi).getTargets(); - final InstructionHandle[] ctargets = ((Select) bc).getTargets(); - for (int j = 0; j < itargets.length; j++) { // Update all targets - ctargets[j] = map.get(itargets[j]); - } - } - } - ih = ih.getNext(); - ch = ch.getNext(); - } - return il; - } - - /** - * Replace all references to the old constant pool with references to the - * new constant pool - */ - public void replaceConstantPool(final ConstantPoolGen old_cp, final ConstantPoolGen new_cp) { - for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { - final Instruction i = ih.getInstruction(); - if (i instanceof CPInstruction) { - final CPInstruction ci = (CPInstruction) i; - final Constant c = old_cp.getConstant(ci.getIndex()); - ci.setIndex(new_cp.addConstant(c, old_cp)); - } - } - } - - private void clear() { - start = end = null; - length = 0; - } - - /** - * Delete contents of list. Provides better memory utilization, because the - * system then may reuse the instruction handles. This method is typically - * called right after {@link MethodGen#getMethod()}. - */ - public void dispose() { - // Traverse in reverse order, because ih.next is overwritten - for (InstructionHandle ih = end; ih != null; ih = ih.getPrev()) { - /* - * Causes BranchInstructions to release target and targeters, - * because it calls dispose() on the contained instruction. - */ - ih.dispose(); - } - clear(); - } - - /** - * @return start of list - */ - public InstructionHandle getStart() { - return start; - } - - /** - * @return end of list - */ - public InstructionHandle getEnd() { - return end; - } - - /** - * @return length of list (Number of instructions, not bytes) - */ - public int getLength() { - return length; - } - - /** - * @return length of list (Number of instructions, not bytes) - */ - public int size() { - return length; - } - - /** - * Redirect all references from old_target to new_target, i.e., update - * targets of branch instructions. - * - * @param old_target - * the old target instruction handle - * @param new_target - * the new target instruction handle - */ - public void redirectBranches(final InstructionHandle old_target, final InstructionHandle new_target) { - for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { - final Instruction i = ih.getInstruction(); - if (i instanceof BranchInstruction) { - final BranchInstruction b = (BranchInstruction) i; - final InstructionHandle target = b.getTarget(); - if (target == old_target) { - b.setTarget(new_target); - } - if (b instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH - final InstructionHandle[] targets = ((Select) b).getTargets(); - for (int j = 0; j < targets.length; j++) { - if (targets[j] == old_target) { - ((Select) b).setTarget(j, new_target); - } - } - } - } - } - } - - /** - * Redirect all references of local variables from old_target to new_target. - * - * @param lg - * array of local variables - * @param old_target - * the old target instruction handle - * @param new_target - * the new target instruction handle - * @see MethodGen - */ - public void redirectLocalVariables(final LocalVariableGen[] lg, final InstructionHandle old_target, final InstructionHandle new_target) { - for (final LocalVariableGen element : lg) { - final InstructionHandle start = element.getStart(); - final InstructionHandle end = element.getEnd(); - if (start == old_target) { - element.setStart(new_target); - } - if (end == old_target) { - element.setEnd(new_target); - } - } - } - - /** - * Redirect all references of exception handlers from old_target to new_target. - * - * @param exceptions - * array of exception handlers - * @param old_target - * the old target instruction handle - * @param new_target - * the new target instruction handle - * @see MethodGen - */ - public void redirectExceptionHandlers(final CodeExceptionGen[] exceptions, - final InstructionHandle old_target, final InstructionHandle new_target) { - for (final CodeExceptionGen exception : exceptions) { - if (exception.getStartPC() == old_target) { - exception.setStartPC(new_target); - } - if (exception.getEndPC() == old_target) { - exception.setEndPC(new_target); - } - if (exception.getHandlerPC() == old_target) { - exception.setHandlerPC(new_target); - } - } - } - - private List observers; - - /** - * Add observer for this object. - */ - public void addObserver(final InstructionListObserver o) { - if (observers == null) { - observers = new ArrayList<>(); - } - observers.add(o); - } - - /** - * Remove observer for this object. - */ - public void removeObserver(final InstructionListObserver o) { - if (observers != null) { - observers.remove(o); - } - } - - /** - * Call notify() method on all observers. This method is not called - * automatically whenever the state has changed, but has to be called by the - * user after he has finished editing the object. + * Call notify() method on all observers. This method is not called automatically whenever the state has changed, but + * has to be called by the user after he has finished editing the object. */ public void update() { if (observers != null) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionListObserver.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionListObserver.java index 116273a44d7..758c455d659 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionListObserver.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionListObserver.java @@ -22,11 +22,10 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Implement this interface if you're interested in changes to an InstructionList object - * and register yourself with addObserver(). - * + * Implement this interface if you're interested in changes to an InstructionList object and register yourself with + * addObserver(). */ public interface InstructionListObserver { - void notify( InstructionList list ); + void notify(InstructionList list); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java index 8cd436b38ce..5146408ef49 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java @@ -22,8 +22,7 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Denote that a class targets InstructionHandles within an InstructionList. Namely - * the following implementers: + * Denote that a class targets InstructionHandles within an InstructionList. Namely the following implementers: * * @see BranchHandle * @see LocalVariableGen @@ -31,6 +30,8 @@ */ public interface InstructionTargeter { + // static final InstructionTargeter[] EMPTY_ARRAY = new InstructionTargeter[0]; + /** * Checks whether this targeter targets the specified instruction handle. */ @@ -39,9 +40,9 @@ public interface InstructionTargeter { /** * Replaces the target of this targeter from this old handle to the new handle. * - * @param old_ih the old handle - * @param new_ih the new handle - * @throws ClassGenException if old_ih is not targeted by this object + * @param oldIh the old handle + * @param newIh the new handle + * @throws ClassGenException if oldIh is not targeted by this object */ - void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) throws ClassGenException; + void updateTarget(InstructionHandle oldIh, InstructionHandle newIh) throws ClassGenException; } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InvokeInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InvokeInstruction.java index 73948914077..0daa3abfc13 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InvokeInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InvokeInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -26,23 +26,21 @@ import com.sun.org.apache.bcel.internal.classfile.Constant; import com.sun.org.apache.bcel.internal.classfile.ConstantCP; import com.sun.org.apache.bcel.internal.classfile.ConstantPool; +import com.sun.org.apache.bcel.internal.classfile.Utility; /** * Super class for the INVOKExxx family of instructions. * - * @LastModified: Jan 2020 + * @LastModified: Feb 2023 */ -public abstract class InvokeInstruction extends FieldOrMethod implements ExceptionThrower, - StackConsumer, StackProducer { +public abstract class InvokeInstruction extends FieldOrMethod implements ExceptionThrower, StackConsumer, StackProducer { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ InvokeInstruction() { } - /** * @param index to constant pool */ @@ -50,39 +48,15 @@ protected InvokeInstruction(final short opcode, final int index) { super(opcode, index); } - /** - * @return mnemonic for instruction with symbolic references resolved - */ - @Override - public String toString( final ConstantPool cp ) { - final Constant c = cp.getConstant(super.getIndex()); - final StringTokenizer tok = new StringTokenizer(cp.constantToString(c)); - - final String opcodeName = Const.getOpcodeName(super.getOpcode()); - - final StringBuilder sb = new StringBuilder(opcodeName); - if (tok.hasMoreTokens()) { - sb.append(" "); - sb.append(tok.nextToken().replace('.', '/')); - if (tok.hasMoreTokens()) { - sb.append(tok.nextToken()); - } - } - - return sb.toString(); - } - - - /** - * Also works for instructions whose stack effect depends on the - * constant pool entry they reference. + * Also works for instructions whose stack effect depends on the constant pool entry they reference. + * * @return Number of words consumed from stack by this instruction */ @Override - public int consumeStack( final ConstantPoolGen cpg ) { + public int consumeStack(final ConstantPoolGen cpg) { int sum; - if ((super.getOpcode() == Const.INVOKESTATIC) || (super.getOpcode() == Const.INVOKEDYNAMIC)) { + if (super.getOpcode() == Const.INVOKESTATIC || super.getOpcode() == Const.INVOKEDYNAMIC) { sum = 0; } else { sum = 1; // this reference @@ -93,23 +67,15 @@ public int consumeStack( final ConstantPoolGen cpg ) { return sum; } - /** - * Also works for instructions whose stack effect depends on the - * constant pool entry they reference. - * @return Number of words produced onto stack by this instruction + * @return argument types of referenced method. */ - @Override - public int produceStack( final ConstantPoolGen cpg ) { - final String signature = getSignature(cpg); - return Type.getReturnTypeSize(signature); + public Type[] getArgumentTypes(final ConstantPoolGen cpg) { + return Type.getArgumentTypes(getSignature(cpg)); } /** - * This overrides the deprecated version as we know here that the referenced class - * may legally be an array. - * - * @deprecated in FieldOrMethod + * This overrides the deprecated version as we know here that the referenced class may legally be an array. * * @return name of the referenced class/interface * @throws IllegalArgumentException if the referenced class is an array (this should not happen) @@ -120,35 +86,62 @@ public String getClassName( final ConstantPoolGen cpg ) { final ConstantPool cp = cpg.getConstantPool(); final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class); - return className.replace('/', '.'); + return Utility.pathToPackage(className); } - /** @return return type of referenced method. + /** + * @return name of referenced method. */ - @Override - public Type getType( final ConstantPoolGen cpg ) { - return getReturnType(cpg); + public String getMethodName(final ConstantPoolGen cpg) { + return getName(cpg); } - - /** @return name of referenced method. + /** + * @return return type of referenced method. */ - public String getMethodName( final ConstantPoolGen cpg ) { - return getName(cpg); + public Type getReturnType(final ConstantPoolGen cpg) { + return Type.getReturnType(getSignature(cpg)); } - - /** @return return type of referenced method. + /** + * @return return type of referenced method. */ - public Type getReturnType( final ConstantPoolGen cpg ) { - return Type.getReturnType(getSignature(cpg)); + @Override + public Type getType(final ConstantPoolGen cpg) { + return getReturnType(cpg); } + /** + * Also works for instructions whose stack effect depends on the constant pool entry they reference. + * + * @return Number of words produced onto stack by this instruction + */ + @Override + public int produceStack(final ConstantPoolGen cpg) { + final String signature = getSignature(cpg); + return Type.getReturnTypeSize(signature); + } - /** @return argument types of referenced method. + /** + * @return mnemonic for instruction with symbolic references resolved */ - public Type[] getArgumentTypes( final ConstantPoolGen cpg ) { - return Type.getArgumentTypes(getSignature(cpg)); + @Override + public String toString(final ConstantPool cp) { + final Constant c = cp.getConstant(super.getIndex()); + final StringTokenizer tok = new StringTokenizer(cp.constantToString(c)); + + final String opcodeName = Const.getOpcodeName(super.getOpcode()); + + final StringBuilder sb = new StringBuilder(opcodeName); + if (tok.hasMoreTokens()) { + sb.append(" "); + sb.append(Utility.packageToPath(tok.nextToken())); + if (tok.hasMoreTokens()) { + sb.append(tok.nextToken()); + } + } + + return sb.toString(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/JSR.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/JSR.java index edcc569ec03..548b321d0bc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/JSR.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/JSR.java @@ -26,29 +26,41 @@ /** * JSR - Jump to subroutine - * */ public class JSR extends JsrInstruction implements VariableLengthInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ JSR() { } - public JSR(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.JSR, target); } + /** + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitStackProducer(this); + v.visitVariableLengthInstruction(this); + v.visitBranchInstruction(this); + v.visitJsrInstruction(this); + v.visitJSR(this); + } /** * Dump instruction as byte code to stream out. + * * @param out Output stream */ @Override - public void dump( final DataOutputStream out ) throws IOException { + public void dump(final DataOutputStream out) throws IOException { super.setIndex(getTargetOffset()); if (super.getOpcode() == com.sun.org.apache.bcel.internal.Const.JSR) { super.dump(out); @@ -59,35 +71,16 @@ public void dump( final DataOutputStream out ) throws IOException { } } - @Override - protected int updatePosition( final int offset, final int max_offset ) { + protected int updatePosition(final int offset, final int maxOffset) { final int i = getTargetOffset(); // Depending on old position value setPosition(getPosition() + offset); // Position may be shifted by preceding expansions - if (Math.abs(i) >= (Short.MAX_VALUE - max_offset)) { // to large for short (estimate) + if (Math.abs(i) >= Short.MAX_VALUE - maxOffset) { // to large for short (estimate) super.setOpcode(com.sun.org.apache.bcel.internal.Const.JSR_W); - final short old_length = (short) super.getLength(); + final short oldLength = (short) super.getLength(); super.setLength(5); - return super.getLength() - old_length; + return super.getLength() - oldLength; } return 0; } - - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. - * - * @param v Visitor object - */ - @Override - public void accept( final Visitor v ) { - v.visitStackProducer(this); - v.visitVariableLengthInstruction(this); - v.visitBranchInstruction(this); - v.visitJsrInstruction(this); - v.visitJSR(this); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/JSR_W.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/JSR_W.java index 7cf3c9289ec..b51d05c6799 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/JSR_W.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/JSR_W.java @@ -28,59 +28,52 @@ /** * JSR_W - Jump to subroutine - * */ public class JSR_W extends JsrInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ JSR_W() { } - public JSR_W(final InstructionHandle target) { super(com.sun.org.apache.bcel.internal.Const.JSR_W, target); super.setLength(5); } + /** + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitStackProducer(this); + v.visitBranchInstruction(this); + v.visitJsrInstruction(this); + v.visitJSR_W(this); + } /** * Dump instruction as byte code to stream out. + * * @param out Output stream */ @Override - public void dump( final DataOutputStream out ) throws IOException { + public void dump(final DataOutputStream out) throws IOException { super.setIndex(getTargetOffset()); out.writeByte(super.getOpcode()); out.writeInt(super.getIndex()); } - /** * Read needed data (e.g. index) from file. */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { super.setIndex(bytes.readInt()); super.setLength(5); } - - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. - * - * @param v Visitor object - */ - @Override - public void accept( final Visitor v ) { - v.visitStackProducer(this); - v.visitBranchInstruction(this); - v.visitJsrInstruction(this); - v.visitJSR_W(this); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/JsrInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/JsrInstruction.java index f999d5ce76b..1ecd736d355 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/JsrInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/JsrInstruction.java @@ -23,42 +23,33 @@ /** * Super class for JSR - Jump to subroutine - * */ -public abstract class JsrInstruction extends BranchInstruction implements UnconditionalBranch, - TypedInstruction, StackProducer { - - JsrInstruction(final short opcode, final InstructionHandle target) { - super(opcode, target); - } - +public abstract class JsrInstruction extends BranchInstruction implements UnconditionalBranch, TypedInstruction, StackProducer { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ JsrInstruction() { } + JsrInstruction(final short opcode, final InstructionHandle target) { + super(opcode, target); + } - /** @return return address type + /** + * @return return address type */ @Override - public Type getType( final ConstantPoolGen cp ) { + public Type getType(final ConstantPoolGen cp) { return new ReturnaddressType(physicalSuccessor()); } - /** - * Returns an InstructionHandle to the physical successor - * of this JsrInstruction. For this method to work, - * this JsrInstruction object must not be shared between - * multiple InstructionHandle objects! - * Formally, there must not be InstructionHandle objects - * i, j where i != j and i.getInstruction() == this == - * j.getInstruction(). - * @return an InstructionHandle to the "next" instruction that - * will be executed when RETurned from a subroutine. + * Returns an InstructionHandle to the physical successor of this JsrInstruction. For this method to work, this + * JsrInstruction object must not be shared between multiple InstructionHandle objects! Formally, there must not be + * InstructionHandle objects i, j where i != j and i.getInstruction() == this == j.getInstruction(). + * + * @return an InstructionHandle to the "next" instruction that will be executed when RETurned from a subroutine. */ public InstructionHandle physicalSuccessor() { InstructionHandle ih = super.getTarget(); @@ -73,7 +64,7 @@ public InstructionHandle physicalSuccessor() { final InstructionHandle toThis = ih; while (ih != null) { ih = ih.getNext(); - if ((ih != null) && (ih.getInstruction() == this)) { + if (ih != null && ih.getInstruction() == this) { throw new IllegalStateException("physicalSuccessor() called on a shared JsrInstruction."); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/L2D.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/L2D.java index 9bfed38607f..b82861f1759 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/L2D.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/L2D.java @@ -23,8 +23,10 @@ /** * L2D - Convert long to double - *
    Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2
    * + *
    + * Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2
    + * 
    */ public class L2D extends ConversionInstruction { @@ -32,17 +34,14 @@ public L2D() { super(com.sun.org.apache.bcel.internal.Const.L2D); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/L2F.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/L2F.java index 460ea64d0f6..a264f8c3bc6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/L2F.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/L2F.java @@ -23,8 +23,10 @@ /** * L2F - Convert long to float - *
    Stack: ..., value.word1, value.word2 -> ..., result
    * + *
    + * Stack: ..., value.word1, value.word2 -> ..., result
    + * 
    */ public class L2F extends ConversionInstruction { @@ -32,17 +34,14 @@ public L2F() { super(com.sun.org.apache.bcel.internal.Const.L2F); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/L2I.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/L2I.java index efcb614abdc..a6fb121586a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/L2I.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/L2I.java @@ -23,8 +23,10 @@ /** * L2I - Convert long to int - *
    Stack: ..., value.word1, value.word2 -> ..., result
    * + *
    + * Stack: ..., value.word1, value.word2 -> ..., result
    + * 
    */ public class L2I extends ConversionInstruction { @@ -32,17 +34,14 @@ public L2I() { super(com.sun.org.apache.bcel.internal.Const.L2I); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LADD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LADD.java index 2bbd2681ae5..0f8163f6f13 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LADD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LADD.java @@ -23,9 +23,12 @@ /** * LADD - Add longs - *
    Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    - * ..., result.word1, result.word2 * + *
    + * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    + * 
    + * + * ..., result.word1, result.word2 */ public class LADD extends ArithmeticInstruction { @@ -33,17 +36,14 @@ public LADD() { super(com.sun.org.apache.bcel.internal.Const.LADD); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LALOAD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LALOAD.java index 0d19b09c867..70fd5255a11 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LALOAD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LALOAD.java @@ -23,28 +23,28 @@ /** * LALOAD - Load long from array - *
    Stack: ..., arrayref, index -> ..., value1, value2
    * + *
    + * Stack: ..., arrayref, index -> ..., value1, value2
    + * 
    */ public class LALOAD extends ArrayInstruction implements StackProducer { - /** Load long from array + /** + * Load long from array */ public LALOAD() { super(com.sun.org.apache.bcel.internal.Const.LALOAD); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LAND.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LAND.java index 03f67c86640..75c18f9c40d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LAND.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LAND.java @@ -23,9 +23,12 @@ /** * LAND - Bitwise AND longs - *
    Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    - * ..., result.word1, result.word2 * + *
    + * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    + * 
    + * + * ..., result.word1, result.word2 */ public class LAND extends ArithmeticInstruction { @@ -33,17 +36,14 @@ public LAND() { super(com.sun.org.apache.bcel.internal.Const.LAND); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LASTORE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LASTORE.java index b59856fc0fc..96f3a951170 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LASTORE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LASTORE.java @@ -22,29 +22,29 @@ package com.sun.org.apache.bcel.internal.generic; /** - * LASTORE - Store into long array - *
    Stack: ..., arrayref, index, value.word1, value.word2 -> ...
    + * LASTORE - Store into long array * + *
    + * Stack: ..., arrayref, index, value.word1, value.word2 -> ...
    + * 
    */ public class LASTORE extends ArrayInstruction implements StackConsumer { - /** Store long into array + /** + * Store long into array */ public LASTORE() { super(com.sun.org.apache.bcel.internal.Const.LASTORE); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java index 9cf73c1ca03..c517b492f0a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java @@ -23,8 +23,10 @@ /** * LCMP - Compare longs: - *
    Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -> ..., result <= -1, 0, 1>
    * + *
    + * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -> ..., result <= -1, 0, 1>
    + * 
    * */ public class LCMP extends Instruction implements TypedInstruction, StackProducer, StackConsumer { @@ -33,28 +35,25 @@ public LCMP() { super(com.sun.org.apache.bcel.internal.Const.LCMP, (short) 1); } - - /** @return Type.LONG - */ - @Override - public Type getType( final ConstantPoolGen cp ) { - return Type.LONG; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); v.visitLCMP(this); } + + /** + * @return Type.LONG + */ + @Override + public Type getType(final ConstantPoolGen cp) { + return Type.LONG; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCONST.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCONST.java index af1ced8e90a..76ff4a26e25 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCONST.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCONST.java @@ -23,22 +23,21 @@ /** * LCONST - Push 0 or 1, other values cause an exception * - *
    Stack: ... -> ..., 
    - * + *
    + * Stack: ... -> ...,
    + * 
    */ public class LCONST extends Instruction implements ConstantPushInstruction { - private long value; - + private final long value; /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ LCONST() { + this(0); } - public LCONST(final long l) { super(com.sun.org.apache.bcel.internal.Const.LCONST_0, (short) 1); if (l == 0) { @@ -51,35 +50,31 @@ public LCONST(final long l) { value = l; } - - @Override - public Number getValue() { - return Long.valueOf(value); - } - - - /** @return Type.LONG - */ - @Override - public Type getType( final ConstantPoolGen cp ) { - return Type.LONG; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitPushInstruction(this); v.visitStackProducer(this); v.visitTypedInstruction(this); v.visitConstantPushInstruction(this); v.visitLCONST(this); } + + /** + * @return Type.LONG + */ + @Override + public Type getType(final ConstantPoolGen cp) { + return Type.LONG; + } + + @Override + public Number getValue() { + return Long.valueOf(value); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java index 92c490a43b4..d95bade23bd 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java @@ -29,44 +29,47 @@ /** * LDC - Push item from constant pool. * - *
    Stack: ... -> ..., item
    - * + *
    + * Stack: ... -> ..., item
    + * 
    * @LastModified: May 2021 */ public class LDC extends CPInstruction implements PushInstruction, ExceptionThrower { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ LDC() { } - public LDC(final int index) { super(com.sun.org.apache.bcel.internal.Const.LDC_W, index); setSize(); } - - // Adjust to proper size - protected final void setSize() { - if (super.getIndex() <= com.sun.org.apache.bcel.internal.Const.MAX_BYTE) { // Fits in one byte? - super.setOpcode(com.sun.org.apache.bcel.internal.Const.LDC); - super.setLength(2); - } else { - super.setOpcode(com.sun.org.apache.bcel.internal.Const.LDC_W); - super.setLength(3); - } + /** + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitStackProducer(this); + v.visitPushInstruction(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitCPInstruction(this); + v.visitLDC(this); } - /** * Dump instruction as byte code to stream out. + * * @param out Output stream */ @Override - public void dump( final DataOutputStream out ) throws IOException { + public void dump(final DataOutputStream out) throws IOException { out.writeByte(super.getOpcode()); if (super.getLength() == 2) { // TODO useless check? out.writeByte(super.getIndex()); @@ -75,86 +78,73 @@ public void dump( final DataOutputStream out ) throws IOException { } } - - /** - * Set the index to constant pool and adjust size. - */ @Override - public final void setIndex( final int index ) { - super.setIndex(index); - setSize(); + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_STRING_RESOLUTION); } - - /** - * Read needed data (e.g. index) from file. - */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { - super.setLength(2); - super.setIndex(bytes.readUnsignedByte()); + public Type getType(final ConstantPoolGen cpg) { + switch (cpg.getConstantPool().getConstant(super.getIndex()).getTag()) { + case com.sun.org.apache.bcel.internal.Const.CONSTANT_String: + return Type.STRING; + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Float: + return Type.FLOAT; + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Integer: + return Type.INT; + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class: + return Type.CLASS; + default: // Never reached + throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex()); + } } - - public Object getValue( final ConstantPoolGen cpg ) { + public Object getValue(final ConstantPoolGen cpg) { com.sun.org.apache.bcel.internal.classfile.Constant c = cpg.getConstantPool().getConstant(super.getIndex()); switch (c.getTag()) { - case com.sun.org.apache.bcel.internal.Const.CONSTANT_String: - final int i = ((com.sun.org.apache.bcel.internal.classfile.ConstantString) c).getStringIndex(); - c = cpg.getConstantPool().getConstant(i); - return ((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes(); - case com.sun.org.apache.bcel.internal.Const.CONSTANT_Float: - return ((com.sun.org.apache.bcel.internal.classfile.ConstantFloat) c).getBytes(); - case com.sun.org.apache.bcel.internal.Const.CONSTANT_Integer: - return ((com.sun.org.apache.bcel.internal.classfile.ConstantInteger) c).getBytes(); - case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class: - final int nameIndex = ((com.sun.org.apache.bcel.internal.classfile.ConstantClass) c).getNameIndex(); - c = cpg.getConstantPool().getConstant(nameIndex); - return new ObjectType(((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes()); - default: // Never reached - throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex()); - } - } - - - @Override - public Type getType( final ConstantPoolGen cpg ) { - switch (cpg.getConstantPool().getConstant(super.getIndex()).getTag()) { - case com.sun.org.apache.bcel.internal.Const.CONSTANT_String: - return Type.STRING; - case com.sun.org.apache.bcel.internal.Const.CONSTANT_Float: - return Type.FLOAT; - case com.sun.org.apache.bcel.internal.Const.CONSTANT_Integer: - return Type.INT; - case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class: - return Type.CLASS; - default: // Never reached - throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex()); + case com.sun.org.apache.bcel.internal.Const.CONSTANT_String: + final int i = ((com.sun.org.apache.bcel.internal.classfile.ConstantString) c).getStringIndex(); + c = cpg.getConstantPool().getConstant(i); + return ((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes(); + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Float: + return Float.valueOf(((com.sun.org.apache.bcel.internal.classfile.ConstantFloat) c).getBytes()); + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Integer: + return Integer.valueOf(((com.sun.org.apache.bcel.internal.classfile.ConstantInteger) c).getBytes()); + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class: + final int nameIndex = ((com.sun.org.apache.bcel.internal.classfile.ConstantClass) c).getNameIndex(); + c = cpg.getConstantPool().getConstant(nameIndex); + return Type.getType(((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes()); + default: // Never reached + throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex()); } } - + /** + * Read needed data (e.g. index) from file. + */ @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_STRING_RESOLUTION); + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { + super.setLength(2); + super.setIndex(bytes.readUnsignedByte()); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. - * - * @param v Visitor object + * Set the index to constant pool and adjust size. */ @Override - public void accept( final Visitor v ) { - v.visitStackProducer(this); - v.visitPushInstruction(this); - v.visitExceptionThrower(this); - v.visitTypedInstruction(this); - v.visitCPInstruction(this); - v.visitLDC(this); + public final void setIndex(final int index) { + super.setIndex(index); + setSize(); + } + + // Adjust to proper size + protected final void setSize() { + if (super.getIndex() <= com.sun.org.apache.bcel.internal.Const.MAX_BYTE) { // Fits in one byte? + super.setOpcode(com.sun.org.apache.bcel.internal.Const.LDC); + super.setLength(2); + } else { + super.setOpcode(com.sun.org.apache.bcel.internal.Const.LDC_W); + super.setLength(3); + } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC2_W.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC2_W.java index ade9b29cd84..dc2ef43bea7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC2_W.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC2_W.java @@ -23,65 +23,59 @@ /** * LDC2_W - Push long or double from constant pool * - *
    Stack: ... -> ..., item.word1, item.word2
    - * + *
    + * Stack: ... -> ..., item.word1, item.word2
    + * 
    * @LastModified: May 2021 */ public class LDC2_W extends CPInstruction implements PushInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ LDC2_W() { } - public LDC2_W(final int index) { super(com.sun.org.apache.bcel.internal.Const.LDC2_W, index); } - - @Override - public Type getType( final ConstantPoolGen cpg ) { - switch (cpg.getConstantPool().getConstant(super.getIndex()).getTag()) { - case com.sun.org.apache.bcel.internal.Const.CONSTANT_Long: - return Type.LONG; - case com.sun.org.apache.bcel.internal.Const.CONSTANT_Double: - return Type.DOUBLE; - default: // Never reached - throw new IllegalArgumentException("Unknown constant type " + super.getOpcode()); - } - } - - - public Number getValue( final ConstantPoolGen cpg ) { - final com.sun.org.apache.bcel.internal.classfile.Constant c = cpg.getConstantPool().getConstant(super.getIndex()); - switch (c.getTag()) { - case com.sun.org.apache.bcel.internal.Const.CONSTANT_Long: - return ((com.sun.org.apache.bcel.internal.classfile.ConstantLong) c).getBytes(); - case com.sun.org.apache.bcel.internal.Const.CONSTANT_Double: - return ((com.sun.org.apache.bcel.internal.classfile.ConstantDouble) c).getBytes(); - default: // Never reached - throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex()); - } - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitPushInstruction(this); v.visitTypedInstruction(this); v.visitCPInstruction(this); v.visitLDC2_W(this); } + + @Override + public Type getType(final ConstantPoolGen cpg) { + switch (cpg.getConstantPool().getConstant(super.getIndex()).getTag()) { + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Long: + return Type.LONG; + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Double: + return Type.DOUBLE; + default: // Never reached + throw new IllegalArgumentException("Unknown constant type " + super.getOpcode()); + } + } + + public Number getValue(final ConstantPoolGen cpg) { + final com.sun.org.apache.bcel.internal.classfile.Constant c = cpg.getConstantPool().getConstant(super.getIndex()); + switch (c.getTag()) { + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Long: + return Long.valueOf(((com.sun.org.apache.bcel.internal.classfile.ConstantLong) c).getBytes()); + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Double: + return Double.valueOf(((com.sun.org.apache.bcel.internal.classfile.ConstantDouble) c).getBytes()); + default: // Never reached + throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex()); + } + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC_W.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC_W.java index c0c0ff7c9ac..07ea06e377c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC_W.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC_W.java @@ -28,29 +28,27 @@ /** * LDC_W - Push item from constant pool (wide index) * - *
    Stack: ... -> ..., item.word1, item.word2
    - * + *
    + * Stack: ... -> ..., item.word1, item.word2
    + * 
    */ public class LDC_W extends LDC { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ LDC_W() { } - public LDC_W(final int index) { super(index); } - /** * Read needed data (i.e., index) from file. */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { setIndex(bytes.readUnsignedShort()); // Override just in case it has been changed super.setOpcode(com.sun.org.apache.bcel.internal.Const.LDC_W); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDIV.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDIV.java index 3d08e15a0b5..819e98dc1e7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDIV.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDIV.java @@ -24,9 +24,12 @@ /** * LDIV - Divide longs - *
    Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    - * ..., result.word1, result.word2 * + *
    + * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    + * 
    + * + * ..., result.word1, result.word2 * @LastModified: Jan 2020 */ public class LDIV extends ArithmeticInstruction implements ExceptionThrower { @@ -35,25 +38,14 @@ public LDIV() { super(com.sun.org.apache.bcel.internal.Const.LDIV); } - - @Override - public Class[] getExceptions() { - return new Class[] { - ExceptionConst.ARITHMETIC_EXCEPTION - }; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackProducer(this); @@ -61,4 +53,9 @@ public void accept( final Visitor v ) { v.visitArithmeticInstruction(this); v.visitLDIV(this); } + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConst.ARITHMETIC_EXCEPTION}; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LLOAD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LLOAD.java index 75a3c753dba..7ae6dc5509d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LLOAD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LLOAD.java @@ -23,35 +23,32 @@ /** * LLOAD - Load long from local variable - *
    Stack ... -> ..., result.word1, result.word2
    * + *
    + * Stack ... -> ..., result.word1, result.word2
    + * 
    */ public class LLOAD extends LoadInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ LLOAD() { super(com.sun.org.apache.bcel.internal.Const.LLOAD, com.sun.org.apache.bcel.internal.Const.LLOAD_0); } - public LLOAD(final int n) { super(com.sun.org.apache.bcel.internal.Const.LLOAD, com.sun.org.apache.bcel.internal.Const.LLOAD_0, n); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { super.accept(v); v.visitLLOAD(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LMUL.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LMUL.java index 9ea55ffbf2b..86972264fdd 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LMUL.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LMUL.java @@ -23,9 +23,12 @@ /** * LMUL - Multiply longs - *
    Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    - * ..., result.word1, result.word2 * + *
    + * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    + * 
    + * + * ..., result.word1, result.word2 */ public class LMUL extends ArithmeticInstruction { @@ -33,17 +36,14 @@ public LMUL() { super(com.sun.org.apache.bcel.internal.Const.LMUL); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LNEG.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LNEG.java index 39c1c636663..69c0d3572dc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LNEG.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LNEG.java @@ -23,8 +23,10 @@ /** * LNEG - Negate long - *
    Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2
    * + *
    + * Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2
    + * 
    */ public class LNEG extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public LNEG() { super(com.sun.org.apache.bcel.internal.Const.LNEG); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LOOKUPSWITCH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LOOKUPSWITCH.java index 1803e565f36..b8e153ca276 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LOOKUPSWITCH.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LOOKUPSWITCH.java @@ -34,75 +34,68 @@ public class LOOKUPSWITCH extends Select { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ LOOKUPSWITCH() { } - - public LOOKUPSWITCH(final int[] match, final InstructionHandle[] targets, - final InstructionHandle defaultTarget) { + public LOOKUPSWITCH(final int[] match, final InstructionHandle[] targets, final InstructionHandle defaultTarget) { super(com.sun.org.apache.bcel.internal.Const.LOOKUPSWITCH, match, targets, defaultTarget); /* alignment remainder assumed 0 here, until dump time. */ - final short _length = (short) (9 + getMatch_length() * 8); - super.setLength(_length); - setFixed_length(_length); + final short length = (short) (9 + getMatchLength() * 8); + super.setLength(length); + setFixedLength(length); } + /** + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitVariableLengthInstruction(this); + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitSelect(this); + v.visitLOOKUPSWITCH(this); + } /** * Dump instruction as byte code to stream out. + * * @param out Output stream */ @Override - public void dump( final DataOutputStream out ) throws IOException { + public void dump(final DataOutputStream out) throws IOException { super.dump(out); - final int _match_length = getMatch_length(); - out.writeInt(_match_length); // npairs - for (int i = 0; i < _match_length; i++) { + final int matchLength = getMatchLength(); + out.writeInt(matchLength); // npairs + for (int i = 0; i < matchLength; i++) { out.writeInt(super.getMatch(i)); // match-offset pairs out.writeInt(setIndices(i, getTargetOffset(super.getTarget(i)))); } } - /** * Read needed data (e.g. index) from file. */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { super.initFromFile(bytes, wide); // reads padding - final int _match_length = bytes.readInt(); - setMatch_length(_match_length); - final short _fixed_length = (short) (9 + _match_length * 8); - setFixed_length(_fixed_length); - final short _length = (short) (_match_length + super.getPadding()); - super.setLength(_length); - super.setMatches(new int[_match_length]); - super.setIndices(new int[_match_length]); - super.setTargets(new InstructionHandle[_match_length]); - for (int i = 0; i < _match_length; i++) { + final int matchLength = bytes.readInt(); + setMatchLength(matchLength); + final short fixedLength = (short) (9 + matchLength * 8); + setFixedLength(fixedLength); + final short length = (short) (matchLength + super.getPadding()); + super.setLength(length); + super.setMatches(new int[matchLength]); + super.setIndices(new int[matchLength]); + super.setTargets(new InstructionHandle[matchLength]); + for (int i = 0; i < matchLength; i++) { super.setMatch(i, bytes.readInt()); super.setIndices(i, bytes.readInt()); } } - - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. - * - * @param v Visitor object - */ - @Override - public void accept( final Visitor v ) { - v.visitVariableLengthInstruction(this); - v.visitStackConsumer(this); - v.visitBranchInstruction(this); - v.visitSelect(this); - v.visitLOOKUPSWITCH(this); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LOR.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LOR.java index ec1cef11bdc..53d4e9bc191 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LOR.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LOR.java @@ -23,8 +23,10 @@ /** * LOR - Bitwise OR long - *
    Stack: ..., value1, value2 -> ..., result
    * + *
    + * Stack: ..., value1, value2 -> ..., result
    + * 
    */ public class LOR extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public LOR() { super(com.sun.org.apache.bcel.internal.Const.LOR); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LREM.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LREM.java index 786cb80ca96..17a535df2d3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LREM.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LREM.java @@ -24,8 +24,10 @@ /** * LREM - Remainder of long - *
    Stack: ..., value1, value2 -> result
    * + *
    + * Stack: ..., value1, value2 -> result
    + * 
    * @LastModified: Jan 2020 */ public class LREM extends ArithmeticInstruction implements ExceptionThrower { @@ -34,25 +36,14 @@ public LREM() { super(com.sun.org.apache.bcel.internal.Const.LREM); } - - @Override - public Class[] getExceptions() { - return new Class[] { - ExceptionConst.ARITHMETIC_EXCEPTION - }; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackProducer(this); @@ -60,4 +51,9 @@ public void accept( final Visitor v ) { v.visitArithmeticInstruction(this); v.visitLREM(this); } + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConst.ARITHMETIC_EXCEPTION}; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LRETURN.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LRETURN.java index 4523f77e2a9..9d40c14f863 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LRETURN.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LRETURN.java @@ -22,9 +22,11 @@ package com.sun.org.apache.bcel.internal.generic; /** - * LRETURN - Return long from method - *
    Stack: ..., value.word1, value.word2 -> <empty>
    + * LRETURN - Return long from method * + *
    + * Stack: ..., value.word1, value.word2 -> <empty>
    + * 
    */ public class LRETURN extends ReturnInstruction { @@ -32,17 +34,14 @@ public LRETURN() { super(com.sun.org.apache.bcel.internal.Const.LRETURN); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSHL.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSHL.java index 491f035e813..72c2aeed22d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSHL.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSHL.java @@ -23,8 +23,10 @@ /** * LSHL - Arithmetic shift left long - *
    Stack: ..., value1.word1, value1.word2, value2 -> ..., result.word1, result.word2
    * + *
    + * Stack: ..., value1.word1, value1.word2, value2 -> ..., result.word1, result.word2
    + * 
    */ public class LSHL extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public LSHL() { super(com.sun.org.apache.bcel.internal.Const.LSHL); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSHR.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSHR.java index c3e238d25f7..d7a51d3cffb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSHR.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSHR.java @@ -23,8 +23,10 @@ /** * LSHR - Arithmetic shift right long - *
    Stack: ..., value1.word1, value1.word2, value2 -> ..., result.word1, result.word2
    * + *
    + * Stack: ..., value1.word1, value1.word2, value2 -> ..., result.word1, result.word2
    + * 
    */ public class LSHR extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public LSHR() { super(com.sun.org.apache.bcel.internal.Const.LSHR); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSTORE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSTORE.java index 1bbdc2c52e2..0b49912dba3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSTORE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSTORE.java @@ -23,35 +23,32 @@ /** * LSTORE - Store long into local variable - *
    Stack: ..., value.word1, value.word2 -> ... 
    * + *
    + * Stack: ..., value.word1, value.word2 -> ...
    + * 
    */ public class LSTORE extends StoreInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ LSTORE() { super(com.sun.org.apache.bcel.internal.Const.LSTORE, com.sun.org.apache.bcel.internal.Const.LSTORE_0); } - public LSTORE(final int n) { super(com.sun.org.apache.bcel.internal.Const.LSTORE, com.sun.org.apache.bcel.internal.Const.LSTORE_0, n); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { super.accept(v); v.visitLSTORE(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSUB.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSUB.java index b33771a6d10..8ffdf4fc5a3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSUB.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LSUB.java @@ -23,9 +23,12 @@ /** * LSUB - Substract longs - *
    Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    - * ..., result.word1, result.word2 * + *
    + * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
    + * 
    + * + * ..., result.word1, result.word2 */ public class LSUB extends ArithmeticInstruction { @@ -33,17 +36,14 @@ public LSUB() { super(com.sun.org.apache.bcel.internal.Const.LSUB); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LUSHR.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LUSHR.java index c7b7e472c1c..0d9d2eab53c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LUSHR.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LUSHR.java @@ -23,8 +23,10 @@ /** * LUSHR - Logical shift right long - *
    Stack: ..., value1, value2 -> ..., result
    * + *
    + * Stack: ..., value1, value2 -> ..., result
    + * 
    */ public class LUSHR extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public LUSHR() { super(com.sun.org.apache.bcel.internal.Const.LUSHR); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LXOR.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LXOR.java index fc8dafcaaab..cf6ac48074a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LXOR.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LXOR.java @@ -23,8 +23,10 @@ /** * LXOR - Bitwise XOR long - *
    Stack: ..., value1, value2 -> ..., result
    * + *
    + * Stack: ..., value1, value2 -> ..., result
    + * 
    */ public class LXOR extends ArithmeticInstruction { @@ -32,17 +34,14 @@ public LXOR() { super(com.sun.org.apache.bcel.internal.Const.LXOR); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitTypedInstruction(this); v.visitStackProducer(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java index b5ac6cda812..3773c21e7b3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java @@ -26,14 +26,16 @@ import com.sun.org.apache.bcel.internal.classfile.LineNumber; /** - * This class represents a line number within a method, i.e., give an instruction - * a line number corresponding to the source code line. + * This class represents a line number within a method, i.e., give an instruction a line number corresponding to the + * source code line. * - * @see LineNumber - * @see MethodGen + * @see LineNumber + * @see MethodGen */ public class LineNumberGen implements InstructionTargeter, Cloneable { + static final LineNumberGen[] EMPTY_ARRAY = {}; + private InstructionHandle ih; private int srcLine; @@ -42,73 +44,65 @@ public class LineNumberGen implements InstructionTargeter, Cloneable { * * @param ih instruction handle to reference */ - public LineNumberGen(final InstructionHandle ih, final int src_line) { + public LineNumberGen(final InstructionHandle ih, final int srcLine) { setInstruction(ih); - setSourceLine(src_line); + setSourceLine(srcLine); } + @Override + public Object clone() { + try { + return super.clone(); + } catch (final CloneNotSupportedException e) { + throw new Error("Clone Not Supported"); // never happens + } + } /** * @return true, if ih is target of this line number */ @Override - public boolean containsTarget( final InstructionHandle ih ) { + public boolean containsTarget(final InstructionHandle ih) { return this.ih == ih; } - - /** - * @param old_ih old target - * @param new_ih new target - */ - @Override - public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) { - if (old_ih != ih) { - throw new ClassGenException("Not targeting " + old_ih + ", but " + ih + "}"); - } - setInstruction(new_ih); + public InstructionHandle getInstruction() { + return ih; } - /** - * Get LineNumber attribute . + * Get LineNumber attribute. * - * This relies on that the instruction list has already been dumped to byte code or - * or that the `setPositions' methods has been called for the instruction list. + * This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods + * has been called for the instruction list. */ public LineNumber getLineNumber() { return new LineNumber(ih.getPosition(), srcLine); } + public int getSourceLine() { + return srcLine; + } - public void setInstruction( final InstructionHandle instructionHandle ) { // TODO could be package-protected? + public void setInstruction(final InstructionHandle instructionHandle) { // TODO could be package-protected? Objects.requireNonNull(instructionHandle, "instructionHandle"); BranchInstruction.notifyTarget(this.ih, instructionHandle, this); this.ih = instructionHandle; } + public void setSourceLine(final int srcLine) { // TODO could be package-protected? + this.srcLine = srcLine; + } + /** + * @param oldIh old target + * @param newIh new target + */ @Override - public Object clone() { - try { - return super.clone(); - } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) { + if (oldIh != ih) { + throw new ClassGenException("Not targeting " + oldIh + ", but " + ih + "}"); } - } - - - public InstructionHandle getInstruction() { - return ih; - } - - - public void setSourceLine( final int src_line ) { // TODO could be package-protected? - this.srcLine = src_line; - } - - - public int getSourceLine() { - return srcLine; + setInstruction(newIh); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LoadClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LoadClass.java index cc697fe99cb..9fad1d1595d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LoadClass.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LoadClass.java @@ -22,32 +22,27 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Denotes that an instruction may start the process of loading and resolving - * the referenced class in the Virtual Machine. - * + * Denotes that an instruction may start the process of loading and resolving the referenced class in the Virtual Machine. */ public interface LoadClass { /** - * Returns the ObjectType of the referenced class or interface - * that may be loaded and resolved. - * @return object type that may be loaded or null if a primitive is - * referenced + * Returns the {@link ObjectType} of the referenced class or interface that may be loaded and resolved. + * + * @param cpg A ConstantPoolGen + * @return object type that may be loaded or null if a primitive is referenced */ - ObjectType getLoadClassType( ConstantPoolGen cpg ); - + ObjectType getLoadClassType(ConstantPoolGen cpg); /** - * Returns the type associated with this instruction. - * LoadClass instances are always typed, but this type - * does not always refer to the type of the class or interface - * that it possibly forces to load. For example, GETFIELD would - * return the type of the field and not the type of the class - * where the field is defined. - * If no class is forced to be loaded, null is returned. - * An example for this is an ANEWARRAY instruction that creates - * an int[][]. + * Returns the type associated with this instruction. LoadClass instances are always typed, but this type does not always refer to the type of the class or + * interface that it possibly forces to load. For example, {@link GETFIELD} would return the type of the field and not the type of the class where the field + * is defined. If no class is forced to be loaded, {@code null} is returned. An example for this is an {@link NEWARRAY} instruction that creates an + * {@code int[][]}. + * + * @param cpg A ConstantPoolGen + * @return the type associated with this instruction. * @see #getLoadClassType(ConstantPoolGen) */ - Type getType( ConstantPoolGen cpg ); + Type getType(ConstantPoolGen cpg); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LoadInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LoadInstruction.java index 245fd08cc54..faaf9fad552 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LoadInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LoadInstruction.java @@ -22,42 +22,35 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Denotes an unparameterized instruction to load a value from a local - * variable, e.g. ILOAD. - * + * Denotes an unparameterized instruction to load a value from a local variable, e.g. ILOAD. */ public abstract class LoadInstruction extends LocalVariableInstruction implements PushInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. - * tag and length are defined in readInstruction and initFromFile, respectively. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. tag and length are defined in + * readInstruction and initFromFile, respectively. */ - LoadInstruction(final short canon_tag, final short c_tag) { - super(canon_tag, c_tag); + LoadInstruction(final short canonTag, final short cTag) { + super(canonTag, cTag); } - /** * @param opcode Instruction opcode - * @param c_tag Instruction number for compact version, ALOAD_0, e.g. + * @param cTag Instruction number for compact version, ALOAD_0, e.g. * @param n local variable index (unsigned short) */ - protected LoadInstruction(final short opcode, final short c_tag, final int n) { - super(opcode, c_tag, n); + protected LoadInstruction(final short opcode, final short cTag, final int n) { + super(opcode, cTag, n); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitPushInstruction(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java index 4693af780e7..830564d42c9 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java @@ -24,13 +24,11 @@ import com.sun.org.apache.bcel.internal.classfile.LocalVariable; /** - * Represents a local variable within a method. It contains its - * scope, name and type. The generated LocalVariable object can be obtained - * with getLocalVariable which needs the instruction list and the constant - * pool as parameters. + * Represents a local variable within a method. It contains its scope, name and type. The generated LocalVariable object + * can be obtained with getLocalVariable which needs the instruction list and the constant pool as parameters. * - * @see LocalVariable - * @see MethodGen + * @see LocalVariable + * @see MethodGen */ public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Cloneable { @@ -42,10 +40,9 @@ public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Clo private int origIndex; // never changes; used to match up with LocalVariableTypeTable entries private boolean liveToEnd; - /** - * Generate a local variable that with index `index'. Note that double and long - * variables need two indexs. Index indices have to be provided by the user. + * Generate a local variable that with index 'index'. Note that double and long variables need two indexs. Index indices + * have to be provided by the user. * * @param index index of local variable * @param name its name @@ -53,10 +50,9 @@ public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Clo * @param start from where the instruction is valid (null means from the start) * @param end until where the instruction is valid (null means to the end) */ - public LocalVariableGen(final int index, final String name, final Type type, final InstructionHandle start, - final InstructionHandle end) { - if ((index < 0) || (index > Const.MAX_SHORT)) { - throw new ClassGenException("Invalid index index: " + index); + public LocalVariableGen(final int index, final String name, final Type type, final InstructionHandle start, final InstructionHandle end) { + if (index < 0 || index > Const.MAX_SHORT) { + throw new ClassGenException("Invalid index: " + index); } this.name = name; this.type = type; @@ -67,10 +63,9 @@ public LocalVariableGen(final int index, final String name, final Type type, fin this.liveToEnd = end == null; } - /** - * Generates a local variable that with index `index'. Note that double and long - * variables need two indexs. Index indices have to be provided by the user. + * Generates a local variable that with index 'index'. Note that double and long variables need two indexs. Index + * indices have to be provided by the user. * * @param index index of local variable * @param name its name @@ -79,187 +74,163 @@ public LocalVariableGen(final int index, final String name, final Type type, fin * @param end until where the instruction is valid (null means to the end) * @param origIndex index of local variable prior to any changes to index */ - public LocalVariableGen(final int index, final String name, final Type type, final InstructionHandle start, - final InstructionHandle end, final int origIndex) { + public LocalVariableGen(final int index, final String name, final Type type, final InstructionHandle start, final InstructionHandle end, + final int origIndex) { this(index, name, type, start, end); this.origIndex = origIndex; } + @Override + public Object clone() { + try { + return super.clone(); + } catch (final CloneNotSupportedException e) { + throw new Error("Clone Not Supported"); // never happens + } + } /** - * Gets LocalVariable object. - * - * This relies on that the instruction list has already been dumped to byte code or - * or that the `setPositions' methods has been called for the instruction list. - * - * Note that due to the conversion from byte code offset to InstructionHandle, - * it is impossible to tell the difference between a live range that ends BEFORE - * the last insturction of the method or a live range that ends AFTER the last - * instruction of the method. Hence the liveToEnd flag to differentiate - * between these two cases. - * - * @param cp constant pool + * @return true, if ih is target of this variable */ - public LocalVariable getLocalVariable( final ConstantPoolGen cp ) { - int start_pc = 0; - int length = 0; - if ((start != null) && (end != null)) { - start_pc = start.getPosition(); - length = end.getPosition() - start_pc; - if ((end.getNext() == null) && liveToEnd) { - length += end.getInstruction().getLength(); - } - } - final int name_index = cp.addUtf8(name); - final int signature_index = cp.addUtf8(type.getSignature()); - return new LocalVariable(start_pc, length, name_index, signature_index, index, cp - .getConstantPool(), origIndex); + @Override + public boolean containsTarget(final InstructionHandle ih) { + return start == ih || end == ih; } - - public void setIndex( final int index ) { - this.index = index; + /** + * Clear the references from and to this variable when it's removed. + */ + void dispose() { + setStart(null); + setEnd(null); } - - public int getIndex() { - return index; + /** + * We consider to local variables to be equal, if the use the same index and are valid in the same range. + */ + @Override + public boolean equals(final Object o) { + if (!(o instanceof LocalVariableGen)) { + return false; + } + final LocalVariableGen l = (LocalVariableGen) o; + return l.index == index && l.start == start && l.end == end; } - - public int getOrigIndex() { - return origIndex; + public InstructionHandle getEnd() { + return end; } - - public void setLiveToEnd( final boolean live_to_end) { - this.liveToEnd = live_to_end; + public int getIndex() { + return index; } - public boolean getLiveToEnd() { return liveToEnd; } - - @Override - public void setName( final String name ) { - this.name = name; + /** + * Gets LocalVariable object. + * + * This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods + * has been called for the instruction list. + * + * Note that due to the conversion from byte code offset to InstructionHandle, it is impossible to tell the difference + * between a live range that ends BEFORE the last insturction of the method or a live range that ends AFTER the last + * instruction of the method. Hence the liveToEnd flag to differentiate between these two cases. + * + * @param cp constant pool + */ + public LocalVariable getLocalVariable(final ConstantPoolGen cp) { + int startPc = 0; + int length = 0; + if (start != null && end != null) { + startPc = start.getPosition(); + length = end.getPosition() - startPc; + if (end.getNext() == null && liveToEnd) { + length += end.getInstruction().getLength(); + } + } + final int nameIndex = cp.addUtf8(name); + final int signatureIndex = cp.addUtf8(type.getSignature()); + return new LocalVariable(startPc, length, nameIndex, signatureIndex, index, cp.getConstantPool(), origIndex); } - @Override public String getName() { return name; } - - @Override - public void setType( final Type type ) { - this.type = type; - } - - - @Override - public Type getType() { - return type; + public int getOrigIndex() { + return origIndex; } - public InstructionHandle getStart() { return start; } - - public InstructionHandle getEnd() { - return end; + @Override + public Type getType() { + return type; } - - public void setStart( final InstructionHandle start ) { // TODO could be package-protected? - BranchInstruction.notifyTarget(this.start, start, this); - this.start = start; + @Override + public int hashCode() { + // If the user changes the name or type, problems with the targeter hashmap will occur. + // Note: index cannot be part of hash as it may be changed by the user. + return name.hashCode() ^ type.hashCode(); } - - public void setEnd( final InstructionHandle end ) { // TODO could be package-protected? + public void setEnd(final InstructionHandle end) { // TODO could be package-protected? BranchInstruction.notifyTarget(this.end, end, this); this.end = end; } - - /** - * @param old_ih old target, either start or end - * @param new_ih new target - */ - @Override - public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) { - boolean targeted = false; - if (start == old_ih) { - targeted = true; - setStart(new_ih); - } - if (end == old_ih) { - targeted = true; - setEnd(new_ih); - } - if (!targeted) { - throw new ClassGenException("Not targeting " + old_ih + ", but {" + start + ", " + end - + "}"); - } + public void setIndex(final int index) { + this.index = index; } - /** - * Clear the references from and to this variable when it's removed. - */ - void dispose() { - setStart(null); - setEnd(null); + public void setLiveToEnd(final boolean liveToEnd) { + this.liveToEnd = liveToEnd; } - /** - * @return true, if ih is target of this variable - */ @Override - public boolean containsTarget( final InstructionHandle ih ) { - return (start == ih) || (end == ih); + public void setName(final String name) { + this.name = name; } - - @Override - public int hashCode() { - // If the user changes the name or type, problems with the targeter hashmap will occur. - // Note: index cannot be part of hash as it may be changed by the user. - return name.hashCode() ^ type.hashCode(); + public void setStart(final InstructionHandle start) { // TODO could be package-protected? + BranchInstruction.notifyTarget(this.start, start, this); + this.start = start; } - - /** - * We consider to local variables to be equal, if the use the same index and - * are valid in the same range. - */ @Override - public boolean equals( final Object o ) { - if (!(o instanceof LocalVariableGen)) { - return false; - } - final LocalVariableGen l = (LocalVariableGen) o; - return (l.index == index) && (l.start == start) && (l.end == end); + public void setType(final Type type) { + this.type = type; } - @Override public String toString() { return "LocalVariableGen(" + name + ", " + type + ", " + start + ", " + end + ")"; } - + /** + * @param oldIh old target, either start or end + * @param newIh new target + */ @Override - public Object clone() { - try { - return super.clone(); - } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) { + boolean targeted = false; + if (start == oldIh) { + targeted = true; + setStart(newIh); + } + if (end == oldIh) { + targeted = true; + setEnd(newIh); + } + if (!targeted) { + throw new ClassGenException("Not targeting " + oldIh + ", but {" + start + ", " + end + "}"); } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java index fb4d7545478..67184c0b9f1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java @@ -30,39 +30,32 @@ * * @LastModified: May 2021 */ -public abstract class LocalVariableInstruction extends Instruction implements TypedInstruction, - IndexedInstruction { +public abstract class LocalVariableInstruction extends Instruction implements TypedInstruction, IndexedInstruction { + + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected int n = -1; // index of referenced variable - private int n = -1; // index of referenced variable private short cTag = -1; // compact version, such as ILOAD_0 private short canonTag = -1; // canonical tag such as ILOAD - - private boolean wide() { - return n > Const.MAX_BYTE; - } - - /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. - * tag and length are defined in readInstruction and initFromFile, respectively. + * Empty constructor needed for Instruction.readInstruction. Also used by IINC()! */ - LocalVariableInstruction(final short canon_tag, final short c_tag) { - super(); - this.canonTag = canon_tag; - this.cTag = c_tag; + LocalVariableInstruction() { } - /** - * Empty constructor needed for Instruction.readInstruction. - * Also used by IINC()! + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. tag and length are defined in + * readInstruction and initFromFile, respectively. */ - LocalVariableInstruction() { + LocalVariableInstruction(final short canonTag, final short cTag) { + this.canonTag = canonTag; + this.cTag = cTag; } - /** * @param opcode Instruction opcode * @param cTag Instruction number for compact version, ALOAD_0, e.g. @@ -75,13 +68,13 @@ protected LocalVariableInstruction(final short opcode, final short cTag, final i setIndex(n); } - /** * Dump instruction as byte code to stream out. + * * @param out Output stream */ @Override - public void dump( final DataOutputStream out ) throws IOException { + public void dump(final DataOutputStream out) throws IOException { if (wide()) { out.writeByte(Const.WIDE); } @@ -95,73 +88,87 @@ public void dump( final DataOutputStream out ) throws IOException { } } + /** + * @return canonical tag for instruction, e.g., ALOAD for ALOAD_0 + */ + public short getCanonicalTag() { + return canonTag; + } /** - * Long output format: - * - * <name of opcode> "["<opcode number>"]" - * "("<length of instruction>")" "<"< local variable index>">" + * @return local variable index (n) referred by this instruction. + */ + @Override + public final int getIndex() { + return n; + } + + /** + * Returns the type associated with the instruction - in case of ALOAD or ASTORE Type.OBJECT is returned. This is just a + * bit incorrect, because ALOAD and ASTORE may work on every ReferenceType (including Type.NULL) and ASTORE may even + * work on a ReturnaddressType . * - * @param verbose long/short format switch - * @return mnemonic for instruction + * @return type associated with the instruction */ @Override - public String toString( final boolean verbose ) { - final short _opcode = super.getOpcode(); - if (((_opcode >= Const.ILOAD_0) && (_opcode <= Const.ALOAD_3)) - || ((_opcode >= Const.ISTORE_0) && (_opcode <= Const.ASTORE_3))) { - return super.toString(verbose); + public Type getType(final ConstantPoolGen cp) { + switch (canonTag) { + case Const.ILOAD: + case Const.ISTORE: + return Type.INT; + case Const.LLOAD: + case Const.LSTORE: + return Type.LONG; + case Const.DLOAD: + case Const.DSTORE: + return Type.DOUBLE; + case Const.FLOAD: + case Const.FSTORE: + return Type.FLOAT; + case Const.ALOAD: + case Const.ASTORE: + return Type.OBJECT; + default: + throw new ClassGenException("Unknown case in switch" + canonTag); } - return super.toString(verbose) + " " + n; } - /** * Read needed data (e.g. index) from file. + * *
          * (ILOAD <= tag <= ALOAD_3) || (ISTORE <= tag <= ASTORE_3)
          * 
    */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { if (wide) { n = bytes.readUnsignedShort(); super.setLength(4); } else { - final short _opcode = super.getOpcode(); - if (((_opcode >= Const.ILOAD) && (_opcode <= Const.ALOAD)) - || ((_opcode >= Const.ISTORE) && (_opcode <= Const.ASTORE))) { + final short opcode = super.getOpcode(); + if (opcode >= Const.ILOAD && opcode <= Const.ALOAD || opcode >= Const.ISTORE && opcode <= Const.ASTORE) { n = bytes.readUnsignedByte(); super.setLength(2); - } else if (_opcode <= Const.ALOAD_3) { // compact load instruction such as ILOAD_2 - n = (_opcode - Const.ILOAD_0) % 4; - super.setLength(1); - } else { // Assert ISTORE_0 <= tag <= ASTORE_3 - n = (_opcode - Const.ISTORE_0) % 4; + } else { + if (opcode <= Const.ALOAD_3) { // compact load instruction such as ILOAD_2 + n = (opcode - Const.ILOAD_0) % 4; + } else { // Assert ISTORE_0 <= tag <= ASTORE_3 + n = (opcode - Const.ISTORE_0) % 4; + } super.setLength(1); } } } - - /** - * @return local variable index (n) referred by this instruction. - */ - @Override - public final int getIndex() { - return n; - } - - /** - * Set the local variable index. - * also updates opcode and length - * TODO Why? + * Set the local variable index. also updates opcode and length TODO Why? + * * @see #setIndexOnly(int) */ @Override - public void setIndex( final int n ) { // TODO could be package-protected? - if ((n < 0) || (n > Const.MAX_SHORT)) { + public void setIndex(final int n) { // TODO could be package-protected? + if (n < 0 || n > Const.MAX_SHORT) { throw new ClassGenException("Illegal value: " + n); } this.n = n; @@ -179,51 +186,35 @@ public void setIndex( final int n ) { // TODO could be package-protected? } } - - /** @return canonical tag for instruction, e.g., ALOAD for ALOAD_0 + /** + * Sets the index of the referenced variable (n) only + * + * @since 6.0 + * @see #setIndex(int) */ - public short getCanonicalTag() { - return canonTag; + final void setIndexOnly(final int n) { + this.n = n; } - /** - * Returns the type associated with the instruction - - * in case of ALOAD or ASTORE Type.OBJECT is returned. - * This is just a bit incorrect, because ALOAD and ASTORE - * may work on every ReferenceType (including Type.NULL) and - * ASTORE may even work on a ReturnaddressType . - * @return type associated with the instruction + * Long output format: + * + * <name of opcode> "["<opcode number>"]" "("<length of instruction>")" "<"< local variable + * index>">" + * + * @param verbose long/short format switch + * @return mnemonic for instruction */ @Override - public Type getType( final ConstantPoolGen cp ) { - switch (canonTag) { - case Const.ILOAD: - case Const.ISTORE: - return Type.INT; - case Const.LLOAD: - case Const.LSTORE: - return Type.LONG; - case Const.DLOAD: - case Const.DSTORE: - return Type.DOUBLE; - case Const.FLOAD: - case Const.FSTORE: - return Type.FLOAT; - case Const.ALOAD: - case Const.ASTORE: - return Type.OBJECT; - default: - throw new ClassGenException("Unknown case in switch" + canonTag); + public String toString(final boolean verbose) { + final short opcode = super.getOpcode(); + if (opcode >= Const.ILOAD_0 && opcode <= Const.ALOAD_3 || opcode >= Const.ISTORE_0 && opcode <= Const.ASTORE_3) { + return super.toString(verbose); } + return super.toString(verbose) + " " + n; } - /** - * Sets the index of the referenced variable (n) only - * @since 6.0 - * @see #setIndex(int) - */ - final void setIndexOnly(final int n) { - this.n = n; + private boolean wide() { + return n > Const.MAX_BYTE; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MONITORENTER.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MONITORENTER.java index a8cb953051f..6ea4f918589 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MONITORENTER.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MONITORENTER.java @@ -24,8 +24,10 @@ /** * MONITORENTER - Enter monitor for object - *
    Stack: ..., objectref -> ...
    * + *
    + * Stack: ..., objectref -> ...
    + * 
    * @LastModified: Jan 2020 */ public class MONITORENTER extends Instruction implements ExceptionThrower, StackConsumer { @@ -34,27 +36,21 @@ public MONITORENTER() { super(com.sun.org.apache.bcel.internal.Const.MONITORENTER, (short) 1); } - - @Override - public Class[] getExceptions() { - return new Class[] { - ExceptionConst.NULL_POINTER_EXCEPTION - }; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitStackConsumer(this); v.visitMONITORENTER(this); } + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConst.NULL_POINTER_EXCEPTION}; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MONITOREXIT.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MONITOREXIT.java index 9c83d55577b..40daeb13ba6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MONITOREXIT.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MONITOREXIT.java @@ -24,8 +24,10 @@ /** * MONITOREXIT - Exit monitor for object - *
    Stack: ..., objectref -> ...
    * + *
    + * Stack: ..., objectref -> ...
    + * 
    * @LastModified: Jan 2020 */ public class MONITOREXIT extends Instruction implements ExceptionThrower, StackConsumer { @@ -34,27 +36,21 @@ public MONITOREXIT() { super(com.sun.org.apache.bcel.internal.Const.MONITOREXIT, (short) 1); } - - @Override - public Class[] getExceptions() { - return new Class[] { - ExceptionConst.NULL_POINTER_EXCEPTION - }; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitStackConsumer(this); v.visitMONITOREXIT(this); } + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConst.NULL_POINTER_EXCEPTION}; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MULTIANEWARRAY.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MULTIANEWARRAY.java index 208410b3c98..9f83842d2ad 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MULTIANEWARRAY.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MULTIANEWARRAY.java @@ -30,23 +30,21 @@ /** * MULTIANEWARRAY - Create new mutidimensional array of references - *
    Stack: ..., count1, [count2, ...] -> ..., arrayref
    * + *
    + * Stack: ..., count1, [count2, ...] -> ..., arrayref
    + * 
    */ -public class MULTIANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction, - ExceptionThrower { +public class MULTIANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction, ExceptionThrower { private short dimensions; - /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ MULTIANEWARRAY() { } - public MULTIANEWARRAY(final int index, final short dimensions) { super(com.sun.org.apache.bcel.internal.Const.MULTIANEWARRAY, index); if (dimensions < 1) { @@ -56,100 +54,89 @@ public MULTIANEWARRAY(final int index, final short dimensions) { super.setLength(4); } - /** - * Dump instruction as byte code to stream out. - * @param out Output stream + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object */ @Override - public void dump( final DataOutputStream out ) throws IOException { - out.writeByte(super.getOpcode()); - out.writeShort(super.getIndex()); - out.writeByte(dimensions); + public void accept(final Visitor v) { + v.visitLoadClass(this); + v.visitAllocationInstruction(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitCPInstruction(this); + v.visitMULTIANEWARRAY(this); } - /** - * Read needed data (i.e., no. dimension) from file. + * Also works for instructions whose stack effect depends on the constant pool entry they reference. + * + * @return Number of words consumed from stack by this instruction */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { - super.initFromFile(bytes, wide); - dimensions = bytes.readByte(); - super.setLength(4); - } - - - /** - * @return number of dimensions to be created - */ - public final short getDimensions() { + public int consumeStack(final ConstantPoolGen cpg) { return dimensions; } - - /** - * @return mnemonic for instruction - */ - @Override - public String toString( final boolean verbose ) { - return super.toString(verbose) + " " + super.getIndex() + " " + dimensions; - } - - /** - * @return mnemonic for instruction with symbolic references resolved + * Dump instruction as byte code to stream out. + * + * @param out Output stream */ @Override - public String toString( final ConstantPool cp ) { - return super.toString(cp) + " " + dimensions; + public void dump(final DataOutputStream out) throws IOException { + out.writeByte(super.getOpcode()); + out.writeShort(super.getIndex()); + out.writeByte(dimensions); } - /** - * Also works for instructions whose stack effect depends on the - * constant pool entry they reference. - * @return Number of words consumed from stack by this instruction + * @return number of dimensions to be created */ - @Override - public int consumeStack( final ConstantPoolGen cpg ) { + public final short getDimensions() { return dimensions; } - @Override public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_CLASS_AND_INTERFACE_RESOLUTION, - ExceptionConst.ILLEGAL_ACCESS_ERROR, + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_CLASS_AND_INTERFACE_RESOLUTION, ExceptionConst.ILLEGAL_ACCESS_ERROR, ExceptionConst.NEGATIVE_ARRAY_SIZE_EXCEPTION); } - @Override - public ObjectType getLoadClassType( final ConstantPoolGen cpg ) { + public ObjectType getLoadClassType(final ConstantPoolGen cpg) { Type t = getType(cpg); if (t instanceof ArrayType) { t = ((ArrayType) t).getBasicType(); } - return (t instanceof ObjectType) ? (ObjectType) t : null; + return t instanceof ObjectType ? (ObjectType) t : null; } + /** + * Read needed data (i.e., no. dimension) from file. + */ + @Override + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { + super.initFromFile(bytes, wide); + dimensions = bytes.readByte(); + super.setLength(4); + } /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. - * - * @param v Visitor object + * @return mnemonic for instruction */ @Override - public void accept( final Visitor v ) { - v.visitLoadClass(this); - v.visitAllocationInstruction(this); - v.visitExceptionThrower(this); - v.visitTypedInstruction(this); - v.visitCPInstruction(this); - v.visitMULTIANEWARRAY(this); + public String toString(final boolean verbose) { + return super.toString(verbose) + " " + super.getIndex() + " " + dimensions; + } + + /** + * @return mnemonic for instruction with symbolic references resolved + */ + @Override + public String toString(final ConstantPool cp) { + return super.toString(cp) + " " + dimensions; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java index f787b44b08d..f6e8333be79 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -19,6 +19,15 @@ */ package com.sun.org.apache.bcel.internal.generic; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import java.util.Stack; + import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry; import com.sun.org.apache.bcel.internal.classfile.Annotations; @@ -37,96 +46,223 @@ import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleParameterAnnotations; import com.sun.org.apache.bcel.internal.classfile.Utility; import com.sun.org.apache.bcel.internal.util.BCELComparator; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Stack; /** - * Template class for building up a method. This is done by defining exception - * handlers, adding thrown exceptions, local variables and attributes, whereas - * the `LocalVariableTable' and `LineNumberTable' attributes will be set - * automatically for the code. Use stripAttributes() if you don't like this. + * Template class for building up a method. This is done by defining exception handlers, adding thrown exceptions, local + * variables and attributes, whereas the 'LocalVariableTable' and 'LineNumberTable' attributes will be set automatically + * for the code. Use stripAttributes() if you don't like this. * - * While generating code it may be necessary to insert NOP operations. You can - * use the `removeNOPs' method to get rid off them. - * The resulting method object can be obtained via the `getMethod()' method. + * While generating code it may be necessary to insert NOP operations. You can use the 'removeNOPs' method to get rid + * off them. The resulting method object can be obtained via the 'getMethod()' method. * - * @see InstructionList - * @see Method - * @LastModified: May 2021 + * @see InstructionList + * @see Method + * @LastModified: Feb 2023 */ public class MethodGen extends FieldGenOrMethodGen { + static final class BranchStack { + + private final Stack branchTargets = new Stack<>(); + private final HashMap visitedTargets = new HashMap<>(); + + public BranchTarget pop() { + if (!branchTargets.empty()) { + return branchTargets.pop(); + } + return null; + } + + public void push(final InstructionHandle target, final int stackDepth) { + if (visited(target)) { + return; + } + branchTargets.push(visit(target, stackDepth)); + } + + private BranchTarget visit(final InstructionHandle target, final int stackDepth) { + final BranchTarget bt = new BranchTarget(target, stackDepth); + visitedTargets.put(target, bt); + return bt; + } + + private boolean visited(final InstructionHandle target) { + return visitedTargets.get(target) != null; + } + } + + static final class BranchTarget { + + final InstructionHandle target; + final int stackDepth; + + BranchTarget(final InstructionHandle target, final int stackDepth) { + this.target = target; + this.stackDepth = stackDepth; + } + } + + private static BCELComparator bcelComparator = new BCELComparator() { + + @Override + public boolean equals(final Object o1, final Object o2) { + final FieldGenOrMethodGen THIS = (FieldGenOrMethodGen) o1; + final FieldGenOrMethodGen THAT = (FieldGenOrMethodGen) o2; + return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature()); + } + + @Override + public int hashCode(final Object o) { + final FieldGenOrMethodGen THIS = (FieldGenOrMethodGen) o; + return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); + } + }; + + private static byte[] getByteCodes(final Method method) { + final Code code = method.getCode(); + if (code == null) { + throw new IllegalStateException(String.format("The method '%s' has no code.", method)); + } + return code.getCode(); + } + + /** + * @return Comparison strategy object + */ + public static BCELComparator getComparator() { + return bcelComparator; + } + + /** + * Computes stack usage of an instruction list by performing control flow analysis. + * + * @return maximum stack depth used by method + */ + public static int getMaxStack(final ConstantPoolGen cp, final InstructionList il, final CodeExceptionGen[] et) { + final BranchStack branchTargets = new BranchStack(); + /* + * Initially, populate the branch stack with the exception handlers, because these aren't (necessarily) branched to + * explicitly. in each case, the stack will have depth 1, containing the exception object. + */ + for (final CodeExceptionGen element : et) { + final InstructionHandle handlerPc = element.getHandlerPC(); + if (handlerPc != null) { + branchTargets.push(handlerPc, 1); + } + } + int stackDepth = 0; + int maxStackDepth = 0; + InstructionHandle ih = il.getStart(); + while (ih != null) { + final Instruction instruction = ih.getInstruction(); + final short opcode = instruction.getOpcode(); + final int delta = instruction.produceStack(cp) - instruction.consumeStack(cp); + stackDepth += delta; + if (stackDepth > maxStackDepth) { + maxStackDepth = stackDepth; + } + // choose the next instruction based on whether current is a branch. + if (instruction instanceof BranchInstruction) { + final BranchInstruction branch = (BranchInstruction) instruction; + if (instruction instanceof Select) { + // explore all of the select's targets. the default target is handled below. + final Select select = (Select) branch; + final InstructionHandle[] targets = select.getTargets(); + for (final InstructionHandle target : targets) { + branchTargets.push(target, stackDepth); + } + // nothing to fall through to. + ih = null; + } else if (!(branch instanceof IfInstruction)) { + // if an instruction that comes back to following PC, + // push next instruction, with stack depth reduced by 1. + if (opcode == Const.JSR || opcode == Const.JSR_W) { + branchTargets.push(ih.getNext(), stackDepth - 1); + } + ih = null; + } + // for all branches, the target of the branch is pushed on the branch stack. + // conditional branches have a fall through case, selects don't, and + // jsr/jsr_w return to the next instruction. + branchTargets.push(branch.getTarget(), stackDepth); + } else // check for instructions that terminate the method. + if (opcode == Const.ATHROW || opcode == Const.RET || opcode >= Const.IRETURN && opcode <= Const.RETURN) { + ih = null; + } + // normal case, go to the next instruction. + if (ih != null) { + ih = ih.getNext(); + } + // if we have no more instructions, see if there are any deferred branches to explore. + if (ih == null) { + final BranchTarget bt = branchTargets.pop(); + if (bt != null) { + ih = bt.target; + stackDepth = bt.stackDepth; + } + } + } + return maxStackDepth; + } + + /** + * @param comparator Comparison strategy object + */ + public static void setComparator(final BCELComparator comparator) { + bcelComparator = comparator; + } + private String className; private Type[] argTypes; private String[] argNames; private int maxLocals; private int maxStack; private InstructionList il; + private boolean stripAttributes; - private LocalVariableTypeTable localVariableTypeTable = null; + private LocalVariableTypeTable localVariableTypeTable; private final List variableList = new ArrayList<>(); + private final List lineNumberList = new ArrayList<>(); + private final List exceptionList = new ArrayList<>(); + private final List throwsList = new ArrayList<>(); + private final List codeAttrsList = new ArrayList<>(); private List[] paramAnnotations; // Array of lists containing AnnotationGen objects - private boolean hasParameterAnnotations = false; - private boolean haveUnpackedParameterAnnotations = false; - - private static BCELComparator bcelComparator = new BCELComparator() { - - @Override - public boolean equals( final Object o1, final Object o2 ) { - final MethodGen THIS = (MethodGen) o1; - final MethodGen THAT = (MethodGen) o2; - return Objects.equals(THIS.getName(), THAT.getName()) - && Objects.equals(THIS.getSignature(), THAT.getSignature()); - } + private boolean hasParameterAnnotations; - @Override - public int hashCode( final Object o ) { - final MethodGen THIS = (MethodGen) o; - return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); - } - }; + private boolean haveUnpackedParameterAnnotations; + private List observers; /** - * Declare method. If the method is non-static the constructor - * automatically declares a local variable `$this' in slot 0. The - * actual code is contained in the `il' parameter, which may further - * manipulated by the user. But he must take care not to remove any - * instruction (handles) that are still referenced from this object. + * Declare method. If the method is non-static the constructor automatically declares a local variable '$this' in slot + * 0. The actual code is contained in the 'il' parameter, which may further manipulated by the user. But they must take + * care not to remove any instruction (handles) that are still referenced from this object. * - * For example one may not add a local variable and later remove the - * instructions it refers to without causing havoc. It is safe - * however if you remove that local variable, too. + * For example one may not add a local variable and later remove the instructions it refers to without causing havoc. It + * is safe however if you remove that local variable, too. * - * @param access_flags access qualifiers - * @param return_type method type + * @param accessFlags access qualifiers + * @param returnType method type * @param argTypes argument types - * @param argNames argument names (if this is null, default names will be provided - * for them) - * @param method_name name of method + * @param argNames argument names (if this is null, default names will be provided for them) + * @param methodName name of method * @param className class name containing this method (may be null, if you don't care) - * @param il instruction list associated with this method, may be null only for - * abstract or native methods + * @param il instruction list associated with this method, may be null only for abstract or native methods * @param cp constant pool */ - public MethodGen(final int access_flags, final Type return_type, final Type[] argTypes, String[] argNames, - final String method_name, final String className, final InstructionList il, final ConstantPoolGen cp) { - super(access_flags); - setType(return_type); + public MethodGen(final int accessFlags, final Type returnType, final Type[] argTypes, String[] argNames, final String methodName, final String className, + final InstructionList il, final ConstantPoolGen cp) { + super(accessFlags); + setType(returnType); setArgumentTypes(argTypes); setArgumentNames(argNames); - setName(method_name); + setName(methodName); setClassName(className); setInstructionList(il); setConstantPool(cp); @@ -136,23 +272,23 @@ public MethodGen(final int access_flags, final Type return_type, final Type[] ar if (!abstract_) { start = il.getStart(); // end == null => live to end of method - /* Add local variables, namely the implicit `this' and the arguments + /* + * Add local variables, namely the implicit 'this' and the arguments */ - if (!isStatic() && (className != null)) { // Instance method -> `this' is local var 0 - addLocalVariable("this", ObjectType.getInstance(className), start, end); + if (!isStatic() && className != null) { // Instance method -> 'this' is local var 0 + addLocalVariable("this", ObjectType.getInstance(className), start, end); } } if (argTypes != null) { final int size = argTypes.length; - for (final Type arg_type : argTypes) { - if (Type.VOID == arg_type) { + for (final Type argType : argTypes) { + if (Type.VOID == argType) { throw new ClassGenException("'void' is an illegal argument type for a method"); } } if (argNames != null) { // Names for variables provided? if (size != argNames.length) { - throw new ClassGenException("Mismatch in argument array lengths: " + size - + " vs. " + argNames.length); + throw new ClassGenException("Mismatch in argument array lengths: " + size + " vs. " + argNames.length); } } else { // Give them dummy names argNames = new String[size]; @@ -169,7 +305,6 @@ public MethodGen(final int access_flags, final Type return_type, final Type[] ar } } - /** * Instantiate from existing method. * @@ -178,13 +313,10 @@ public MethodGen(final int access_flags, final Type return_type, final Type[] ar * @param cp constant pool */ public MethodGen(final Method method, final String className, final ConstantPoolGen cp) { - this(method.getAccessFlags(), Type.getReturnType(method.getSignature()), - Type.getArgumentTypes(method.getSignature()), null /* may be overridden anyway */ + this(method.getAccessFlags(), Type.getReturnType(method.getSignature()), Type.getArgumentTypes(method.getSignature()), + null /* may be overridden anyway */ , method.getName(), className, - ((method.getAccessFlags() & (Const.ACC_ABSTRACT | Const.ACC_NATIVE)) == 0) - ? new InstructionList(getByteCodes(method)) - : null, - cp); + (method.getAccessFlags() & (Const.ACC_ABSTRACT | Const.ACC_NATIVE)) == 0 ? new InstructionList(getByteCodes(method)) : null, cp); final Attribute[] attributes = method.getAttributes(); for (final Attribute attribute : attributes) { Attribute a = attribute; @@ -196,36 +328,33 @@ public MethodGen(final Method method, final String className, final ConstantPool if (ces != null) { for (final CodeException ce : ces) { final int type = ce.getCatchType(); - ObjectType c_type = null; + ObjectType cType = null; if (type > 0) { - final String cen = method.getConstantPool().getConstantString(type, - Const.CONSTANT_Class); - c_type = ObjectType.getInstance(cen); + final String cen = method.getConstantPool().getConstantString(type, Const.CONSTANT_Class); + cType = ObjectType.getInstance(cen); } - final int end_pc = ce.getEndPC(); + final int endPc = ce.getEndPC(); final int length = getByteCodes(method).length; InstructionHandle end; - if (length == end_pc) { // May happen, because end_pc is exclusive + if (length == endPc) { // May happen, because end_pc is exclusive end = il.getEnd(); } else { - end = il.findHandle(end_pc); + end = il.findHandle(endPc); end = end.getPrev(); // Make it inclusive } - addExceptionHandler(il.findHandle(ce.getStartPC()), end, - il.findHandle(ce.getHandlerPC()), c_type); + addExceptionHandler(il.findHandle(ce.getStartPC()), end, il.findHandle(ce.getHandlerPC()), cType); } } - final Attribute[] c_attributes = c.getAttributes(); - for (final Attribute c_attribute : c_attributes) { - a = c_attribute; + final Attribute[] cAttributes = c.getAttributes(); + for (final Attribute cAttribute : cAttributes) { + a = cAttribute; if (a instanceof LineNumberTable) { - final LineNumber[] ln = ((LineNumberTable) a).getLineNumberTable(); - for (final LineNumber l : ln) { + ((LineNumberTable) a).forEach(l -> { final InstructionHandle ih = il.findHandle(l.getStartPC()); if (ih != null) { addLineNumber(ih, l.getLineNumber()); } - } + }); } else if (a instanceof LocalVariableTable) { updateLocalVariableTable((LocalVariableTable) a); } else if (a instanceof LocalVariableTypeTable) { @@ -235,474 +364,478 @@ public MethodGen(final Method method, final String className, final ConstantPool } } } else if (a instanceof ExceptionTable) { - final String[] names = ((ExceptionTable) a).getExceptionNames(); - for (final String name2 : names) { - addException(name2); - } + Collections.addAll(throwsList, ((ExceptionTable) a).getExceptionNames()); } else if (a instanceof Annotations) { final Annotations runtimeAnnotations = (Annotations) a; - final AnnotationEntry[] aes = runtimeAnnotations.getAnnotationEntries(); - for (final AnnotationEntry element : aes) { - addAnnotationEntry(new AnnotationEntryGen(element, cp, false)); - } + runtimeAnnotations.forEach(element -> addAnnotationEntry(new AnnotationEntryGen(element, cp, false))); } else { addAttribute(a); } } } + /** + * @since 6.0 + */ + public void addAnnotationsAsAttribute(final ConstantPoolGen cp) { + addAll(AnnotationEntryGen.getAnnotationAttributes(cp, super.getAnnotationEntries())); + } - private static byte[] getByteCodes(final Method method) { - final Code code = method.getCode(); - if (code == null) { - throw new IllegalStateException(String.format("The method '%s' has no code.", method)); + /** + * Add an attribute to the code. Currently, the JVM knows about the LineNumberTable, LocalVariableTable and StackMap + * attributes, where the former two will be generated automatically and the latter is used for the MIDP only. Other + * attributes will be ignored by the JVM but do no harm. + * + * @param a attribute to be added + */ + public void addCodeAttribute(final Attribute a) { + codeAttrsList.add(a); + } + + /** + * Add an exception possibly thrown by this method. + * + * @param className (fully qualified) name of exception + */ + public void addException(final String className) { + throwsList.add(className); + } + + /** + * Add an exception handler, i.e., specify region where a handler is active and an instruction where the actual handling + * is done. + * + * @param startPc Start of region (inclusive) + * @param endPc End of region (inclusive) + * @param handlerPc Where handling is done + * @param catchType class type of handled exception or null if any exception is handled + * @return new exception handler object + */ + public CodeExceptionGen addExceptionHandler(final InstructionHandle startPc, final InstructionHandle endPc, final InstructionHandle handlerPc, + final ObjectType catchType) { + if (startPc == null || endPc == null || handlerPc == null) { + throw new ClassGenException("Exception handler target is null instruction"); } - return code.getCode(); + final CodeExceptionGen c = new CodeExceptionGen(startPc, endPc, handlerPc, catchType); + exceptionList.add(c); + return c; } /** - * Adds a local variable to this method. + * Give an instruction a line number corresponding to the source code line. + * + * @param ih instruction to tag + * @return new line number object + * @see LineNumber + */ + public LineNumberGen addLineNumber(final InstructionHandle ih, final int srcLine) { + final LineNumberGen l = new LineNumberGen(ih, srcLine); + lineNumberList.add(l); + return l; + } + + /** + * Adds a local variable to this method and assigns an index automatically. * * @param name variable name * @param type variable type - * @param slot the index of the local variable, if type is long or double, the next available - * index is slot+2 - * @param start from where the variable is valid - * @param end until where the variable is valid - * @param orig_index the index of the local variable prior to any modifications + * @param start from where the variable is valid, if this is null, it is valid from the start + * @param end until where the variable is valid, if this is null, it is valid to the end * @return new local variable object * @see LocalVariable */ - public LocalVariableGen addLocalVariable( final String name, final Type type, final int slot, - final InstructionHandle start, final InstructionHandle end, final int orig_index ) { - final byte t = type.getType(); - if (t != Const.T_ADDRESS) { - final int add = type.getSize(); - if (slot + add > maxLocals) { - maxLocals = slot + add; - } - final LocalVariableGen l = new LocalVariableGen(slot, name, type, start, end, orig_index); - int i; - if ((i = variableList.indexOf(l)) >= 0) { - variableList.set(i, l); - } else { - variableList.add(l); - } - return l; - } - throw new IllegalArgumentException("Can not use " + type - + " as type for local variable"); + public LocalVariableGen addLocalVariable(final String name, final Type type, final InstructionHandle start, final InstructionHandle end) { + return addLocalVariable(name, type, maxLocals, start, end); } - /** * Adds a local variable to this method. * * @param name variable name * @param type variable type - * @param slot the index of the local variable, if type is long or double, the next available - * index is slot+2 + * @param slot the index of the local variable, if type is long or double, the next available index is slot+2 * @param start from where the variable is valid * @param end until where the variable is valid * @return new local variable object * @see LocalVariable */ - public LocalVariableGen addLocalVariable( final String name, final Type type, final int slot, - final InstructionHandle start, final InstructionHandle end ) { + public LocalVariableGen addLocalVariable(final String name, final Type type, final int slot, final InstructionHandle start, final InstructionHandle end) { return addLocalVariable(name, type, slot, start, end, slot); } /** - * Adds a local variable to this method and assigns an index automatically. + * Adds a local variable to this method. * * @param name variable name * @param type variable type - * @param start from where the variable is valid, if this is null, - * it is valid from the start - * @param end until where the variable is valid, if this is null, - * it is valid to the end + * @param slot the index of the local variable, if type is long or double, the next available index is slot+2 + * @param start from where the variable is valid + * @param end until where the variable is valid + * @param origIndex the index of the local variable prior to any modifications * @return new local variable object * @see LocalVariable */ - public LocalVariableGen addLocalVariable( final String name, final Type type, final InstructionHandle start, - final InstructionHandle end ) { - return addLocalVariable(name, type, maxLocals, start, end); + public LocalVariableGen addLocalVariable(final String name, final Type type, final int slot, final InstructionHandle start, final InstructionHandle end, + final int origIndex) { + final byte t = type.getType(); + if (t != Const.T_ADDRESS) { + final int add = type.getSize(); + if (slot + add > maxLocals) { + maxLocals = slot + add; + } + final LocalVariableGen l = new LocalVariableGen(slot, name, type, start, end, origIndex); + int i; + if ((i = variableList.indexOf(l)) >= 0) { + variableList.set(i, l); + } else { + variableList.add(l); + } + return l; + } + throw new IllegalArgumentException("Can not use " + type + " as type for local variable"); } - /** - * Remove a local variable, its slot will not be reused, if you do not use - * addLocalVariable with an explicit index argument. + * Add observer for this object. */ - public void removeLocalVariable(final LocalVariableGen l) { - variableList.remove(l); + public void addObserver(final MethodObserver o) { + if (observers == null) { + observers = new ArrayList<>(); + } + observers.add(o); } - - /** - * Remove all local variables. - */ - public void removeLocalVariables() { - variableList.clear(); - } - - - /* - * If the range of the variable has not been set yet, it will be set to be valid from - * the start to the end of the instruction list. - * - * @return array of declared local variables sorted by index - */ - public LocalVariableGen[] getLocalVariables() { - final int size = variableList.size(); - final LocalVariableGen[] lg = new LocalVariableGen[size]; - variableList.toArray(lg); - for (int i = 0; i < size; i++) { - if ((lg[i].getStart() == null) && (il != null)) { - lg[i].setStart(il.getStart()); - } - if ((lg[i].getEnd() == null) && (il != null)) { - lg[i].setEnd(il.getEnd()); - } + public void addParameterAnnotation(final int parameterIndex, final AnnotationEntryGen annotation) { + ensureExistingParameterAnnotationsUnpacked(); + if (!hasParameterAnnotations) { + @SuppressWarnings({"rawtypes", "unchecked"}) + final List[] parmList = (List[])new List[argTypes.length]; + paramAnnotations = parmList; + hasParameterAnnotations = true; } - if (size > 1) { - Arrays.sort(lg, (o1, o2) -> o1.getIndex() - o2.getIndex()); + final List existingAnnotations = paramAnnotations[parameterIndex]; + if (existingAnnotations != null) { + existingAnnotations.add(annotation); + } else { + final List l = new ArrayList<>(); + l.add(annotation); + paramAnnotations[parameterIndex] = l; } - return lg; } - /** - * @return `LocalVariableTable' attribute of all the local variables of this method. + * @since 6.0 */ - public LocalVariableTable getLocalVariableTable( final ConstantPoolGen cp ) { - final LocalVariableGen[] lg = getLocalVariables(); - final int size = lg.length; - final LocalVariable[] lv = new LocalVariable[size]; - for (int i = 0; i < size; i++) { - lv[i] = lg[i].getLocalVariable(cp); + public void addParameterAnnotationsAsAttribute(final ConstantPoolGen cp) { + if (!hasParameterAnnotations) { + return; + } + final Attribute[] attrs = AnnotationEntryGen.getParameterAnnotationAttributes(cp, paramAnnotations); + if (attrs != null) { + addAll(attrs); } - return new LocalVariableTable(cp.addUtf8("LocalVariableTable"), 2 + lv.length * 10, lv, cp - .getConstantPool()); } - /** - * @return `LocalVariableTypeTable' attribute of this method. - */ - public LocalVariableTypeTable getLocalVariableTypeTable() { - return localVariableTypeTable; + private Attribute[] addRuntimeAnnotationsAsAttribute(final ConstantPoolGen cp) { + final Attribute[] attrs = AnnotationEntryGen.getAnnotationAttributes(cp, super.getAnnotationEntries()); + addAll(attrs); + return attrs; } - /** - * Give an instruction a line number corresponding to the source code line. - * - * @param ih instruction to tag - * @return new line number object - * @see LineNumber - */ - public LineNumberGen addLineNumber( final InstructionHandle ih, final int srcLine ) { - final LineNumberGen l = new LineNumberGen(ih, srcLine); - lineNumberList.add(l); - return l; + private Attribute[] addRuntimeParameterAnnotationsAsAttribute(final ConstantPoolGen cp) { + if (!hasParameterAnnotations) { + return Attribute.EMPTY_ARRAY; + } + final Attribute[] attrs = AnnotationEntryGen.getParameterAnnotationAttributes(cp, paramAnnotations); + addAll(attrs); + return attrs; } - - /** - * Remove a line number. - */ - public void removeLineNumber( final LineNumberGen l ) { - lineNumberList.remove(l); + private void adjustLocalVariableTypeTable(final LocalVariableTable lvt) { + final LocalVariable[] lv = lvt.getLocalVariableTable(); + for (final LocalVariable element : localVariableTypeTable.getLocalVariableTypeTable()) { + for (final LocalVariable l : lv) { + if (element.getName().equals(l.getName()) && element.getIndex() == l.getOrigIndex()) { + element.setLength(l.getLength()); + element.setStartPC(l.getStartPC()); + element.setIndex(l.getIndex()); + break; + } + } + } } - /** - * Remove all line numbers. - */ - public void removeLineNumbers() { - lineNumberList.clear(); - } - - - /* - * @return array of line numbers + * @return deep copy of this method */ - public LineNumberGen[] getLineNumbers() { - final LineNumberGen[] lg = new LineNumberGen[lineNumberList.size()]; - lineNumberList.toArray(lg); - return lg; + public MethodGen copy(final String className, final ConstantPoolGen cp) { + final Method m = ((MethodGen) clone()).getMethod(); + final MethodGen mg = new MethodGen(m, className, super.getConstantPool()); + if (super.getConstantPool() != cp) { + mg.setConstantPool(cp); + mg.getInstructionList().replaceConstantPool(super.getConstantPool(), cp); + } + return mg; } - /** - * @return `LineNumberTable' attribute of all the local variables of this method. + * Goes through the attributes on the method and identifies any that are RuntimeParameterAnnotations, extracting their + * contents and storing them as parameter annotations. There are two kinds of parameter annotation - visible and + * invisible. Once they have been unpacked, these attributes are deleted. (The annotations will be rebuilt as attributes + * when someone builds a Method object out of this MethodGen object). */ - public LineNumberTable getLineNumberTable( final ConstantPoolGen cp ) { - final int size = lineNumberList.size(); - final LineNumber[] ln = new LineNumber[size]; - for (int i = 0; i < size; i++) { - ln[i] = lineNumberList.get(i).getLineNumber(); + private void ensureExistingParameterAnnotationsUnpacked() { + if (haveUnpackedParameterAnnotations) { + return; + } + // Find attributes that contain parameter annotation data + final Attribute[] attrs = getAttributes(); + ParameterAnnotations paramAnnVisAttr = null; + ParameterAnnotations paramAnnInvisAttr = null; + for (final Attribute attribute : attrs) { + if (attribute instanceof ParameterAnnotations) { + // Initialize paramAnnotations + if (!hasParameterAnnotations) { + @SuppressWarnings({"rawtypes", "unchecked"}) + final List[] parmList = (List[])new List[argTypes.length]; + paramAnnotations = parmList; + Arrays.setAll(paramAnnotations, i -> new ArrayList<>()); + } + hasParameterAnnotations = true; + final ParameterAnnotations rpa = (ParameterAnnotations) attribute; + if (rpa instanceof RuntimeVisibleParameterAnnotations) { + paramAnnVisAttr = rpa; + } else { + paramAnnInvisAttr = rpa; + } + final ParameterAnnotationEntry[] parameterAnnotationEntries = rpa.getParameterAnnotationEntries(); + for (int j = 0; j < parameterAnnotationEntries.length; j++) { + // This returns Annotation[] ... + final ParameterAnnotationEntry immutableArray = rpa.getParameterAnnotationEntries()[j]; + // ... which needs transforming into an AnnotationGen[] ... + final List mutable = makeMutableVersion(immutableArray.getAnnotationEntries()); + // ... then add these to any we already know about + paramAnnotations[j].addAll(mutable); + } + } + } + if (paramAnnVisAttr != null) { + removeAttribute(paramAnnVisAttr); + } + if (paramAnnInvisAttr != null) { + removeAttribute(paramAnnInvisAttr); } - return new LineNumberTable(cp.addUtf8("LineNumberTable"), 2 + ln.length * 4, ln, cp - .getConstantPool()); + haveUnpackedParameterAnnotations = true; } - /** - * Add an exception handler, i.e., specify region where a handler is active and an - * instruction where the actual handling is done. + * Return value as defined by given BCELComparator strategy. By default two MethodGen objects are said to be equal when + * their names and signatures are equal. * - * @param start_pc Start of region (inclusive) - * @param end_pc End of region (inclusive) - * @param handler_pc Where handling is done - * @param catch_type class type of handled exception or null if any - * exception is handled - * @return new exception handler object + * @see Object#equals(Object) */ - public CodeExceptionGen addExceptionHandler( final InstructionHandle start_pc, - final InstructionHandle end_pc, final InstructionHandle handler_pc, final ObjectType catch_type ) { - if ((start_pc == null) || (end_pc == null) || (handler_pc == null)) { - throw new ClassGenException("Exception handler target is null instruction"); - } - final CodeExceptionGen c = new CodeExceptionGen(start_pc, end_pc, handler_pc, catch_type); - exceptionList.add(c); - return c; + @Override + public boolean equals(final Object obj) { + return bcelComparator.equals(this, obj); } - + // J5TODO: Should paramAnnotations be an array of arrays? Rather than an array of lists, this + // is more likely to suggest to the caller it is readonly (which a List does not). /** - * Remove an exception handler. + * Return a list of AnnotationGen objects representing parameter annotations + * + * @since 6.0 */ - public void removeExceptionHandler( final CodeExceptionGen c ) { - exceptionList.remove(c); + public List getAnnotationsOnParameter(final int i) { + ensureExistingParameterAnnotationsUnpacked(); + if (!hasParameterAnnotations || i > argTypes.length) { + return null; + } + return paramAnnotations[i]; } - - /** - * Remove all line numbers. - */ - public void removeExceptionHandlers() { - exceptionList.clear(); + public String getArgumentName(final int i) { + return argNames[i]; } + public String[] getArgumentNames() { + return argNames.clone(); + } - /* - * @return array of declared exception handlers - */ - public CodeExceptionGen[] getExceptionHandlers() { - final CodeExceptionGen[] cg = new CodeExceptionGen[exceptionList.size()]; - exceptionList.toArray(cg); - return cg; + public Type getArgumentType(final int i) { + return argTypes[i]; } + public Type[] getArgumentTypes() { + return argTypes.clone(); + } /** - * @return code exceptions for `Code' attribute + * @return class that contains this method */ - private CodeException[] getCodeExceptions() { - final int size = exceptionList.size(); - final CodeException[] c_exc = new CodeException[size]; - for (int i = 0; i < size; i++) { - final CodeExceptionGen c = exceptionList.get(i); - c_exc[i] = c.getCodeException(super.getConstantPool()); - } - return c_exc; + public String getClassName() { + return className; } - /** - * Add an exception possibly thrown by this method. - * - * @param className (fully qualified) name of exception + * @return all attributes of this method. */ - public void addException( final String className ) { - throwsList.add(className); + public Attribute[] getCodeAttributes() { + return codeAttrsList.toArray(Attribute.EMPTY_ARRAY); } - /** - * Remove an exception. + * @return code exceptions for 'Code' attribute */ - public void removeException( final String c ) { - throwsList.remove(c); + private CodeException[] getCodeExceptions() { + final int size = exceptionList.size(); + final CodeException[] cExc = new CodeException[size]; + Arrays.setAll(cExc, i -> exceptionList.get(i).getCodeException(super.getConstantPool())); + return cExc; } - - /** - * Remove all exceptions. + /* + * @return array of declared exception handlers */ - public void removeExceptions() { - throwsList.clear(); + public CodeExceptionGen[] getExceptionHandlers() { + return exceptionList.toArray(CodeExceptionGen.EMPTY_ARRAY); } - /* * @return array of thrown exceptions */ public String[] getExceptions() { - return throwsList.toArray(new String[0]); + return throwsList.toArray(Const.EMPTY_STRING_ARRAY); } - /** - * @return `Exceptions' attribute of all the exceptions thrown by this method. + * @return 'Exceptions' attribute of all the exceptions thrown by this method. */ - private ExceptionTable getExceptionTable( final ConstantPoolGen cp ) { + private ExceptionTable getExceptionTable(final ConstantPoolGen cp) { final int size = throwsList.size(); final int[] ex = new int[size]; - for (int i = 0; i < size; i++) { - ex[i] = cp.addClass(throwsList.get(i)); - } + Arrays.setAll(ex, i -> cp.addClass(throwsList.get(i))); return new ExceptionTable(cp.addUtf8("Exceptions"), 2 + 2 * size, ex, cp.getConstantPool()); } + public InstructionList getInstructionList() { + return il; + } - /** - * Add an attribute to the code. Currently, the JVM knows about the - * LineNumberTable, LocalVariableTable and StackMap attributes, - * where the former two will be generated automatically and the - * latter is used for the MIDP only. Other attributes will be - * ignored by the JVM but do no harm. - * - * @param a attribute to be added + /* + * @return array of line numbers */ - public void addCodeAttribute( final Attribute a ) { - codeAttrsList.add(a); + public LineNumberGen[] getLineNumbers() { + return lineNumberList.toArray(LineNumberGen.EMPTY_ARRAY); } - /** - * Remove the LocalVariableTypeTable + * @return 'LineNumberTable' attribute of all the local variables of this method. */ - public void removeLocalVariableTypeTable( ) { - localVariableTypeTable = null; + public LineNumberTable getLineNumberTable(final ConstantPoolGen cp) { + final int size = lineNumberList.size(); + final LineNumber[] ln = new LineNumber[size]; + Arrays.setAll(ln, i -> lineNumberList.get(i).getLineNumber()); + return new LineNumberTable(cp.addUtf8("LineNumberTable"), 2 + ln.length * 4, ln, cp.getConstantPool()); } - /** - * Remove a code attribute. + /* + * If the range of the variable has not been set yet, it will be set to be valid from the start to the end of the + * instruction list. + * + * @return array of declared local variables sorted by index */ - public void removeCodeAttribute( final Attribute a ) { - codeAttrsList.remove(a); + public LocalVariableGen[] getLocalVariables() { + final int size = variableList.size(); + final LocalVariableGen[] lg = new LocalVariableGen[size]; + variableList.toArray(lg); + for (int i = 0; i < size; i++) { + if (lg[i].getStart() == null && il != null) { + lg[i].setStart(il.getStart()); + } + if (lg[i].getEnd() == null && il != null) { + lg[i].setEnd(il.getEnd()); + } + } + if (size > 1) { + Arrays.sort(lg, Comparator.comparingInt(LocalVariableGen::getIndex)); + } + return lg; } - /** - * Remove all code attributes. + * @return 'LocalVariableTable' attribute of all the local variables of this method. */ - public void removeCodeAttributes() { - localVariableTypeTable = null; - codeAttrsList.clear(); + public LocalVariableTable getLocalVariableTable(final ConstantPoolGen cp) { + final LocalVariableGen[] lg = getLocalVariables(); + final int size = lg.length; + final LocalVariable[] lv = new LocalVariable[size]; + Arrays.setAll(lv, i -> lg[i].getLocalVariable(cp)); + return new LocalVariableTable(cp.addUtf8("LocalVariableTable"), 2 + lv.length * 10, lv, cp.getConstantPool()); } - /** - * @return all attributes of this method. + * @return 'LocalVariableTypeTable' attribute of this method. */ - public Attribute[] getCodeAttributes() { - return codeAttrsList.toArray(new Attribute[0]); + public LocalVariableTypeTable getLocalVariableTypeTable() { + return localVariableTypeTable; } - /** - * @since 6.0 - */ - public void addAnnotationsAsAttribute(final ConstantPoolGen cp) { - final Attribute[] attrs = AnnotationEntryGen.getAnnotationAttributes(cp, super.getAnnotationEntries()); - for (final Attribute attr : attrs) { - addAttribute(attr); - } - } - - /** - * @since 6.0 - */ - public void addParameterAnnotationsAsAttribute(final ConstantPoolGen cp) { - if (!hasParameterAnnotations) { - return; - } - final Attribute[] attrs = AnnotationEntryGen.getParameterAnnotationAttributes(cp, paramAnnotations); - if (attrs != null) { - for (final Attribute attr : attrs) { - addAttribute(attr); - } - } - } - - private Attribute[] addRuntimeAnnotationsAsAttribute(final ConstantPoolGen cp) { - final Attribute[] attrs = AnnotationEntryGen.getAnnotationAttributes(cp, super.getAnnotationEntries()); - for (final Attribute attr : attrs) { - addAttribute(attr); - } - return attrs; - } - - private Attribute[] addRuntimeParameterAnnotationsAsAttribute(final ConstantPoolGen cp) { - if (!hasParameterAnnotations) { - return new Attribute[0]; - } - final Attribute[] attrs = AnnotationEntryGen.getParameterAnnotationAttributes(cp, paramAnnotations); - for (final Attribute attr : attrs) { - addAttribute(attr); - } - return attrs; + public int getMaxLocals() { + return maxLocals; } - /** - * Would prefer to make this private, but need a way to test if client is - * using BCEL version 6.5.0 or later that contains fix for BCEL-329. - * @since 6.5.0 - */ - public void removeRuntimeAttributes(final Attribute[] attrs) { - for (final Attribute attr : attrs) { - removeAttribute(attr); - } + public int getMaxStack() { + return maxStack; } - /** - * Get method object. Never forget to call setMaxStack() or setMaxStack(max), respectively, - * before calling this method (the same applies for max locals). + * Get method object. Never forget to call setMaxStack() or setMaxStack(max), respectively, before calling this method + * (the same applies for max locals). * * @return method object */ public Method getMethod() { final String signature = getSignature(); - final ConstantPoolGen _cp = super.getConstantPool(); - final int name_index = _cp.addUtf8(super.getName()); - final int signature_index = _cp.addUtf8(signature); - /* Also updates positions of instructions, i.e., their indices + final ConstantPoolGen cp = super.getConstantPool(); + final int nameIndex = cp.addUtf8(super.getName()); + final int signatureIndex = cp.addUtf8(signature); + /* + * Also updates positions of instructions, i.e., their indices */ - byte[] byte_code = null; - if (il != null) { - byte_code = il.getByteCode(); - } + final byte[] byteCode = il != null ? il.getByteCode() : null; LineNumberTable lnt = null; LocalVariableTable lvt = null; - /* Create LocalVariableTable and LineNumberTable attributes (for debuggers, e.g.) + /* + * Create LocalVariableTable and LineNumberTable attributes (for debuggers, e.g.) */ - if ((variableList.size() > 0) && !stripAttributes) { - updateLocalVariableTable(getLocalVariableTable(_cp)); - addCodeAttribute(lvt = getLocalVariableTable(_cp)); + if (!variableList.isEmpty() && !stripAttributes) { + updateLocalVariableTable(getLocalVariableTable(cp)); + addCodeAttribute(lvt = getLocalVariableTable(cp)); } if (localVariableTypeTable != null) { - // LocalVariable length in LocalVariableTypeTable is not updated automatically. It's a difference with LocalVariableTable. + // LocalVariable length in LocalVariableTypeTable is not updated automatically. It's a difference with + // LocalVariableTable. if (lvt != null) { adjustLocalVariableTypeTable(lvt); } addCodeAttribute(localVariableTypeTable); } - if ((lineNumberList.size() > 0) && !stripAttributes) { - addCodeAttribute(lnt = getLineNumberTable(_cp)); + if (!lineNumberList.isEmpty() && !stripAttributes) { + addCodeAttribute(lnt = getLineNumberTable(cp)); } - final Attribute[] code_attrs = getCodeAttributes(); - /* Each attribute causes 6 additional header bytes + final Attribute[] codeAttrs = getCodeAttributes(); + /* + * Each attribute causes 6 additional header bytes */ - int attrs_len = 0; - for (final Attribute code_attr : code_attrs) { - attrs_len += code_attr.getLength() + 6; + int attrsLen = 0; + for (final Attribute codeAttr : codeAttrs) { + attrsLen += codeAttr.getLength() + 6; } - final CodeException[] c_exc = getCodeExceptions(); - final int exc_len = c_exc.length * 8; // Every entry takes 8 bytes + final CodeException[] cExc = getCodeExceptions(); + final int excLen = cExc.length * 8; // Every entry takes 8 bytes Code code = null; - if ((il != null) && !isAbstract() && !isNative()) { + if (byteCode != null && !isAbstract() && !isNative()) { // Remove any stale code attribute final Attribute[] attributes = getAttributes(); for (final Attribute a : attributes) { @@ -710,21 +843,20 @@ public Method getMethod() { removeAttribute(a); } } - code = new Code(_cp.addUtf8("Code"), 8 + byte_code.length + // prologue byte code - 2 + exc_len + // exceptions - 2 + attrs_len, // attributes - maxStack, maxLocals, byte_code, c_exc, code_attrs, _cp.getConstantPool()); + code = new Code(cp.addUtf8("Code"), 8 + byteCode.length + // prologue byte code + 2 + excLen + // exceptions + 2 + attrsLen, // attributes + maxStack, maxLocals, byteCode, cExc, codeAttrs, cp.getConstantPool()); addAttribute(code); } - final Attribute[] annotations = addRuntimeAnnotationsAsAttribute(_cp); - final Attribute[] parameterAnnotations = addRuntimeParameterAnnotationsAsAttribute(_cp); + final Attribute[] annotations = addRuntimeAnnotationsAsAttribute(cp); + final Attribute[] parameterAnnotations = addRuntimeParameterAnnotationsAsAttribute(cp); ExceptionTable et = null; - if (throwsList.size() > 0) { - addAttribute(et = getExceptionTable(_cp)); - // Add `Exceptions' if there are "throws" clauses + if (!throwsList.isEmpty()) { + addAttribute(et = getExceptionTable(cp)); + // Add 'Exceptions' if there are "throws" clauses } - final Method m = new Method(super.getAccessFlags(), name_index, signature_index, getAttributes(), _cp - .getConstantPool()); + final Method m = new Method(super.getAccessFlags(), nameIndex, signatureIndex, getAttributes(), cp.getConstantPool()); // Undo effects of adding attributes if (lvt != null) { removeCodeAttribute(lvt); @@ -746,185 +878,185 @@ public Method getMethod() { return m; } - private void updateLocalVariableTable(final LocalVariableTable a) { - final LocalVariable[] lv = a.getLocalVariableTable(); - removeLocalVariables(); - for (final LocalVariable l : lv) { - InstructionHandle start = il.findHandle(l.getStartPC()); - final InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength()); - // Repair malformed handles - if (null == start) { - start = il.getStart(); - } - // end == null => live to end of method - // Since we are recreating the LocalVaraible, we must - // propagate the orig_index to new copy. - addLocalVariable(l.getName(), Type.getType(l.getSignature()), l - .getIndex(), start, end, l.getOrigIndex()); - } + public Type getReturnType() { + return getType(); } - private void adjustLocalVariableTypeTable(final LocalVariableTable lvt) { - final LocalVariable[] lv = lvt.getLocalVariableTable(); - final LocalVariable[] lvg = localVariableTypeTable.getLocalVariableTypeTable(); - - for (final LocalVariable element : lvg) { - for (final LocalVariable l : lv) { - if (element.getName().equals(l.getName()) && element.getIndex() == l.getOrigIndex()) { - element.setLength(l.getLength()); - element.setStartPC(l.getStartPC()); - element.setIndex(l.getIndex()); - break; - } - } - } + @Override + public String getSignature() { + return Type.getMethodSignature(super.getType(), argTypes); } - /** - * Remove all NOPs from the instruction list (if possible) and update every - * object referring to them, i.e., branch instructions, local variables and - * exception handlers. + * Return value as defined by given BCELComparator strategy. By default return the hashcode of the method's name XOR + * signature. + * + * @see Object#hashCode() */ - public void removeNOPs() { - if (il != null) { - InstructionHandle next; - /* Check branch instructions. - */ - for (InstructionHandle ih = il.getStart(); ih != null; ih = next) { - next = ih.getNext(); - if ((next != null) && (ih.getInstruction() instanceof NOP)) { - try { - il.delete(ih); - } catch (final TargetLostException e) { - for (final InstructionHandle target : e.getTargets()) { - for (final InstructionTargeter targeter : target.getTargeters()) { - targeter.updateTarget(target, next); - } - } - } - } - } - } + @Override + public int hashCode() { + return bcelComparator.hashCode(this); } + private List makeMutableVersion(final AnnotationEntry[] mutableArray) { + final List result = new ArrayList<>(); + for (final AnnotationEntry element : mutableArray) { + result.add(new AnnotationEntryGen(element, getConstantPool(), false)); + } + return result; + } /** - * Set maximum number of local variables. + * Remove a code attribute. */ - public void setMaxLocals( final int m ) { - maxLocals = m; + public void removeCodeAttribute(final Attribute a) { + codeAttrsList.remove(a); } - - public int getMaxLocals() { - return maxLocals; + /** + * Remove all code attributes. + */ + public void removeCodeAttributes() { + localVariableTypeTable = null; + codeAttrsList.clear(); } - /** - * Set maximum stack size for this method. + * Remove an exception. */ - public void setMaxStack( final int m ) { // TODO could be package-protected? - maxStack = m; + public void removeException(final String c) { + throwsList.remove(c); } - - public int getMaxStack() { - return maxStack; + /** + * Remove an exception handler. + */ + public void removeExceptionHandler(final CodeExceptionGen c) { + exceptionList.remove(c); } - - /** @return class that contains this method + /** + * Remove all line numbers. */ - public String getClassName() { - return className; + public void removeExceptionHandlers() { + exceptionList.clear(); } - - public void setClassName( final String class_name ) { // TODO could be package-protected? - this.className = class_name; + /** + * Remove all exceptions. + */ + public void removeExceptions() { + throwsList.clear(); } - - public void setReturnType( final Type return_type ) { - setType(return_type); + /** + * Remove a line number. + */ + public void removeLineNumber(final LineNumberGen l) { + lineNumberList.remove(l); } - - public Type getReturnType() { - return getType(); + /** + * Remove all line numbers. + */ + public void removeLineNumbers() { + lineNumberList.clear(); } - - public void setArgumentTypes( final Type[] arg_types ) { - this.argTypes = arg_types; + /** + * Remove a local variable, its slot will not be reused, if you do not use addLocalVariable with an explicit index + * argument. + */ + public void removeLocalVariable(final LocalVariableGen l) { + variableList.remove(l); } - - public Type[] getArgumentTypes() { - return argTypes.clone(); + /** + * Remove all local variables. + */ + public void removeLocalVariables() { + variableList.clear(); } - - public void setArgumentType( final int i, final Type type ) { - argTypes[i] = type; + /** + * Remove the LocalVariableTypeTable + */ + public void removeLocalVariableTypeTable() { + localVariableTypeTable = null; } - - public Type getArgumentType( final int i ) { - return argTypes[i]; + /** + * Remove all NOPs from the instruction list (if possible) and update every object referring to them, i.e., branch + * instructions, local variables and exception handlers. + */ + public void removeNOPs() { + if (il != null) { + InstructionHandle next; + /* + * Check branch instructions. + */ + for (InstructionHandle ih = il.getStart(); ih != null; ih = next) { + next = ih.getNext(); + if (next != null && ih.getInstruction() instanceof NOP) { + try { + il.delete(ih); + } catch (final TargetLostException e) { + for (final InstructionHandle target : e.getTargets()) { + for (final InstructionTargeter targeter : target.getTargeters()) { + targeter.updateTarget(target, next); + } + } + } + } + } + } } - - public void setArgumentNames( final String[] arg_names ) { - this.argNames = arg_names; + /** + * Remove observer for this object. + */ + public void removeObserver(final MethodObserver o) { + if (observers != null) { + observers.remove(o); + } } - - public String[] getArgumentNames() { - return argNames.clone(); + /** + * Would prefer to make this private, but need a way to test if client is using BCEL version 6.5.0 or later that + * contains fix for BCEL-329. + * + * @since 6.5.0 + */ + public void removeRuntimeAttributes(final Attribute[] attrs) { + for (final Attribute attr : attrs) { + removeAttribute(attr); + } } - - public void setArgumentName( final int i, final String name ) { + public void setArgumentName(final int i, final String name) { argNames[i] = name; } - - public String getArgumentName( final int i ) { - return argNames[i]; + public void setArgumentNames(final String[] argNames) { + this.argNames = argNames; } - - public InstructionList getInstructionList() { - return il; + public void setArgumentType(final int i, final Type type) { + argTypes[i] = type; } - - public void setInstructionList( final InstructionList il ) { // TODO could be package-protected? - this.il = il; + public void setArgumentTypes(final Type[] argTypes) { + this.argTypes = argTypes; } - - @Override - public String getSignature() { - return Type.getMethodSignature(super.getType(), argTypes); + public void setClassName(final String className) { // TODO could be package-protected? + this.className = className; } - - /** - * Computes max. stack size by performing control flow analysis. - */ - public void setMaxStack() { // TODO could be package-protected? (some tests would need repackaging) - if (il != null) { - maxStack = getMaxStack(super.getConstantPool(), il, getExceptionHandlers()); - } else { - maxStack = 0; - } + public void setInstructionList(final InstructionList il) { // TODO could be package-protected? + this.il = il; } - /** * Compute maximum number of local variables. */ @@ -932,16 +1064,14 @@ public void setMaxLocals() { // TODO could be package-protected? (some tests wou if (il != null) { int max = isStatic() ? 0 : 1; if (argTypes != null) { - for (final Type arg_type : argTypes) { - max += arg_type.getSize(); + for (final Type argType : argTypes) { + max += argType.getSize(); } } for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) { final Instruction ins = ih.getInstruction(); - if ((ins instanceof LocalVariableInstruction) || (ins instanceof RET) - || (ins instanceof IINC)) { - final int index = ((IndexedInstruction) ins).getIndex() - + ((TypedInstruction) ins).getType(super.getConstantPool()).getSize(); + if (ins instanceof LocalVariableInstruction || ins instanceof RET || ins instanceof IINC) { + final int index = ((IndexedInstruction) ins).getIndex() + ((TypedInstruction) ins).getType(super.getConstantPool()).getSize(); if (index > max) { max = index; } @@ -953,176 +1083,45 @@ public void setMaxLocals() { // TODO could be package-protected? (some tests wou } } - - /** Do not/Do produce attributes code attributesLineNumberTable and - * LocalVariableTable, like javac -O + /** + * Set maximum number of local variables. */ - public void stripAttributes( final boolean flag ) { - stripAttributes = flag; - } - - static final class BranchTarget { - - final InstructionHandle target; - final int stackDepth; - - - BranchTarget(final InstructionHandle target, final int stackDepth) { - this.target = target; - this.stackDepth = stackDepth; - } - } - - static final class BranchStack { - - private final Stack branchTargets = new Stack<>(); - private final Map visitedTargets = new HashMap<>(); - - - public void push( final InstructionHandle target, final int stackDepth ) { - if (visited(target)) { - return; - } - branchTargets.push(visit(target, stackDepth)); - } - - - public BranchTarget pop() { - if (!branchTargets.empty()) { - final BranchTarget bt = branchTargets.pop(); - return bt; - } - return null; - } - - - private BranchTarget visit( final InstructionHandle target, final int stackDepth ) { - final BranchTarget bt = new BranchTarget(target, stackDepth); - visitedTargets.put(target, bt); - return bt; - } - - - private boolean visited( final InstructionHandle target ) { - return visitedTargets.get(target) != null; - } + public void setMaxLocals(final int m) { + maxLocals = m; } - /** - * Computes stack usage of an instruction list by performing control flow analysis. - * - * @return maximum stack depth used by method + * Computes max. stack size by performing control flow analysis. */ - public static int getMaxStack( final ConstantPoolGen cp, final InstructionList il, final CodeExceptionGen[] et ) { - final BranchStack branchTargets = new BranchStack(); - /* Initially, populate the branch stack with the exception - * handlers, because these aren't (necessarily) branched to - * explicitly. in each case, the stack will have depth 1, - * containing the exception object. - */ - for (final CodeExceptionGen element : et) { - final InstructionHandle handler_pc = element.getHandlerPC(); - if (handler_pc != null) { - branchTargets.push(handler_pc, 1); - } - } - int stackDepth = 0; - int maxStackDepth = 0; - InstructionHandle ih = il.getStart(); - while (ih != null) { - final Instruction instruction = ih.getInstruction(); - final short opcode = instruction.getOpcode(); - final int delta = instruction.produceStack(cp) - instruction.consumeStack(cp); - stackDepth += delta; - if (stackDepth > maxStackDepth) { - maxStackDepth = stackDepth; - } - // choose the next instruction based on whether current is a branch. - if (instruction instanceof BranchInstruction) { - final BranchInstruction branch = (BranchInstruction) instruction; - if (instruction instanceof Select) { - // explore all of the select's targets. the default target is handled below. - final Select select = (Select) branch; - final InstructionHandle[] targets = select.getTargets(); - for (final InstructionHandle target : targets) { - branchTargets.push(target, stackDepth); - } - // nothing to fall through to. - ih = null; - } else if (!(branch instanceof IfInstruction)) { - // if an instruction that comes back to following PC, - // push next instruction, with stack depth reduced by 1. - if (opcode == Const.JSR || opcode == Const.JSR_W) { - branchTargets.push(ih.getNext(), stackDepth - 1); - } - ih = null; - } - // for all branches, the target of the branch is pushed on the branch stack. - // conditional branches have a fall through case, selects don't, and - // jsr/jsr_w return to the next instruction. - branchTargets.push(branch.getTarget(), stackDepth); - } else { - // check for instructions that terminate the method. - if (opcode == Const.ATHROW || opcode == Const.RET - || (opcode >= Const.IRETURN && opcode <= Const.RETURN)) { - ih = null; - } - } - // normal case, go to the next instruction. - if (ih != null) { - ih = ih.getNext(); - } - // if we have no more instructions, see if there are any deferred branches to explore. - if (ih == null) { - final BranchTarget bt = branchTargets.pop(); - if (bt != null) { - ih = bt.target; - stackDepth = bt.stackDepth; - } - } + public void setMaxStack() { // TODO could be package-protected? (some tests would need repackaging) + if (il != null) { + maxStack = getMaxStack(super.getConstantPool(), il, getExceptionHandlers()); + } else { + maxStack = 0; } - return maxStackDepth; } - private List observers; - - - /** Add observer for this object. + /** + * Set maximum stack size for this method. */ - public void addObserver( final MethodObserver o ) { - if (observers == null) { - observers = new ArrayList<>(); - } - observers.add(o); + public void setMaxStack(final int m) { // TODO could be package-protected? + maxStack = m; } - - /** Remove observer for this object. - */ - public void removeObserver( final MethodObserver o ) { - if (observers != null) { - observers.remove(o); - } + public void setReturnType(final Type returnType) { + setType(returnType); } - - /** Call notify() method on all observers. This method is not called - * automatically whenever the state has changed, but has to be - * called by the user after he has finished editing the object. + /** + * Do not/Do produce attributes code attributesLineNumberTable and LocalVariableTable, like javac -O */ - public void update() { - if (observers != null) { - for (final MethodObserver observer : observers) { - observer.notify(this); - } - } + public void stripAttributes(final boolean flag) { + stripAttributes = flag; } - /** - * Return string representation close to declaration format, - * `public static void main(String[]) throws IOException', e.g. + * Return string representation close to declaration format, 'public static void main(String[]) throws IOException', + * e.g. * * @return String representation of the method. */ @@ -1130,16 +1129,15 @@ public void update() { public final String toString() { final String access = Utility.accessToString(super.getAccessFlags()); String signature = Type.getMethodSignature(super.getType(), argTypes); - signature = Utility.methodSignatureToString(signature, super.getName(), access, true, - getLocalVariableTable(super.getConstantPool())); + signature = Utility.methodSignatureToString(signature, super.getName(), access, true, getLocalVariableTable(super.getConstantPool())); final StringBuilder buf = new StringBuilder(signature); for (final Attribute a : getAttributes()) { - if (!((a instanceof Code) || (a instanceof ExceptionTable))) { + if (!(a instanceof Code || a instanceof ExceptionTable)) { buf.append(" [").append(a).append("]"); } } - if (throwsList.size() > 0) { + if (!throwsList.isEmpty()) { for (final String throwsDescriptor : throwsList) { buf.append("\n\t\tthrows ").append(throwsDescriptor); } @@ -1147,162 +1145,31 @@ public final String toString() { return buf.toString(); } - - /** @return deep copy of this method - */ - public MethodGen copy( final String className, final ConstantPoolGen cp ) { - final Method m = ((MethodGen) clone()).getMethod(); - final MethodGen mg = new MethodGen(m, className, super.getConstantPool()); - if (super.getConstantPool() != cp) { - mg.setConstantPool(cp); - mg.getInstructionList().replaceConstantPool(super.getConstantPool(), cp); - } - return mg; - } - - //J5TODO: Should paramAnnotations be an array of arrays? Rather than an array of lists, this - // is more likely to suggest to the caller it is readonly (which a List does not). - /** - * Return a list of AnnotationGen objects representing parameter annotations - * @since 6.0 - */ - public List getAnnotationsOnParameter(final int i) { - ensureExistingParameterAnnotationsUnpacked(); - if (!hasParameterAnnotations || i > argTypes.length) { - return null; - } - return paramAnnotations[i]; - } - /** - * Goes through the attributes on the method and identifies any that are - * RuntimeParameterAnnotations, extracting their contents and storing them - * as parameter annotations. There are two kinds of parameter annotation - - * visible and invisible. Once they have been unpacked, these attributes are - * deleted. (The annotations will be rebuilt as attributes when someone - * builds a Method object out of this MethodGen object). + * Call notify() method on all observers. This method is not called automatically whenever the state has changed, but + * has to be called by the user after they have finished editing the object. */ - private void ensureExistingParameterAnnotationsUnpacked() - { - if (haveUnpackedParameterAnnotations) { - return; - } - // Find attributes that contain parameter annotation data - final Attribute[] attrs = getAttributes(); - ParameterAnnotations paramAnnVisAttr = null; - ParameterAnnotations paramAnnInvisAttr = null; - for (final Attribute attribute : attrs) { - if (attribute instanceof ParameterAnnotations) - { - // Initialize paramAnnotations - if (!hasParameterAnnotations) - { - @SuppressWarnings({"rawtypes", "unchecked"}) // OK - final List[] parmList = new List[argTypes.length]; - paramAnnotations = parmList; - for (int j = 0; j < argTypes.length; j++) { - paramAnnotations[j] = new ArrayList<>(); - } - } - hasParameterAnnotations = true; - final ParameterAnnotations rpa = (ParameterAnnotations) attribute; - if (rpa instanceof RuntimeVisibleParameterAnnotations) { - paramAnnVisAttr = rpa; - } else { - paramAnnInvisAttr = rpa; - } - final ParameterAnnotationEntry[] parameterAnnotationEntries = rpa.getParameterAnnotationEntries(); - for (int j = 0; j < parameterAnnotationEntries.length; j++) - { - // This returns Annotation[] ... - final ParameterAnnotationEntry immutableArray = rpa.getParameterAnnotationEntries()[j]; - // ... which needs transforming into an AnnotationGen[] ... - final List mutable = makeMutableVersion(immutableArray.getAnnotationEntries()); - // ... then add these to any we already know about - paramAnnotations[j].addAll(mutable); - } + public void update() { + if (observers != null) { + for (final MethodObserver observer : observers) { + observer.notify(this); } } - if (paramAnnVisAttr != null) { - removeAttribute(paramAnnVisAttr); - } - if (paramAnnInvisAttr != null) { - removeAttribute(paramAnnInvisAttr); - } - haveUnpackedParameterAnnotations = true; - } - - private List makeMutableVersion(final AnnotationEntry[] mutableArray) - { - final List result = new ArrayList<>(); - for (final AnnotationEntry element : mutableArray) { - result.add(new AnnotationEntryGen(element, getConstantPool(), - false)); - } - return result; } - public void addParameterAnnotation(final int parameterIndex, - final AnnotationEntryGen annotation) - { - ensureExistingParameterAnnotationsUnpacked(); - if (!hasParameterAnnotations) - { - @SuppressWarnings({"rawtypes", "unchecked"}) - final List[] parmList = new List[argTypes.length]; - paramAnnotations = parmList; - hasParameterAnnotations = true; - } - final List existingAnnotations = paramAnnotations[parameterIndex]; - if (existingAnnotations != null) - { - existingAnnotations.add(annotation); - } - else - { - final List l = new ArrayList<>(); - l.add(annotation); - paramAnnotations[parameterIndex] = l; + private void updateLocalVariableTable(final LocalVariableTable a) { + removeLocalVariables(); + for (final LocalVariable l : a.getLocalVariableTable()) { + InstructionHandle start = il.findHandle(l.getStartPC()); + final InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength()); + // Repair malformed handles + if (null == start) { + start = il.getStart(); + } + // end == null => live to end of method + // Since we are recreating the LocalVaraible, we must + // propagate the orig_index to new copy. + addLocalVariable(l.getName(), Type.getType(l.getSignature()), l.getIndex(), start, end, l.getOrigIndex()); } } - - /** - * @return Comparison strategy object - */ - public static BCELComparator getComparator() { - return bcelComparator; - } - - - /** - * @param comparator Comparison strategy object - */ - public static void setComparator( final BCELComparator comparator ) { - bcelComparator = comparator; - } - - - /** - * Return value as defined by given BCELComparator strategy. - * By default two MethodGen objects are said to be equal when - * their names and signatures are equal. - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals( final Object obj ) { - return bcelComparator.equals(this, obj); - } - - - /** - * Return value as defined by given BCELComparator strategy. - * By default return the hashcode of the method's name XOR signature. - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - return bcelComparator.hashCode(this); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodObserver.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodObserver.java index e3e6899fa74..22e773ea4b7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodObserver.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodObserver.java @@ -22,11 +22,10 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Implement this interface if you're interested in changes to a MethodGen object - * and register yourself with addObserver(). - * + * Implement this interface if you're interested in changes to a MethodGen object and register yourself with + * addObserver(). */ public interface MethodObserver { - void notify( MethodGen method ); + void notify(MethodGen method); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NEW.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NEW.java index 58b233919f1..53b938581ee 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NEW.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NEW.java @@ -25,49 +25,31 @@ /** * NEW - Create new object - *
    Stack: ... -> ..., objectref
    * + *
    + * Stack: ... -> ..., objectref
    + * 
    */ -public class NEW extends CPInstruction implements LoadClass, AllocationInstruction, - ExceptionThrower, StackProducer { +public class NEW extends CPInstruction implements LoadClass, AllocationInstruction, ExceptionThrower, StackProducer { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ NEW() { } - public NEW(final int index) { super(com.sun.org.apache.bcel.internal.Const.NEW, index); } - - @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_CLASS_AND_INTERFACE_RESOLUTION, - ExceptionConst.ILLEGAL_ACCESS_ERROR, - ExceptionConst.INSTANTIATION_ERROR); - } - - - @Override - public ObjectType getLoadClassType( final ConstantPoolGen cpg ) { - return (ObjectType) getType(cpg); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitLoadClass(this); v.visitAllocationInstruction(this); v.visitExceptionThrower(this); @@ -76,4 +58,15 @@ public void accept( final Visitor v ) { v.visitCPInstruction(this); v.visitNEW(this); } + + @Override + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_CLASS_AND_INTERFACE_RESOLUTION, ExceptionConst.ILLEGAL_ACCESS_ERROR, + ExceptionConst.INSTANTIATION_ERROR); + } + + @Override + public ObjectType getLoadClassType(final ConstantPoolGen cpg) { + return (ObjectType) getType(cpg); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NEWARRAY.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NEWARRAY.java index e12aee50ced..be2c64a0953 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NEWARRAY.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NEWARRAY.java @@ -27,56 +27,64 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence; /** - * NEWARRAY - Create new array of basic type (int, short, ...) - *
    Stack: ..., count -> ..., arrayref
    - * type must be one of T_INT, T_SHORT, ... + * NEWARRAY - Create new array of basic type (int, short, ...) + * + *
    + * Stack: ..., count -> ..., arrayref
    + * 
    * + * type must be one of T_INT, T_SHORT, ... * @LastModified: Jan 2020 */ -public class NEWARRAY extends Instruction implements AllocationInstruction, ExceptionThrower, - StackProducer { +public class NEWARRAY extends Instruction implements AllocationInstruction, ExceptionThrower, StackProducer { private byte type; - /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ NEWARRAY() { } + public NEWARRAY(final BasicType type) { + this(type.getType()); + } public NEWARRAY(final byte type) { super(com.sun.org.apache.bcel.internal.Const.NEWARRAY, (short) 2); this.type = type; } - - public NEWARRAY(final BasicType type) { - this(type.getType()); + /** + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitAllocationInstruction(this); + v.visitExceptionThrower(this); + v.visitStackProducer(this); + v.visitNEWARRAY(this); } - /** * Dump instruction as byte code to stream out. + * * @param out Output stream */ @Override - public void dump( final DataOutputStream out ) throws IOException { + public void dump(final DataOutputStream out) throws IOException { out.writeByte(super.getOpcode()); out.writeByte(type); } - - /** - * @return numeric code for basic element type - */ - public final byte getTypecode() { - return type; + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConst.NEGATIVE_ARRAY_SIZE_EXCEPTION}; } - /** * @return type of constructed array */ @@ -84,47 +92,27 @@ public final Type getType() { return new ArrayType(BasicType.getType(type), 1); } - /** - * @return mnemonic for instruction + * @return numeric code for basic element type */ - @Override - public String toString( final boolean verbose ) { - return super.toString(verbose) + " " + com.sun.org.apache.bcel.internal.Const.getTypeName(type); + public final byte getTypecode() { + return type; } - /** * Read needed data (e.g. index) from file. */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { type = bytes.readByte(); super.setLength(2); } - - @Override - public Class[] getExceptions() { - return new Class[] { - ExceptionConst.NEGATIVE_ARRAY_SIZE_EXCEPTION - }; - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. - * - * @param v Visitor object + * @return mnemonic for instruction */ @Override - public void accept( final Visitor v ) { - v.visitAllocationInstruction(this); - v.visitExceptionThrower(this); - v.visitStackProducer(this); - v.visitNEWARRAY(this); + public String toString(final boolean verbose) { + return super.toString(verbose) + " " + com.sun.org.apache.bcel.internal.Const.getTypeName(type); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NOP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NOP.java index 4408334f365..37f73953e0a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NOP.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NOP.java @@ -23,7 +23,6 @@ /** * NOP - Do nothing - * */ public class NOP extends Instruction { @@ -31,17 +30,14 @@ public NOP() { super(com.sun.org.apache.bcel.internal.Const.NOP, (short) 1); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitNOP(this); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NameSignatureInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NameSignatureInstruction.java index 58ea53cf497..3b79c821956 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NameSignatureInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NameSignatureInstruction.java @@ -27,27 +27,36 @@ import com.sun.org.apache.bcel.internal.classfile.ConstantUtf8; /** - * Super class for FieldOrMethod and INVOKEDYNAMIC, since they both have - * names and signatures + * Super class for FieldOrMethod and INVOKEDYNAMIC, since they both have names and signatures * * @since 6.0 */ public abstract class NameSignatureInstruction extends CPInstruction { public NameSignatureInstruction() { - super(); } public NameSignatureInstruction(final short opcode, final int index) { super(opcode, index); } + /** + * @return name of referenced method/field. + */ + public String getName(final ConstantPoolGen cpg) { + final ConstantPool cp = cpg.getConstantPool(); + final ConstantNameAndType cnat = getNameAndType(cpg); + return ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getBytes(); + } + public ConstantNameAndType getNameAndType(final ConstantPoolGen cpg) { final ConstantPool cp = cpg.getConstantPool(); final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); - return (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); + return (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); } - /** @return signature of referenced method/field. + + /** + * @return signature of referenced method/field. */ public String getSignature(final ConstantPoolGen cpg) { final ConstantPool cp = cpg.getConstantPool(); @@ -55,12 +64,4 @@ public String getSignature(final ConstantPoolGen cpg) { return ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getBytes(); } - /** @return name of referenced method/field. - */ - public String getName(final ConstantPoolGen cpg) { - final ConstantPool cp = cpg.getConstantPool(); - final ConstantNameAndType cnat = getNameAndType(cpg); - return ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getBytes(); - } - } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NamedAndTyped.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NamedAndTyped.java index 25d9a50a176..a46e7aa2dac 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NamedAndTyped.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/NamedAndTyped.java @@ -22,20 +22,15 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Denote entity that has both name and type. This is true for local variables, - * methods and fields. - * + * Denote entity that has both name and type. This is true for local variables, methods and fields. */ public interface NamedAndTyped { String getName(); - Type getType(); + void setName(String name); - void setName( String name ); - - - void setType( Type type ); + void setType(Type type); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java index 13cb8eaa346..46378a1b71e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java @@ -24,62 +24,78 @@ import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.Repository; import com.sun.org.apache.bcel.internal.classfile.JavaClass; +import com.sun.org.apache.bcel.internal.classfile.Utility; /** * Denotes reference such as java.lang.String. - * */ public class ObjectType extends ReferenceType { - private final String className; // Class name of type - /** + * Constructs a new instance. + * + * @param className fully qualified class name, e.g. java.lang.String + * @return a new instance. * @since 6.0 */ public static ObjectType getInstance(final String className) { return new ObjectType(className); } + private final String className; // Class name of type + /** + * Constructs a new instance. + * * @param className fully qualified class name, e.g. java.lang.String */ public ObjectType(final String className) { - super(Const.T_REFERENCE, "L" + className.replace('.', '/') + ";"); - this.className = className.replace('/', '.'); + super(Const.T_REFERENCE, "L" + Utility.packageToPath(className) + ";"); + this.className = Utility.pathToPackage(className); } - - /** @return name of referenced class + /** + * Java Virtual Machine Specification edition 2, 5.4.4 Access Control + * + * @throws ClassNotFoundException if the class referenced by this type can't be found */ - public String getClassName() { - return className; + public boolean accessibleTo(final ObjectType accessor) throws ClassNotFoundException { + final JavaClass jc = Repository.lookupClass(className); + if (jc.isPublic()) { + return true; + } + final JavaClass acc = Repository.lookupClass(accessor.className); + return acc.getPackageName().equals(jc.getPackageName()); } - - /** @return a hash code value for the object. + /** + * @return true if both type objects refer to the same class. */ @Override - public int hashCode() { - return className.hashCode(); + public boolean equals(final Object type) { + return type instanceof ObjectType && ((ObjectType) type).className.equals(className); } - - /** @return true if both type objects refer to the same class. + /** + * @return name of referenced class */ @Override - public boolean equals( final Object type ) { - return (type instanceof ObjectType) - ? ((ObjectType) type).className.equals(className) - : false; + public String getClassName() { + return className; } + /** + * @return a hash code value for the object. + */ + @Override + public int hashCode() { + return className.hashCode(); + } /** - * If "this" doesn't reference a class, it references an interface - * or a non-existant entity. - * @deprecated (since 6.0) this method returns an inaccurate result - * if the class or interface referenced cannot - * be found: use referencesClassExact() instead + * If "this" doesn't reference a class, it references an interface or a non-existant entity. + * @deprecated (since 6.0) this method returns an inaccurate result if the class or interface referenced cannot be + * found: use referencesClassExact() instead */ @Deprecated public boolean referencesClass() { @@ -91,13 +107,22 @@ public boolean referencesClass() { } } + /** + * Return true if this type references a class, false if it references an interface. + * + * @return true if the type references a class, false if it references an interface + * @throws ClassNotFoundException if the class or interface referenced by this type can't be found + */ + public boolean referencesClassExact() throws ClassNotFoundException { + final JavaClass jc = Repository.lookupClass(className); + return jc.isClass(); + } /** - * If "this" doesn't reference an interface, it references a class - * or a non-existant entity. - * @deprecated (since 6.0) this method returns an inaccurate result - * if the class or interface referenced cannot - * be found: use referencesInterfaceExact() instead + * If "this" doesn't reference an interface, it references a class or a non-existant entity. + * + * @deprecated (since 6.0) this method returns an inaccurate result if the class or interface referenced cannot be + * found: use referencesInterfaceExact() instead */ @Deprecated public boolean referencesInterface() { @@ -109,59 +134,26 @@ public boolean referencesInterface() { } } - /** - * Return true if this type references a class, - * false if it references an interface. - * @return true if the type references a class, false if - * it references an interface - * @throws ClassNotFoundException if the class or interface - * referenced by this type can't be found - */ - public boolean referencesClassExact() throws ClassNotFoundException { - final JavaClass jc = Repository.lookupClass(className); - return jc.isClass(); - } - - - /** - * Return true if this type references an interface, - * false if it references a class. - * @return true if the type references an interface, false if - * it references a class - * @throws ClassNotFoundException if the class or interface - * referenced by this type can't be found + * Return true if this type references an interface, false if it references a class. + * + * @return true if the type references an interface, false if it references a class + * @throws ClassNotFoundException if the class or interface referenced by this type can't be found */ public boolean referencesInterfaceExact() throws ClassNotFoundException { final JavaClass jc = Repository.lookupClass(className); return !jc.isClass(); } - /** * Return true if this type is a subclass of given ObjectType. - * @throws ClassNotFoundException if any of this class's superclasses - * can't be found + * + * @throws ClassNotFoundException if any of this class's superclasses can't be found */ - public boolean subclassOf( final ObjectType superclass ) throws ClassNotFoundException { + public boolean subclassOf(final ObjectType superclass) throws ClassNotFoundException { if (this.referencesInterfaceExact() || superclass.referencesInterfaceExact()) { return false; } return Repository.instanceOf(this.className, superclass.className); } - - - /** - * Java Virtual Machine Specification edition 2, 5.4.4 Access Control - * @throws ClassNotFoundException if the class referenced by this type - * can't be found - */ - public boolean accessibleTo( final ObjectType accessor ) throws ClassNotFoundException { - final JavaClass jc = Repository.lookupClass(className); - if (jc.isPublic()) { - return true; - } - final JavaClass acc = Repository.lookupClass(accessor.className); - return acc.getPackageName().equals(jc.getPackageName()); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/POP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/POP.java index 9683a24cebf..e826dd78ce3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/POP.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/POP.java @@ -24,8 +24,9 @@ /** * POP - Pop top operand stack word * - *
    Stack: ..., word -> ...
    - * + *
    + * Stack: ..., word -> ...
    + * 
    */ public class POP extends StackInstruction implements PopInstruction { @@ -33,17 +34,14 @@ public POP() { super(com.sun.org.apache.bcel.internal.Const.POP); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitPopInstruction(this); v.visitStackInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/POP2.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/POP2.java index 0f52de75fc1..5124f4177fc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/POP2.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/POP2.java @@ -24,8 +24,9 @@ /** * POP2 - Pop two top operand stack words * - *
    Stack: ..., word2, word1 -> ...
    - * + *
    + * Stack: ..., word2, word1 -> ...
    + * 
    */ public class POP2 extends StackInstruction implements PopInstruction { @@ -33,17 +34,14 @@ public POP2() { super(com.sun.org.apache.bcel.internal.Const.POP2); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitPopInstruction(this); v.visitStackInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PUSH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PUSH.java index 532575bc519..cac2027586f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PUSH.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PUSH.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,79 +20,61 @@ package com.sun.org.apache.bcel.internal.generic; +import java.util.Objects; + import com.sun.org.apache.bcel.internal.Const; /** - * Wrapper class for push operations, which are implemented either as BIPUSH, - * LDC or xCONST_n instructions. - * - * @LastModified: Jan 2020 + * Wrapper class for push operations, which are implemented either as BIPUSH, LDC or xCONST_n instructions. + * @LastModified: Feb 2023 */ public final class PUSH implements CompoundInstruction, VariableLengthInstruction { - private Instruction instruction; - + private final Instruction instruction; /** - * This constructor also applies for values of type short, char, byte + * Pushes an array type constant, for example {@code int[].class}, {@code String[].class}, and so on. * - * @param cp Constant pool - * @param value to be pushed + * @param cp generated constant pool. + * @param value to be pushed. + * @since 6.7.0 */ - public PUSH(final ConstantPoolGen cp, final int value) { - if ((value >= -1) && (value <= 5)) { - instruction = InstructionConst.getInstruction(Const.ICONST_0 + value); - } else if (Instruction.isValidByte(value)) { - instruction = new BIPUSH((byte) value); - } else if (Instruction.isValidShort(value)) { - instruction = new SIPUSH((short) value); + public PUSH(final ConstantPoolGen cp, final ArrayType value) { + if (value == null) { + instruction = InstructionConst.ACONST_NULL; } else { - instruction = new LDC(cp.addInteger(value)); + instruction = new LDC(cp.addArrayClass(value)); } } - - /** + /** * @param cp Constant pool * @param value to be pushed */ public PUSH(final ConstantPoolGen cp, final boolean value) { + Objects.requireNonNull(cp, "cp"); instruction = InstructionConst.getInstruction(Const.ICONST_0 + (value ? 1 : 0)); } - /** * @param cp Constant pool * @param value to be pushed */ - public PUSH(final ConstantPoolGen cp, final float value) { - if (value == 0.0) { - instruction = InstructionConst.FCONST_0; - } else if (value == 1.0) { - instruction = InstructionConst.FCONST_1; - } else if (value == 2.0) { - instruction = InstructionConst.FCONST_2; - } else { - instruction = new LDC(cp.addFloat(value)); - } + public PUSH(final ConstantPoolGen cp, final Boolean value) { + this(cp, value.booleanValue()); } - /** + * creates a push object from a Character value. Warning: Make sure not to attempt to allow autoboxing to create this + * value parameter, as an alternative constructor will be called + * * @param cp Constant pool * @param value to be pushed */ - public PUSH(final ConstantPoolGen cp, final long value) { - if (value == 0) { - instruction = InstructionConst.LCONST_0; - } else if (value == 1) { - instruction = InstructionConst.LCONST_1; - } else { - instruction = new LDC2_W(cp.addLong(value)); - } + public PUSH(final ConstantPoolGen cp, final Character value) { + this(cp, value.charValue()); } - /** * @param cp Constant pool * @param value to be pushed @@ -107,30 +89,51 @@ public PUSH(final ConstantPoolGen cp, final double value) { } } - /** * @param cp Constant pool * @param value to be pushed */ - public PUSH(final ConstantPoolGen cp, final String value) { - if (value == null) { - instruction = InstructionConst.ACONST_NULL; + public PUSH(final ConstantPoolGen cp, final float value) { + if (value == 0.0) { + instruction = InstructionConst.FCONST_0; + } else if (value == 1.0) { + instruction = InstructionConst.FCONST_1; + } else if (value == 2.0) { + instruction = InstructionConst.FCONST_2; } else { - instruction = new LDC(cp.addString(value)); + instruction = new LDC(cp.addFloat(value)); } } /** + * This constructor also applies for values of type short, char, byte * - * @param cp - * @param value - * @since 6.0 + * @param cp Constant pool + * @param value to be pushed */ - public PUSH(final ConstantPoolGen cp, final ObjectType value) { - if (value == null) { - instruction = InstructionConst.ACONST_NULL; + public PUSH(final ConstantPoolGen cp, final int value) { + if (value >= -1 && value <= 5) { + instruction = InstructionConst.getInstruction(Const.ICONST_0 + value); + } else if (Instruction.isValidByte(value)) { + instruction = new BIPUSH((byte) value); + } else if (Instruction.isValidShort(value)) { + instruction = new SIPUSH((short) value); } else { - instruction = new LDC(cp.addClass(value)); + instruction = new LDC(cp.addInteger(value)); + } + } + + /** + * @param cp Constant pool + * @param value to be pushed + */ + public PUSH(final ConstantPoolGen cp, final long value) { + if (value == 0) { + instruction = InstructionConst.LCONST_0; + } else if (value == 1) { + instruction = InstructionConst.LCONST_1; + } else { + instruction = new LDC2_W(cp.addLong(value)); } } @@ -139,7 +142,7 @@ public PUSH(final ConstantPoolGen cp, final ObjectType value) { * @param value to be pushed */ public PUSH(final ConstantPoolGen cp, final Number value) { - if ((value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) { + if (value instanceof Integer || value instanceof Short || value instanceof Byte) { instruction = new PUSH(cp, value.intValue()).instruction; } else if (value instanceof Double) { instruction = new PUSH(cp, value.doubleValue()).instruction; @@ -152,39 +155,41 @@ public PUSH(final ConstantPoolGen cp, final Number value) { } } - /** - * creates a push object from a Character value. Warning: Make sure not to attempt to allow - * autoboxing to create this value parameter, as an alternative constructor will be called * - * @param cp Constant pool - * @param value to be pushed + * @param cp + * @param value + * @since 6.0 */ - public PUSH(final ConstantPoolGen cp, final Character value) { - this(cp, value.charValue()); + public PUSH(final ConstantPoolGen cp, final ObjectType value) { + if (value == null) { + instruction = InstructionConst.ACONST_NULL; + } else { + instruction = new LDC(cp.addClass(value)); + } } - /** * @param cp Constant pool * @param value to be pushed */ - public PUSH(final ConstantPoolGen cp, final Boolean value) { - this(cp, value.booleanValue()); + public PUSH(final ConstantPoolGen cp, final String value) { + if (value == null) { + instruction = InstructionConst.ACONST_NULL; + } else { + instruction = new LDC(cp.addString(value)); + } } + public Instruction getInstruction() { + return instruction; + } @Override public InstructionList getInstructionList() { return new InstructionList(instruction); } - - public Instruction getInstruction() { - return instruction; - } - - /** * @return mnemonic for instruction */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PUTFIELD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PUTFIELD.java index 10979bd2374..185a014774b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PUTFIELD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PUTFIELD.java @@ -26,50 +26,37 @@ /** * PUTFIELD - Put field in object - *
    Stack: ..., objectref, value -> ...
    + * + *
    + * Stack: ..., objectref, value -> ...
    + * 
    + * * OR - *
    Stack: ..., objectref, value.word1, value.word2 -> ...
    * + *
    + * Stack: ..., objectref, value.word1, value.word2 -> ...
    + * 
    */ public class PUTFIELD extends FieldInstruction implements PopInstruction, ExceptionThrower { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ PUTFIELD() { } - public PUTFIELD(final int index) { super(Const.PUTFIELD, index); } - - @Override - public int consumeStack( final ConstantPoolGen cpg ) { - return getFieldSize(cpg) + 1; - } - - - @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, - ExceptionConst.NULL_POINTER_EXCEPTION, - ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitStackConsumer(this); v.visitPopInstruction(this); @@ -80,4 +67,15 @@ public void accept( final Visitor v ) { v.visitFieldInstruction(this); v.visitPUTFIELD(this); } + + @Override + public int consumeStack(final ConstantPoolGen cpg) { + return getFieldSize(cpg) + 1; + } + + @Override + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, ExceptionConst.NULL_POINTER_EXCEPTION, + ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PUTSTATIC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PUTSTATIC.java index 0a482566844..f74ec347e9d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PUTSTATIC.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PUTSTATIC.java @@ -26,49 +26,37 @@ /** * PUTSTATIC - Put static field in class - *
    Stack: ..., value -> ...
    + * + *
    + * Stack: ..., value -> ...
    + * 
    + * * OR - *
    Stack: ..., value.word1, value.word2 -> ...
    * + *
    + * Stack: ..., value.word1, value.word2 -> ...
    + * 
    */ public class PUTSTATIC extends FieldInstruction implements ExceptionThrower, PopInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ PUTSTATIC() { } - public PUTSTATIC(final int index) { super(Const.PUTSTATIC, index); } - - @Override - public int consumeStack( final ConstantPoolGen cpg ) { - return getFieldSize(cpg); - } - - - @Override - public Class[] getExceptions() { - return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, - ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); - } - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitStackConsumer(this); v.visitPopInstruction(this); @@ -79,4 +67,14 @@ public void accept( final Visitor v ) { v.visitFieldInstruction(this); v.visitPUTSTATIC(this); } + + @Override + public int consumeStack(final ConstantPoolGen cpg) { + return getFieldSize(cpg); + } + + @Override + public Class[] getExceptions() { + return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PopInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PopInstruction.java index e9ac138377f..206299930e3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PopInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PopInstruction.java @@ -22,8 +22,7 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Denotes an unparameterized instruction to pop a value on top from the stack, - * such as ISTORE, POP, PUTSTATIC. + * Denotes an unparameterized instruction to pop a value on top from the stack, such as ISTORE, POP, PUTSTATIC. * * @see ISTORE * @see POP diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PushInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PushInstruction.java index 6359f85ef6b..e792b38a83f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PushInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/PushInstruction.java @@ -22,10 +22,10 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Denotes an unparameterized instruction to produce a value on top of the stack, - * such as ILOAD, LDC, SIPUSH, DUP, ICONST, etc. + * Denotes an unparameterized instruction to produce a value on top of the stack, such as ILOAD, LDC, SIPUSH, DUP, + * ICONST, etc. + * * - * @see ILOAD * @see ICONST * @see LDC diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java index e6d2c99fbd4..a7cacc7c165 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java @@ -29,35 +29,44 @@ /** * RET - Return from subroutine * - *
    Stack: ... -> ...
    - * + *
    + * Stack: ... -> ...
    + * 
    */ public class RET extends Instruction implements IndexedInstruction, TypedInstruction { private boolean wide; private int index; // index to local variable containg the return address - /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ RET() { } - public RET(final int index) { super(com.sun.org.apache.bcel.internal.Const.RET, (short) 2); setIndex(index); // May set wide as side effect } + /** + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitRET(this); + } /** * Dump instruction as byte code to stream out. + * * @param out Output stream */ @Override - public void dump( final DataOutputStream out ) throws IOException { + public void dump(final DataOutputStream out) throws IOException { if (wide) { out.writeByte(com.sun.org.apache.bcel.internal.Const.WIDE); } @@ -69,22 +78,27 @@ public void dump( final DataOutputStream out ) throws IOException { } } - - private void setWide() { - wide = index > com.sun.org.apache.bcel.internal.Const.MAX_BYTE; - if (wide) { - super.setLength(4); // Including the wide byte - } else { - super.setLength(2); - } + /** + * @return index of local variable containg the return address + */ + @Override + public final int getIndex() { + return index; } + /** + * @return return address type + */ + @Override + public Type getType(final ConstantPoolGen cp) { + return ReturnaddressType.NO_TARGET; + } /** * Read needed data (e.g. index) from file. */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { this.wide = wide; if (wide) { index = bytes.readUnsignedShort(); @@ -95,21 +109,11 @@ protected void initFromFile( final ByteSequence bytes, final boolean wide ) thro } } - - /** - * @return index of local variable containg the return address - */ - @Override - public final int getIndex() { - return index; - } - - /** * Set index of local variable containg the return address */ @Override - public final void setIndex( final int n ) { + public final void setIndex(final int n) { if (n < 0) { throw new ClassGenException("Negative index value: " + n); } @@ -117,34 +121,20 @@ public final void setIndex( final int n ) { setWide(); } + private void setWide() { + wide = index > com.sun.org.apache.bcel.internal.Const.MAX_BYTE; + if (wide) { + super.setLength(4); // Including the wide byte + } else { + super.setLength(2); + } + } /** * @return mnemonic for instruction */ @Override - public String toString( final boolean verbose ) { + public String toString(final boolean verbose) { return super.toString(verbose) + " " + index; } - - - /** @return return address type - */ - @Override - public Type getType( final ConstantPoolGen cp ) { - return ReturnaddressType.NO_TARGET; - } - - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. - * - * @param v Visitor object - */ - @Override - public void accept( final Visitor v ) { - v.visitRET(this); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RETURN.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RETURN.java index 271d2c91e2c..0e6b594fafa 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RETURN.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RETURN.java @@ -22,9 +22,11 @@ package com.sun.org.apache.bcel.internal.generic; /** - * RETURN - Return from void method - *
    Stack: ... -> <empty>
    + * RETURN - Return from void method * + *
    + * Stack: ... -> <empty>
    + * 
    */ public class RETURN extends ReturnInstruction { @@ -32,17 +34,14 @@ public RETURN() { super(com.sun.org.apache.bcel.internal.Const.RETURN); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitExceptionThrower(this); v.visitTypedInstruction(this); v.visitStackConsumer(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java index ebe3db5cfbf..fe75792e213 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java @@ -26,133 +26,204 @@ /** * Super class for object and array types. - * */ public abstract class ReferenceType extends Type { + /** + * Class is non-abstract but not instantiable from the outside + */ + ReferenceType() { + super(Const.T_OBJECT, ""); + } + protected ReferenceType(final byte t, final String s) { super(t, s); } - - /** Class is non-abstract but not instantiable from the outside + /** + * This commutative operation returns the first common superclass (narrowest ReferenceType referencing a class, not an + * interface). If one of the types is a superclass of the other, the former is returned. If "this" is Type.NULL, then t + * is returned. If t is Type.NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If + * "this" or t is an ArrayType, then Type.OBJECT is returned. If "this" or t is a ReferenceType referencing an + * interface, then Type.OBJECT is returned. If not all of the two classes' superclasses cannot be found, "null" is + * returned. See the JVM specification edition 2, "4.9.2 The Bytecode Verifier". + * + * @deprecated use getFirstCommonSuperclass(ReferenceType t) which has slightly changed semantics. + * @throws ClassNotFoundException on failure to find superclasses of this type, or the type passed as a parameter */ - ReferenceType() { - super(Const.T_OBJECT, ""); + @Deprecated + public ReferenceType firstCommonSuperclass(final ReferenceType t) throws ClassNotFoundException { + if (this.equals(Type.NULL)) { + return t; + } + if (t.equals(Type.NULL) || this.equals(t)) { + return this; + /* + * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by Type.NULL so we can also + * say all the objects referenced by Type.NULL were derived from java.lang.Object. However, the Java Language's + * "instanceof" operator proves us wrong: "null" is not referring to an instance of java.lang.Object :) + */ + } + if (this instanceof ArrayType || t instanceof ArrayType) { + return Type.OBJECT; + // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType? + } + return getFirstCommonSuperclassInternal(t); } - /** - * Return true iff this type is castable to another type t as defined in - * the JVM specification. The case where this is Type.NULL is not - * defined (see the CHECKCAST definition in the JVM specification). - * However, because e.g. CHECKCAST doesn't throw a - * ClassCastException when casting a null reference to any Object, - * true is returned in this case. + * This commutative operation returns the first common superclass (narrowest ReferenceType referencing a class, not an + * interface). If one of the types is a superclass of the other, the former is returned. If "this" is Type.NULL, then t + * is returned. If t is Type.NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If + * "this" or t is an ArrayType, then Type.OBJECT is returned; unless their dimensions match. Then an ArrayType of the + * same number of dimensions is returned, with its basic type being the first common super class of the basic types of + * "this" and t. If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned. If not all of + * the two classes' superclasses cannot be found, "null" is returned. See the JVM specification edition 2, "4.9.2 The + * Bytecode Verifier". * - * @throws ClassNotFoundException if any classes or interfaces required - * to determine assignment compatibility can't be found + * @throws ClassNotFoundException on failure to find superclasses of this type, or the type passed as a parameter */ - public boolean isCastableTo( final Type t ) throws ClassNotFoundException { + public ReferenceType getFirstCommonSuperclass(final ReferenceType t) throws ClassNotFoundException { if (this.equals(Type.NULL)) { - return t instanceof ReferenceType; // If this is ever changed in isAssignmentCompatible() + return t; } - return isAssignmentCompatibleWith(t); - /* Yes, it's true: It's the same definition. - * See vmspec2 AASTORE / CHECKCAST definitions. - */ + if (t.equals(Type.NULL) || this.equals(t)) { + return this; + /* + * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by Type.NULL so we can also + * say all the objects referenced by Type.NULL were derived from java.lang.Object. However, the Java Language's + * "instanceof" operator proves us wrong: "null" is not referring to an instance of java.lang.Object :) + */ + } + /* This code is from a bug report by Konstantin Shagin */ + if (this instanceof ArrayType && t instanceof ArrayType) { + final ArrayType arrType1 = (ArrayType) this; + final ArrayType arrType2 = (ArrayType) t; + if (arrType1.getDimensions() == arrType2.getDimensions() && arrType1.getBasicType() instanceof ObjectType + && arrType2.getBasicType() instanceof ObjectType) { + return new ArrayType(((ObjectType) arrType1.getBasicType()).getFirstCommonSuperclass((ObjectType) arrType2.getBasicType()), + arrType1.getDimensions()); + } + } + if (this instanceof ArrayType || t instanceof ArrayType) { + return Type.OBJECT; + // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType? + } + return getFirstCommonSuperclassInternal(t); } + private ReferenceType getFirstCommonSuperclassInternal(final ReferenceType t) throws ClassNotFoundException { + if (this instanceof ObjectType && ((ObjectType) this).referencesInterfaceExact() + || t instanceof ObjectType && ((ObjectType) t).referencesInterfaceExact()) { + return Type.OBJECT; + // TODO: The above line is correct comparing to the vmspec2. But one could + // make class file verification a bit stronger here by using the notion of + // superinterfaces or even castability or assignment compatibility. + } + // this and t are ObjectTypes, see above. + final ObjectType thiz = (ObjectType) this; + final ObjectType other = (ObjectType) t; + final JavaClass[] thizSups = Repository.getSuperClasses(thiz.getClassName()); + final JavaClass[] otherSups = Repository.getSuperClasses(other.getClassName()); + if (thizSups == null || otherSups == null) { + return null; + } + // Waaahh... + final JavaClass[] thisSups = new JavaClass[thizSups.length + 1]; + final JavaClass[] tSups = new JavaClass[otherSups.length + 1]; + System.arraycopy(thizSups, 0, thisSups, 1, thizSups.length); + System.arraycopy(otherSups, 0, tSups, 1, otherSups.length); + thisSups[0] = Repository.lookupClass(thiz.getClassName()); + tSups[0] = Repository.lookupClass(other.getClassName()); + for (final JavaClass tSup : tSups) { + for (final JavaClass thisSup : thisSups) { + if (thisSup.equals(tSup)) { + return ObjectType.getInstance(thisSup.getClassName()); + } + } + } + // Huh? Did you ask for Type.OBJECT's superclass?? + return null; + } /** - * Return true iff this is assignment compatible with another type t - * as defined in the JVM specification; see the AASTORE definition - * there. - * @throws ClassNotFoundException if any classes or interfaces required - * to determine assignment compatibility can't be found + * Return true iff this is assignment compatible with another type t as defined in the JVM specification; see the + * AASTORE definition there. + * + * @throws ClassNotFoundException if any classes or interfaces required to determine assignment compatibility can't be + * found */ - public boolean isAssignmentCompatibleWith( final Type t ) throws ClassNotFoundException { + public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundException { if (!(t instanceof ReferenceType)) { return false; } final ReferenceType T = (ReferenceType) t; if (this.equals(Type.NULL)) { - return true; // This is not explicitely stated, but clear. Isn't it? + return true; // This is not explicitly stated, but clear. Isn't it? } - /* If this is a class type then + /* + * If this is a class type then */ - if ((this instanceof ObjectType) && (((ObjectType) this).referencesClassExact())) { - /* If T is a class type, then this must be the same class as T, - or this must be a subclass of T; + if (this instanceof ObjectType && ((ObjectType) this).referencesClassExact()) { + /* + * If T is a class type, then this must be the same class as T, or this must be a subclass of T; */ - if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) { - if (this.equals(T)) { - return true; - } - if (Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T) - .getClassName())) { - return true; - } + if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() + && (this.equals(T) || Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) { + return true; } - /* If T is an interface type, this must implement interface T. + /* + * If T is an interface type, this must implement interface T. */ - if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) { - if (Repository.implementationOf(((ObjectType) this).getClassName(), - ((ObjectType) T).getClassName())) { - return true; - } + if (T instanceof ObjectType && ((ObjectType) T).referencesInterfaceExact() + && Repository.implementationOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName())) { + return true; } } - /* If this is an interface type, then: + /* + * If this is an interface type, then: */ - if ((this instanceof ObjectType) && (((ObjectType) this).referencesInterfaceExact())) { - /* If T is a class type, then T must be Object (2.4.7). + if (this instanceof ObjectType && ((ObjectType) this).referencesInterfaceExact()) { + /* + * If T is a class type, then T must be Object (2.4.7). */ - if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) { - if (T.equals(Type.OBJECT)) { - return true; - } + if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(Type.OBJECT)) { + return true; } - /* If T is an interface type, then T must be the same interface - * as this or a superinterface of this (2.13.2). + /* + * If T is an interface type, then T must be the same interface as this or a superinterface of this (2.13.2). */ - if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) { - if (this.equals(T)) { - return true; - } - if (Repository.implementationOf(((ObjectType) this).getClassName(), - ((ObjectType) T).getClassName())) { - return true; - } + if (T instanceof ObjectType && ((ObjectType) T).referencesInterfaceExact() + && (this.equals(T) || Repository.implementationOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) { + return true; } } - /* If this is an array type, namely, the type SC[], that is, an - * array of components of type SC, then: + /* + * If this is an array type, namely, the type SC[], that is, an array of components of type SC, then: */ if (this instanceof ArrayType) { - /* If T is a class type, then T must be Object (2.4.7). + /* + * If T is a class type, then T must be Object (2.4.7). */ - if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) { - if (T.equals(Type.OBJECT)) { - return true; - } + if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(Type.OBJECT)) { + return true; } - /* If T is an array type TC[], that is, an array of components - * of type TC, then one of the following must be true: + /* + * If T is an array type TC[], that is, an array of components of type TC, then one of the following must be true: */ if (T instanceof ArrayType) { - /* TC and SC are the same primitive type (2.4.1). + /* + * TC and SC are the same primitive type (2.4.1). */ final Type sc = ((ArrayType) this).getElementType(); final Type tc = ((ArrayType) T).getElementType(); if (sc instanceof BasicType && tc instanceof BasicType && sc.equals(tc)) { return true; } - /* TC and SC are reference types (2.4.6), and type SC is - * assignable to TC by these runtime rules. + /* + * TC and SC are reference types (2.4.6), and type SC is assignable to TC by these runtime rules. */ - if (tc instanceof ReferenceType && sc instanceof ReferenceType - && ((ReferenceType) sc).isAssignmentCompatibleWith(tc)) { + if (tc instanceof ReferenceType && sc instanceof ReferenceType && ((ReferenceType) sc).isAssignmentCompatibleWith(tc)) { return true; } } @@ -162,7 +233,7 @@ public boolean isAssignmentCompatibleWith( final Type t ) throws ClassNotFoundEx // are at least two different pages where assignment compatibility is defined and // on one of them "interfaces implemented by arrays" is exchanged with "'Cloneable' or // 'java.io.Serializable'" - if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) { + if (T instanceof ObjectType && ((ObjectType) T).referencesInterfaceExact()) { for (final String element : Const.getInterfacesImplementedByArrays()) { if (T.equals(ObjectType.getInstance(element))) { return true; @@ -173,160 +244,21 @@ public boolean isAssignmentCompatibleWith( final Type t ) throws ClassNotFoundEx return false; // default. } - /** - * This commutative operation returns the first common superclass (narrowest ReferenceType - * referencing a class, not an interface). - * If one of the types is a superclass of the other, the former is returned. - * If "this" is Type.NULL, then t is returned. - * If t is Type.NULL, then "this" is returned. - * If "this" equals t ['this.equals(t)'] "this" is returned. - * If "this" or t is an ArrayType, then Type.OBJECT is returned; - * unless their dimensions match. Then an ArrayType of the same - * number of dimensions is returned, with its basic type being the - * first common super class of the basic types of "this" and t. - * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned. - * If not all of the two classes' superclasses cannot be found, "null" is returned. - * See the JVM specification edition 2, "4.9.2 The Bytecode Verifier". + * Return true iff this type is castable to another type t as defined in the JVM specification. The case where this is + * Type.NULL is not defined (see the CHECKCAST definition in the JVM specification). However, because e.g. CHECKCAST + * doesn't throw a ClassCastException when casting a null reference to any Object, true is returned in this case. * - * @throws ClassNotFoundException on failure to find superclasses of this - * type, or the type passed as a parameter + * @throws ClassNotFoundException if any classes or interfaces required to determine assignment compatibility can't be + * found */ - public ReferenceType getFirstCommonSuperclass( final ReferenceType t ) throws ClassNotFoundException { + public boolean isCastableTo(final Type t) throws ClassNotFoundException { if (this.equals(Type.NULL)) { - return t; - } - if (t.equals(Type.NULL)) { - return this; - } - if (this.equals(t)) { - return this; - /* - * TODO: Above sounds a little arbitrary. On the other hand, there is - * no object referenced by Type.NULL so we can also say all the objects - * referenced by Type.NULL were derived from java.lang.Object. - * However, the Java Language's "instanceof" operator proves us wrong: - * "null" is not referring to an instance of java.lang.Object :) - */ - } - /* This code is from a bug report by Konstantin Shagin */ - if ((this instanceof ArrayType) && (t instanceof ArrayType)) { - final ArrayType arrType1 = (ArrayType) this; - final ArrayType arrType2 = (ArrayType) t; - if ((arrType1.getDimensions() == arrType2.getDimensions()) - && arrType1.getBasicType() instanceof ObjectType - && arrType2.getBasicType() instanceof ObjectType) { - return new ArrayType(((ObjectType) arrType1.getBasicType()) - .getFirstCommonSuperclass((ObjectType) arrType2.getBasicType()), arrType1 - .getDimensions()); - } - } - if ((this instanceof ArrayType) || (t instanceof ArrayType)) { - return Type.OBJECT; - // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType? - } - if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterfaceExact()) - || ((t instanceof ObjectType) && ((ObjectType) t).referencesInterfaceExact())) { - return Type.OBJECT; - // TODO: The above line is correct comparing to the vmspec2. But one could - // make class file verification a bit stronger here by using the notion of - // superinterfaces or even castability or assignment compatibility. - } - // this and t are ObjectTypes, see above. - final ObjectType thiz = (ObjectType) this; - final ObjectType other = (ObjectType) t; - final JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName()); - final JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName()); - if ((thiz_sups == null) || (other_sups == null)) { - return null; - } - // Waaahh... - final JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1]; - final JavaClass[] t_sups = new JavaClass[other_sups.length + 1]; - System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length); - System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length); - this_sups[0] = Repository.lookupClass(thiz.getClassName()); - t_sups[0] = Repository.lookupClass(other.getClassName()); - for (final JavaClass t_sup : t_sups) { - for (final JavaClass this_sup : this_sups) { - if (this_sup.equals(t_sup)) { - return ObjectType.getInstance(this_sup.getClassName()); - } - } - } - // Huh? Did you ask for Type.OBJECT's superclass?? - return null; - } - - /** - * This commutative operation returns the first common superclass (narrowest ReferenceType - * referencing a class, not an interface). - * If one of the types is a superclass of the other, the former is returned. - * If "this" is Type.NULL, then t is returned. - * If t is Type.NULL, then "this" is returned. - * If "this" equals t ['this.equals(t)'] "this" is returned. - * If "this" or t is an ArrayType, then Type.OBJECT is returned. - * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned. - * If not all of the two classes' superclasses cannot be found, "null" is returned. - * See the JVM specification edition 2, "4.9.2 The Bytecode Verifier". - * - * @deprecated use getFirstCommonSuperclass(ReferenceType t) which has - * slightly changed semantics. - * @throws ClassNotFoundException on failure to find superclasses of this - * type, or the type passed as a parameter - */ - @Deprecated - public ReferenceType firstCommonSuperclass( final ReferenceType t ) throws ClassNotFoundException { - if (this.equals(Type.NULL)) { - return t; - } - if (t.equals(Type.NULL)) { - return this; - } - if (this.equals(t)) { - return this; - /* - * TODO: Above sounds a little arbitrary. On the other hand, there is - * no object referenced by Type.NULL so we can also say all the objects - * referenced by Type.NULL were derived from java.lang.Object. - * However, the Java Language's "instanceof" operator proves us wrong: - * "null" is not referring to an instance of java.lang.Object :) - */ - } - if ((this instanceof ArrayType) || (t instanceof ArrayType)) { - return Type.OBJECT; - // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType? - } - if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterface()) - || ((t instanceof ObjectType) && ((ObjectType) t).referencesInterface())) { - return Type.OBJECT; - // TODO: The above line is correct comparing to the vmspec2. But one could - // make class file verification a bit stronger here by using the notion of - // superinterfaces or even castability or assignment compatibility. - } - // this and t are ObjectTypes, see above. - final ObjectType thiz = (ObjectType) this; - final ObjectType other = (ObjectType) t; - final JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName()); - final JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName()); - if ((thiz_sups == null) || (other_sups == null)) { - return null; - } - // Waaahh... - final JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1]; - final JavaClass[] t_sups = new JavaClass[other_sups.length + 1]; - System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length); - System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length); - this_sups[0] = Repository.lookupClass(thiz.getClassName()); - t_sups[0] = Repository.lookupClass(other.getClassName()); - for (final JavaClass t_sup : t_sups) { - for (final JavaClass this_sup : this_sups) { - if (this_sup.equals(t_sup)) { - return ObjectType.getInstance(this_sup.getClassName()); - } - } + return t instanceof ReferenceType; // If this is ever changed in isAssignmentCompatible() } - // Huh? Did you ask for Type.OBJECT's superclass?? - return null; + return isAssignmentCompatibleWith(t); + /* + * Yes, it's true: It's the same definition. See vmspec2 AASTORE / CHECKCAST definitions. + */ } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReturnInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReturnInstruction.java index 90a0fcbc72d..0e132f431c4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReturnInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReturnInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -26,19 +26,16 @@ /** * Super class for the xRETURN family of instructions. * - * @LastModified: Jan 2020 + * @LastModified: Feb 2023 */ -public abstract class ReturnInstruction extends Instruction implements ExceptionThrower, - TypedInstruction, StackConsumer { +public abstract class ReturnInstruction extends Instruction implements ExceptionThrower, TypedInstruction, StackConsumer { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ ReturnInstruction() { } - /** * @param opcode of instruction */ @@ -46,40 +43,36 @@ protected ReturnInstruction(final short opcode) { super(opcode, (short) 1); } - - public Type getType() { - final short _opcode = super.getOpcode(); - switch (_opcode) { - case Const.IRETURN: - return Type.INT; - case Const.LRETURN: - return Type.LONG; - case Const.FRETURN: - return Type.FLOAT; - case Const.DRETURN: - return Type.DOUBLE; - case Const.ARETURN: - return Type.OBJECT; - case Const.RETURN: - return Type.VOID; - default: // Never reached - throw new ClassGenException("Unknown type " + _opcode); - } - } - - @Override public Class[] getExceptions() { - return new Class[] { - ExceptionConst.ILLEGAL_MONITOR_STATE - }; + return new Class[] {ExceptionConst.ILLEGAL_MONITOR_STATE}; } + public Type getType() { + final short opcode = super.getOpcode(); + switch (opcode) { + case Const.IRETURN: + return Type.INT; + case Const.LRETURN: + return Type.LONG; + case Const.FRETURN: + return Type.FLOAT; + case Const.DRETURN: + return Type.DOUBLE; + case Const.ARETURN: + return Type.OBJECT; + case Const.RETURN: + return Type.VOID; + default: // Never reached + throw new ClassGenException("Unknown type " + opcode); + } + } - /** @return type associated with the instruction + /** + * @return type associated with the instruction */ @Override - public Type getType( final ConstantPoolGen cp ) { + public Type getType(final ConstantPoolGen cp) { return getType(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReturnaddressType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReturnaddressType.java index 63ba12a15b7..a35e83d26fd 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReturnaddressType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReturnaddressType.java @@ -33,7 +33,6 @@ public class ReturnaddressType extends Type { public static final ReturnaddressType NO_TARGET = new ReturnaddressType(); private InstructionHandle returnTarget; - /** * A Returnaddress [that doesn't know where to return to]. */ @@ -41,7 +40,6 @@ private ReturnaddressType() { super(Const.T_ADDRESS, ""); } - /** * Creates a ReturnaddressType object with a target. */ @@ -50,23 +48,11 @@ public ReturnaddressType(final InstructionHandle returnTarget) { this.returnTarget = returnTarget; } - - /** @return a hash code value for the object. - */ - @Override - public int hashCode() { - if (returnTarget == null) { - return 0; - } - return returnTarget.hashCode(); - } - - /** * Returns if the two Returnaddresses refer to the same target. */ @Override - public boolean equals( final Object rat ) { + public boolean equals(final Object rat) { if (!(rat instanceof ReturnaddressType)) { return false; } @@ -77,11 +63,21 @@ public boolean equals( final Object rat ) { return that.returnTarget.equals(this.returnTarget); } - /** * @return the target of this ReturnaddressType */ public InstructionHandle getTarget() { return returnTarget; } + + /** + * @return a hash code value for the object. + */ + @Override + public int hashCode() { + if (returnTarget == null) { + return 0; + } + return returnTarget.hashCode(); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SALOAD.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SALOAD.java index b25da298870..9499e5660f0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SALOAD.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SALOAD.java @@ -23,8 +23,10 @@ /** * SALOAD - Load short from array - *
    Stack: ..., arrayref, index -> ..., value
    * + *
    + * Stack: ..., arrayref, index -> ..., value
    + * 
    */ public class SALOAD extends ArrayInstruction implements StackProducer { @@ -32,17 +34,14 @@ public SALOAD() { super(com.sun.org.apache.bcel.internal.Const.SALOAD); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackProducer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SASTORE.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SASTORE.java index 2c5e6565677..c9c42d3d339 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SASTORE.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SASTORE.java @@ -23,8 +23,10 @@ /** * SASTORE - Store into short array - *
    Stack: ..., arrayref, index, value -> ...
    * + *
    + * Stack: ..., arrayref, index, value -> ...
    + * 
    */ public class SASTORE extends ArrayInstruction implements StackConsumer { @@ -32,17 +34,14 @@ public SASTORE() { super(com.sun.org.apache.bcel.internal.Const.SASTORE); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitExceptionThrower(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SIPUSH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SIPUSH.java index 6d3a38804e4..513495e062f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SIPUSH.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SIPUSH.java @@ -28,85 +28,76 @@ /** * SIPUSH - Push short * - *
    Stack: ... -> ..., value
    - * + *
    + * Stack: ... -> ..., value
    + * 
    */ public class SIPUSH extends Instruction implements ConstantPushInstruction { private short b; - /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ SIPUSH() { } - public SIPUSH(final short b) { super(com.sun.org.apache.bcel.internal.Const.SIPUSH, (short) 3); this.b = b; } - /** - * Dump instruction as short code to stream out. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object */ @Override - public void dump( final DataOutputStream out ) throws IOException { - super.dump(out); - out.writeShort(b); + public void accept(final Visitor v) { + v.visitPushInstruction(this); + v.visitStackProducer(this); + v.visitTypedInstruction(this); + v.visitConstantPushInstruction(this); + v.visitSIPUSH(this); } - /** - * @return mnemonic for instruction + * Dump instruction as short code to stream out. */ @Override - public String toString( final boolean verbose ) { - return super.toString(verbose) + " " + b; + public void dump(final DataOutputStream out) throws IOException { + super.dump(out); + out.writeShort(b); } - /** - * Read needed data (e.g. index) from file. + * @return Type.SHORT */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { - super.setLength(3); - b = bytes.readShort(); + public Type getType(final ConstantPoolGen cp) { + return Type.SHORT; } - @Override public Number getValue() { return Integer.valueOf(b); } - - /** @return Type.SHORT + /** + * Read needed data (e.g. index) from file. */ @Override - public Type getType( final ConstantPoolGen cp ) { - return Type.SHORT; + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { + super.setLength(3); + b = bytes.readShort(); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. - * - * @param v Visitor object + * @return mnemonic for instruction */ @Override - public void accept( final Visitor v ) { - v.visitPushInstruction(this); - v.visitStackProducer(this); - v.visitTypedInstruction(this); - v.visitConstantPushInstruction(this); - v.visitSIPUSH(this); + public String toString(final boolean verbose) { + return super.toString(verbose) + " " + b; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWAP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWAP.java index 57bf1b7df22..e3c0a46de73 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWAP.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWAP.java @@ -23,8 +23,10 @@ /** * SWAP - Swa top operand stack word - *
    Stack: ..., word2, word1 -> ..., word1, word2
    * + *
    + * Stack: ..., word2, word1 -> ..., word1, word2
    + * 
    */ public class SWAP extends StackInstruction implements StackConsumer, StackProducer { @@ -32,17 +34,14 @@ public SWAP() { super(com.sun.org.apache.bcel.internal.Const.SWAP); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitStackProducer(this); v.visitStackInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java index bd2f25413c8..aed1626ec0d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java @@ -21,91 +21,34 @@ package com.sun.org.apache.bcel.internal.generic; +import java.util.Arrays; + /** - * SWITCH - Branch depending on int value, generates either LOOKUPSWITCH or - * TABLESWITCH instruction, depending on whether the match values (int[]) can be - * sorted with no gaps between the numbers. - * + * SWITCH - Branch depending on int value, generates either LOOKUPSWITCH or TABLESWITCH instruction, depending on + * whether the match values (int[]) can be sorted with no gaps between the numbers. */ public final class SWITCH implements CompoundInstruction { - private int[] match; - private InstructionHandle[] targets; - private Select instruction; - private int matchLength; - - /** - * Template for switch() constructs. If the match array can be - * sorted in ascending order with gaps no larger than max_gap - * between the numbers, a TABLESWITCH instruction is generated, and - * a LOOKUPSWITCH otherwise. The former may be more efficient, but - * needs more space. - * - * Note, that the key array always will be sorted, though we leave - * the original arrays unaltered. - * - * @param match array of match values (case 2: ... case 7: ..., etc.) - * @param targets the instructions to be branched to for each case - * @param target the default target - * @param max_gap maximum gap that may between case branches + * @return match is sorted in ascending order with no gap bigger than maxGap? */ - public SWITCH(final int[] match, final InstructionHandle[] targets, final InstructionHandle target, final int max_gap) { - this.match = match.clone(); - this.targets = targets.clone(); - if ((matchLength = match.length) < 2) { - instruction = new TABLESWITCH(match, targets, target); - } else { - sort(0, matchLength - 1); - if (matchIsOrdered(max_gap)) { - fillup(max_gap, target); - instruction = new TABLESWITCH(this.match, this.targets, target); - } else { - instruction = new LOOKUPSWITCH(this.match, this.targets, target); - } - } - } - - - public SWITCH(final int[] match, final InstructionHandle[] targets, final InstructionHandle target) { - this(match, targets, target, 1); - } - - - private void fillup( final int max_gap, final InstructionHandle target ) { - final int max_size = matchLength + matchLength * max_gap; - final int[] m_vec = new int[max_size]; - final InstructionHandle[] t_vec = new InstructionHandle[max_size]; - int count = 1; - m_vec[0] = match[0]; - t_vec[0] = targets[0]; + private static boolean matchIsOrdered(final int[] match, final int matchLength, final int maxGap) { for (int i = 1; i < matchLength; i++) { - final int prev = match[i - 1]; - final int gap = match[i] - prev; - for (int j = 1; j < gap; j++) { - m_vec[count] = prev + j; - t_vec[count] = target; - count++; + if (match[i] - match[i - 1] > maxGap) { + return false; } - m_vec[count] = match[i]; - t_vec[count] = targets[i]; - count++; } - match = new int[count]; - targets = new InstructionHandle[count]; - System.arraycopy(m_vec, 0, match, 0, count); - System.arraycopy(t_vec, 0, targets, 0, count); + return true; } - /** - * Sort match and targets array with QuickSort. + * Sorts match and targets array with QuickSort. */ - private void sort( final int l, final int r ) { + private static void sort(final int l, final int r, final int[] match, final InstructionHandle[] targets) { int i = l; int j = r; int h; - final int m = match[(l + r) >>> 1]; + final int m = match[l + r >>> 1]; InstructionHandle h2; do { while (match[i] < m) { @@ -126,34 +69,71 @@ private void sort( final int l, final int r ) { } } while (i <= j); if (l < j) { - sort(l, j); + sort(l, j, match, targets); } if (i < r) { - sort(i, r); + sort(i, r, match, targets); } } + private final Select instruction; + + public SWITCH(final int[] match, final InstructionHandle[] targets, final InstructionHandle target) { + this(match, targets, target, 1); + } /** - * @return match is sorted in ascending order with no gap bigger than max_gap? + * Template for switch() constructs. If the match array can be sorted in ascending order with gaps no larger than + * maxGap between the numbers, a TABLESWITCH instruction is generated, and a LOOKUPSWITCH otherwise. The former may be + * more efficient, but needs more space. + * + * Note, that the key array always will be sorted, though we leave the original arrays unaltered. + * + * @param match array of match values (case 2: ... case 7: ..., etc.) + * @param targets the instructions to be branched to for each case + * @param target the default target + * @param maxGap maximum gap that may between case branches */ - private boolean matchIsOrdered( final int max_gap ) { - for (int i = 1; i < matchLength; i++) { - if (match[i] - match[i - 1] > max_gap) { - return false; + public SWITCH(final int[] match, final InstructionHandle[] targets, final InstructionHandle target, final int maxGap) { + int[] matchClone = match.clone(); + final InstructionHandle[] targetsClone = targets.clone(); + final int matchLength = match.length; + if (matchLength < 2) { + instruction = new TABLESWITCH(match, targets, target); + } else { + sort(0, matchLength - 1, matchClone, targetsClone); + if (matchIsOrdered(matchClone, matchLength, maxGap)) { + final int maxSize = matchLength + matchLength * maxGap; + final int[] mVec = new int[maxSize]; + final InstructionHandle[] tVec = new InstructionHandle[maxSize]; + int count = 1; + mVec[0] = match[0]; + tVec[0] = targets[0]; + for (int i = 1; i < matchLength; i++) { + final int prev = match[i - 1]; + final int gap = match[i] - prev; + for (int j = 1; j < gap; j++) { + mVec[count] = prev + j; + tVec[count] = target; + count++; + } + mVec[count] = match[i]; + tVec[count] = targets[i]; + count++; + } + instruction = new TABLESWITCH(Arrays.copyOf(mVec, count), Arrays.copyOf(tVec, count), target); + } else { + instruction = new LOOKUPSWITCH(matchClone, targetsClone, target); } } - return true; } + public Instruction getInstruction() { + return instruction; + } @Override public InstructionList getInstructionList() { return new InstructionList(instruction); } - - - public Instruction getInstruction() { - return instruction; - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java index a9dc01e2600..a90e795e99f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java @@ -27,34 +27,60 @@ /** * Select - Abstract super class for LOOKUPSWITCH and TABLESWITCH instructions. * - *

    We use our super's {@code target} property as the default target. + *

    + * We use our super's {@code target} property as the default target. * * @see LOOKUPSWITCH * @see TABLESWITCH * @see InstructionList * @LastModified: May 2021 */ -public abstract class Select extends BranchInstruction implements VariableLengthInstruction, - StackConsumer /* @since 6.0 */, StackProducer { +public abstract class Select extends BranchInstruction implements VariableLengthInstruction, StackConsumer /* @since 6.0 */, StackProducer { - private int[] match; // matches, i.e., case 1: ... TODO could be package-protected? - private int[] indices; // target offsets TODO could be package-protected? - private InstructionHandle[] targets; // target objects in instruction list TODO could be package-protected? - private int fixed_length; // fixed length defined by subclasses TODO could be package-protected? - private int match_length; // number of cases TODO could be package-protected? - private int padding = 0; // number of pad bytes for alignment TODO could be package-protected? + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected int[] match; // matches, i.e., case 1: ... TODO could be package-protected? + + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected int[] indices; // target offsets TODO could be package-protected? + + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected InstructionHandle[] targets; // target objects in instruction list TODO could be package-protected? /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected int fixed_length; // fixed length defined by subclasses TODO could be package-protected? + + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected int match_length; // number of cases TODO could be package-protected? + + /** + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + */ + @Deprecated + protected int padding; // number of pad bytes for alignment TODO could be package-protected? + + /** + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ Select() { } - /** - * (Match, target) pairs for switch. - * `Match' and `targets' must have the same length of course. + * (Match, target) pairs for switch. 'Match' and 'targets' must have the same length of course. * * @param match array of matching values * @param targets instruction targets @@ -71,126 +97,25 @@ public abstract class Select extends BranchInstruction implements VariableLength notifyTarget(null, target2, this); } if ((match_length = match.length) != targets.length) { - throw new ClassGenException("Match and target array have not the same length: Match length: " + - match.length + " Target length: " + targets.length); + throw new ClassGenException("Match and target array have not the same length: Match length: " + match.length + " Target length: " + targets.length); } indices = new int[match_length]; } - - /** - * Since this is a variable length instruction, it may shift the following - * instructions which then need to update their position. - * - * Called by InstructionList.setPositions when setting the position for every - * instruction. In the presence of variable length instructions `setPositions' - * performs multiple passes over the instruction list to calculate the - * correct (byte) positions and offsets by calling this function. - * - * @param offset additional offset caused by preceding (variable length) instructions - * @param max_offset the maximum offset that may be caused by these instructions - * @return additional offset caused by possible change of this instruction's length - */ - @Override - protected int updatePosition( final int offset, final int max_offset ) { - setPosition(getPosition() + offset); // Additional offset caused by preceding SWITCHs, GOTOs, etc. - final short old_length = (short) super.getLength(); - /* Alignment on 4-byte-boundary, + 1, because of tag byte. - */ - padding = (4 - ((getPosition() + 1) % 4)) % 4; - super.setLength((short) (fixed_length + padding)); // Update length - return super.getLength() - old_length; - } - - - /** - * Dump instruction as byte code to stream out. - * @param out Output stream - */ - @Override - public void dump( final DataOutputStream out ) throws IOException { - out.writeByte(super.getOpcode()); - for (int i = 0; i < padding; i++) { - out.writeByte(0); - } - super.setIndex(getTargetOffset()); // Write default target offset - out.writeInt(super.getIndex()); - } - - - /** - * Read needed data (e.g. index) from file. - */ - @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { - padding = (4 - (bytes.getIndex() % 4)) % 4; // Compute number of pad bytes - for (int i = 0; i < padding; i++) { - bytes.readByte(); - } - // Default branch target common for both cases (TABLESWITCH, LOOKUPSWITCH) - super.setIndex(bytes.readInt()); - } - - - /** - * @return mnemonic for instruction - */ - @Override - public String toString( final boolean verbose ) { - final StringBuilder buf = new StringBuilder(super.toString(verbose)); - if (verbose) { - for (int i = 0; i < match_length; i++) { - String s = "null"; - if (targets[i] != null) { - s = targets[i].getInstruction().toString(); - } - buf.append("(").append(match[i]).append(", ").append(s).append(" = {").append( - indices[i]).append("})"); - } - } else { - buf.append(" ..."); - } - return buf.toString(); - } - - - /** - * Set branch target for `i'th case - */ - public void setTarget( final int i, final InstructionHandle target ) { // TODO could be package-protected? - notifyTarget(targets[i], target, this); - targets[i] = target; - } - - - /** - * @param old_ih old target - * @param new_ih new target - */ @Override - public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) { - boolean targeted = false; - if (super.getTarget() == old_ih) { - targeted = true; - setTarget(new_ih); - } - for (int i = 0; i < targets.length; i++) { - if (targets[i] == old_ih) { - targeted = true; - setTarget(i, new_ih); - } - } - if (!targeted) { - throw new ClassGenException("Not targeting " + old_ih); - } + protected Object clone() throws CloneNotSupportedException { + final Select copy = (Select) super.clone(); + copy.match = match.clone(); + copy.indices = indices.clone(); + copy.targets = targets.clone(); + return copy; } - /** * @return true, if ih is target of this instruction */ @Override - public boolean containsTarget( final InstructionHandle ih ) { + public boolean containsTarget(final InstructionHandle ih) { if (super.getTarget() == ih) { return true; } @@ -202,17 +127,6 @@ public boolean containsTarget( final InstructionHandle ih ) { return false; } - - @Override - protected Object clone() throws CloneNotSupportedException { - final Select copy = (Select) super.clone(); - copy.match = match.clone(); - copy.indices = indices.clone(); - copy.targets = targets.clone(); - return copy; - } - - /** * Inform targets that they're not targeted anymore. */ @@ -224,14 +138,28 @@ void dispose() { } } - /** - * @return array of match indices + * Dump instruction as byte code to stream out. + * + * @param out Output stream */ - public int[] getMatchs() { - return match; + @Override + public void dump(final DataOutputStream out) throws IOException { + out.writeByte(super.getOpcode()); + for (int i = 0; i < padding; i++) { + out.writeByte(0); + } + super.setIndex(getTargetOffset()); // Write default target offset + out.writeInt(super.getIndex()); } + /** + * @return the fixed_length + * @since 6.0 + */ + final int getFixedLength() { + return fixed_length; + } /** * @return array of match target offsets @@ -240,12 +168,12 @@ public int[] getIndices() { return indices; } - /** - * @return array of match targets + * @return index entry from indices + * @since 6.0 */ - public InstructionHandle[] getTargets() { - return targets; + final int getIndices(final int index) { + return indices[index]; } /** @@ -256,13 +184,28 @@ final int getMatch(final int index) { return match[index]; } + /** + * @return the match_length + * @since 6.0 + */ + final int getMatchLength() { + return match_length; + } /** - * @return index entry from indices + * @return array of match indices + */ + public int[] getMatchs() { + return match; + } + + /** + * + * @return the padding * @since 6.0 */ - final int getIndices(final int index) { - return indices[index]; + final int getPadding() { + return padding; } /** @@ -273,41 +216,47 @@ final InstructionHandle getTarget(final int index) { return targets[index]; } - /** - * @return the fixed_length - * @since 6.0 + * @return array of match targets */ - final int getFixed_length() { - return fixed_length; + public InstructionHandle[] getTargets() { + return targets; } - /** - * @param fixed_length the fixed_length to set - * @since 6.0 + * Read needed data (e.g. index) from file. */ - final void setFixed_length(final int fixed_length) { - this.fixed_length = fixed_length; + @Override + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { + padding = (4 - bytes.getIndex() % 4) % 4; // Compute number of pad bytes + for (int i = 0; i < padding; i++) { + bytes.readByte(); + } + // Default branch target common for both cases (TABLESWITCH, LOOKUPSWITCH) + super.setIndex(bytes.readInt()); } - /** - * @return the match_length + * @param fixedLength the fixed_length to set * @since 6.0 */ - final int getMatch_length() { - return match_length; + final void setFixedLength(final int fixedLength) { + this.fixed_length = fixedLength; } + /** @since 6.0 */ + final int setIndices(final int i, final int value) { + indices[i] = value; + return value; // Allow use in nested calls + } /** - * @param match_length the match_length to set + * + * @param array * @since 6.0 */ - final int setMatch_length(final int match_length) { - this.match_length = match_length; - return match_length; + final void setIndices(final int[] array) { + indices = array; } /** @@ -325,17 +274,25 @@ final void setMatch(final int index, final int value) { * @param array * @since 6.0 */ - final void setIndices(final int[] array) { - indices = array; + final void setMatches(final int[] array) { + match = array; } /** - * - * @param array + * @param matchLength the match_length to set * @since 6.0 */ - final void setMatches(final int[] array) { - match = array; + final int setMatchLength(final int matchLength) { + this.match_length = matchLength; + return matchLength; + } + + /** + * Set branch target for 'i'th case + */ + public void setTarget(final int i, final InstructionHandle target) { // TODO could be package-protected? + notifyTarget(targets[i], target, this); + targets[i] = target; } /** @@ -348,18 +305,68 @@ final void setTargets(final InstructionHandle[] array) { } /** - * - * @return the padding - * @since 6.0 + * @return mnemonic for instruction */ - final int getPadding() { - return padding; + @Override + public String toString(final boolean verbose) { + final StringBuilder buf = new StringBuilder(super.toString(verbose)); + if (verbose) { + for (int i = 0; i < match_length; i++) { + String s = "null"; + if (targets[i] != null) { + s = targets[i].getInstruction().toString(); + } + buf.append("(").append(match[i]).append(", ").append(s).append(" = {").append(indices[i]).append("})"); + } + } else { + buf.append(" ..."); + } + return buf.toString(); } + /** + * Since this is a variable length instruction, it may shift the following instructions which then need to update their + * position. + * + * Called by InstructionList.setPositions when setting the position for every instruction. In the presence of variable + * length instructions 'setPositions' performs multiple passes over the instruction list to calculate the correct (byte) + * positions and offsets by calling this function. + * + * @param offset additional offset caused by preceding (variable length) instructions + * @param maxOffset the maximum offset that may be caused by these instructions + * @return additional offset caused by possible change of this instruction's length + */ + @Override + protected int updatePosition(final int offset, final int maxOffset) { + setPosition(getPosition() + offset); // Additional offset caused by preceding SWITCHs, GOTOs, etc. + final short oldLength = (short) super.getLength(); + /* + * Alignment on 4-byte-boundary, + 1, because of tag byte. + */ + padding = (4 - (getPosition() + 1) % 4) % 4; + super.setLength((short) (fixed_length + padding)); // Update length + return super.getLength() - oldLength; + } - /** @since 6.0 */ - final int setIndices(final int i, final int value) { - indices[i] = value; - return value; // Allow use in nested calls + /** + * @param oldIh old target + * @param newIh new target + */ + @Override + public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) { + boolean targeted = false; + if (super.getTarget() == oldIh) { + targeted = true; + setTarget(newIh); + } + for (int i = 0; i < targets.length; i++) { + if (targets[i] == oldIh) { + targeted = true; + setTarget(i, newIh); + } + } + if (!targeted) { + throw new ClassGenException("Not targeting " + oldIh); + } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java index bccb59cabaf..a4de20315d7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java @@ -35,102 +35,84 @@ /** * @since 6.0 */ -public class SimpleElementValueGen extends ElementValueGen -{ +public class SimpleElementValueGen extends ElementValueGen { // For primitive types and string type, this points to the value entry in // the cpGen // For 'class' this points to the class entry in the cpGen - private int idx; + private final int idx; - // ctors for each supported type... type could be inferred but for now lets - // force it to be passed - /** - * Protected ctor used for deserialization, doesn't *put* an entry in the - * constant pool, assumes the one at the supplied index is correct. - */ - protected SimpleElementValueGen(final int type, final int idx, final ConstantPoolGen cpGen) - { + public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final boolean value) { super(type, cpGen); - this.idx = idx; + if (value) { + idx = getConstantPool().addInteger(1); + } else { + idx = getConstantPool().addInteger(0); + } } - public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final int value) - { + public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final byte value) { super(type, cpGen); idx = getConstantPool().addInteger(value); } - public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final long value) - { + public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final char value) { super(type, cpGen); - idx = getConstantPool().addLong(value); + idx = getConstantPool().addInteger(value); } - public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final double value) - { + public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final double value) { super(type, cpGen); idx = getConstantPool().addDouble(value); } - public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final float value) - { + public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final float value) { super(type, cpGen); idx = getConstantPool().addFloat(value); } - public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final short value) - { + public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final int value) { super(type, cpGen); idx = getConstantPool().addInteger(value); } - public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final byte value) - { + public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final long value) { super(type, cpGen); - idx = getConstantPool().addInteger(value); + idx = getConstantPool().addLong(value); } - public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final char value) - { + public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final short value) { super(type, cpGen); idx = getConstantPool().addInteger(value); } - public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final boolean value) - { + public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final String value) { super(type, cpGen); - if (value) { - idx = getConstantPool().addInteger(1); - } else { - idx = getConstantPool().addInteger(0); - } + idx = getConstantPool().addUtf8(value); } - public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final String value) - { + // ctors for each supported type... type could be inferred but for now lets + // force it to be passed + /** + * Protected ctor used for deserialization, doesn't *put* an entry in the constant pool, assumes the one at the supplied + * index is correct. + */ + protected SimpleElementValueGen(final int type, final int idx, final ConstantPoolGen cpGen) { super(type, cpGen); - idx = getConstantPool().addUtf8(value); + this.idx = idx; } /** - * The boolean controls whether we copy info from the 'old' constant pool to - * the 'new'. You need to use this ctor if the annotation is being copied - * from one file to another. + * The boolean controls whether we copy info from the 'old' constant pool to the 'new'. You need to use this ctor if the + * annotation is being copied from one file to another. */ - public SimpleElementValueGen(final SimpleElementValue value, - final ConstantPoolGen cpool, final boolean copyPoolEntries) - { + public SimpleElementValueGen(final SimpleElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) { super(value.getElementValueType(), cpool); - if (!copyPoolEntries) - { + if (!copyPoolEntries) { // J5ASSERT: Could assert value.stringifyValue() is the same as // cpool.getConstant(SimpleElementValuevalue.getIndex()) idx = value.getIndex(); - } - else - { - switch (value.getElementValueType()) - { + } else { + switch (value.getElementValueType()) { case STRING: idx = cpool.addUtf8(value.getValueString()); break; @@ -153,12 +135,9 @@ public SimpleElementValueGen(final SimpleElementValue value, idx = cpool.addDouble(value.getValueDouble()); break; case PRIMITIVE_BOOLEAN: - if (value.getValueBoolean()) - { + if (value.getValueBoolean()) { idx = cpool.addInteger(1); - } - else - { + } else { idx = cpool.addInteger(0); } break; @@ -166,52 +145,63 @@ public SimpleElementValueGen(final SimpleElementValue value, idx = cpool.addInteger(value.getValueShort()); break; default: - throw new IllegalArgumentException( - "SimpleElementValueGen class does not know how to copy this type " + super.getElementValueType()); + throw new IllegalArgumentException("SimpleElementValueGen class does not know how to copy this type " + super.getElementValueType()); } } } + @Override + public void dump(final DataOutputStream dos) throws IOException { + dos.writeByte(super.getElementValueType()); // u1 kind of value + switch (super.getElementValueType()) { + case PRIMITIVE_INT: + case PRIMITIVE_BYTE: + case PRIMITIVE_CHAR: + case PRIMITIVE_FLOAT: + case PRIMITIVE_LONG: + case PRIMITIVE_BOOLEAN: + case PRIMITIVE_SHORT: + case PRIMITIVE_DOUBLE: + case STRING: + dos.writeShort(idx); + break; + default: + throw new IllegalStateException("SimpleElementValueGen doesnt know how to write out type " + super.getElementValueType()); + } + } + /** * Return immutable variant */ @Override - public ElementValue getElementValue() - { + public ElementValue getElementValue() { return new SimpleElementValue(super.getElementValueType(), idx, getConstantPool().getConstantPool()); } - public int getIndex() - { + public int getIndex() { return idx; } - public String getValueString() - { - if (super.getElementValueType() != STRING) { - throw new IllegalStateException( - "Dont call getValueString() on a non STRING ElementValue"); + public int getValueInt() { + if (super.getElementValueType() != PRIMITIVE_INT) { + throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue"); } - final ConstantUtf8 c = (ConstantUtf8) getConstantPool().getConstant(idx); + final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx); return c.getBytes(); } - public int getValueInt() - { - if (super.getElementValueType() != PRIMITIVE_INT) { - throw new IllegalStateException( - "Dont call getValueString() on a non STRING ElementValue"); + public String getValueString() { + if (super.getElementValueType() != STRING) { + throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue"); } - final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx); + final ConstantUtf8 c = (ConstantUtf8) getConstantPool().getConstant(idx); return c.getBytes(); } // Whatever kind of value it is, return it as a string @Override - public String stringifyValue() - { - switch (super.getElementValueType()) - { + public String stringifyValue() { + switch (super.getElementValueType()) { case PRIMITIVE_INT: final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx); return Integer.toString(c.getBytes()); @@ -243,31 +233,7 @@ public String stringifyValue() final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(idx); return cu8.getBytes(); default: - throw new IllegalStateException( - "SimpleElementValueGen class does not know how to stringify type " + super.getElementValueType()); - } - } - - @Override - public void dump(final DataOutputStream dos) throws IOException - { - dos.writeByte(super.getElementValueType()); // u1 kind of value - switch (super.getElementValueType()) - { - case PRIMITIVE_INT: - case PRIMITIVE_BYTE: - case PRIMITIVE_CHAR: - case PRIMITIVE_FLOAT: - case PRIMITIVE_LONG: - case PRIMITIVE_BOOLEAN: - case PRIMITIVE_SHORT: - case PRIMITIVE_DOUBLE: - case STRING: - dos.writeShort(idx); - break; - default: - throw new IllegalStateException( - "SimpleElementValueGen doesnt know how to write out type " + super.getElementValueType()); + throw new IllegalStateException("SimpleElementValueGen class does not know how to stringify type " + super.getElementValueType()); } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StackConsumer.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StackConsumer.java index 2740be3eedc..c0709a46b28 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StackConsumer.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StackConsumer.java @@ -23,11 +23,11 @@ /** * Denote an instruction that may consume a value from the stack. - * */ public interface StackConsumer { - /** @return how many words are consumed from stack + /** + * @return how many words are consumed from stack */ - int consumeStack( ConstantPoolGen cpg ); + int consumeStack(ConstantPoolGen cpg); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StackInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StackInstruction.java index 4306800468c..31321512295 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StackInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StackInstruction.java @@ -23,18 +23,15 @@ /** * Super class for stack operations like DUP and POP. - * */ public abstract class StackInstruction extends Instruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ StackInstruction() { } - /** * @param opcode instruction opcode */ @@ -42,10 +39,10 @@ protected StackInstruction(final short opcode) { super(opcode, (short) 1); } - - /** @return Type.UNKNOWN + /** + * @return Type.UNKNOWN */ - public Type getType( final ConstantPoolGen cp ) { + public Type getType(final ConstantPoolGen cp) { return Type.UNKNOWN; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StackProducer.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StackProducer.java index fa3c00eec27..f660e3b329f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StackProducer.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StackProducer.java @@ -22,13 +22,12 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Denote an instruction that may produce a value on top of the stack - * (this excludes DUP_X1, e.g.) - * + * Denotes an instruction that may produce a value on top of the stack (this excludes DUP_X1, e.g.) */ public interface StackProducer { - /** @return how many words are produced on stack + /** + * @return how many words are produced on stack */ - int produceStack( ConstantPoolGen cpg ); + int produceStack(ConstantPoolGen cpg); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StoreInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StoreInstruction.java index be039391012..ceef3a8b794 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StoreInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/StoreInstruction.java @@ -22,42 +22,35 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Denotes an unparameterized instruction to store a value into a local variable, - * e.g. ISTORE. - * + * Denotes an unparameterized instruction to store a value into a local variable, e.g. ISTORE. */ public abstract class StoreInstruction extends LocalVariableInstruction implements PopInstruction { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. - * tag and length are defined in readInstruction and initFromFile, respectively. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. tag and length are defined in + * readInstruction and initFromFile, respectively. */ - StoreInstruction(final short canon_tag, final short c_tag) { - super(canon_tag, c_tag); + StoreInstruction(final short canonTag, final short cTag) { + super(canonTag, cTag); } - /** * @param opcode Instruction opcode - * @param c_tag Instruction number for compact version, ASTORE_0, e.g. + * @param cTag Instruction number for compact version, ASTORE_0, e.g. * @param n local variable index (unsigned short) */ - protected StoreInstruction(final short opcode, final short c_tag, final int n) { - super(opcode, c_tag, n); + protected StoreInstruction(final short opcode, final short cTag, final int n) { + super(opcode, cTag, n); } - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. * * @param v Visitor object */ @Override - public void accept( final Visitor v ) { + public void accept(final Visitor v) { v.visitStackConsumer(this); v.visitPopInstruction(this); v.visitTypedInstruction(this); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TABLESWITCH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TABLESWITCH.java index 3ed2e100fe4..e38da5eec77 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TABLESWITCH.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TABLESWITCH.java @@ -34,83 +34,76 @@ public class TABLESWITCH extends Select { /** - * Empty constructor needed for Instruction.readInstruction. - * Not to be used otherwise. + * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. */ TABLESWITCH() { } - /** - * @param match sorted array of match values, match[0] must be low value, - * match[match_length - 1] high value + * @param match sorted array of match values, match[0] must be low value, match[match_length - 1] high value * @param targets where to branch for matched values * @param defaultTarget default branch */ public TABLESWITCH(final int[] match, final InstructionHandle[] targets, final InstructionHandle defaultTarget) { super(com.sun.org.apache.bcel.internal.Const.TABLESWITCH, match, targets, defaultTarget); /* Alignment remainder assumed 0 here, until dump time */ - final short _length = (short) (13 + getMatch_length() * 4); - super.setLength(_length); - setFixed_length(_length); + final short length = (short) (13 + getMatchLength() * 4); + super.setLength(length); + setFixedLength(length); } + /** + * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call + * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitVariableLengthInstruction(this); + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitSelect(this); + v.visitTABLESWITCH(this); + } /** * Dump instruction as byte code to stream out. + * * @param out Output stream */ @Override - public void dump( final DataOutputStream out ) throws IOException { + public void dump(final DataOutputStream out) throws IOException { super.dump(out); - final int _match_length = getMatch_length(); - final int low = (_match_length > 0) ? super.getMatch(0) : 0; + final int matchLength = getMatchLength(); + final int low = matchLength > 0 ? super.getMatch(0) : 0; out.writeInt(low); - final int high = (_match_length > 0) ? super.getMatch(_match_length - 1) : 0; + final int high = matchLength > 0 ? super.getMatch(matchLength - 1) : 0; out.writeInt(high); - for (int i = 0; i < _match_length; i++) { + for (int i = 0; i < matchLength; i++) { out.writeInt(setIndices(i, getTargetOffset(super.getTarget(i)))); } } - /** * Read needed data (e.g. index) from file. */ @Override - protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { super.initFromFile(bytes, wide); final int low = bytes.readInt(); final int high = bytes.readInt(); - final int _match_length = high - low + 1; - setMatch_length(_match_length); - final short _fixed_length = (short) (13 + _match_length * 4); - setFixed_length(_fixed_length); - super.setLength((short) (_fixed_length + super.getPadding())); - super.setMatches(new int[_match_length]); - super.setIndices(new int[_match_length]); - super.setTargets(new InstructionHandle[_match_length]); - for (int i = 0; i < _match_length; i++) { + final int matchLength = high - low + 1; + setMatchLength(matchLength); + final short fixedLength = (short) (13 + matchLength * 4); + setFixedLength(fixedLength); + super.setLength((short) (fixedLength + super.getPadding())); + super.setMatches(new int[matchLength]); + super.setIndices(new int[matchLength]); + super.setTargets(new InstructionHandle[matchLength]); + for (int i = 0; i < matchLength; i++) { super.setMatch(i, low + i); super.setIndices(i, bytes.readInt()); } } - - - /** - * Call corresponding visitor method(s). The order is: - * Call visitor methods of implemented interfaces first, then - * call methods according to the class hierarchy in descending order, - * i.e., the most specific visitXXX() call comes last. - * - * @param v Visitor object - */ - @Override - public void accept( final Visitor v ) { - v.visitVariableLengthInstruction(this); - v.visitStackConsumer(this); - v.visitBranchInstruction(this); - v.visitSelect(this); - v.visitTABLESWITCH(this); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java index e0aa29747f5..30310356f21 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -22,14 +21,14 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Thrown by InstructionList.remove() when one or multiple disposed instructions - * are still being referenced by an InstructionTargeter object. I.e. the - * InstructionTargeter has to be notified that (one of) the InstructionHandle it - * is referencing is being removed from the InstructionList and thus not valid anymore. + * Thrown by InstructionList.remove() when one or multiple disposed instructions are still being referenced by an + * InstructionTargeter object. I.e. the InstructionTargeter has to be notified that (one of) the InstructionHandle it is + * referencing is being removed from the InstructionList and thus not valid anymore. * - *

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

    + *

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

    * *
      *     ...
    @@ -47,19 +46,18 @@
      * @see InstructionHandle
      * @see InstructionList
      * @see InstructionTargeter
    + * @LastModified: Feb 2023
      */
     public final class TargetLostException extends Exception {
     
         private static final long serialVersionUID = -6857272667645328384L;
         private final InstructionHandle[] targets;
     
    -
         TargetLostException(final InstructionHandle[] t, final String mesg) {
             super(mesg);
             targets = t;
         }
     
    -
         /**
          * @return list of instructions still being targeted.
          */
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java
    index 2e366dfc8d9..ea20710af2e 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java
    @@ -20,26 +20,26 @@
     package com.sun.org.apache.bcel.internal.generic;
     
     import java.util.ArrayList;
    +import java.util.Arrays;
     import java.util.List;
    +import java.util.Objects;
     
     import com.sun.org.apache.bcel.internal.Const;
     import com.sun.org.apache.bcel.internal.classfile.ClassFormatException;
     import com.sun.org.apache.bcel.internal.classfile.Utility;
     
     /**
    - * Abstract super class for all possible java types, namely basic types
    - * such as int, object types like String and array types, e.g. int[]
    - *
    + * Abstract super class for all possible java types, namely basic types such as int, object types like String and array
    + * types, e.g. int[]
      * @LastModified: May 2021
      */
     public abstract class Type {
     
    -    private final byte type;
    -    private String signature; // signature for the type
         /**
          * Predefined constants
          */
         public static final BasicType VOID = new BasicType(Const.T_VOID);
    +
         public static final BasicType BOOLEAN = new BasicType(Const.T_BOOLEAN);
         public static final BasicType INT = new BasicType(Const.T_INT);
         public static final BasicType SHORT = new BasicType(Const.T_SHORT);
    @@ -53,176 +53,104 @@ public abstract class Type {
         public static final ObjectType STRING = new ObjectType("java.lang.String");
         public static final ObjectType STRINGBUFFER = new ObjectType("java.lang.StringBuffer");
         public static final ObjectType THROWABLE = new ObjectType("java.lang.Throwable");
    -    public static final Type[] NO_ARGS = new Type[0]; // EMPTY, so immutable
    -    public static final ReferenceType NULL = new ReferenceType() {
    -    };
    -    public static final Type UNKNOWN = new Type(Const.T_UNKNOWN, "") {
    -    };
    -
    -
    -    protected Type(final byte t, final String s) {
    -        type = t;
    -        signature = s;
    -    }
    -
     
         /**
    -     * @return hashcode of Type
    +     * Empty array.
          */
    -    @Override
    -    public int hashCode() {
    -        return type ^ signature.hashCode();
    -    }
    -
    +    public static final Type[] NO_ARGS = {};
    +    public static final ReferenceType NULL = new ReferenceType() {
    +    };
     
    -    /**
    -     * @return whether the Types are equal
    -     */
    -    @Override
    -    public boolean equals(final Object o) {
    -          if (o instanceof Type) {
    -              final Type t = (Type)o;
    -              return (type == t.type) && signature.equals(t.signature);
    -          }
    -          return false;
    -    }
    +    public static final Type UNKNOWN = new Type(Const.T_UNKNOWN, "") {
    +    };
     
    +    private static final ThreadLocal CONSUMED_CHARS = ThreadLocal.withInitial(() -> Integer.valueOf(0));
     
    -    /**
    -     * @return signature for given type.
    -     */
    -    public String getSignature() {
    -        return signature;
    +    // int consumed_chars=0; // Remember position in string, see getArgumentTypes
    +    static int consumed(final int coded) {
    +        return coded >> 2;
         }
     
    -
    -    /**
    -     * @return type as defined in Constants
    -     */
    -    public byte getType() {
    -        return type;
    +    static int encode(final int size, final int consumed) {
    +        return consumed << 2 | size;
         }
     
         /**
    -     * boolean, short and char variable are considered as int in the stack or local variable area.
    -     * Returns {@link Type#INT} for {@link Type#BOOLEAN}, {@link Type#SHORT} or {@link Type#CHAR}, otherwise
    -     * returns the given type.
    -     * @since 6.0
    +     * Convert arguments of a method (signature) to an array of Type objects.
    +     *
    +     * @param signature signature string such as (Ljava/lang/String;)V
    +     * @return array of argument types
          */
    -    public Type normalizeForStackOrLocal() {
    -        if (this == Type.BOOLEAN || this == Type.BYTE || this == Type.SHORT || this == Type.CHAR) {
    -            return Type.INT;
    +    public static Type[] getArgumentTypes(final String signature) {
    +        final List vec = new ArrayList<>();
    +        int index;
    +        try {
    +            // Skip any type arguments to read argument declarations between '(' and ')'
    +            index = signature.indexOf('(') + 1;
    +            if (index <= 0) {
    +                throw new ClassFormatException("Invalid method signature: " + signature);
    +            }
    +            while (signature.charAt(index) != ')') {
    +                vec.add(getType(signature.substring(index)));
    +                // corrected concurrent private static field acess
    +                index += unwrap(CONSUMED_CHARS); // update position
    +            }
    +        } catch (final StringIndexOutOfBoundsException e) { // Should never occur
    +            throw new ClassFormatException("Invalid method signature: " + signature, e);
             }
    -        return this;
    +        final Type[] types = new Type[vec.size()];
    +        vec.toArray(types);
    +        return types;
         }
     
    -    /**
    -     * @return stack size of this type (2 for long and double, 0 for void, 1 otherwise)
    -     */
    -    public int getSize() {
    -        switch (type) {
    -            case Const.T_DOUBLE:
    -            case Const.T_LONG:
    -                return 2;
    -            case Const.T_VOID:
    -                return 0;
    -            default:
    -                return 1;
    +    static int getArgumentTypesSize(final String signature) {
    +        int res = 0;
    +        int index;
    +        try {
    +            // Skip any type arguments to read argument declarations between '(' and ')'
    +            index = signature.indexOf('(') + 1;
    +            if (index <= 0) {
    +                throw new ClassFormatException("Invalid method signature: " + signature);
    +            }
    +            while (signature.charAt(index) != ')') {
    +                final int coded = getTypeSize(signature.substring(index));
    +                res += size(coded);
    +                index += consumed(coded);
    +            }
    +        } catch (final StringIndexOutOfBoundsException e) { // Should never occur
    +            throw new ClassFormatException("Invalid method signature: " + signature, e);
             }
    +        return res;
         }
     
    -
    -    /**
    -     * @return Type string, e.g. `int[]'
    -     */
    -    @Override
    -    public String toString() {
    -        return ((this.equals(Type.NULL) || (type >= Const.T_UNKNOWN))) ? signature : Utility
    -                .signatureToString(signature, false);
    -    }
    -
    -
         /**
    -     * Convert type to Java method signature, e.g. int[] f(java.lang.String x)
    -     * becomes (Ljava/lang/String;)[I
    +     * Convert type to Java method signature, e.g. int[] f(java.lang.String x) becomes (Ljava/lang/String;)[I
          *
    -     * @param return_type what the method returns
    -     * @param arg_types what are the argument types
    +     * @param returnType what the method returns
    +     * @param argTypes what are the argument types
          * @return method signature for given type(s).
          */
    -    public static String getMethodSignature( final Type return_type, final Type[] arg_types ) {
    +    public static String getMethodSignature(final Type returnType, final Type[] argTypes) {
             final StringBuilder buf = new StringBuilder("(");
    -        if (arg_types != null) {
    -            for (final Type arg_type : arg_types) {
    -                buf.append(arg_type.getSignature());
    +        if (argTypes != null) {
    +            for (final Type argType : argTypes) {
    +                buf.append(argType.getSignature());
                 }
             }
             buf.append(')');
    -        buf.append(return_type.getSignature());
    +        buf.append(returnType.getSignature());
             return buf.toString();
         }
     
    -    private static final ThreadLocal consumed_chars = new ThreadLocal() {
    -
    -        @Override
    -        protected Integer initialValue() {
    -            return Integer.valueOf(0);
    -        }
    -    };//int consumed_chars=0; // Remember position in string, see getArgumentTypes
    -
    -
    -    private static int unwrap( final ThreadLocal tl ) {
    -        return tl.get().intValue();
    -    }
    -
    -
    -    private static void wrap( final ThreadLocal tl, final int value ) {
    -        tl.set(Integer.valueOf(value));
    -    }
    -
    -
    -    /**
    -     * Convert signature to a Type object.
    -     * @param signature signature string such as Ljava/lang/String;
    -     * @return type object
    -     */
    -    // @since 6.0 no longer final
    -    public static Type getType( final String signature ) throws StringIndexOutOfBoundsException {
    -        final byte type = Utility.typeOfSignature(signature);
    -        if (type <= Const.T_VOID) {
    -            //corrected concurrent private static field acess
    -            wrap(consumed_chars, 1);
    -            return BasicType.getType(type);
    -        } else if (type == Const.T_ARRAY) {
    -            int dim = 0;
    -            do { // Count dimensions
    -                dim++;
    -            } while (signature.charAt(dim) == '[');
    -            // Recurse, but just once, if the signature is ok
    -            final Type t = getType(signature.substring(dim));
    -            //corrected concurrent private static field acess
    -            //  consumed_chars += dim; // update counter - is replaced by
    -            final int _temp = unwrap(consumed_chars) + dim;
    -            wrap(consumed_chars, _temp);
    -            return new ArrayType(t, dim);
    -        } else { // type == T_REFERENCE
    -            // Utility.typeSignatureToString understands how to parse generic types.
    -            final String parsedSignature = Utility.typeSignatureToString(signature, false);
    -            wrap(consumed_chars, parsedSignature.length() + 2); // "Lblabla;" `L' and `;' are removed
    -            return ObjectType.getInstance(parsedSignature.replace('/', '.'));
    -        }
    -    }
    -
    -
         /**
          * Convert return value of a method (signature) to a Type object.
          *
          * @param signature signature string such as (Ljava/lang/String;)V
          * @return return type
          */
    -    public static Type getReturnType( final String signature ) {
    +    public static Type getReturnType(final String signature) {
             try {
    -            // Read return type after `)'
    +            // Read return type after ')'
                 final int index = signature.lastIndexOf(')') + 1;
                 return getType(signature.substring(index));
             } catch (final StringIndexOutOfBoundsException e) { // Should never occur
    @@ -230,170 +158,242 @@ public static Type getReturnType( final String signature ) {
             }
         }
     
    +    static int getReturnTypeSize(final String signature) {
    +        final int index = signature.lastIndexOf(')') + 1;
    +        return Type.size(getTypeSize(signature.substring(index)));
    +    }
     
    -    /**
    -     * Convert arguments of a method (signature) to an array of Type objects.
    -     * @param signature signature string such as (Ljava/lang/String;)V
    -     * @return array of argument types
    -     */
    -    public static Type[] getArgumentTypes( final String signature ) {
    -        final List vec = new ArrayList<>();
    -        int index;
    -        Type[] types;
    -        try {
    -            // Skip any type arguments to read argument declarations between `(' and `)'
    -            index = signature.indexOf('(') + 1;
    -            if (index <= 0) {
    -                throw new ClassFormatException("Invalid method signature: " + signature);
    -            }
    -            while (signature.charAt(index) != ')') {
    -                vec.add(getType(signature.substring(index)));
    -                //corrected concurrent private static field acess
    -                index += unwrap(consumed_chars); // update position
    -            }
    -        } catch (final StringIndexOutOfBoundsException e) { // Should never occur
    -            throw new ClassFormatException("Invalid method signature: " + signature, e);
    +    public static String getSignature(final java.lang.reflect.Method meth) {
    +        final StringBuilder sb = new StringBuilder("(");
    +        final Class[] params = meth.getParameterTypes(); // avoid clone
    +        for (final Class param : params) {
    +            sb.append(getType(param).getSignature());
             }
    -        types = new Type[vec.size()];
    -        vec.toArray(types);
    -        return types;
    +        sb.append(")");
    +        sb.append(getType(meth.getReturnType()).getSignature());
    +        return sb.toString();
         }
     
    -
    -    /** Convert runtime java.lang.Class to BCEL Type object.
    -     * @param cl Java class
    +    /**
    +     * Convert runtime java.lang.Class to BCEL Type object.
    +     *
    +     * @param cls Java class
          * @return corresponding Type object
          */
    -    public static Type getType( final java.lang.Class cl ) {
    -        if (cl == null) {
    -            throw new IllegalArgumentException("Class must not be null");
    -        }
    -        /* That's an amzingly easy case, because getName() returns
    -         * the signature. That's what we would have liked anyway.
    +    public static Type getType(final Class cls) {
    +        Objects.requireNonNull(cls, "cls");
    +        /*
    +         * That's an amzingly easy case, because getName() returns the signature. That's what we would have liked anyway.
              */
    -        if (cl.isArray()) {
    -            return getType(cl.getName());
    -        } else if (cl.isPrimitive()) {
    -            if (cl == Integer.TYPE) {
    -                return INT;
    -            } else if (cl == Void.TYPE) {
    -                return VOID;
    -            } else if (cl == Double.TYPE) {
    -                return DOUBLE;
    -            } else if (cl == Float.TYPE) {
    -                return FLOAT;
    -            } else if (cl == Boolean.TYPE) {
    -                return BOOLEAN;
    -            } else if (cl == Byte.TYPE) {
    -                return BYTE;
    -            } else if (cl == Short.TYPE) {
    -                return SHORT;
    -            } else if (cl == Byte.TYPE) {
    -                return BYTE;
    -            } else if (cl == Long.TYPE) {
    -                return LONG;
    -            } else if (cl == Character.TYPE) {
    -                return CHAR;
    -            } else {
    -                throw new IllegalStateException("Unknown primitive type " + cl);
    -            }
    -        } else { // "Real" class
    -            return ObjectType.getInstance(cl.getName());
    +        if (cls.isArray()) {
    +            return getType(cls.getName());
    +        }
    +        if (!cls.isPrimitive()) { // "Real" class
    +            return ObjectType.getInstance(cls.getName());
    +        }
    +        if (cls == Integer.TYPE) {
    +            return INT;
    +        }
    +        if (cls == Void.TYPE) {
    +            return VOID;
    +        }
    +        if (cls == Double.TYPE) {
    +            return DOUBLE;
    +        }
    +        if (cls == Float.TYPE) {
    +            return FLOAT;
    +        }
    +        if (cls == Boolean.TYPE) {
    +            return BOOLEAN;
    +        }
    +        if (cls == Byte.TYPE) {
    +            return BYTE;
    +        }
    +        if (cls == Short.TYPE) {
    +            return SHORT;
    +        }
    +        if (cls == Long.TYPE) {
    +            return LONG;
             }
    +        if (cls == Character.TYPE) {
    +            return CHAR;
    +        }
    +        throw new IllegalStateException("Unknown primitive type " + cls);
         }
     
    +    /**
    +     * Convert signature to a Type object.
    +     *
    +     * @param signature signature string such as Ljava/lang/String;
    +     * @return type object
    +     */
    +    public static Type getType(final String signature) throws StringIndexOutOfBoundsException {
    +        final byte type = Utility.typeOfSignature(signature);
    +        if (type <= Const.T_VOID) {
    +            // corrected concurrent private static field acess
    +            wrap(CONSUMED_CHARS, 1);
    +            return BasicType.getType(type);
    +        }
    +        if (type != Const.T_ARRAY) { // type == T_REFERENCE
    +            // Utility.typeSignatureToString understands how to parse generic types.
    +            final String parsedSignature = Utility.typeSignatureToString(signature, false);
    +            wrap(CONSUMED_CHARS, parsedSignature.length() + 2); // "Lblabla;" 'L' and ';' are removed
    +            return ObjectType.getInstance(Utility.pathToPackage(parsedSignature));
    +        }
    +        int dim = 0;
    +        do { // Count dimensions
    +            dim++;
    +        } while (signature.charAt(dim) == '[');
    +        // Recurse, but just once, if the signature is ok
    +        final Type t = getType(signature.substring(dim));
    +        // corrected concurrent private static field acess
    +        // consumed_chars += dim; // update counter - is replaced by
    +        final int temp = unwrap(CONSUMED_CHARS) + dim;
    +        wrap(CONSUMED_CHARS, temp);
    +        return new ArrayType(t, dim);
    +    }
     
         /**
          * Convert runtime java.lang.Class[] to BCEL Type objects.
    +     *
          * @param classes an array of runtime class objects
          * @return array of corresponding Type objects
          */
    -    public static Type[] getTypes( final java.lang.Class[] classes ) {
    +    public static Type[] getTypes(final Class[] classes) {
             final Type[] ret = new Type[classes.length];
    -        for (int i = 0; i < ret.length; i++) {
    -            ret[i] = getType(classes[i]);
    -        }
    +        Arrays.setAll(ret, i -> getType(classes[i]));
             return ret;
         }
     
    -
    -    public static String getSignature( final java.lang.reflect.Method meth ) {
    -        final StringBuilder sb = new StringBuilder("(");
    -        final Class[] params = meth.getParameterTypes(); // avoid clone
    -        for (final Class param : params) {
    -            sb.append(getType(param).getSignature());
    +    static int getTypeSize(final String signature) throws StringIndexOutOfBoundsException {
    +        final byte type = Utility.typeOfSignature(signature);
    +        if (type <= Const.T_VOID) {
    +            return encode(BasicType.getType(type).getSize(), 1);
             }
    -        sb.append(")");
    -        sb.append(getType(meth.getReturnType()).getSignature());
    -        return sb.toString();
    +        if (type == Const.T_ARRAY) {
    +            int dim = 0;
    +            do { // Count dimensions
    +                dim++;
    +            } while (signature.charAt(dim) == '[');
    +            // Recurse, but just once, if the signature is ok
    +            final int consumed = consumed(getTypeSize(signature.substring(dim)));
    +            return encode(1, dim + consumed);
    +        }
    +        final int index = signature.indexOf(';'); // Look for closing ';'
    +        if (index < 0) {
    +            throw new ClassFormatException("Invalid signature: " + signature);
    +        }
    +        return encode(1, index + 1);
         }
     
         static int size(final int coded) {
             return coded & 3;
         }
     
    -    static int consumed(final int coded) {
    -        return coded >> 2;
    +    private static int unwrap(final ThreadLocal tl) {
    +        return tl.get().intValue();
         }
     
    -    static int encode(final int size, final int consumed) {
    -        return consumed << 2 | size;
    +    private static void wrap(final ThreadLocal tl, final int value) {
    +        tl.set(Integer.valueOf(value));
         }
     
    -    static int getArgumentTypesSize( final String signature ) {
    -        int res = 0;
    -        int index;
    -        try {
    -            // Skip any type arguments to read argument declarations between `(' and `)'
    -            index = signature.indexOf('(') + 1;
    -            if (index <= 0) {
    -                throw new ClassFormatException("Invalid method signature: " + signature);
    -            }
    -            while (signature.charAt(index) != ')') {
    -                final int coded = getTypeSize(signature.substring(index));
    -                res += size(coded);
    -                index += consumed(coded);
    -            }
    -        } catch (final StringIndexOutOfBoundsException e) { // Should never occur
    -            throw new ClassFormatException("Invalid method signature: " + signature, e);
    +    /**
    +     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
    +     */
    +    @Deprecated
    +    protected byte type; // TODO should be final (and private)
    +
    +    /**
    +     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
    +     */
    +    @Deprecated
    +    protected String signature; // signature for the type TODO should be private
    +
    +    protected Type(final byte type, final String signature) {
    +        this.type = type;
    +        this.signature = signature;
    +    }
    +
    +    /**
    +     * @return whether the Types are equal
    +     */
    +    @Override
    +    public boolean equals(final Object o) {
    +        if (o instanceof Type) {
    +            final Type t = (Type) o;
    +            return type == t.type && signature.equals(t.signature);
             }
    -        return res;
    +        return false;
         }
     
    -    static int getTypeSize( final String signature ) throws StringIndexOutOfBoundsException {
    -        final byte type = Utility.typeOfSignature(signature);
    -        if (type <= Const.T_VOID) {
    -            return encode(BasicType.getType(type).getSize(), 1);
    -        } else if (type == Const.T_ARRAY) {
    -            int dim = 0;
    -            do { // Count dimensions
    -                dim++;
    -            } while (signature.charAt(dim) == '[');
    -            // Recurse, but just once, if the signature is ok
    -            final int consumed = consumed(getTypeSize(signature.substring(dim)));
    -            return encode(1, dim + consumed);
    -        } else { // type == T_REFERENCE
    -            final int index = signature.indexOf(';'); // Look for closing `;'
    -            if (index < 0) {
    -                throw new ClassFormatException("Invalid signature: " + signature);
    -            }
    -            return encode(1, index + 1);
    +    public String getClassName() {
    +        return toString();
    +    }
    +
    +    /**
    +     * @return signature for given type.
    +     */
    +    public String getSignature() {
    +        return signature;
    +    }
    +
    +    /**
    +     * @return stack size of this type (2 for long and double, 0 for void, 1 otherwise)
    +     */
    +    public int getSize() {
    +        switch (type) {
    +        case Const.T_DOUBLE:
    +        case Const.T_LONG:
    +            return 2;
    +        case Const.T_VOID:
    +            return 0;
    +        default:
    +            return 1;
             }
         }
     
    +    /**
    +     * @return type as defined in Constants
    +     */
    +    public byte getType() {
    +        return type;
    +    }
     
    -    static int getReturnTypeSize(final String signature) {
    -        final int index = signature.lastIndexOf(')') + 1;
    -        return Type.size(getTypeSize(signature.substring(index)));
    +    /**
    +     * @return hashcode of Type
    +     */
    +    @Override
    +    public int hashCode() {
    +        return type ^ signature.hashCode();
         }
     
    +    /**
    +     * boolean, short and char variable are considered as int in the stack or local variable area. Returns {@link Type#INT}
    +     * for {@link Type#BOOLEAN}, {@link Type#SHORT} or {@link Type#CHAR}, otherwise returns the given type.
    +     *
    +     * @since 6.0
    +     */
    +    public Type normalizeForStackOrLocal() {
    +        if (this == Type.BOOLEAN || this == Type.BYTE || this == Type.SHORT || this == Type.CHAR) {
    +            return Type.INT;
    +        }
    +        return this;
    +    }
     
         /*
    -     * Currently only used by the ArrayType constructor.
    -     * The signature has a complicated dependency on other parameter
    -     * so it's tricky to do it in a call to the super ctor.
    +     * Currently only used by the ArrayType constructor. The signature has a complicated dependency on other parameter so
    +     * it's tricky to do it in a call to the super ctor.
          */
         void setSignature(final String signature) {
             this.signature = signature;
         }
    +
    +    /**
    +     * @return Type string, e.g. 'int[]'
    +     */
    +    @Override
    +    public String toString() {
    +        return this.equals(Type.NULL) || type >= Const.T_UNKNOWN ? signature : Utility.signatureToString(signature, false);
    +    }
     }
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java
    index 21f9f10b131..5a22942a6a7 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java
    @@ -22,11 +22,9 @@
     package com.sun.org.apache.bcel.internal.generic;
     
     /**
    - * Get the type associated with an instruction, int for ILOAD, or the type
    - * of the field of a PUTFIELD instruction, e.g..
    - *
    + * Get the type associated with an instruction, int for ILOAD, or the type of the field of a PUTFIELD instruction, e.g..
      */
     public interface TypedInstruction {
     
    -    Type getType( ConstantPoolGen cpg );
    +    Type getType(ConstantPoolGen cpg);
     }
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/UnconditionalBranch.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/UnconditionalBranch.java
    index 9f467cd3c64..8ccd7313e11 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/UnconditionalBranch.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/UnconditionalBranch.java
    @@ -24,7 +24,6 @@
     /**
      * Denotes an instruction to perform an unconditional branch, i.e., GOTO, JSR.
      *
    -
      * @see GOTO
      * @see JSR
      */
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/VariableLengthInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/VariableLengthInstruction.java
    index c146578cea3..63504550efc 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/VariableLengthInstruction.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/VariableLengthInstruction.java
    @@ -22,10 +22,9 @@
     package com.sun.org.apache.bcel.internal.generic;
     
     /**
    - * Denotes an instruction to be a variable length instruction, such as
    - * GOTO, JSR, LOOKUPSWITCH and TABLESWITCH.
    + * Denotes an instruction to be a variable length instruction, such as GOTO, JSR, LOOKUPSWITCH and TABLESWITCH.
    + *
      *
    -
      * @see GOTO
      * @see JSR
      * @see LOOKUPSWITCH
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Visitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Visitor.java
    index fa26c082f5c..fd70e8cd554 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Visitor.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Visitor.java
    @@ -22,556 +22,373 @@
     package com.sun.org.apache.bcel.internal.generic;
     
     /**
    - * Interface implementing the Visitor pattern programming style.
    - * I.e., a class that implements this interface can handle all types of
    - * instructions with the properly typed methods just by calling the accept()
    - * method.
    - *
    + * Interface implementing the Visitor pattern programming style. I.e., a class that implements this interface can handle
    + * all types of instructions with the properly typed methods just by calling the accept() method.
      */
     public interface Visitor {
     
    -    void visitStackInstruction( StackInstruction obj );
    -
    -
    -    void visitLocalVariableInstruction( LocalVariableInstruction obj );
    -
    -
    -    void visitBranchInstruction( BranchInstruction obj );
    -
    -
    -    void visitLoadClass( LoadClass obj );
    -
    -
    -    void visitFieldInstruction( FieldInstruction obj );
    -
    -
    -    void visitIfInstruction( IfInstruction obj );
    -
    -
    -    void visitConversionInstruction( ConversionInstruction obj );
    -
    -
    -    void visitPopInstruction( PopInstruction obj );
    -
    -
    -    void visitStoreInstruction( StoreInstruction obj );
    -
    -
    -    void visitTypedInstruction( TypedInstruction obj );
    -
    -
    -    void visitSelect( Select obj );
    -
    -
    -    void visitJsrInstruction( JsrInstruction obj );
    -
    -
    -    void visitGotoInstruction( GotoInstruction obj );
    -
    -
    -    void visitUnconditionalBranch( UnconditionalBranch obj );
    -
    -
    -    void visitPushInstruction( PushInstruction obj );
    -
    -
    -    void visitArithmeticInstruction( ArithmeticInstruction obj );
    -
    -
    -    void visitCPInstruction( CPInstruction obj );
    -
    -
    -    void visitInvokeInstruction( InvokeInstruction obj );
    -
    -
    -    void visitArrayInstruction( ArrayInstruction obj );
    -
    -
    -    void visitAllocationInstruction( AllocationInstruction obj );
    -
    -
    -    void visitReturnInstruction( ReturnInstruction obj );
    -
    -
    -    void visitFieldOrMethod( FieldOrMethod obj );
    -
    -
    -    void visitConstantPushInstruction( ConstantPushInstruction obj );
    -
    -
    -    void visitExceptionThrower( ExceptionThrower obj );
    -
    -
    -    void visitLoadInstruction( LoadInstruction obj );
    -
    -
    -    void visitVariableLengthInstruction( VariableLengthInstruction obj );
    -
    -
    -    void visitStackProducer( StackProducer obj );
    -
    -
    -    void visitStackConsumer( StackConsumer obj );
    -
    -
    -    void visitACONST_NULL( ACONST_NULL obj );
    -
    -
    -    void visitGETSTATIC( GETSTATIC obj );
    -
    -
    -    void visitIF_ICMPLT( IF_ICMPLT obj );
    -
    -
    -    void visitMONITOREXIT( MONITOREXIT obj );
    -
    -
    -    void visitIFLT( IFLT obj );
    -
    -
    -    void visitLSTORE( LSTORE obj );
    -
    -
    -    void visitPOP2( POP2 obj );
    -
    -
    -    void visitBASTORE( BASTORE obj );
    -
    -
    -    void visitISTORE( ISTORE obj );
    -
    -
    -    void visitCHECKCAST( CHECKCAST obj );
    -
    -
    -    void visitFCMPG( FCMPG obj );
    -
    -
    -    void visitI2F( I2F obj );
    -
    -
    -    void visitATHROW( ATHROW obj );
    -
    -
    -    void visitDCMPL( DCMPL obj );
    -
    -
    -    void visitARRAYLENGTH( ARRAYLENGTH obj );
    -
    -
    -    void visitDUP( DUP obj );
    -
    -
    -    void visitINVOKESTATIC( INVOKESTATIC obj );
    -
    -
    -    void visitLCONST( LCONST obj );
    +    void visitAALOAD(AALOAD obj);
     
    +    void visitAASTORE(AASTORE obj);
     
    -    void visitDREM( DREM obj );
    +    void visitACONST_NULL(ACONST_NULL obj);
     
    +    void visitAllocationInstruction(AllocationInstruction obj);
     
    -    void visitIFGE( IFGE obj );
    +    void visitALOAD(ALOAD obj);
     
    +    void visitANEWARRAY(ANEWARRAY obj);
     
    -    void visitCALOAD( CALOAD obj );
    +    void visitARETURN(ARETURN obj);
     
    +    void visitArithmeticInstruction(ArithmeticInstruction obj);
     
    -    void visitLASTORE( LASTORE obj );
    +    void visitArrayInstruction(ArrayInstruction obj);
     
    +    void visitARRAYLENGTH(ARRAYLENGTH obj);
     
    -    void visitI2D( I2D obj );
    +    void visitASTORE(ASTORE obj);
     
    +    void visitATHROW(ATHROW obj);
     
    -    void visitDADD( DADD obj );
    +    void visitBALOAD(BALOAD obj);
     
    +    void visitBASTORE(BASTORE obj);
     
    -    void visitINVOKESPECIAL( INVOKESPECIAL obj );
    +    void visitBIPUSH(BIPUSH obj);
     
    +    void visitBranchInstruction(BranchInstruction obj);
     
    -    void visitIAND( IAND obj );
    +    void visitBREAKPOINT(BREAKPOINT obj);
     
    +    void visitCALOAD(CALOAD obj);
     
    -    void visitPUTFIELD( PUTFIELD obj );
    +    void visitCASTORE(CASTORE obj);
     
    +    void visitCHECKCAST(CHECKCAST obj);
     
    -    void visitILOAD( ILOAD obj );
    +    void visitConstantPushInstruction(ConstantPushInstruction obj);
     
    +    void visitConversionInstruction(ConversionInstruction obj);
     
    -    void visitDLOAD( DLOAD obj );
    +    void visitCPInstruction(CPInstruction obj);
     
    +    void visitD2F(D2F obj);
     
    -    void visitDCONST( DCONST obj );
    +    void visitD2I(D2I obj);
     
    +    void visitD2L(D2L obj);
     
    -    void visitNEW( NEW obj );
    +    void visitDADD(DADD obj);
     
    +    void visitDALOAD(DALOAD obj);
     
    -    void visitIFNULL( IFNULL obj );
    +    void visitDASTORE(DASTORE obj);
     
    +    void visitDCMPG(DCMPG obj);
     
    -    void visitLSUB( LSUB obj );
    +    void visitDCMPL(DCMPL obj);
     
    +    void visitDCONST(DCONST obj);
     
    -    void visitL2I( L2I obj );
    +    void visitDDIV(DDIV obj);
     
    +    void visitDLOAD(DLOAD obj);
     
    -    void visitISHR( ISHR obj );
    +    void visitDMUL(DMUL obj);
     
    +    void visitDNEG(DNEG obj);
     
    -    void visitTABLESWITCH( TABLESWITCH obj );
    +    void visitDREM(DREM obj);
     
    +    void visitDRETURN(DRETURN obj);
     
    -    void visitIINC( IINC obj );
    +    void visitDSTORE(DSTORE obj);
     
    +    void visitDSUB(DSUB obj);
     
    -    void visitDRETURN( DRETURN obj );
    +    void visitDUP(DUP obj);
     
    +    void visitDUP_X1(DUP_X1 obj);
     
    -    void visitFSTORE( FSTORE obj );
    +    void visitDUP_X2(DUP_X2 obj);
     
    +    void visitDUP2(DUP2 obj);
     
    -    void visitDASTORE( DASTORE obj );
    +    void visitDUP2_X1(DUP2_X1 obj);
     
    +    void visitDUP2_X2(DUP2_X2 obj);
     
    -    void visitIALOAD( IALOAD obj );
    +    void visitExceptionThrower(ExceptionThrower obj);
     
    +    void visitF2D(F2D obj);
     
    -    void visitDDIV( DDIV obj );
    +    void visitF2I(F2I obj);
     
    +    void visitF2L(F2L obj);
     
    -    void visitIF_ICMPGE( IF_ICMPGE obj );
    +    void visitFADD(FADD obj);
     
    +    void visitFALOAD(FALOAD obj);
     
    -    void visitLAND( LAND obj );
    +    void visitFASTORE(FASTORE obj);
     
    +    void visitFCMPG(FCMPG obj);
     
    -    void visitIDIV( IDIV obj );
    +    void visitFCMPL(FCMPL obj);
     
    +    void visitFCONST(FCONST obj);
     
    -    void visitLOR( LOR obj );
    +    void visitFDIV(FDIV obj);
     
    +    void visitFieldInstruction(FieldInstruction obj);
     
    -    void visitCASTORE( CASTORE obj );
    +    void visitFieldOrMethod(FieldOrMethod obj);
     
    +    void visitFLOAD(FLOAD obj);
     
    -    void visitFREM( FREM obj );
    +    void visitFMUL(FMUL obj);
     
    +    void visitFNEG(FNEG obj);
     
    -    void visitLDC( LDC obj );
    +    void visitFREM(FREM obj);
     
    +    void visitFRETURN(FRETURN obj);
     
    -    void visitBIPUSH( BIPUSH obj );
    +    void visitFSTORE(FSTORE obj);
     
    +    void visitFSUB(FSUB obj);
     
    -    void visitDSTORE( DSTORE obj );
    +    void visitGETFIELD(GETFIELD obj);
     
    +    void visitGETSTATIC(GETSTATIC obj);
     
    -    void visitF2L( F2L obj );
    +    void visitGOTO(GOTO obj);
     
    +    void visitGOTO_W(GOTO_W obj);
     
    -    void visitFMUL( FMUL obj );
    +    void visitGotoInstruction(GotoInstruction obj);
     
    +    void visitI2B(I2B obj);
     
    -    void visitLLOAD( LLOAD obj );
    +    void visitI2C(I2C obj);
     
    +    void visitI2D(I2D obj);
     
    -    void visitJSR( JSR obj );
    +    void visitI2F(I2F obj);
     
    +    void visitI2L(I2L obj);
     
    -    void visitFSUB( FSUB obj );
    +    void visitI2S(I2S obj);
     
    +    void visitIADD(IADD obj);
     
    -    void visitSASTORE( SASTORE obj );
    +    void visitIALOAD(IALOAD obj);
     
    +    void visitIAND(IAND obj);
     
    -    void visitALOAD( ALOAD obj );
    +    void visitIASTORE(IASTORE obj);
     
    +    void visitICONST(ICONST obj);
     
    -    void visitDUP2_X2( DUP2_X2 obj );
    +    void visitIDIV(IDIV obj);
     
    +    void visitIF_ACMPEQ(IF_ACMPEQ obj);
     
    -    void visitRETURN( RETURN obj );
    +    void visitIF_ACMPNE(IF_ACMPNE obj);
     
    +    void visitIF_ICMPEQ(IF_ICMPEQ obj);
     
    -    void visitDALOAD( DALOAD obj );
    +    void visitIF_ICMPGE(IF_ICMPGE obj);
     
    +    void visitIF_ICMPGT(IF_ICMPGT obj);
     
    -    void visitSIPUSH( SIPUSH obj );
    +    void visitIF_ICMPLE(IF_ICMPLE obj);
     
    +    void visitIF_ICMPLT(IF_ICMPLT obj);
     
    -    void visitDSUB( DSUB obj );
    +    void visitIF_ICMPNE(IF_ICMPNE obj);
     
    +    void visitIFEQ(IFEQ obj);
     
    -    void visitL2F( L2F obj );
    +    void visitIFGE(IFGE obj);
     
    +    void visitIFGT(IFGT obj);
     
    -    void visitIF_ICMPGT( IF_ICMPGT obj );
    +    void visitIfInstruction(IfInstruction obj);
     
    +    void visitIFLE(IFLE obj);
     
    -    void visitF2D( F2D obj );
    +    void visitIFLT(IFLT obj);
     
    +    void visitIFNE(IFNE obj);
     
    -    void visitI2L( I2L obj );
    +    void visitIFNONNULL(IFNONNULL obj);
     
    +    void visitIFNULL(IFNULL obj);
     
    -    void visitIF_ACMPNE( IF_ACMPNE obj );
    +    void visitIINC(IINC obj);
     
    +    void visitILOAD(ILOAD obj);
     
    -    void visitPOP( POP obj );
    +    void visitIMPDEP1(IMPDEP1 obj);
     
    +    void visitIMPDEP2(IMPDEP2 obj);
     
    -    void visitI2S( I2S obj );
    +    void visitIMUL(IMUL obj);
     
    +    void visitINEG(INEG obj);
     
    -    void visitIFEQ( IFEQ obj );
    -
    -
    -    void visitSWAP( SWAP obj );
    -
    -
    -    void visitIOR( IOR obj );
    -
    -
    -    void visitIREM( IREM obj );
    -
    -
    -    void visitIASTORE( IASTORE obj );
    -
    -
    -    void visitNEWARRAY( NEWARRAY obj );
    -
    -
    -    void visitINVOKEINTERFACE( INVOKEINTERFACE obj );
    -
    -
    -    void visitINEG( INEG obj );
    -
    -
    -    void visitLCMP( LCMP obj );
    -
    -
    -    void visitJSR_W( JSR_W obj );
    -
    -
    -    void visitMULTIANEWARRAY( MULTIANEWARRAY obj );
    -
    -
    -    void visitDUP_X2( DUP_X2 obj );
    -
    -
    -    void visitSALOAD( SALOAD obj );
    -
    -
    -    void visitIFNONNULL( IFNONNULL obj );
    -
    -
    -    void visitDMUL( DMUL obj );
    -
    -
    -    void visitIFNE( IFNE obj );
    -
    -
    -    void visitIF_ICMPLE( IF_ICMPLE obj );
    -
    -
    -    void visitLDC2_W( LDC2_W obj );
    -
    -
    -    void visitGETFIELD( GETFIELD obj );
    -
    -
    -    void visitLADD( LADD obj );
    -
    -
    -    void visitNOP( NOP obj );
    -
    -
    -    void visitFALOAD( FALOAD obj );
    -
    -
    -    void visitINSTANCEOF( INSTANCEOF obj );
    -
    -
    -    void visitIFLE( IFLE obj );
    -
    -
    -    void visitLXOR( LXOR obj );
    -
    -
    -    void visitLRETURN( LRETURN obj );
    -
    -
    -    void visitFCONST( FCONST obj );
    -
    -
    -    void visitIUSHR( IUSHR obj );
    -
    -
    -    void visitBALOAD( BALOAD obj );
    -
    -
    -    void visitDUP2( DUP2 obj );
    -
    -
    -    void visitIF_ACMPEQ( IF_ACMPEQ obj );
    -
    -
    -    void visitIMPDEP1( IMPDEP1 obj );
    -
    -
    -    void visitMONITORENTER( MONITORENTER obj );
    -
    -
    -    void visitLSHL( LSHL obj );
    -
    -
    -    void visitDCMPG( DCMPG obj );
    -
    -
    -    void visitD2L( D2L obj );
    -
    -
    -    void visitIMPDEP2( IMPDEP2 obj );
    -
    -
    -    void visitL2D( L2D obj );
    -
    -
    -    void visitRET( RET obj );
    -
    -
    -    void visitIFGT( IFGT obj );
    -
    -
    -    void visitIXOR( IXOR obj );
    -
    -
    -    void visitINVOKEVIRTUAL( INVOKEVIRTUAL obj );
    -
    +    void visitINSTANCEOF(INSTANCEOF obj);
     
         /**
          * @since 6.0
          */
    -    void visitINVOKEDYNAMIC( INVOKEDYNAMIC obj );
    -
    -
    -    void visitFASTORE( FASTORE obj );
    -
    -
    -    void visitIRETURN( IRETURN obj );
    -
    -
    -    void visitIF_ICMPNE( IF_ICMPNE obj );
    -
    +    void visitINVOKEDYNAMIC(INVOKEDYNAMIC obj);
     
    -    void visitFLOAD( FLOAD obj );
    +    void visitInvokeInstruction(InvokeInstruction obj);
     
    +    void visitINVOKEINTERFACE(INVOKEINTERFACE obj);
     
    -    void visitLDIV( LDIV obj );
    +    void visitINVOKESPECIAL(INVOKESPECIAL obj);
     
    +    void visitINVOKESTATIC(INVOKESTATIC obj);
     
    -    void visitPUTSTATIC( PUTSTATIC obj );
    +    void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj);
     
    +    void visitIOR(IOR obj);
     
    -    void visitAALOAD( AALOAD obj );
    +    void visitIREM(IREM obj);
     
    +    void visitIRETURN(IRETURN obj);
     
    -    void visitD2I( D2I obj );
    +    void visitISHL(ISHL obj);
     
    +    void visitISHR(ISHR obj);
     
    -    void visitIF_ICMPEQ( IF_ICMPEQ obj );
    +    void visitISTORE(ISTORE obj);
     
    +    void visitISUB(ISUB obj);
     
    -    void visitAASTORE( AASTORE obj );
    +    void visitIUSHR(IUSHR obj);
     
    +    void visitIXOR(IXOR obj);
     
    -    void visitARETURN( ARETURN obj );
    +    void visitJSR(JSR obj);
     
    +    void visitJSR_W(JSR_W obj);
     
    -    void visitDUP2_X1( DUP2_X1 obj );
    +    void visitJsrInstruction(JsrInstruction obj);
     
    +    void visitL2D(L2D obj);
     
    -    void visitFNEG( FNEG obj );
    +    void visitL2F(L2F obj);
     
    +    void visitL2I(L2I obj);
     
    -    void visitGOTO_W( GOTO_W obj );
    +    void visitLADD(LADD obj);
     
    +    void visitLALOAD(LALOAD obj);
     
    -    void visitD2F( D2F obj );
    +    void visitLAND(LAND obj);
     
    +    void visitLASTORE(LASTORE obj);
     
    -    void visitGOTO( GOTO obj );
    +    void visitLCMP(LCMP obj);
     
    +    void visitLCONST(LCONST obj);
     
    -    void visitISUB( ISUB obj );
    +    void visitLDC(LDC obj);
     
    +    void visitLDC2_W(LDC2_W obj);
     
    -    void visitF2I( F2I obj );
    +    void visitLDIV(LDIV obj);
     
    +    void visitLLOAD(LLOAD obj);
     
    -    void visitDNEG( DNEG obj );
    +    void visitLMUL(LMUL obj);
     
    +    void visitLNEG(LNEG obj);
     
    -    void visitICONST( ICONST obj );
    +    void visitLoadClass(LoadClass obj);
     
    +    void visitLoadInstruction(LoadInstruction obj);
     
    -    void visitFDIV( FDIV obj );
    +    void visitLocalVariableInstruction(LocalVariableInstruction obj);
     
    +    void visitLOOKUPSWITCH(LOOKUPSWITCH obj);
     
    -    void visitI2B( I2B obj );
    +    void visitLOR(LOR obj);
     
    +    void visitLREM(LREM obj);
     
    -    void visitLNEG( LNEG obj );
    +    void visitLRETURN(LRETURN obj);
     
    +    void visitLSHL(LSHL obj);
     
    -    void visitLREM( LREM obj );
    +    void visitLSHR(LSHR obj);
     
    +    void visitLSTORE(LSTORE obj);
     
    -    void visitIMUL( IMUL obj );
    +    void visitLSUB(LSUB obj);
     
    +    void visitLUSHR(LUSHR obj);
     
    -    void visitIADD( IADD obj );
    +    void visitLXOR(LXOR obj);
     
    +    void visitMONITORENTER(MONITORENTER obj);
     
    -    void visitLSHR( LSHR obj );
    +    void visitMONITOREXIT(MONITOREXIT obj);
     
    +    void visitMULTIANEWARRAY(MULTIANEWARRAY obj);
     
    -    void visitLOOKUPSWITCH( LOOKUPSWITCH obj );
    +    void visitNEW(NEW obj);
     
    +    void visitNEWARRAY(NEWARRAY obj);
     
    -    void visitDUP_X1( DUP_X1 obj );
    +    void visitNOP(NOP obj);
     
    +    void visitPOP(POP obj);
     
    -    void visitFCMPL( FCMPL obj );
    +    void visitPOP2(POP2 obj);
     
    +    void visitPopInstruction(PopInstruction obj);
     
    -    void visitI2C( I2C obj );
    +    void visitPushInstruction(PushInstruction obj);
     
    +    void visitPUTFIELD(PUTFIELD obj);
     
    -    void visitLMUL( LMUL obj );
    +    void visitPUTSTATIC(PUTSTATIC obj);
     
    +    void visitRET(RET obj);
     
    -    void visitLUSHR( LUSHR obj );
    +    void visitRETURN(RETURN obj);
     
    +    void visitReturnInstruction(ReturnInstruction obj);
     
    -    void visitISHL( ISHL obj );
    +    void visitSALOAD(SALOAD obj);
     
    +    void visitSASTORE(SASTORE obj);
     
    -    void visitLALOAD( LALOAD obj );
    +    void visitSelect(Select obj);
     
    +    void visitSIPUSH(SIPUSH obj);
     
    -    void visitASTORE( ASTORE obj );
    +    void visitStackConsumer(StackConsumer obj);
     
    +    void visitStackInstruction(StackInstruction obj);
     
    -    void visitANEWARRAY( ANEWARRAY obj );
    +    void visitStackProducer(StackProducer obj);
     
    +    void visitStoreInstruction(StoreInstruction obj);
     
    -    void visitFRETURN( FRETURN obj );
    +    void visitSWAP(SWAP obj);
     
    +    void visitTABLESWITCH(TABLESWITCH obj);
     
    -    void visitFADD( FADD obj );
    +    void visitTypedInstruction(TypedInstruction obj);
     
    +    void visitUnconditionalBranch(UnconditionalBranch obj);
     
    -    void visitBREAKPOINT( BREAKPOINT obj );
    +    void visitVariableLengthInstruction(VariableLengthInstruction obj);
     }
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Args.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Args.java
    new file mode 100644
    index 00000000000..a61d9d35d2a
    --- /dev/null
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Args.java
    @@ -0,0 +1,148 @@
    +/*
    + * reserved comment block
    + * DO NOT REMOVE OR ALTER!
    + */
    +/*
    + * Licensed to the Apache Software Foundation (ASF) under one or more
    + * contributor license agreements.  See the NOTICE file distributed with
    + * this work for additional information regarding copyright ownership.
    + * The ASF licenses this file to You under the Apache License, Version 2.0
    + * (the "License"); you may not use this file except in compliance with
    + * the License.  You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + *  Unless required by applicable law or agreed to in writing, software
    + *  distributed under the License is distributed on an "AS IS" BASIS,
    + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + *  See the License for the specific language governing permissions and
    + *  limitations under the License.
    + */
    +
    +package com.sun.org.apache.bcel.internal.util;
    +
    +import com.sun.org.apache.bcel.internal.Const;
    +import com.sun.org.apache.bcel.internal.classfile.ClassFormatException;
    +
    +/**
    + * Argument validation.
    + *
    + * @since 6.7.0
    + */
    +public class Args {
    +
    +    /**
    +     * Requires a specific value.
    +     *
    +     * @param value    The value to test.
    +     * @param required The required value.
    +     * @param message  The message prefix
    +     * @return The value to test.
    +     */
    +    public static int require(final int value, final int required, final String message) {
    +        if (value != required) {
    +            throw new ClassFormatException(String.format("%s [Value must be 0: %,d]", message, value));
    +        }
    +        return value;
    +    }
    +
    +    /**
    +     * Requires a 0 value.
    +     *
    +     * @param value   The value to test.
    +     * @param message The message prefix
    +     * @return The value to test.
    +     */
    +    public static int require0(final int value, final String message) {
    +        return require(value, 0, message);
    +    }
    +
    +    /**
    +     * Requires a u1 value.
    +     *
    +     * @param value   The value to test.
    +     * @param message The message prefix
    +     * @return The value to test.
    +     */
    +    public static int requireU1(final int value, final String message) {
    +        if (value < 0 || value > Const.MAX_BYTE) {
    +            throw new ClassFormatException(String.format("%s [Value out of range (0 - %,d) for type u1: %,d]", message, Const.MAX_BYTE, value));
    +        }
    +        return value;
    +    }
    +
    +    /**
    +     * Requires a u2 value of at least {@code min} and not above {@code max}.
    +     *
    +     * @param value   The value to test.
    +     * @param min     The minimum required u2 value.
    +     * @param max     The maximum required u2 value.
    +     * @param message The message prefix
    +     * @return The value to test.
    +     */
    +    public static int requireU2(final int value, final int min, final int max, final String message) {
    +        if (max > Const.MAX_SHORT) {
    +            throw new IllegalArgumentException(String.format("%s programming error: max %,d > %,d", message, max, Const.MAX_SHORT));
    +        }
    +        if (min < 0) {
    +            throw new IllegalArgumentException(String.format("%s programming error: min %,d < 0", message, min));
    +        }
    +        if (value < min || value > max) {
    +            throw new ClassFormatException(String.format("%s [Value out of range (%,d - %,d) for type u2: %,d]", message, min, Const.MAX_SHORT, value));
    +        }
    +        return value;
    +    }
    +
    +    /**
    +     * Requires a u2 value of at least {@code min}.
    +     *
    +     * @param value   The value to test.
    +     * @param min     The minimum required value.
    +     * @param message The message prefix
    +     * @return The value to test.
    +     */
    +    public static int requireU2(final int value, final int min, final String message) {
    +        return requireU2(value, min, Const.MAX_SHORT, message);
    +    }
    +
    +    /**
    +     * Requires a u2 value.
    +     *
    +     * @param value   The value to test.
    +     * @param message The message prefix
    +     * @return The value to test.
    +     */
    +    public static int requireU2(final int value, final String message) {
    +        return requireU2(value, 0, message);
    +    }
    +
    +    /**
    +     * Requires a u4 value of at least {@code min}.
    +     *
    +     * @param value   The value to test.
    +     * @param min     The minimum required value.
    +     * @param message The message prefix
    +     * @return The value to test.
    +     */
    +    public static int requireU4(final int value, final int min, final String message) {
    +        if (min < 0) {
    +            throw new IllegalArgumentException(String.format("%s programming error: min %,d < 0", message, min));
    +        }
    +        if (value < min) {
    +            throw new ClassFormatException(
    +                    String.format("%s [Value out of range (%,d - %,d) for type u2: %,d]", message, min, Integer.MAX_VALUE, value & 0xFFFFFFFFL));
    +        }
    +        return value;
    +    }
    +
    +    /**
    +     * Requires a u4 value.
    +     *
    +     * @param value   The value to test.
    +     * @param message The message prefix
    +     * @return The value to test.
    +     */
    +    public static int requireU4(final int value, final String message) {
    +        return requireU4(value, 0, message);
    +    }
    +}
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/AttributeHTML.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/AttributeHTML.java
    index 6dafdd79b13..4a84901fc56 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/AttributeHTML.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/AttributeHTML.java
    @@ -21,196 +21,175 @@
     
     package com.sun.org.apache.bcel.internal.util;
     
    -import java.io.FileOutputStream;
    -import java.io.IOException;
    +import java.io.Closeable;
    +import java.io.FileNotFoundException;
     import java.io.PrintWriter;
    +import java.io.UnsupportedEncodingException;
    +import java.nio.charset.Charset;
     
     import com.sun.org.apache.bcel.internal.Const;
     import com.sun.org.apache.bcel.internal.classfile.Attribute;
     import com.sun.org.apache.bcel.internal.classfile.Code;
     import com.sun.org.apache.bcel.internal.classfile.CodeException;
     import com.sun.org.apache.bcel.internal.classfile.ConstantPool;
    -import com.sun.org.apache.bcel.internal.classfile.ConstantUtf8;
     import com.sun.org.apache.bcel.internal.classfile.ConstantValue;
     import com.sun.org.apache.bcel.internal.classfile.ExceptionTable;
     import com.sun.org.apache.bcel.internal.classfile.InnerClass;
     import com.sun.org.apache.bcel.internal.classfile.InnerClasses;
     import com.sun.org.apache.bcel.internal.classfile.LineNumber;
     import com.sun.org.apache.bcel.internal.classfile.LineNumberTable;
    -import com.sun.org.apache.bcel.internal.classfile.LocalVariable;
     import com.sun.org.apache.bcel.internal.classfile.LocalVariableTable;
     import com.sun.org.apache.bcel.internal.classfile.SourceFile;
     import com.sun.org.apache.bcel.internal.classfile.Utility;
     
     /**
      * Convert found attributes into HTML file.
    - *
    - *
      */
    -final class AttributeHTML {
    +final class AttributeHTML implements Closeable {
     
    -    private final String class_name; // name of current class
    -    private final PrintWriter file; // file to write to
    -    private int attr_count = 0;
    -    private final ConstantHTML constant_html;
    -    private final ConstantPool constant_pool;
    +    private final String className; // name of current class
    +    private final PrintWriter printWriter; // file to write to
    +    private int attrCount;
    +    private final ConstantHTML constantHtml;
    +    private final ConstantPool constantPool;
     
    -
    -    AttributeHTML(final String dir, final String class_name, final ConstantPool constant_pool,
    -            final ConstantHTML constant_html) throws IOException {
    -        this.class_name = class_name;
    -        this.constant_pool = constant_pool;
    -        this.constant_html = constant_html;
    -        file = new PrintWriter(new FileOutputStream(dir + class_name + "_attributes.html"));
    -        file.println("");
    +    AttributeHTML(final String dir, final String className, final ConstantPool constantPool, final ConstantHTML constantHtml, final Charset charset)
    +        throws FileNotFoundException, UnsupportedEncodingException {
    +        this.className = className;
    +        this.constantPool = constantPool;
    +        this.constantHtml = constantHtml;
    +        printWriter = new PrintWriter(dir + className + "_attributes.html", charset.name());
    +        printWriter.print("");
    +        printWriter.println("
    "); } - - private String codeLink( final int link, final int method_number ) { - return "" + link + ""; + @Override + public void close() { + printWriter.println("
    "); + printWriter.close(); } - - void close() { - file.println(""); - file.close(); + private String codeLink(final int link, final int methodNumber) { + return "" + link + ""; } - - void writeAttribute( final Attribute attribute, final String anchor ) { + void writeAttribute(final Attribute attribute, final String anchor) { writeAttribute(attribute, anchor, 0); } - - void writeAttribute( final Attribute attribute, final String anchor, final int method_number ) { + void writeAttribute(final Attribute attribute, final String anchor, final int methodNumber) { final byte tag = attribute.getTag(); int index; if (tag == Const.ATTR_UNKNOWN) { return; } - attr_count++; // Increment number of attributes found so far - if (attr_count % 2 == 0) { - file.print(""); + attrCount++; // Increment number of attributes found so far + if (attrCount % 2 == 0) { + printWriter.print(""); } else { - file.print(""); + printWriter.print(""); } - file.println("

    " + attr_count + " " + Const.getAttributeName(tag) - + "

    "); - /* Handle different attributes + printWriter.println("

    " + attrCount + " " + Const.getAttributeName(tag) + "

    "); + /* + * Handle different attributes */ switch (tag) { - case Const.ATTR_CODE: - final Code c = (Code) attribute; - // Some directly printable values - file.print("
    • Maximum stack size = " + c.getMaxStack() - + "
    • \n
    • Number of local variables = " + c.getMaxLocals() - + "
    • \n
    • Byte code
    \n"); - // Get handled exceptions and list them - final CodeException[] ce = c.getExceptionTable(); - final int len = ce.length; - if (len > 0) { - file.print("

    Exceptions handled

      "); - for (final CodeException cex : ce) { - final int catch_type = cex.getCatchType(); // Index in constant pool - file.print("
    • "); - if (catch_type != 0) { - file.print(constant_html.referenceConstant(catch_type)); // Create Link to _cp.html - } else { - file.print("Any Exception"); - } - file.print("
      (Ranging from lines " - + codeLink(cex.getStartPC(), method_number) + " to " - + codeLink(cex.getEndPC(), method_number) + ", handled at line " - + codeLink(cex.getHandlerPC(), method_number) + ")
    • "); - } - file.print("
    "); - } - break; - case Const.ATTR_CONSTANT_VALUE: - index = ((ConstantValue) attribute).getConstantValueIndex(); - // Reference _cp.html - file.print("\n"); - break; - case Const.ATTR_SOURCE_FILE: - index = ((SourceFile) attribute).getSourceFileIndex(); - // Reference _cp.html - file.print("\n"); - break; - case Const.ATTR_EXCEPTIONS: - // List thrown exceptions - final int[] indices = ((ExceptionTable) attribute).getExceptionIndexTable(); - file.print("\n"); - break; - case Const.ATTR_LINE_NUMBER_TABLE: - final LineNumber[] line_numbers = ((LineNumberTable) attribute).getLineNumberTable(); - // List line number pairs - file.print("

    "); - for (int i = 0; i < line_numbers.length; i++) { - file.print("(" + line_numbers[i].getStartPC() + ", " - + line_numbers[i].getLineNumber() + ")"); - if (i < line_numbers.length - 1) { - file.print(", "); // breakable + case Const.ATTR_CODE: + final Code c = (Code) attribute; + // Some directly printable values + printWriter.print("

    • Maximum stack size = " + c.getMaxStack() + "
    • \n
    • Number of local variables = " + c.getMaxLocals() + + "
    • \n
    • Byte code
    \n"); + // Get handled exceptions and list them + final CodeException[] ce = c.getExceptionTable(); + final int len = ce.length; + if (len > 0) { + printWriter.print("

    Exceptions handled

      "); + for (final CodeException cex : ce) { + final int catchType = cex.getCatchType(); // Index in constant pool + printWriter.print("
    • "); + if (catchType != 0) { + printWriter.print(constantHtml.referenceConstant(catchType)); // Create Link to _cp.html + } else { + printWriter.print("Any Exception"); } + printWriter.print("
      (Ranging from lines " + codeLink(cex.getStartPC(), methodNumber) + " to " + codeLink(cex.getEndPC(), methodNumber) + + ", handled at line " + codeLink(cex.getHandlerPC(), methodNumber) + ")
    • "); } - break; - case Const.ATTR_LOCAL_VARIABLE_TABLE: - final LocalVariable[] vars = ((LocalVariableTable) attribute).getLocalVariableTable(); - // List name, range and type - file.print("
        "); - for (final LocalVariable var : vars) { - index = var.getSignatureIndex(); - String signature = ((ConstantUtf8) constant_pool.getConstant(index, - Const.CONSTANT_Utf8)).getBytes(); - signature = Utility.signatureToString(signature, false); - final int start = var.getStartPC(); - final int end = start + var.getLength(); - file.println("
      • " + Class2HTML.referenceType(signature) + " " - + var.getName() + " in slot %" + var.getIndex() - + "
        Valid from lines " + "" - + start + " to " + "" + end + "
      • "); + printWriter.print("
      "); + } + break; + case Const.ATTR_CONSTANT_VALUE: + index = ((ConstantValue) attribute).getConstantValueIndex(); + // Reference _cp.html + printWriter + .print("\n"); + break; + case Const.ATTR_SOURCE_FILE: + index = ((SourceFile) attribute).getSourceFileIndex(); + // Reference _cp.html + printWriter + .print("\n"); + break; + case Const.ATTR_EXCEPTIONS: + // List thrown exceptions + final int[] indices = ((ExceptionTable) attribute).getExceptionIndexTable(); + printWriter.print("\n"); + break; + case Const.ATTR_LINE_NUMBER_TABLE: + final LineNumber[] lineNumbers = ((LineNumberTable) attribute).getLineNumberTable(); + // List line number pairs + printWriter.print("

      "); + for (int i = 0; i < lineNumbers.length; i++) { + printWriter.print("(" + lineNumbers[i].getStartPC() + ", " + lineNumbers[i].getLineNumber() + ")"); + if (i < lineNumbers.length - 1) { + printWriter.print(", "); // breakable } - file.print("

    \n"); - break; - case Const.ATTR_INNER_CLASSES: - final InnerClass[] classes = ((InnerClasses) attribute).getInnerClasses(); - // List inner classes - file.print("
      "); - for (final InnerClass classe : classes) { - String name; - String access; - index = classe.getInnerNameIndex(); - if (index > 0) { - name = ((ConstantUtf8) constant_pool.getConstant(index, Const.CONSTANT_Utf8)) - .getBytes(); - } else { - name = "<anonymous>"; - } - access = Utility.accessToString(classe.getInnerAccessFlags()); - file.print("
    • " + access + " " - + constant_html.referenceConstant(classe.getInnerClassIndex()) - + " in class " - + constant_html.referenceConstant(classe.getOuterClassIndex()) - + " named " + name + "
    • \n"); + } + break; + case Const.ATTR_LOCAL_VARIABLE_TABLE: + // List name, range and type + printWriter.print("
        "); + ((LocalVariableTable) attribute).forEach(var -> { + final int sigIdx = var.getSignatureIndex(); + String signature = constantPool.getConstantUtf8(sigIdx).getBytes(); + signature = Utility.signatureToString(signature, false); + final int start = var.getStartPC(); + final int end = start + var.getLength(); + printWriter.println("
      • " + Class2HTML.referenceType(signature) + " " + var.getName() + " in slot %" + var.getIndex() + + "
        Valid from lines " + "" + start + + " to " + "" + end + "
      • "); + }); + printWriter.print("
      \n"); + break; + case Const.ATTR_INNER_CLASSES: + // List inner classes + printWriter.print("
        "); + for (final InnerClass clazz : ((InnerClasses) attribute).getInnerClasses()) { + final String name; + final String access; + index = clazz.getInnerNameIndex(); + if (index > 0) { + name = constantPool.getConstantUtf8(index).getBytes(); + } else { + name = "<anonymous>"; } - file.print("
      \n"); - break; - default: // Such as Unknown attribute or Deprecated - file.print("

      " + attribute); + access = Utility.accessToString(clazz.getInnerAccessFlags()); + printWriter.print("

    • " + access + " " + constantHtml.referenceConstant(clazz.getInnerClassIndex()) + + " in class " + constantHtml.referenceConstant(clazz.getOuterClassIndex()) + " named " + name + "
    • \n"); + } + printWriter.print("
    \n"); + break; + default: // Such as Unknown attribute or Deprecated + printWriter.print("

    " + attribute); } - file.println(""); - file.flush(); + printWriter.println(""); + printWriter.flush(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java index e83fd24c1cb..2e663bfdaa1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java @@ -35,8 +35,7 @@ public interface BCELComparator { * @param THAT * @return true if and only if THIS equals THAT */ - boolean equals( Object THIS, Object THAT ); - + boolean equals(Object THIS, Object THAT); /** * Return hashcode for THIS.hashCode() @@ -44,5 +43,5 @@ public interface BCELComparator { * @param THIS * @return hashcode for THIS.hashCode() */ - int hashCode( Object THIS ); + int hashCode(Object THIS); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java index ae7f74099e9..c931fb1e422 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -60,45 +60,85 @@ import com.sun.org.apache.bcel.internal.generic.Type; /** - * Factory creates il.append() statements, and sets instruction targets. - * A helper class for BCELifier. + * Factory creates il.append() statements, and sets instruction targets. A helper class for BCELifier. * * @see BCELifier - * @LastModified: May 2021 + * @LastModified: Feb 2023 */ class BCELFactory extends EmptyVisitor { - private static final String CONSTANT_PREFIX = Const.class.getSimpleName()+"."; - private final MethodGen _mg; - private final PrintWriter _out; - private final ConstantPoolGen _cp; + private static final String CONSTANT_PREFIX = Const.class.getSimpleName() + "."; + private final MethodGen methodGen; + private final PrintWriter printWriter; + private final ConstantPoolGen constantPoolGen; + private final Map branchMap = new HashMap<>(); + + // Memorize BranchInstructions that need an update + private final List branches = new ArrayList<>(); BCELFactory(final MethodGen mg, final PrintWriter out) { - _mg = mg; - _cp = mg.getConstantPool(); - _out = out; + methodGen = mg; + constantPoolGen = mg.getConstantPool(); + printWriter = out; } - private final Map branch_map = new HashMap<>(); + private void createConstant(final Object value) { + String embed = value.toString(); + if (value instanceof String) { + embed = '"' + Utility.convertString(embed) + '"'; + } else if (value instanceof Character) { + embed = "(char)0x" + Integer.toHexString(((Character) value).charValue()); + } else if (value instanceof Float) { + final Float f = (Float) value; + if (Float.isNaN(f)) { + embed = "Float.NaN"; + } else if (f == Float.POSITIVE_INFINITY) { + embed = "Float.POSITIVE_INFINITY"; + } else if (f == Float.NEGATIVE_INFINITY) { + embed = "Float.NEGATIVE_INFINITY"; + } else { + embed += "f"; + } + } else if (value instanceof Double) { + final Double d = (Double) value; + if (Double.isNaN(d)) { + embed = "Double.NaN"; + } else if (d == Double.POSITIVE_INFINITY) { + embed = "Double.POSITIVE_INFINITY"; + } else if (d == Double.NEGATIVE_INFINITY) { + embed = "Double.NEGATIVE_INFINITY"; + } else { + embed += "d"; + } + } else if (value instanceof Long) { + embed += "L"; + } else if (value instanceof ObjectType) { + final ObjectType ot = (ObjectType) value; + embed = "new ObjectType(\"" + ot.getClassName() + "\")"; + } else if (value instanceof ArrayType) { + final ArrayType at = (ArrayType) value; + embed = "new ArrayType(" + BCELifier.printType(at.getBasicType()) + ", " + at.getDimensions() + ")"; + } + printWriter.println("il.append(new PUSH(_cp, " + embed + "));"); + } public void start() { - if (!_mg.isAbstract() && !_mg.isNative()) { - for (InstructionHandle ih = _mg.getInstructionList().getStart(); ih != null; ih = ih - .getNext()) { + if (!methodGen.isAbstract() && !methodGen.isNative()) { + for (InstructionHandle ih = methodGen.getInstructionList().getStart(); ih != null; ih = ih.getNext()) { final Instruction i = ih.getInstruction(); if (i instanceof BranchInstruction) { - branch_map.put(i, ih); // memorize container + branchMap.put(i, ih); // memorize container } if (ih.hasTargeters()) { if (i instanceof BranchInstruction) { - _out.println(" InstructionHandle ih_" + ih.getPosition() + ";"); + printWriter.println(" InstructionHandle ih_" + ih.getPosition() + ";"); } else { - _out.print(" InstructionHandle ih_" + ih.getPosition() + " = "); + printWriter.print(" InstructionHandle ih_" + ih.getPosition() + " = "); } } else { - _out.print(" "); + printWriter.print(" "); } if (!visitInstruction(i)) { i.accept(this); @@ -109,167 +149,74 @@ public void start() { } } - - private boolean visitInstruction( final Instruction i ) { - final short opcode = i.getOpcode(); - if ((InstructionConst.getInstruction(opcode) != null) - && !(i instanceof ConstantPushInstruction) && !(i instanceof ReturnInstruction)) { // Handled below - _out.println("il.append(InstructionConst." - + i.getName().toUpperCase(Locale.ENGLISH) + ");"); - return true; - } - return false; + private void updateBranchTargets() { + branches.forEach(bi -> { + final BranchHandle bh = (BranchHandle) branchMap.get(bi); + final int pos = bh.getPosition(); + final String name = bi.getName() + "_" + pos; + int targetPos = bh.getTarget().getPosition(); + printWriter.println(" " + name + ".setTarget(ih_" + targetPos + ");"); + if (bi instanceof Select) { + final InstructionHandle[] ihs = ((Select) bi).getTargets(); + for (int j = 0; j < ihs.length; j++) { + targetPos = ihs[j].getPosition(); + printWriter.println(" " + name + ".setTarget(" + j + ", ih_" + targetPos + ");"); + } + } + }); } - - @Override - public void visitLocalVariableInstruction( final LocalVariableInstruction i ) { - final short opcode = i.getOpcode(); - final Type type = i.getType(_cp); - if (opcode == Const.IINC) { - _out.println("il.append(new IINC(" + i.getIndex() + ", " + ((IINC) i).getIncrement() - + "));"); - } else { - final String kind = (opcode < Const.ISTORE) ? "Load" : "Store"; - _out.println("il.append(_factory.create" + kind + "(" + BCELifier.printType(type) - + ", " + i.getIndex() + "));"); + private void updateExceptionHandlers() { + final CodeExceptionGen[] handlers = methodGen.getExceptionHandlers(); + for (final CodeExceptionGen h : handlers) { + final String type = h.getCatchType() == null ? "null" : BCELifier.printType(h.getCatchType()); + printWriter.println(" method.addExceptionHandler(" + "ih_" + h.getStartPC().getPosition() + ", " + "ih_" + h.getEndPC().getPosition() + ", " + + "ih_" + h.getHandlerPC().getPosition() + ", " + type + ");"); } } - - @Override - public void visitArrayInstruction( final ArrayInstruction i ) { - final short opcode = i.getOpcode(); - final Type type = i.getType(_cp); - final String kind = (opcode < Const.IASTORE) ? "Load" : "Store"; - _out.println("il.append(_factory.createArray" + kind + "(" + BCELifier.printType(type) - + "));"); - } - - - @Override - public void visitFieldInstruction( final FieldInstruction i ) { - final short opcode = i.getOpcode(); - final String class_name = i.getReferenceType(_cp).getSignature(); - final String field_name = i.getFieldName(_cp); - final Type type = i.getFieldType(_cp); - _out.println("il.append(_factory.createFieldAccess(\"" + class_name + "\", \"" + field_name - + "\", " + BCELifier.printType(type) + ", " + CONSTANT_PREFIX - + Const.getOpcodeName(opcode).toUpperCase(Locale.ENGLISH) + "));"); - } - - - @Override - public void visitInvokeInstruction( final InvokeInstruction i ) { - final short opcode = i.getOpcode(); - final String class_name = i.getReferenceType(_cp).getSignature(); - final String method_name = i.getMethodName(_cp); - final Type type = i.getReturnType(_cp); - final Type[] arg_types = i.getArgumentTypes(_cp); - _out.println("il.append(_factory.createInvoke(\"" + class_name + "\", \"" + method_name - + "\", " + BCELifier.printType(type) + ", " - + BCELifier.printArgumentTypes(arg_types) + ", " + CONSTANT_PREFIX - + Const.getOpcodeName(opcode).toUpperCase(Locale.ENGLISH) + "));"); - } - - @Override @SuppressWarnings("fallthrough") // by design for case Const.ANEWARRAY - public void visitAllocationInstruction( final AllocationInstruction i ) { + public void visitAllocationInstruction(final AllocationInstruction i) { Type type; if (i instanceof CPInstruction) { - type = ((CPInstruction) i).getType(_cp); + type = ((CPInstruction) i).getType(constantPoolGen); } else { type = ((NEWARRAY) i).getType(); } final short opcode = ((Instruction) i).getOpcode(); int dim = 1; switch (opcode) { - case Const.NEW: - _out.println("il.append(_factory.createNew(\"" + ((ObjectType) type).getClassName() - + "\"));"); - break; - case Const.MULTIANEWARRAY: - dim = ((MULTIANEWARRAY) i).getDimensions(); - //$FALL-THROUGH$ - case Const.ANEWARRAY: - case Const.NEWARRAY: - if (type instanceof ArrayType) { - type = ((ArrayType) type).getBasicType(); - } - _out.println("il.append(_factory.createNewArray(" + BCELifier.printType(type) - + ", (short) " + dim + "));"); - break; - default: - throw new IllegalArgumentException("Unhandled opcode: " + opcode); - } - } - - - private void createConstant( final Object value ) { - String embed = value.toString(); - if (value instanceof String) { - embed = '"' + Utility.convertString(embed) + '"'; - } else if (value instanceof Character) { - embed = "(char)0x" + Integer.toHexString(((Character) value).charValue()); - } else if (value instanceof Float) { - embed += "f"; - } else if (value instanceof Long) { - embed += "L"; - } else if (value instanceof ObjectType) { - final ObjectType ot = (ObjectType) value; - embed = "new ObjectType(\""+ot.getClassName()+"\")"; + case Const.NEW: + printWriter.println("il.append(_factory.createNew(\"" + ((ObjectType) type).getClassName() + "\"));"); + break; + case Const.MULTIANEWARRAY: + dim = ((MULTIANEWARRAY) i).getDimensions(); + //$FALL-THROUGH$ + case Const.NEWARRAY: + if (type instanceof ArrayType) { + type = ((ArrayType) type).getBasicType(); + } + //$FALL-THROUGH$ + case Const.ANEWARRAY: + printWriter.println("il.append(_factory.createNewArray(" + BCELifier.printType(type) + ", (short) " + dim + "));"); + break; + default: + throw new IllegalArgumentException("Unhandled opcode: " + opcode); } - - _out.println("il.append(new PUSH(_cp, " + embed + "));"); - } - - - @Override - public void visitLDC( final LDC i ) { - createConstant(i.getValue(_cp)); - } - - - @Override - public void visitLDC2_W( final LDC2_W i ) { - createConstant(i.getValue(_cp)); } - @Override - public void visitConstantPushInstruction( final ConstantPushInstruction i ) { - createConstant(i.getValue()); - } - - - @Override - public void visitINSTANCEOF( final INSTANCEOF i ) { - final Type type = i.getType(_cp); - _out.println("il.append(new INSTANCEOF(_cp.addClass(" + BCELifier.printType(type) + ")));"); - } - - - @Override - public void visitCHECKCAST( final CHECKCAST i ) { - final Type type = i.getType(_cp); - _out.println("il.append(_factory.createCheckCast(" + BCELifier.printType(type) + "));"); + public void visitArrayInstruction(final ArrayInstruction i) { + final short opcode = i.getOpcode(); + final Type type = i.getType(constantPoolGen); + final String kind = opcode < Const.IASTORE ? "Load" : "Store"; + printWriter.println("il.append(_factory.createArray" + kind + "(" + BCELifier.printType(type) + "));"); } - @Override - public void visitReturnInstruction( final ReturnInstruction i ) { - final Type type = i.getType(_cp); - _out.println("il.append(_factory.createReturn(" + BCELifier.printType(type) + "));"); - } - - // Memorize BranchInstructions that need an update - private final List branches = new ArrayList<>(); - - - @Override - public void visitBranchInstruction( final BranchInstruction bi ) { - final BranchHandle bh = (BranchHandle) branch_map.get(bi); + public void visitBranchInstruction(final BranchInstruction bi) { + final BranchHandle bh = (BranchHandle) branchMap.get(bi); final int pos = bh.getPosition(); final String name = bi.getName() + "_" + pos; if (bi instanceof Select) { @@ -284,68 +231,110 @@ public void visitBranchInstruction( final BranchInstruction bi ) { } } args.append(" }"); - _out.print("Select " + name + " = new " + bi.getName().toUpperCase(Locale.ENGLISH) - + "(" + args + ", new InstructionHandle[] { "); + printWriter.print("Select " + name + " = new " + bi.getName().toUpperCase(Locale.ENGLISH) + "(" + args + ", new InstructionHandle[] { "); for (int i = 0; i < matchs.length; i++) { - _out.print("null"); + printWriter.print("null"); if (i < matchs.length - 1) { - _out.print(", "); + printWriter.print(", "); } } - _out.println(" }, null);"); + printWriter.println(" }, null);"); } else { - final int t_pos = bh.getTarget().getPosition(); + final int tPos = bh.getTarget().getPosition(); String target; - if (pos > t_pos) { - target = "ih_" + t_pos; + if (pos > tPos) { + target = "ih_" + tPos; } else { branches.add(bi); target = "null"; } - _out.println(" BranchInstruction " + name + " = _factory.createBranchInstruction(" - + CONSTANT_PREFIX + bi.getName().toUpperCase(Locale.ENGLISH) + ", " + target - + ");"); + printWriter.println(" BranchInstruction " + name + " = _factory.createBranchInstruction(" + CONSTANT_PREFIX + + bi.getName().toUpperCase(Locale.ENGLISH) + ", " + target + ");"); } if (bh.hasTargeters()) { - _out.println(" ih_" + pos + " = il.append(" + name + ");"); + printWriter.println(" ih_" + pos + " = il.append(" + name + ");"); } else { - _out.println(" il.append(" + name + ");"); + printWriter.println(" il.append(" + name + ");"); } } + @Override + public void visitCHECKCAST(final CHECKCAST i) { + final Type type = i.getType(constantPoolGen); + printWriter.println("il.append(_factory.createCheckCast(" + BCELifier.printType(type) + "));"); + } + + @Override + public void visitConstantPushInstruction(final ConstantPushInstruction i) { + createConstant(i.getValue()); + } @Override - public void visitRET( final RET i ) { - _out.println("il.append(new RET(" + i.getIndex() + ")));"); + public void visitFieldInstruction(final FieldInstruction i) { + final short opcode = i.getOpcode(); + final String className = i.getReferenceType(constantPoolGen).getClassName(); + final String fieldName = i.getFieldName(constantPoolGen); + final Type type = i.getFieldType(constantPoolGen); + printWriter.println("il.append(_factory.createFieldAccess(\"" + className + "\", \"" + fieldName + "\", " + BCELifier.printType(type) + ", " + + CONSTANT_PREFIX + Const.getOpcodeName(opcode).toUpperCase(Locale.ENGLISH) + "));"); } + @Override + public void visitINSTANCEOF(final INSTANCEOF i) { + final Type type = i.getType(constantPoolGen); + printWriter.println("il.append(_factory.createInstanceOf(" + BCELifier.printType(type) + "));"); + } - private void updateBranchTargets() { - for (final BranchInstruction bi : branches) { - final BranchHandle bh = (BranchHandle) branch_map.get(bi); - final int pos = bh.getPosition(); - final String name = bi.getName() + "_" + pos; - int t_pos = bh.getTarget().getPosition(); - _out.println(" " + name + ".setTarget(ih_" + t_pos + ");"); - if (bi instanceof Select) { - final InstructionHandle[] ihs = ((Select) bi).getTargets(); - for (int j = 0; j < ihs.length; j++) { - t_pos = ihs[j].getPosition(); - _out.println(" " + name + ".setTarget(" + j + ", ih_" + t_pos + ");"); - } - } + private boolean visitInstruction(final Instruction i) { + final short opcode = i.getOpcode(); + if (InstructionConst.getInstruction(opcode) != null && !(i instanceof ConstantPushInstruction) && !(i instanceof ReturnInstruction)) { // Handled below + printWriter.println("il.append(InstructionConst." + i.getName().toUpperCase(Locale.ENGLISH) + ");"); + return true; } + return false; } + @Override + public void visitInvokeInstruction(final InvokeInstruction i) { + final short opcode = i.getOpcode(); + final String className = i.getReferenceType(constantPoolGen).getClassName(); + final String methodName = i.getMethodName(constantPoolGen); + final Type type = i.getReturnType(constantPoolGen); + final Type[] argTypes = i.getArgumentTypes(constantPoolGen); + printWriter.println("il.append(_factory.createInvoke(\"" + className + "\", \"" + methodName + "\", " + BCELifier.printType(type) + ", " + + BCELifier.printArgumentTypes(argTypes) + ", " + CONSTANT_PREFIX + Const.getOpcodeName(opcode).toUpperCase(Locale.ENGLISH) + "));"); + } - private void updateExceptionHandlers() { - final CodeExceptionGen[] handlers = _mg.getExceptionHandlers(); - for (final CodeExceptionGen h : handlers) { - final String type = (h.getCatchType() == null) ? "null" : BCELifier.printType(h - .getCatchType()); - _out.println(" method.addExceptionHandler(" + "ih_" + h.getStartPC().getPosition() - + ", " + "ih_" + h.getEndPC().getPosition() + ", " + "ih_" - + h.getHandlerPC().getPosition() + ", " + type + ");"); + @Override + public void visitLDC(final LDC i) { + createConstant(i.getValue(constantPoolGen)); + } + + @Override + public void visitLDC2_W(final LDC2_W i) { + createConstant(i.getValue(constantPoolGen)); + } + + @Override + public void visitLocalVariableInstruction(final LocalVariableInstruction i) { + final short opcode = i.getOpcode(); + final Type type = i.getType(constantPoolGen); + if (opcode == Const.IINC) { + printWriter.println("il.append(new IINC(" + i.getIndex() + ", " + ((IINC) i).getIncrement() + "));"); + } else { + final String kind = opcode < Const.ISTORE ? "Load" : "Store"; + printWriter.println("il.append(_factory.create" + kind + "(" + BCELifier.printType(type) + ", " + i.getIndex() + "));"); } } + + @Override + public void visitRET(final RET i) { + printWriter.println("il.append(new RET(" + i.getIndex() + "));"); + } + + @Override + public void visitReturnInstruction(final ReturnInstruction i) { + final Type type = i.getType(constantPoolGen); + printWriter.println("il.append(_factory.createReturn(" + BCELifier.printType(type) + "));"); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java index efe19524cdb..151083ea71b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -23,13 +22,16 @@ import java.io.IOException; import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; import java.util.Locale; import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.Repository; import com.sun.org.apache.bcel.internal.classfile.ClassParser; import com.sun.org.apache.bcel.internal.classfile.ConstantValue; +import com.sun.org.apache.bcel.internal.classfile.ExceptionTable; import com.sun.org.apache.bcel.internal.classfile.Field; import com.sun.org.apache.bcel.internal.classfile.JavaClass; import com.sun.org.apache.bcel.internal.classfile.Method; @@ -40,12 +42,11 @@ import com.sun.org.apache.bcel.internal.generic.Type; /** - * This class takes a given JavaClass object and converts it to a - * Java program that creates that very class using BCEL. This - * gives new users of BCEL a useful example showing how things - * are done with BCEL. It does not cover all features of BCEL, - * but tries to mimic hand-written code as close as possible. + * This class takes a given JavaClass object and converts it to a Java program that creates that very class using BCEL. + * This gives new users of BCEL a useful example showing how things are done with BCEL. It does not cover all features + * of BCEL, but tries to mimic hand-written code as close as possible. * + * @LastModified: Feb 2023 */ public class BCELifier extends com.sun.org.apache.bcel.internal.classfile.EmptyVisitor { @@ -53,186 +54,79 @@ public class BCELifier extends com.sun.org.apache.bcel.internal.classfile.EmptyV * Enum corresponding to flag source. */ public enum FLAGS { - UNKNOWN, - CLASS, - METHOD, + UNKNOWN, CLASS, METHOD, } // The base package name for imports; assumes Const is at the top level // N.B we use the class so renames will be detected by the compiler/IDE private static final String BASE_PACKAGE = Const.class.getPackage().getName(); - private static final String CONSTANT_PREFIX = Const.class.getSimpleName()+"."; + private static final String CONSTANT_PREFIX = Const.class.getSimpleName() + "."; - private final JavaClass _clazz; - private final PrintWriter _out; - private final ConstantPoolGen _cp; - - /** @param clazz Java class to "decompile" - * @param out where to output Java program - */ - public BCELifier(final JavaClass clazz, final OutputStream out) { - _clazz = clazz; - _out = new PrintWriter(out); - _cp = new ConstantPoolGen(_clazz.getConstantPool()); + // Needs to be accessible from unit test code + static JavaClass getJavaClass(final String name) throws ClassNotFoundException, IOException { + JavaClass javaClass; + if ((javaClass = Repository.lookupClass(name)) == null) { + javaClass = new ClassParser(name).parse(); // May throw IOException + } + return javaClass; } - - /** Start Java code generation + /** + * Default main method */ - public void start() { - visitJavaClass(_clazz); - _out.flush(); - } - - - @Override - public void visitJavaClass( final JavaClass clazz ) { - String class_name = clazz.getClassName(); - final String super_name = clazz.getSuperclassName(); - final String package_name = clazz.getPackageName(); - final String inter = Utility.printArray(clazz.getInterfaceNames(), false, true); - if (!"".equals(package_name)) { - class_name = class_name.substring(package_name.length() + 1); - _out.println("package " + package_name + ";"); - _out.println(); - } - _out.println("import " + BASE_PACKAGE + ".generic.*;"); - _out.println("import " + BASE_PACKAGE + ".classfile.*;"); - _out.println("import " + BASE_PACKAGE + ".*;"); - _out.println("import java.io.*;"); - _out.println(); - _out.println("public class " + class_name + "Creator {"); - _out.println(" private InstructionFactory _factory;"); - _out.println(" private ConstantPoolGen _cp;"); - _out.println(" private ClassGen _cg;"); - _out.println(); - _out.println(" public " + class_name + "Creator() {"); - _out.println(" _cg = new ClassGen(\"" - + (("".equals(package_name)) ? class_name : package_name + "." + class_name) - + "\", \"" + super_name + "\", " + "\"" + clazz.getSourceFileName() + "\", " - + printFlags(clazz.getAccessFlags(), FLAGS.CLASS) + ", " - + "new String[] { " + inter + " });"); - _out.println(" _cg.setMajor(" + clazz.getMajor() +");"); - _out.println(" _cg.setMinor(" + clazz.getMinor() +");"); - _out.println(); - _out.println(" _cp = _cg.getConstantPool();"); - _out.println(" _factory = new InstructionFactory(_cg, _cp);"); - _out.println(" }"); - _out.println(); - printCreate(); - final Field[] fields = clazz.getFields(); - if (fields.length > 0) { - _out.println(" private void createFields() {"); - _out.println(" FieldGen field;"); - for (final Field field : fields) { - field.accept(this); - } - _out.println(" }"); - _out.println(); - } - final Method[] methods = clazz.getMethods(); - for (int i = 0; i < methods.length; i++) { - _out.println(" private void createMethod_" + i + "() {"); - methods[i].accept(this); - _out.println(" }"); - _out.println(); + public static void _main(final String[] argv) throws Exception { + if (argv.length != 1) { + System.out.println("Usage: BCELifier className"); + System.out.println("\tThe class must exist on the classpath"); + return; } - printMain(); - _out.println("}"); + final BCELifier bcelifier = new BCELifier(getJavaClass(argv[0]), System.out); + bcelifier.start(); } - - private void printCreate() { - _out.println(" public void create(OutputStream out) throws IOException {"); - final Field[] fields = _clazz.getFields(); - if (fields.length > 0) { - _out.println(" createFields();"); - } - final Method[] methods = _clazz.getMethods(); - for (int i = 0; i < methods.length; i++) { - _out.println(" createMethod_" + i + "();"); + static String printArgumentTypes(final Type[] argTypes) { + if (argTypes.length == 0) { + return "Type.NO_ARGS"; } - _out.println(" _cg.getJavaClass().dump(out);"); - _out.println(" }"); - _out.println(); - } - - - private void printMain() { - final String class_name = _clazz.getClassName(); - _out.println(" public static void main(String[] args) throws Exception {"); - _out.println(" " + class_name + "Creator creator = new " + class_name + "Creator();"); - _out.println(" creator.create(new FileOutputStream(\"" + class_name + ".class\"));"); - _out.println(" }"); - } - - - @Override - public void visitField( final Field field ) { - _out.println(); - _out.println(" field = new FieldGen(" + printFlags(field.getAccessFlags()) + ", " - + printType(field.getSignature()) + ", \"" + field.getName() + "\", _cp);"); - final ConstantValue cv = field.getConstantValue(); - if (cv != null) { - final String value = cv.toString(); - _out.println(" field.setInitValue(" + value + ")"); + final StringBuilder args = new StringBuilder(); + for (int i = 0; i < argTypes.length; i++) { + args.append(printType(argTypes[i])); + if (i < argTypes.length - 1) { + args.append(", "); + } } - _out.println(" _cg.addField(field.getField());"); - } - - - @Override - public void visitMethod( final Method method ) { - final MethodGen mg = new MethodGen(method, _clazz.getClassName(), _cp); - _out.println(" InstructionList il = new InstructionList();"); - _out.println(" MethodGen method = new MethodGen(" - + printFlags(method.getAccessFlags(), FLAGS.METHOD) + ", " - + printType(mg.getReturnType()) + ", " - + printArgumentTypes(mg.getArgumentTypes()) + ", " - + "new String[] { " + Utility.printArray(mg.getArgumentNames(), false, true) - + " }, \"" + method.getName() + "\", \"" + _clazz.getClassName() + "\", il, _cp);"); - _out.println(); - final BCELFactory factory = new BCELFactory(mg, _out); - factory.start(); - _out.println(" method.setMaxStack();"); - _out.println(" method.setMaxLocals();"); - _out.println(" _cg.addMethod(method.getMethod());"); - _out.println(" il.dispose();"); + return "new Type[] { " + args.toString() + " }"; } - - static String printFlags( final int flags ) { + static String printFlags(final int flags) { return printFlags(flags, FLAGS.UNKNOWN); } /** * Return a string with the flag settings + * * @param flags the flags field to interpret * @param location the item type * @return the formatted string * @since 6.0 made public */ - public static String printFlags( final int flags, final FLAGS location ) { + public static String printFlags(final int flags, final FLAGS location) { if (flags == 0) { return "0"; } final StringBuilder buf = new StringBuilder(); for (int i = 0, pow = 1; pow <= Const.MAX_ACC_FLAG_I; i++) { if ((flags & pow) != 0) { - if ((pow == Const.ACC_SYNCHRONIZED) && (location == FLAGS.CLASS)) { - buf.append(CONSTANT_PREFIX+"ACC_SUPER | "); - } else if ((pow == Const.ACC_VOLATILE) && (location == FLAGS.METHOD)) { - buf.append(CONSTANT_PREFIX+"ACC_BRIDGE | "); - } else if ((pow == Const.ACC_TRANSIENT) && (location == FLAGS.METHOD)) { - buf.append(CONSTANT_PREFIX+"ACC_VARARGS | "); + if (pow == Const.ACC_SYNCHRONIZED && location == FLAGS.CLASS) { + buf.append(CONSTANT_PREFIX).append("ACC_SUPER | "); + } else if (pow == Const.ACC_VOLATILE && location == FLAGS.METHOD) { + buf.append(CONSTANT_PREFIX).append("ACC_BRIDGE | "); + } else if (pow == Const.ACC_TRANSIENT && location == FLAGS.METHOD) { + buf.append(CONSTANT_PREFIX).append("ACC_VARARGS | "); + } else if (i < Const.ACCESS_NAMES_LENGTH) { + buf.append(CONSTANT_PREFIX).append("ACC_").append(Const.getAccessName(i).toUpperCase(Locale.ENGLISH)).append(" | "); } else { - if (i < Const.ACCESS_NAMES_LENGTH) { - buf.append(CONSTANT_PREFIX+"ACC_") - .append(Const.getAccessName(i).toUpperCase(Locale.ENGLISH)) - .append( " | "); - } else { - buf.append(String.format (CONSTANT_PREFIX+"ACC_BIT %x | ", pow)); - } + buf.append(String.format(CONSTANT_PREFIX + "ACC_BIT %x | ", pow)); } } pow <<= 1; @@ -241,68 +135,188 @@ public static String printFlags( final int flags, final FLAGS location ) { return str.substring(0, str.length() - 3); } - - static String printArgumentTypes( final Type[] arg_types ) { - if (arg_types.length == 0) { - return "Type.NO_ARGS"; - } - final StringBuilder args = new StringBuilder(); - for (int i = 0; i < arg_types.length; i++) { - args.append(printType(arg_types[i])); - if (i < arg_types.length - 1) { - args.append(", "); - } - } - return "new Type[] { " + args.toString() + " }"; - } - - - static String printType( final Type type ) { - return printType(type.getSignature()); - } - - - static String printType( final String signature ) { + static String printType(final String signature) { final Type type = Type.getType(signature); final byte t = type.getType(); if (t <= Const.T_VOID) { return "Type." + Const.getTypeName(t).toUpperCase(Locale.ENGLISH); - } else if (type.toString().equals("java.lang.String")) { + } + if (type.toString().equals("java.lang.String")) { return "Type.STRING"; - } else if (type.toString().equals("java.lang.Object")) { + } + if (type.toString().equals("java.lang.Object")) { return "Type.OBJECT"; - } else if (type.toString().equals("java.lang.StringBuffer")) { + } + if (type.toString().equals("java.lang.StringBuffer")) { return "Type.STRINGBUFFER"; - } else if (type instanceof ArrayType) { + } + if (type instanceof ArrayType) { final ArrayType at = (ArrayType) type; - return "new ArrayType(" + printType(at.getBasicType()) + ", " + at.getDimensions() - + ")"; - } else { - return "new ObjectType(\"" + Utility.signatureToString(signature, false) + "\")"; + return "new ArrayType(" + printType(at.getBasicType()) + ", " + at.getDimensions() + ")"; } + return "new ObjectType(\"" + Utility.signatureToString(signature, false) + "\")"; } + static String printType(final Type type) { + return printType(type.getSignature()); + } - /** Default main method + private final JavaClass clazz; + + private final PrintWriter printWriter; + + private final ConstantPoolGen constantPoolGen; + + /** + * Constructs a new instance. + * + * @param clazz Java class to "decompile". + * @param out where to print the Java program in UTF-8. */ - public static void main( final String[] argv ) throws Exception { - if (argv.length != 1) { - System.out.println("Usage: BCELifier classname"); - System.out.println("\tThe class must exist on the classpath"); - return; + public BCELifier(final JavaClass clazz, final OutputStream out) { + this.clazz = clazz; + this.printWriter = new PrintWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8), false); + this.constantPoolGen = new ConstantPoolGen(this.clazz.getConstantPool()); + } + + private void printCreate() { + printWriter.println(" public void create(OutputStream out) throws IOException {"); + final Field[] fields = clazz.getFields(); + if (fields.length > 0) { + printWriter.println(" createFields();"); } - final JavaClass java_class = getJavaClass(argv[0]); - final BCELifier bcelifier = new BCELifier(java_class, System.out); - bcelifier.start(); + final Method[] methods = clazz.getMethods(); + for (int i = 0; i < methods.length; i++) { + printWriter.println(" createMethod_" + i + "();"); + } + printWriter.println(" _cg.getJavaClass().dump(out);"); + printWriter.println(" }"); + printWriter.println(); } + private void printMain() { + final String className = clazz.getClassName(); + printWriter.println(" public static void main(String[] args) throws Exception {"); + printWriter.println(" " + className + "Creator creator = new " + className + "Creator();"); + printWriter.println(" creator.create(new FileOutputStream(\"" + className + ".class\"));"); + printWriter.println(" }"); + } - // Needs to be accessible from unit test code - static JavaClass getJavaClass(final String name) throws ClassNotFoundException, IOException { - JavaClass java_class; - if ((java_class = Repository.lookupClass(name)) == null) { - java_class = new ClassParser(name).parse(); // May throw IOException + /** + * Start Java code generation + */ + public void start() { + visitJavaClass(clazz); + printWriter.flush(); + } + + @Override + public void visitField(final Field field) { + printWriter.println(); + printWriter.println( + " field = new FieldGen(" + printFlags(field.getAccessFlags()) + ", " + printType(field.getSignature()) + ", \"" + field.getName() + "\", _cp);"); + final ConstantValue cv = field.getConstantValue(); + if (cv != null) { + printWriter.print(" field.setInitValue("); + if (field.getType() == Type.CHAR) { + printWriter.print("(char)"); + } + if (field.getType() == Type.SHORT) { + printWriter.print("(short)"); + } + if (field.getType() == Type.BYTE) { + printWriter.print("(byte)"); + } + printWriter.print(cv); + if (field.getType() == Type.LONG) { + printWriter.print("L"); + } + if (field.getType() == Type.FLOAT) { + printWriter.print("F"); + } + if (field.getType() == Type.DOUBLE) { + printWriter.print("D"); + } + printWriter.println(");"); + } + printWriter.println(" _cg.addField(field.getField());"); + } + + @Override + public void visitJavaClass(final JavaClass clazz) { + String className = clazz.getClassName(); + final String superName = clazz.getSuperclassName(); + final String packageName = clazz.getPackageName(); + final String inter = Utility.printArray(clazz.getInterfaceNames(), false, true); + if (packageName != null && !packageName.trim().isEmpty()) { + className = className.substring(packageName.length() + 1); + printWriter.println("package " + packageName + ";"); + printWriter.println(); } - return java_class; + printWriter.println("import " + BASE_PACKAGE + ".generic.*;"); + printWriter.println("import " + BASE_PACKAGE + ".classfile.*;"); + printWriter.println("import " + BASE_PACKAGE + ".*;"); + printWriter.println("import java.io.*;"); + printWriter.println(); + printWriter.println("public class " + className + "Creator {"); + printWriter.println(" private InstructionFactory _factory;"); + printWriter.println(" private ConstantPoolGen _cp;"); + printWriter.println(" private ClassGen _cg;"); + printWriter.println(); + printWriter.println(" public " + className + "Creator() {"); + printWriter.println(" _cg = new ClassGen(\"" + (packageName.isEmpty() ? className : packageName + "." + className) + "\", \"" + superName + + "\", " + "\"" + clazz.getSourceFileName() + "\", " + printFlags(clazz.getAccessFlags(), FLAGS.CLASS) + ", " + "new String[] { " + inter + " });"); + printWriter.println(" _cg.setMajor(" + clazz.getMajor() + ");"); + printWriter.println(" _cg.setMinor(" + clazz.getMinor() + ");"); + printWriter.println(); + printWriter.println(" _cp = _cg.getConstantPool();"); + printWriter.println(" _factory = new InstructionFactory(_cg, _cp);"); + printWriter.println(" }"); + printWriter.println(); + printCreate(); + final Field[] fields = clazz.getFields(); + if (fields.length > 0) { + printWriter.println(" private void createFields() {"); + printWriter.println(" FieldGen field;"); + for (final Field field : fields) { + field.accept(this); + } + printWriter.println(" }"); + printWriter.println(); + } + final Method[] methods = clazz.getMethods(); + for (int i = 0; i < methods.length; i++) { + printWriter.println(" private void createMethod_" + i + "() {"); + methods[i].accept(this); + printWriter.println(" }"); + printWriter.println(); + } + printMain(); + printWriter.println("}"); + } + + @Override + public void visitMethod(final Method method) { + final MethodGen mg = new MethodGen(method, clazz.getClassName(), constantPoolGen); + printWriter.println(" InstructionList il = new InstructionList();"); + printWriter.println(" MethodGen method = new MethodGen(" + printFlags(method.getAccessFlags(), FLAGS.METHOD) + ", " + printType(mg.getReturnType()) + + ", " + printArgumentTypes(mg.getArgumentTypes()) + ", " + "new String[] { " + Utility.printArray(mg.getArgumentNames(), false, true) + " }, \"" + + method.getName() + "\", \"" + clazz.getClassName() + "\", il, _cp);"); + final ExceptionTable exceptionTable = method.getExceptionTable(); + if (exceptionTable != null) { + final String[] exceptionNames = exceptionTable.getExceptionNames(); + for (final String exceptionName : exceptionNames) { + printWriter.print(" method.addException(\""); + printWriter.print(exceptionName); + printWriter.println("\");"); + } + } + printWriter.println(); + final BCELFactory factory = new BCELFactory(mg, printWriter); + factory.start(); + printWriter.println(" method.setMaxStack();"); + printWriter.println(" method.setMaxLocals();"); + printWriter.println(" _cg.addMethod(method.getMethod());"); + printWriter.println(" il.dispose();"); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ByteSequence.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ByteSequence.java index 67ac04543ec..65dfd3f3eaf 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ByteSequence.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ByteSequence.java @@ -25,31 +25,11 @@ import java.io.DataInputStream; /** - * Utility class that implements a sequence of bytes which can be read - * via the `readByte()' method. This is used to implement a wrapper for the - * Java byte code stream to gain some more readability. - * + * Utility class that implements a sequence of bytes which can be read via the 'readByte()' method. This is used to + * implement a wrapper for the Java byte code stream to gain some more readability. */ public final class ByteSequence extends DataInputStream { - private final ByteArrayStream byteStream; - - - public ByteSequence(final byte[] bytes) { - super(new ByteArrayStream(bytes)); - byteStream = (ByteArrayStream) in; - } - - - public int getIndex() { - return byteStream.getPosition(); - } - - - void unreadByte() { - byteStream.unreadByte(); - } - private static final class ByteArrayStream extends ByteArrayInputStream { ByteArrayStream(final byte[] bytes) { @@ -67,4 +47,19 @@ void unreadByte() { } } } + + private final ByteArrayStream byteStream; + + public ByteSequence(final byte[] bytes) { + super(new ByteArrayStream(bytes)); + byteStream = (ByteArrayStream) in; + } + + public int getIndex() { + return byteStream.getPosition(); + } + + void unreadByte() { + byteStream.unreadByte(); + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java index 8ee30c5936d..f644c698b72 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,9 +20,12 @@ package com.sun.org.apache.bcel.internal.util; import java.io.File; -import java.io.FileOutputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.HashSet; import java.util.Set; @@ -37,89 +40,49 @@ /** * Read class file(s) and convert them into HTML files. * - * Given a JavaClass object "class" that is in package "package" five files - * will be created in the specified directory. + * Given a JavaClass object "class" that is in package "package" five files will be created in the specified directory. * *

      - *
    1. "package"."class".html as the main file which defines the frames for - * the following subfiles. - *
    2. "package"."class"_attributes.html contains all (known) attributes found in the file - *
    3. "package"."class"_cp.html contains the constant pool - *
    4. "package"."class"_code.html contains the byte code - *
    5. "package"."class"_methods.html contains references to all methods and fields of the class + *
    6. "package"."class".html as the main file which defines the frames for the following subfiles. + *
    7. "package"."class"_attributes.html contains all (known) attributes found in the file + *
    8. "package"."class"_cp.html contains the constant pool + *
    9. "package"."class"_code.html contains the byte code + *
    10. "package"."class"_methods.html contains references to all methods and fields of the class *
    * - * All subfiles reference each other appropriately, e.g. clicking on a - * method in the Method's frame will jump to the appropriate method in - * the Code frame. + * All subfiles reference each other appropriately, e.g. clicking on a method in the Method's frame will jump to the + * appropriate method in the Code frame. * - * @LastModified: Jan 2020 + * @LastModified: Feb 2023 */ public class Class2HTML { - private final JavaClass java_class; // current class object - private final String dir; - private static String class_package; // name of package, unclean to make it static, but ... - private static String class_name; // name of current class, dito - private static ConstantPool constant_pool; - private static final Set basic_types = new HashSet<>(); - + private static String classPackage; // name of package, unclean to make it static, but ... + private static String className; // name of current class, dito + private static ConstantPool constantPool; + private static final Set basicTypes = new HashSet<>(); static { - basic_types.add("int"); - basic_types.add("short"); - basic_types.add("boolean"); - basic_types.add("void"); - basic_types.add("char"); - basic_types.add("byte"); - basic_types.add("long"); - basic_types.add("double"); - basic_types.add("float"); + basicTypes.add("int"); + basicTypes.add("short"); + basicTypes.add("boolean"); + basicTypes.add("void"); + basicTypes.add("char"); + basicTypes.add("byte"); + basicTypes.add("long"); + basicTypes.add("double"); + basicTypes.add("float"); } - /** - * Write contents of the given JavaClass into HTML files. - * - * @param java_class The class to write - * @param dir The directory to put the files in - */ - public Class2HTML(final JavaClass java_class, final String dir) throws IOException { - final Method[] methods = java_class.getMethods(); - this.java_class = java_class; - this.dir = dir; - class_name = java_class.getClassName(); // Remember full name - constant_pool = java_class.getConstantPool(); - // Get package name by tacking off everything after the last `.' - final int index = class_name.lastIndexOf('.'); - if (index > -1) { - class_package = class_name.substring(0, index); - } else { - class_package = ""; // default package - } - final ConstantHTML constant_html = new ConstantHTML(dir, class_name, class_package, methods, - constant_pool); - /* Attributes can't be written in one step, so we just open a file - * which will be written consequently. - */ - final AttributeHTML attribute_html = new AttributeHTML(dir, class_name, constant_pool, - constant_html); - new MethodHTML(dir, class_name, methods, java_class.getFields(), - constant_html, attribute_html); - // Write main file (with frames, yuk) - writeMainHTML(attribute_html); - new CodeHTML(dir, class_name, methods, constant_pool, constant_html); - attribute_html.close(); - } - - - public static void main( final String[] argv ) throws IOException { - final String[] file_name = new String[argv.length]; + public static void _main(final String[] argv) throws IOException { + final String[] fileName = new String[argv.length]; int files = 0; ClassParser parser = null; - JavaClass java_class = null; - String zip_file = null; + JavaClass javaClass = null; + String zipFile = null; final char sep = File.separatorChar; String dir = "." + sep; // Where to store HTML files - /* Parse command line arguments. + /* + * Parse command line arguments. */ for (int i = 0; i < argv.length; i++) { if (argv[i].charAt(0) == '-') { // command line switch @@ -131,108 +94,138 @@ public static void main( final String[] argv ) throws IOException { final File store = new File(dir); if (!store.isDirectory()) { final boolean created = store.mkdirs(); // Create target directory if necessary - if (!created) { - if (!store.isDirectory()) { - System.out.println("Tried to create the directory " + dir + " but failed"); - } + if (!created && !store.isDirectory()) { + System.out.println("Tried to create the directory " + dir + " but failed"); } } } else if (argv[i].equals("-zip")) { - zip_file = argv[++i]; + zipFile = argv[++i]; } else { System.out.println("Unknown option " + argv[i]); } } else { - file_name[files++] = argv[i]; + fileName[files++] = argv[i]; } } if (files == 0) { System.err.println("Class2HTML: No input files specified."); } else { // Loop through files ... for (int i = 0; i < files; i++) { - System.out.print("Processing " + file_name[i] + "..."); - if (zip_file == null) { - parser = new ClassParser(file_name[i]); // Create parser object from file + System.out.print("Processing " + fileName[i] + "..."); + if (zipFile == null) { + parser = new ClassParser(fileName[i]); // Create parser object from file } else { - parser = new ClassParser(zip_file, file_name[i]); // Create parser object from zip file + parser = new ClassParser(zipFile, fileName[i]); // Create parser object from zip file } - java_class = parser.parse(); - new Class2HTML(java_class, dir); + javaClass = parser.parse(); + new Class2HTML(javaClass, dir); System.out.println("Done."); } } } /** - * Utility method that converts a class reference in the constant pool, - * i.e., an index to a string. + * Utility method that converts a class reference in the constant pool, i.e., an index to a string. */ static String referenceClass(final int index) { - String str = constant_pool.getConstantString(index, Const.CONSTANT_Class); + String str = constantPool.getConstantString(index, Const.CONSTANT_Class); str = Utility.compactClassName(str); - str = Utility.compactClassName(str, class_package + ".", true); - return "" + str - + ""; + str = Utility.compactClassName(str, classPackage + ".", true); + return "" + str + ""; } - - static String referenceType( final String type ) { - String short_type = Utility.compactClassName(type); - short_type = Utility.compactClassName(short_type, class_package + ".", true); + static String referenceType(final String type) { + String shortType = Utility.compactClassName(type); + shortType = Utility.compactClassName(shortType, classPackage + ".", true); final int index = type.indexOf('['); // Type is an array? - String base_type = type; + String baseType = type; if (index > -1) { - base_type = type.substring(0, index); // Tack of the `[' + baseType = type.substring(0, index); // Tack of the '[' } // test for basic type - if (basic_types.contains(base_type)) { + if (basicTypes.contains(baseType)) { return "" + type + ""; } - return "" + short_type + ""; + return "" + shortType + ""; } - - static String toHTML( final String str ) { + static String toHTML(final String str) { final StringBuilder buf = new StringBuilder(); for (int i = 0; i < str.length(); i++) { char ch; switch (ch = str.charAt(i)) { - case '<': - buf.append("<"); - break; - case '>': - buf.append(">"); - break; - case '\n': - buf.append("\\n"); - break; - case '\r': - buf.append("\\r"); - break; - default: - buf.append(ch); + case '<': + buf.append("<"); + break; + case '>': + buf.append(">"); + break; + case '\n': + buf.append("\\n"); + break; + case '\r': + buf.append("\\r"); + break; + default: + buf.append(ch); } } return buf.toString(); } + private final JavaClass javaClass; // current class object + + private final String dir; + + /** + * Write contents of the given JavaClass into HTML files. + * + * @param javaClass The class to write + * @param dir The directory to put the files in + * @throws IOException Thrown when an I/O exception of some sort has occurred. + */ + public Class2HTML(final JavaClass javaClass, final String dir) throws IOException { + this(javaClass, dir, StandardCharsets.UTF_8); + } + + private Class2HTML(final JavaClass javaClass, final String dir, final Charset charset) throws IOException { + final Method[] methods = javaClass.getMethods(); + this.javaClass = javaClass; + this.dir = dir; + className = javaClass.getClassName(); // Remember full name + constantPool = javaClass.getConstantPool(); + // Get package name by tacking off everything after the last '.' + final int index = className.lastIndexOf('.'); + if (index > -1) { + classPackage = className.substring(0, index); + } else { + classPackage = ""; // default package + } + final ConstantHTML constantHtml = new ConstantHTML(dir, className, classPackage, methods, constantPool, charset); + /* + * Attributes can't be written in one step, so we just open a file which will be written consequently. + */ + try (AttributeHTML attributeHtml = new AttributeHTML(dir, className, constantPool, constantHtml, charset)) { + new MethodHTML(dir, className, methods, javaClass.getFields(), constantHtml, attributeHtml, charset); + // Write main file (with frames, yuk) + writeMainHTML(attributeHtml, charset); + new CodeHTML(dir, className, methods, constantPool, constantHtml, charset); + } + } - private void writeMainHTML( final AttributeHTML attribute_html ) throws IOException { - try (PrintWriter file = new PrintWriter(new FileOutputStream(dir + class_name + ".html"))) { - file.println("\n" + "Documentation for " + class_name + "" + "\n" - + "\n" + "\n" - + "\n" + "\n" + "\n" - + "\n" + "\n" - + "\n" + ""); + private void writeMainHTML(final AttributeHTML attributeHtml, final Charset charset) throws FileNotFoundException, UnsupportedEncodingException { + try (PrintWriter file = new PrintWriter(dir + className + ".html", charset.name())) { + file.println("\n" + "Documentation for " + className + "" + "\n" + "\n" + + "\n" + "\n" + "\n" + "\n" + + "\n" + "\n" + "\n" + ""); } - final Attribute[] attributes = java_class.getAttributes(); + final Attribute[] attributes = javaClass.getAttributes(); for (int i = 0; i < attributes.length; i++) { - attribute_html.writeAttribute(attributes[i], "class" + i); + attributeHtml.writeAttribute(attributes[i], "class" + i); } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassQueue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassQueue.java index 8120820d5c9..82c4e52168c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassQueue.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassQueue.java @@ -24,30 +24,28 @@ import com.sun.org.apache.bcel.internal.classfile.JavaClass; /** - * Utility class implementing a (typesafe) queue of JavaClass - * objects. - * + * Utility class implementing a (typesafe) queue of JavaClass objects. * @LastModified: Jan 2020 */ public class ClassQueue { - private final LinkedList vec = new LinkedList<>(); - - - public void enqueue( final JavaClass clazz ) { - vec.addLast(clazz); - } - + /** + * @deprecated (since 6.0) will be made private; do not access + */ + @Deprecated + protected LinkedList vec = new LinkedList<>(); // TODO not used externally public JavaClass dequeue() { return vec.removeFirst(); } - public boolean empty() { return vec.isEmpty(); } + public void enqueue(final JavaClass clazz) { + vec.addLast(clazz); + } @Override public String toString() { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java index 8e542098941..178ccc786b1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -21,53 +20,39 @@ package com.sun.org.apache.bcel.internal.util; -import java.util.Collection; +import com.sun.org.apache.bcel.internal.Const; import java.util.HashMap; import java.util.Map; import com.sun.org.apache.bcel.internal.classfile.JavaClass; /** - * Utility class implementing a (typesafe) set of JavaClass objects. - * Since JavaClass has no equals() method, the name of the class is - * used for comparison. + * Utility class implementing a (type-safe) set of JavaClass objects. Since JavaClass has no equals() method, the name of the class is used for comparison. * * @see ClassStack + * @LastModified: Feb 2023 */ public class ClassSet { private final Map map = new HashMap<>(); - - public boolean add( final JavaClass clazz ) { - boolean result = false; - if (!map.containsKey(clazz.getClassName())) { - result = true; - map.put(clazz.getClassName(), clazz); - } - return result; + public boolean add(final JavaClass clazz) { + return map.putIfAbsent(clazz.getClassName(), clazz) != null; } - - public void remove( final JavaClass clazz ) { - map.remove(clazz.getClassName()); - } - - public boolean empty() { return map.isEmpty(); } - - public JavaClass[] toArray() { - final Collection values = map.values(); - final JavaClass[] classes = new JavaClass[values.size()]; - values.toArray(classes); - return classes; + public String[] getClassNames() { + return map.keySet().toArray(Const.EMPTY_STRING_ARRAY); } + public void remove(final JavaClass clazz) { + map.remove(clazz.getClassName()); + } - public String[] getClassNames() { - return map.keySet().toArray(new String[map.size()]); + public JavaClass[] toArray() { + return map.values().toArray(JavaClass.EMPTY_ARRAY); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassStack.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassStack.java index e545e3625dc..cc07acf7dbc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassStack.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassStack.java @@ -34,23 +34,19 @@ public class ClassStack { private final Stack stack = new Stack<>(); - - public void push( final JavaClass clazz ) { - stack.push(clazz); + public boolean empty() { + return stack.empty(); } - public JavaClass pop() { return stack.pop(); } + public void push(final JavaClass clazz) { + stack.push(clazz); + } public JavaClass top() { return stack.peek(); } - - - public boolean empty() { - return stack.empty(); - } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java index fe8e9388391..723fc07509b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java @@ -21,9 +21,9 @@ package com.sun.org.apache.bcel.internal.util; -import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; +import java.nio.charset.Charset; import java.util.BitSet; import com.sun.org.apache.bcel.internal.Const; @@ -36,363 +36,349 @@ import com.sun.org.apache.bcel.internal.classfile.ConstantMethodref; import com.sun.org.apache.bcel.internal.classfile.ConstantNameAndType; import com.sun.org.apache.bcel.internal.classfile.ConstantPool; -import com.sun.org.apache.bcel.internal.classfile.LocalVariable; import com.sun.org.apache.bcel.internal.classfile.LocalVariableTable; import com.sun.org.apache.bcel.internal.classfile.Method; import com.sun.org.apache.bcel.internal.classfile.Utility; /** * Convert code into HTML file. - * - * */ final class CodeHTML { + private static boolean wide; private final String className; // name of current class -// private Method[] methods; // Methods to print - private final PrintWriter file; // file to write to + // private Method[] methods; // Methods to print + private final PrintWriter printWriter; // file to write to private BitSet gotoSet; private final ConstantPool constantPool; private final ConstantHTML constantHtml; - private static boolean wide = false; - - CodeHTML(final String dir, final String class_name, final Method[] methods, final ConstantPool constant_pool, - final ConstantHTML constant_html) throws IOException { - this.className = class_name; + CodeHTML(final String dir, final String className, final Method[] methods, final ConstantPool constantPool, final ConstantHTML constantHtml, + final Charset charset) throws IOException { + this.className = className; // this.methods = methods; - this.constantPool = constant_pool; - this.constantHtml = constant_html; - file = new PrintWriter(new FileOutputStream(dir + class_name + "_code.html")); - file.println(""); - for (int i = 0; i < methods.length; i++) { - writeMethod(methods[i], i); + this.constantPool = constantPool; + this.constantHtml = constantHtml; + try (PrintWriter newPrintWriter = new PrintWriter(dir + className + "_code.html", charset.name())) { + printWriter = newPrintWriter; + printWriter.print(""); + printWriter.println(""); + for (int i = 0; i < methods.length; i++) { + writeMethod(methods[i], i); + } + printWriter.println(""); } - file.println(""); - file.close(); } - /** - * Disassemble a stream of byte codes and return the - * string representation. + * Disassemble a stream of byte codes and return the string representation. * - * @param stream data input stream + * @param stream data input stream * @return String representation of byte code */ - private String codeToHTML( final ByteSequence bytes, final int method_number ) throws IOException { + private String codeToHTML(final ByteSequence bytes, final int methodNumber) throws IOException { final short opcode = (short) bytes.readUnsignedByte(); String name; String signature; - int default_offset = 0; + int defaultOffset = 0; int low; int high; int index; - int class_index; + int classIndex; int vindex; int constant; - int[] jump_table; - int no_pad_bytes = 0; + int[] jumpTable; + int noPadBytes = 0; int offset; final StringBuilder buf = new StringBuilder(256); // CHECKSTYLE IGNORE MagicNumber buf.append("").append(Const.getOpcodeName(opcode)).append(""); - /* Special case: Skip (0-3) padding bytes, i.e., the - * following bytes are 4-byte-aligned + /* + * Special case: Skip (0-3) padding bytes, i.e., the following bytes are 4-byte-aligned */ - if ((opcode == Const.TABLESWITCH) || (opcode == Const.LOOKUPSWITCH)) { + if (opcode == Const.TABLESWITCH || opcode == Const.LOOKUPSWITCH) { final int remainder = bytes.getIndex() % 4; - no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder; - for (int i = 0; i < no_pad_bytes; i++) { + noPadBytes = remainder == 0 ? 0 : 4 - remainder; + for (int i = 0; i < noPadBytes; i++) { bytes.readByte(); } // Both cases have a field default_offset in common - default_offset = bytes.readInt(); + defaultOffset = bytes.readInt(); } switch (opcode) { - case Const.TABLESWITCH: - low = bytes.readInt(); - high = bytes.readInt(); - offset = bytes.getIndex() - 12 - no_pad_bytes - 1; - default_offset += offset; - buf.append(""); - // Print switch indices in first row (and default) - jump_table = new int[high - low + 1]; - for (int i = 0; i < jump_table.length; i++) { - jump_table[i] = offset + bytes.readInt(); - buf.append(""); - } - buf.append("\n"); - // Print target and default indices in second row - for (final int element : jump_table) { - buf.append(""); + case Const.TABLESWITCH: + low = bytes.readInt(); + high = bytes.readInt(); + offset = bytes.getIndex() - 12 - noPadBytes - 1; + defaultOffset += offset; + buf.append("
    ").append(low + i).append("default
    ").append(element).append("
    "); + // Print switch indices in first row (and default) + jumpTable = new int[high - low + 1]; + for (int i = 0; i < jumpTable.length; i++) { + jumpTable[i] = offset + bytes.readInt(); + buf.append(""); } - buf.append("\n
    ").append(low + i).append("").append(default_offset).append( - "
    \n"); - break; - /* Lookup switch has variable length arguments. - */ - case Const.LOOKUPSWITCH: - final int npairs = bytes.readInt(); - offset = bytes.getIndex() - 8 - no_pad_bytes - 1; - jump_table = new int[npairs]; - default_offset += offset; - buf.append(""); - // Print switch indices in first row (and default) - for (int i = 0; i < npairs; i++) { - final int match = bytes.readInt(); - jump_table[i] = offset + bytes.readInt(); - buf.append(""); - } - buf.append("\n"); - // Print target and default indices in second row - for (int i = 0; i < npairs; i++) { - buf.append(""); - } - buf.append("\n
    ").append(match).append("default
    ").append(jump_table[i]).append("").append(default_offset).append( - "
    \n"); - break; - /* Two address bytes + offset from start of byte stream form the - * jump target. - */ - case Const.GOTO: - case Const.IFEQ: - case Const.IFGE: - case Const.IFGT: - case Const.IFLE: - case Const.IFLT: - case Const.IFNE: - case Const.IFNONNULL: - case Const.IFNULL: - case Const.IF_ACMPEQ: - case Const.IF_ACMPNE: - case Const.IF_ICMPEQ: - case Const.IF_ICMPGE: - case Const.IF_ICMPGT: - case Const.IF_ICMPLE: - case Const.IF_ICMPLT: - case Const.IF_ICMPNE: - case Const.JSR: - index = bytes.getIndex() + bytes.readShort() - 1; - buf.append("").append(index).append(""); - break; - /* Same for 32-bit wide jumps - */ - case Const.GOTO_W: - case Const.JSR_W: - final int windex = bytes.getIndex() + bytes.readInt() - 1; - buf.append("").append(windex).append(""); - break; - /* Index byte references local variable (register) - */ - case Const.ALOAD: - case Const.ASTORE: - case Const.DLOAD: - case Const.DSTORE: - case Const.FLOAD: - case Const.FSTORE: - case Const.ILOAD: - case Const.ISTORE: - case Const.LLOAD: - case Const.LSTORE: - case Const.RET: - if (wide) { - vindex = bytes.readShort(); - wide = false; // Clear flag - } else { - vindex = bytes.readUnsignedByte(); - } - buf.append("%").append(vindex); - break; - /* - * Remember wide byte which is used to form a 16-bit address in the - * following instruction. Relies on that the method is called again with - * the following opcode. - */ - case Const.WIDE: - wide = true; - buf.append("(wide)"); - break; - /* Array of basic type. - */ - case Const.NEWARRAY: - buf.append("").append(Const.getTypeName(bytes.readByte())).append( - ""); - break; - /* Access object/class fields. - */ - case Const.GETFIELD: - case Const.GETSTATIC: - case Const.PUTFIELD: - case Const.PUTSTATIC: - index = bytes.readShort(); - final ConstantFieldref c1 = (ConstantFieldref) constantPool.getConstant(index, - Const.CONSTANT_Fieldref); - class_index = c1.getClassIndex(); - name = constantPool.getConstantString(class_index, Const.CONSTANT_Class); - name = Utility.compactClassName(name, false); - index = c1.getNameAndTypeIndex(); - final String field_name = constantPool.constantToString(index, Const.CONSTANT_NameAndType); - if (name.equals(className)) { // Local field - buf.append("").append(field_name) - .append("\n"); - } else { - buf.append(constantHtml.referenceConstant(class_index)).append(".").append( - field_name); - } - break; - /* Operands are references to classes in constant pool - */ - case Const.CHECKCAST: - case Const.INSTANCEOF: - case Const.NEW: - index = bytes.readShort(); - buf.append(constantHtml.referenceConstant(index)); - break; - /* Operands are references to methods in constant pool - */ - case Const.INVOKESPECIAL: - case Const.INVOKESTATIC: - case Const.INVOKEVIRTUAL: - case Const.INVOKEINTERFACE: - case Const.INVOKEDYNAMIC: - final int m_index = bytes.readShort(); - String str; - if (opcode == Const.INVOKEINTERFACE) { // Special treatment needed - bytes.readUnsignedByte(); // Redundant - bytes.readUnsignedByte(); // Reserved + buf.append("default\n"); + // Print target and default indices in second row + for (final int element : jumpTable) { + buf.append("").append(element).append(""); + } + buf.append("").append(defaultOffset) + .append("\n\n"); + break; + /* + * Lookup switch has variable length arguments. + */ + case Const.LOOKUPSWITCH: + final int npairs = bytes.readInt(); + offset = bytes.getIndex() - 8 - noPadBytes - 1; + jumpTable = new int[npairs]; + defaultOffset += offset; + buf.append(""); + // Print switch indices in first row (and default) + for (int i = 0; i < npairs; i++) { + final int match = bytes.readInt(); + jumpTable[i] = offset + bytes.readInt(); + buf.append(""); + } + buf.append("\n"); + // Print target and default indices in second row + for (int i = 0; i < npairs; i++) { + buf.append(""); + } + buf.append("\n
    ").append(match).append("default
    ").append(jumpTable[i]) + .append("").append(defaultOffset) + .append("
    \n"); + break; + /* + * Two address bytes + offset from start of byte stream form the jump target. + */ + case Const.GOTO: + case Const.IFEQ: + case Const.IFGE: + case Const.IFGT: + case Const.IFLE: + case Const.IFLT: + case Const.IFNE: + case Const.IFNONNULL: + case Const.IFNULL: + case Const.IF_ACMPEQ: + case Const.IF_ACMPNE: + case Const.IF_ICMPEQ: + case Const.IF_ICMPGE: + case Const.IF_ICMPGT: + case Const.IF_ICMPLE: + case Const.IF_ICMPLT: + case Const.IF_ICMPNE: + case Const.JSR: + index = bytes.getIndex() + bytes.readShort() - 1; + buf.append("").append(index).append(""); + break; + /* + * Same for 32-bit wide jumps + */ + case Const.GOTO_W: + case Const.JSR_W: + final int windex = bytes.getIndex() + bytes.readInt() - 1; + buf.append("").append(windex).append(""); + break; + /* + * Index byte references local variable (register) + */ + case Const.ALOAD: + case Const.ASTORE: + case Const.DLOAD: + case Const.DSTORE: + case Const.FLOAD: + case Const.FSTORE: + case Const.ILOAD: + case Const.ISTORE: + case Const.LLOAD: + case Const.LSTORE: + case Const.RET: + if (wide) { + vindex = bytes.readShort(); + wide = false; // Clear flag + } else { + vindex = bytes.readUnsignedByte(); + } + buf.append("%").append(vindex); + break; + /* + * Remember wide byte which is used to form a 16-bit address in the following instruction. Relies on that the method is + * called again with the following opcode. + */ + case Const.WIDE: + wide = true; + buf.append("(wide)"); + break; + /* + * Array of basic type. + */ + case Const.NEWARRAY: + buf.append("").append(Const.getTypeName(bytes.readByte())).append(""); + break; + /* + * Access object/class fields. + */ + case Const.GETFIELD: + case Const.GETSTATIC: + case Const.PUTFIELD: + case Const.PUTSTATIC: + index = bytes.readShort(); + final ConstantFieldref c1 = constantPool.getConstant(index, Const.CONSTANT_Fieldref, ConstantFieldref.class); + classIndex = c1.getClassIndex(); + name = constantPool.getConstantString(classIndex, Const.CONSTANT_Class); + name = Utility.compactClassName(name, false); + index = c1.getNameAndTypeIndex(); + final String fieldName = constantPool.constantToString(index, Const.CONSTANT_NameAndType); + if (name.equals(className)) { // Local field + buf.append("").append(fieldName) + .append("\n"); + } else { + buf.append(constantHtml.referenceConstant(classIndex)).append(".").append(fieldName); + } + break; + /* + * Operands are references to classes in constant pool + */ + case Const.CHECKCAST: + case Const.INSTANCEOF: + case Const.NEW: + index = bytes.readShort(); + buf.append(constantHtml.referenceConstant(index)); + break; + /* + * Operands are references to methods in constant pool + */ + case Const.INVOKESPECIAL: + case Const.INVOKESTATIC: + case Const.INVOKEVIRTUAL: + case Const.INVOKEINTERFACE: + case Const.INVOKEDYNAMIC: + final int mIndex = bytes.readShort(); + String str; + if (opcode == Const.INVOKEINTERFACE) { // Special treatment needed + bytes.readUnsignedByte(); // Redundant + bytes.readUnsignedByte(); // Reserved // int nargs = bytes.readUnsignedByte(); // Redundant // int reserved = bytes.readUnsignedByte(); // Reserved - final ConstantInterfaceMethodref c = (ConstantInterfaceMethodref) constantPool - .getConstant(m_index, Const.CONSTANT_InterfaceMethodref); - class_index = c.getClassIndex(); - index = c.getNameAndTypeIndex(); - name = Class2HTML.referenceClass(class_index); - } else if (opcode == Const.INVOKEDYNAMIC) { // Special treatment needed - bytes.readUnsignedByte(); // Reserved - bytes.readUnsignedByte(); // Reserved - final ConstantInvokeDynamic c = (ConstantInvokeDynamic) constantPool - .getConstant(m_index, Const.CONSTANT_InvokeDynamic); - index = c.getNameAndTypeIndex(); - name = "#" + c.getBootstrapMethodAttrIndex(); - } else { - // UNDONE: Java8 now allows INVOKESPECIAL and INVOKESTATIC to - // reference EITHER a Methodref OR an InterfaceMethodref. - // Not sure if that affects this code or not. (markro) - final ConstantMethodref c = (ConstantMethodref) constantPool.getConstant(m_index, - Const.CONSTANT_Methodref); - class_index = c.getClassIndex(); - index = c.getNameAndTypeIndex(); - name = Class2HTML.referenceClass(class_index); - } - str = Class2HTML.toHTML(constantPool.constantToString(constantPool.getConstant( - index, Const.CONSTANT_NameAndType))); - // Get signature, i.e., types - final ConstantNameAndType c2 = (ConstantNameAndType) constantPool.getConstant(index, - Const.CONSTANT_NameAndType); - signature = constantPool.constantToString(c2.getSignatureIndex(), Const.CONSTANT_Utf8); - final String[] args = Utility.methodSignatureArgumentTypes(signature, false); - final String type = Utility.methodSignatureReturnType(signature, false); - buf.append(name).append(".").append(str).append( - "").append("("); - // List arguments - for (int i = 0; i < args.length; i++) { - buf.append(Class2HTML.referenceType(args[i])); - if (i < args.length - 1) { - buf.append(", "); - } - } - // Attach return type - buf.append("):").append(Class2HTML.referenceType(type)); - break; - /* Operands are references to items in constant pool - */ - case Const.LDC_W: - case Const.LDC2_W: - index = bytes.readShort(); - buf.append("").append( - Class2HTML.toHTML(constantPool.constantToString(index, - constantPool.getConstant(index).getTag()))).append(""); - break; - case Const.LDC: - index = bytes.readUnsignedByte(); - buf.append("").append( - Class2HTML.toHTML(constantPool.constantToString(index, - constantPool.getConstant(index).getTag()))).append(""); - break; - /* Array of references. - */ - case Const.ANEWARRAY: - index = bytes.readShort(); - buf.append(constantHtml.referenceConstant(index)); - break; - /* Multidimensional array of references. - */ - case Const.MULTIANEWARRAY: - index = bytes.readShort(); - final int dimensions = bytes.readByte(); - buf.append(constantHtml.referenceConstant(index)).append(":").append(dimensions) - .append("-dimensional"); - break; - /* Increment local variable. - */ - case Const.IINC: - if (wide) { - vindex = bytes.readShort(); - constant = bytes.readShort(); - wide = false; - } else { - vindex = bytes.readUnsignedByte(); - constant = bytes.readByte(); + final ConstantInterfaceMethodref c = constantPool.getConstant(mIndex, Const.CONSTANT_InterfaceMethodref, ConstantInterfaceMethodref.class); + classIndex = c.getClassIndex(); + index = c.getNameAndTypeIndex(); + name = Class2HTML.referenceClass(classIndex); + } else if (opcode == Const.INVOKEDYNAMIC) { // Special treatment needed + bytes.readUnsignedByte(); // Reserved + bytes.readUnsignedByte(); // Reserved + final ConstantInvokeDynamic c = constantPool.getConstant(mIndex, Const.CONSTANT_InvokeDynamic, ConstantInvokeDynamic.class); + index = c.getNameAndTypeIndex(); + name = "#" + c.getBootstrapMethodAttrIndex(); + } else { + // UNDONE: Java8 now allows INVOKESPECIAL and INVOKESTATIC to + // reference EITHER a Methodref OR an InterfaceMethodref. + // Not sure if that affects this code or not. (markro) + final ConstantMethodref c = constantPool.getConstant(mIndex, Const.CONSTANT_Methodref, ConstantMethodref.class); + classIndex = c.getClassIndex(); + index = c.getNameAndTypeIndex(); + name = Class2HTML.referenceClass(classIndex); + } + str = Class2HTML.toHTML(constantPool.constantToString(constantPool.getConstant(index, Const.CONSTANT_NameAndType))); + // Get signature, i.e., types + final ConstantNameAndType c2 = constantPool.getConstant(index, Const.CONSTANT_NameAndType, ConstantNameAndType.class); + signature = constantPool.constantToString(c2.getSignatureIndex(), Const.CONSTANT_Utf8); + final String[] args = Utility.methodSignatureArgumentTypes(signature, false); + final String type = Utility.methodSignatureReturnType(signature, false); + buf.append(name).append(".").append(str) + .append("").append("("); + // List arguments + for (int i = 0; i < args.length; i++) { + buf.append(Class2HTML.referenceType(args[i])); + if (i < args.length - 1) { + buf.append(", "); } - buf.append("%").append(vindex).append(" ").append(constant); - break; - default: - if (Const.getNoOfOperands(opcode) > 0) { - for (int i = 0; i < Const.getOperandTypeCount(opcode); i++) { - switch (Const.getOperandType(opcode, i)) { - case Const.T_BYTE: - buf.append(bytes.readUnsignedByte()); - break; - case Const.T_SHORT: // Either branch or index - buf.append(bytes.readShort()); - break; - case Const.T_INT: - buf.append(bytes.readInt()); - break; - default: // Never reached - throw new IllegalStateException( - "Unreachable default case reached! " + - Const.getOperandType(opcode, i)); - } - buf.append(" "); + } + // Attach return type + buf.append("):").append(Class2HTML.referenceType(type)); + break; + /* + * Operands are references to items in constant pool + */ + case Const.LDC_W: + case Const.LDC2_W: + index = bytes.readShort(); + buf.append("") + .append(Class2HTML.toHTML(constantPool.constantToString(index, constantPool.getConstant(index).getTag()))).append(""); + break; + case Const.LDC: + index = bytes.readUnsignedByte(); + buf.append("") + .append(Class2HTML.toHTML(constantPool.constantToString(index, constantPool.getConstant(index).getTag()))).append(""); + break; + /* + * Array of references. + */ + case Const.ANEWARRAY: + index = bytes.readShort(); + buf.append(constantHtml.referenceConstant(index)); + break; + /* + * Multidimensional array of references. + */ + case Const.MULTIANEWARRAY: + index = bytes.readShort(); + final int dimensions = bytes.readByte(); + buf.append(constantHtml.referenceConstant(index)).append(":").append(dimensions).append("-dimensional"); + break; + /* + * Increment local variable. + */ + case Const.IINC: + if (wide) { + vindex = bytes.readShort(); + constant = bytes.readShort(); + wide = false; + } else { + vindex = bytes.readUnsignedByte(); + constant = bytes.readByte(); + } + buf.append("%").append(vindex).append(" ").append(constant); + break; + default: + if (Const.getNoOfOperands(opcode) > 0) { + for (int i = 0; i < Const.getOperandTypeCount(opcode); i++) { + switch (Const.getOperandType(opcode, i)) { + case Const.T_BYTE: + buf.append(bytes.readUnsignedByte()); + break; + case Const.T_SHORT: // Either branch or index + buf.append(bytes.readShort()); + break; + case Const.T_INT: + buf.append(bytes.readInt()); + break; + default: // Never reached + throw new IllegalStateException("Unreachable default case reached! " + Const.getOperandType(opcode, i)); } + buf.append(" "); } + } } buf.append(""); return buf.toString(); } - /** - * Find all target addresses in code, so that they can be marked - * with <A NAME = ...>. Target addresses are kept in an BitSet object. + * Find all target addresses in code, so that they can be marked with <A NAME = ...>. Target addresses are kept in + * an BitSet object. */ - private void findGotos( final ByteSequence bytes, final Code code ) throws IOException { + private void findGotos(final ByteSequence bytes, final Code code) throws IOException { int index; gotoSet = new BitSet(bytes.available()); int opcode; - /* First get Code attribute from method and the exceptions handled - * (try .. catch) in this method. We only need the line number here. + /* + * First get Code attribute from method and the exceptions handled (try .. catch) in this method. We only need the line + * number here. */ if (code != null) { final CodeException[] ce = code.getExceptionTable(); @@ -405,98 +391,94 @@ private void findGotos( final ByteSequence bytes, final Code code ) throws IOExc final Attribute[] attributes = code.getAttributes(); for (final Attribute attribute : attributes) { if (attribute.getTag() == Const.ATTR_LOCAL_VARIABLE_TABLE) { - final LocalVariable[] vars = ((LocalVariableTable) attribute) - .getLocalVariableTable(); - for (final LocalVariable var : vars) { + ((LocalVariableTable) attribute).forEach(var -> { final int start = var.getStartPC(); - final int end = start + var.getLength(); gotoSet.set(start); - gotoSet.set(end); - } + gotoSet.set(start + var.getLength()); + }); break; } } } // Get target addresses from GOTO, JSR, TABLESWITCH, etc. - for (; bytes.available() > 0;) { + while (bytes.available() > 0) { opcode = bytes.readUnsignedByte(); - //System.out.println(getOpcodeName(opcode)); + // System.out.println(getOpcodeName(opcode)); switch (opcode) { - case Const.TABLESWITCH: - case Const.LOOKUPSWITCH: - //bytes.readByte(); // Skip already read byte - final int remainder = bytes.getIndex() % 4; - final int no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder; - int default_offset; - int offset; - for (int j = 0; j < no_pad_bytes; j++) { - bytes.readByte(); + case Const.TABLESWITCH: + case Const.LOOKUPSWITCH: + // bytes.readByte(); // Skip already read byte + final int remainder = bytes.getIndex() % 4; + final int noPadBytes = remainder == 0 ? 0 : 4 - remainder; + int defaultOffset; + int offset; + for (int j = 0; j < noPadBytes; j++) { + bytes.readByte(); + } + // Both cases have a field default_offset in common + defaultOffset = bytes.readInt(); + if (opcode == Const.TABLESWITCH) { + final int low = bytes.readInt(); + final int high = bytes.readInt(); + offset = bytes.getIndex() - 12 - noPadBytes - 1; + defaultOffset += offset; + gotoSet.set(defaultOffset); + for (int j = 0; j < high - low + 1; j++) { + index = offset + bytes.readInt(); + gotoSet.set(index); } - // Both cases have a field default_offset in common - default_offset = bytes.readInt(); - if (opcode == Const.TABLESWITCH) { - final int low = bytes.readInt(); - final int high = bytes.readInt(); - offset = bytes.getIndex() - 12 - no_pad_bytes - 1; - default_offset += offset; - gotoSet.set(default_offset); - for (int j = 0; j < (high - low + 1); j++) { - index = offset + bytes.readInt(); - gotoSet.set(index); - } - } else { // LOOKUPSWITCH - final int npairs = bytes.readInt(); - offset = bytes.getIndex() - 8 - no_pad_bytes - 1; - default_offset += offset; - gotoSet.set(default_offset); - for (int j = 0; j < npairs; j++) { + } else { // LOOKUPSWITCH + final int npairs = bytes.readInt(); + offset = bytes.getIndex() - 8 - noPadBytes - 1; + defaultOffset += offset; + gotoSet.set(defaultOffset); + for (int j = 0; j < npairs; j++) { // int match = bytes.readInt(); - bytes.readInt(); - index = offset + bytes.readInt(); - gotoSet.set(index); - } + bytes.readInt(); + index = offset + bytes.readInt(); + gotoSet.set(index); } - break; - case Const.GOTO: - case Const.IFEQ: - case Const.IFGE: - case Const.IFGT: - case Const.IFLE: - case Const.IFLT: - case Const.IFNE: - case Const.IFNONNULL: - case Const.IFNULL: - case Const.IF_ACMPEQ: - case Const.IF_ACMPNE: - case Const.IF_ICMPEQ: - case Const.IF_ICMPGE: - case Const.IF_ICMPGT: - case Const.IF_ICMPLE: - case Const.IF_ICMPLT: - case Const.IF_ICMPNE: - case Const.JSR: - //bytes.readByte(); // Skip already read byte - index = bytes.getIndex() + bytes.readShort() - 1; - gotoSet.set(index); - break; - case Const.GOTO_W: - case Const.JSR_W: - //bytes.readByte(); // Skip already read byte - index = bytes.getIndex() + bytes.readInt() - 1; - gotoSet.set(index); - break; - default: - bytes.unreadByte(); - codeToHTML(bytes, 0); // Ignore output + } + break; + case Const.GOTO: + case Const.IFEQ: + case Const.IFGE: + case Const.IFGT: + case Const.IFLE: + case Const.IFLT: + case Const.IFNE: + case Const.IFNONNULL: + case Const.IFNULL: + case Const.IF_ACMPEQ: + case Const.IF_ACMPNE: + case Const.IF_ICMPEQ: + case Const.IF_ICMPGE: + case Const.IF_ICMPGT: + case Const.IF_ICMPLE: + case Const.IF_ICMPLT: + case Const.IF_ICMPNE: + case Const.JSR: + // bytes.readByte(); // Skip already read byte + index = bytes.getIndex() + bytes.readShort() - 1; + gotoSet.set(index); + break; + case Const.GOTO_W: + case Const.JSR_W: + // bytes.readByte(); // Skip already read byte + index = bytes.getIndex() + bytes.readInt() - 1; + gotoSet.set(index); + break; + default: + bytes.unreadByte(); + codeToHTML(bytes, 0); // Ignore output } } } - /** * Write a single method with the byte code associated with it. */ - private void writeMethod( final Method method, final int method_number ) throws IOException { + private void writeMethod(final Method method, final int methodNumber) throws IOException { // Get raw signature final String signature = method.getSignature(); // Get array of strings containing the argument types @@ -505,84 +487,79 @@ private void writeMethod( final Method method, final int method_number ) throws final String type = Utility.methodSignatureReturnType(signature, false); // Get method name final String name = method.getName(); - final String html_name = Class2HTML.toHTML(name); + final String htmlName = Class2HTML.toHTML(name); // Get method's access flags String access = Utility.accessToString(method.getAccessFlags()); access = Utility.replace(access, " ", " "); // Get the method's attributes, the Code Attribute in particular final Attribute[] attributes = method.getAttributes(); - file.print("

    " + access + " " + "" + Class2HTML.referenceType(type) + " " - + html_name + "("); + printWriter.print("

    " + access + " " + "" + Class2HTML.referenceType(type) + + " " + htmlName + "("); for (int i = 0; i < args.length; i++) { - file.print(Class2HTML.referenceType(args[i])); + printWriter.print(Class2HTML.referenceType(args[i])); if (i < args.length - 1) { - file.print(", "); + printWriter.print(", "); } } - file.println(")

    "); + printWriter.println(")

    "); Code c = null; byte[] code = null; if (attributes.length > 0) { - file.print("

    Attributes

      \n"); + printWriter.print("

      Attributes

        \n"); for (int i = 0; i < attributes.length; i++) { byte tag = attributes[i].getTag(); if (tag != Const.ATTR_UNKNOWN) { - file.print("
      • " - + Const.getAttributeName(tag) + "
      • \n"); + printWriter.print("
      • " + + Const.getAttributeName(tag) + "
      • \n"); } else { - file.print("
      • " + attributes[i] + "
      • "); + printWriter.print("
      • " + attributes[i] + "
      • "); } if (tag == Const.ATTR_CODE) { c = (Code) attributes[i]; final Attribute[] attributes2 = c.getAttributes(); code = c.getCode(); - file.print(""); } } - file.println("
      "); + printWriter.println("
    "); } if (code != null) { // No code, an abstract method, e.g. - //System.out.println(name + "\n" + Utility.codeToString(code, constantPool, 0, -1)); + // System.out.println(name + "\n" + Utility.codeToString(code, constantPool, 0, -1)); // Print the byte code try (ByteSequence stream = new ByteSequence(code)) { stream.mark(stream.available()); findGotos(stream, c); stream.reset(); - file.println("" - + ""); - for (; stream.available() > 0;) { + printWriter.println("
    Byte
    offset
    InstructionArgument
    " + ""); + while (stream.available() > 0) { final int offset = stream.getIndex(); - final String str = codeToHTML(stream, method_number); + final String str = codeToHTML(stream, methodNumber); String anchor = ""; /* - * Set an anchor mark if this line is targetted by a goto, jsr, etc. Defining an anchor for every - * line is very inefficient! + * Set an anchor mark if this line is targetted by a goto, jsr, etc. Defining an anchor for every line is very + * inefficient! */ if (gotoSet.get(offset)) { - anchor = ""; + anchor = ""; } String anchor2; if (stream.getIndex() == code.length) { - anchor2 = "" + offset + ""; + anchor2 = "" + offset + ""; } else { anchor2 = "" + offset; } - file.println(""); + printWriter.println(""); } } // Mark last line, may be targetted from Attributes window - file.println(""); - file.println("
    Byte
    offset
    InstructionArgument
    " + anchor2 + "" + anchor + str + "
    " + anchor2 + "" + anchor + str + "
    "); + printWriter.println(" "); + printWriter.println(""); } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ConstantHTML.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ConstantHTML.java index e2d5b4b5103..b3197f6d45a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ConstantHTML.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ConstantHTML.java @@ -21,9 +21,10 @@ package com.sun.org.apache.bcel.internal.util; -import java.io.FileOutputStream; -import java.io.IOException; +import java.io.FileNotFoundException; import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.classfile.Constant; @@ -39,198 +40,164 @@ /** * Convert constant pool into HTML file. - * - * */ final class ConstantHTML { private final String className; // name of current class private final String classPackage; // name of package private final ConstantPool constantPool; // reference to constant pool - private final PrintWriter file; // file to write to + private final PrintWriter printWriter; // file to write to private final String[] constantRef; // String to return for cp[i] private final Constant[] constants; // The constants in the cp private final Method[] methods; - - ConstantHTML(final String dir, final String class_name, final String class_package, final Method[] methods, - final ConstantPool constant_pool) throws IOException { - this.className = class_name; - this.classPackage = class_package; - this.constantPool = constant_pool; + ConstantHTML(final String dir, final String className, final String classPackage, final Method[] methods, final ConstantPool constantPool, + final Charset charset) throws FileNotFoundException, UnsupportedEncodingException { + this.className = className; + this.classPackage = classPackage; + this.constantPool = constantPool; this.methods = methods; - constants = constant_pool.getConstantPool(); - file = new PrintWriter(new FileOutputStream(dir + class_name + "_cp.html")); - constantRef = new String[constants.length]; - constantRef[0] = "<unknown>"; - file.println(""); - // Loop through constants, constants[0] is reserved - for (int i = 1; i < constants.length; i++) { - if (i % 2 == 0) { - file.print("
    "); - } else { - file.print("
    "); - } - if (constants[i] != null) { - writeConstant(i); + this.constants = constantPool.getConstantPool(); + try (PrintWriter newPrintWriter = new PrintWriter(dir + className + "_cp.html", charset.name())) { + printWriter = newPrintWriter; + constantRef = new String[constants.length]; + constantRef[0] = "<unknown>"; + printWriter.print(""); + printWriter.println(""); + // Loop through constants, constants[0] is reserved + for (int i = 1; i < constants.length; i++) { + if (i % 2 == 0) { + printWriter.print("\n"); } - file.print("\n"); + printWriter.println("
    "); + } else { + printWriter.print("
    "); + } + if (constants[i] != null) { + writeConstant(i); + } + printWriter.print("
    "); } - file.println("
    "); - file.close(); } + private int getMethodNumber(final String str) { + for (int i = 0; i < methods.length; i++) { + final String cmp = methods[i].getName() + methods[i].getSignature(); + if (cmp.equals(str)) { + return i; + } + } + return -1; + } - String referenceConstant( final int index ) { + String referenceConstant(final int index) { return constantRef[index]; } - - private void writeConstant( final int index ) { + private void writeConstant(final int index) { final byte tag = constants[index].getTag(); - int class_index; - int name_index; + int classIndex; + int nameIndex; String ref; // The header is always the same - file.println("

    " + index + " " + Const.getConstantName(tag) - + "

    "); - /* For every constant type get the needed parameters and print them appropiately + printWriter.println("

    " + index + " " + Const.getConstantName(tag) + "

    "); + /* + * For every constant type get the needed parameters and print them appropriately */ switch (tag) { - case Const.CONSTANT_InterfaceMethodref: - case Const.CONSTANT_Methodref: - // Get class_index and name_and_type_index, depending on type - if (tag == Const.CONSTANT_Methodref) { - final ConstantMethodref c = (ConstantMethodref) constantPool.getConstant(index, - Const.CONSTANT_Methodref); - class_index = c.getClassIndex(); - name_index = c.getNameAndTypeIndex(); - } else { - final ConstantInterfaceMethodref c1 = (ConstantInterfaceMethodref) constantPool - .getConstant(index, Const.CONSTANT_InterfaceMethodref); - class_index = c1.getClassIndex(); - name_index = c1.getNameAndTypeIndex(); - } - // Get method name and its class - final String method_name = constantPool.constantToString(name_index, - Const.CONSTANT_NameAndType); - final String html_method_name = Class2HTML.toHTML(method_name); - // Partially compacted class name, i.e., / -> . - final String method_class = constantPool.constantToString(class_index, Const.CONSTANT_Class); - String short_method_class = Utility.compactClassName(method_class); // I.e., remove java.lang. - short_method_class = Utility.compactClassName(short_method_class, classPackage - + ".", true); // Remove class package prefix - // Get method signature - final ConstantNameAndType c2 = (ConstantNameAndType) constantPool.getConstant( - name_index, Const.CONSTANT_NameAndType); - final String signature = constantPool.constantToString(c2.getSignatureIndex(), - Const.CONSTANT_Utf8); - // Get array of strings containing the argument types - final String[] args = Utility.methodSignatureArgumentTypes(signature, false); - // Get return type string - final String type = Utility.methodSignatureReturnType(signature, false); - final String ret_type = Class2HTML.referenceType(type); - final StringBuilder buf = new StringBuilder("("); - for (int i = 0; i < args.length; i++) { - buf.append(Class2HTML.referenceType(args[i])); - if (i < args.length - 1) { - buf.append(", "); - } - } - buf.append(")"); - final String arg_types = buf.toString(); - if (method_class.equals(className)) { - ref = "" - + html_method_name + ""; - } else { - ref = "" - + short_method_class + "." + html_method_name; - } - constantRef[index] = ret_type + " " + short_method_class - + "." + html_method_name + " " + arg_types; - file.println("

    " + ret_type + " " + ref + arg_types - + " \n

    "); - break; - case Const.CONSTANT_Fieldref: - // Get class_index and name_and_type_index - final ConstantFieldref c3 = (ConstantFieldref) constantPool.getConstant(index, - Const.CONSTANT_Fieldref); - class_index = c3.getClassIndex(); - name_index = c3.getNameAndTypeIndex(); - // Get method name and its class (compacted) - final String field_class = constantPool.constantToString(class_index, Const.CONSTANT_Class); - String short_field_class = Utility.compactClassName(field_class); // I.e., remove java.lang. - short_field_class = Utility.compactClassName(short_field_class, - classPackage + ".", true); // Remove class package prefix - final String field_name = constantPool - .constantToString(name_index, Const.CONSTANT_NameAndType); - if (field_class.equals(className)) { - ref = "" + field_name + ""; - } else { - ref = "" + short_field_class - + "." + field_name + "\n"; + case Const.CONSTANT_InterfaceMethodref: + case Const.CONSTANT_Methodref: + // Get class_index and name_and_type_index, depending on type + if (tag == Const.CONSTANT_Methodref) { + final ConstantMethodref c = constantPool.getConstant(index, Const.CONSTANT_Methodref, ConstantMethodref.class); + classIndex = c.getClassIndex(); + nameIndex = c.getNameAndTypeIndex(); + } else { + final ConstantInterfaceMethodref c1 = constantPool.getConstant(index, Const.CONSTANT_InterfaceMethodref, ConstantInterfaceMethodref.class); + classIndex = c1.getClassIndex(); + nameIndex = c1.getNameAndTypeIndex(); + } + // Get method name and its class + final String methodName = constantPool.constantToString(nameIndex, Const.CONSTANT_NameAndType); + final String htmlMethodName = Class2HTML.toHTML(methodName); + // Partially compacted class name, i.e., / -> . + final String methodClass = constantPool.constantToString(classIndex, Const.CONSTANT_Class); + String shortMethodClass = Utility.compactClassName(methodClass); // I.e., remove java.lang. + shortMethodClass = Utility.compactClassName(shortMethodClass, classPackage + ".", true); // Remove class package prefix + // Get method signature + final ConstantNameAndType c2 = constantPool.getConstant(nameIndex, Const.CONSTANT_NameAndType, ConstantNameAndType.class); + final String signature = constantPool.constantToString(c2.getSignatureIndex(), Const.CONSTANT_Utf8); + // Get array of strings containing the argument types + final String[] args = Utility.methodSignatureArgumentTypes(signature, false); + // Get return type string + final String type = Utility.methodSignatureReturnType(signature, false); + final String retType = Class2HTML.referenceType(type); + final StringBuilder buf = new StringBuilder("("); + for (int i = 0; i < args.length; i++) { + buf.append(Class2HTML.referenceType(args[i])); + if (i < args.length - 1) { + buf.append(", "); } - constantRef[index] = "" + short_field_class + "." - + field_name + ""; - file.println("

    " + ref + "
    \n" + "

    "); - break; - case Const.CONSTANT_Class: - final ConstantClass c4 = (ConstantClass) constantPool.getConstant(index, Const.CONSTANT_Class); - name_index = c4.getNameIndex(); - final String class_name2 = constantPool.constantToString(index, tag); // / -> . - String short_class_name = Utility.compactClassName(class_name2); // I.e., remove java.lang. - short_class_name = Utility.compactClassName(short_class_name, classPackage + ".", - true); // Remove class package prefix - ref = "" + short_class_name - + ""; - constantRef[index] = "" + short_class_name + ""; - file.println("

    " + ref + "

    \n"); - break; - case Const.CONSTANT_String: - final ConstantString c5 = (ConstantString) constantPool.getConstant(index, - Const.CONSTANT_String); - name_index = c5.getStringIndex(); - final String str = Class2HTML.toHTML(constantPool.constantToString(index, tag)); - file.println("

    " + str + "

    \n"); - break; - case Const.CONSTANT_NameAndType: - final ConstantNameAndType c6 = (ConstantNameAndType) constantPool.getConstant(index, - Const.CONSTANT_NameAndType); - name_index = c6.getNameIndex(); - final int signature_index = c6.getSignatureIndex(); - file.println("

    " - + Class2HTML.toHTML(constantPool.constantToString(index, tag)) - + "

    \n"); - break; - default: - file.println("

    " + Class2HTML.toHTML(constantPool.constantToString(index, tag)) + "\n"); - } // switch - } - - - private int getMethodNumber( final String str ) { - for (int i = 0; i < methods.length; i++) { - final String cmp = methods[i].getName() + methods[i].getSignature(); - if (cmp.equals(str)) { - return i; } - } - return -1; + buf.append(")"); + final String argTypes = buf.toString(); + if (methodClass.equals(className)) { + ref = "" + htmlMethodName + ""; + } else { + ref = "" + shortMethodClass + "." + htmlMethodName; + } + constantRef[index] = retType + " " + shortMethodClass + + "." + htmlMethodName + " " + argTypes; + printWriter.println("

    " + retType + " " + ref + argTypes + " \n

    "); + break; + case Const.CONSTANT_Fieldref: + // Get class_index and name_and_type_index + final ConstantFieldref c3 = constantPool.getConstant(index, Const.CONSTANT_Fieldref, ConstantFieldref.class); + classIndex = c3.getClassIndex(); + nameIndex = c3.getNameAndTypeIndex(); + // Get method name and its class (compacted) + final String fieldClass = constantPool.constantToString(classIndex, Const.CONSTANT_Class); + String shortFieldClass = Utility.compactClassName(fieldClass); // I.e., remove java.lang. + shortFieldClass = Utility.compactClassName(shortFieldClass, classPackage + ".", true); // Remove class package prefix + final String fieldName = constantPool.constantToString(nameIndex, Const.CONSTANT_NameAndType); + if (fieldClass.equals(className)) { + ref = "" + fieldName + ""; + } else { + ref = "" + shortFieldClass + "." + fieldName + "\n"; + } + constantRef[index] = "" + shortFieldClass + "." + fieldName + ""; + printWriter.println("

    " + ref + "
    \n" + "

    "); + break; + case Const.CONSTANT_Class: + final ConstantClass c4 = constantPool.getConstant(index, Const.CONSTANT_Class, ConstantClass.class); + nameIndex = c4.getNameIndex(); + final String className2 = constantPool.constantToString(index, tag); // / -> . + String shortClassName = Utility.compactClassName(className2); // I.e., remove java.lang. + shortClassName = Utility.compactClassName(shortClassName, classPackage + ".", true); // Remove class package prefix + ref = "" + shortClassName + ""; + constantRef[index] = "" + shortClassName + ""; + printWriter.println("

    " + ref + "

    \n"); + break; + case Const.CONSTANT_String: + final ConstantString c5 = constantPool.getConstant(index, Const.CONSTANT_String, ConstantString.class); + nameIndex = c5.getStringIndex(); + final String str = Class2HTML.toHTML(constantPool.constantToString(index, tag)); + printWriter.println("

    " + str + "

    \n"); + break; + case Const.CONSTANT_NameAndType: + final ConstantNameAndType c6 = constantPool.getConstant(index, Const.CONSTANT_NameAndType, ConstantNameAndType.class); + nameIndex = c6.getNameIndex(); + final int signatureIndex = c6.getSignatureIndex(); + printWriter.println("

    " + Class2HTML.toHTML(constantPool.constantToString(index, tag)) + "

    \n"); + break; + default: + printWriter.println("

    " + Class2HTML.toHTML(constantPool.constantToString(index, tag)) + "\n"); + } // switch } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java index 46d22379524..5b045bf08cc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java @@ -20,11 +20,8 @@ package com.sun.org.apache.bcel.internal.util; -import com.sun.org.apache.bcel.internal.Const; -import com.sun.org.apache.bcel.internal.generic.ClassGenException; -import com.sun.org.apache.bcel.internal.generic.InstructionHandle; -import com.sun.org.apache.bcel.internal.generic.InstructionList; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -33,16 +30,18 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.generic.ClassGenException; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; + /** - * InstructionFinder is a tool to search for given instructions patterns, i.e., - * match sequences of instructions in an instruction list via regular - * expressions. This can be used, e.g., in order to implement a peep hole - * optimizer that looks for code patterns and replaces them with faster - * equivalents. + * InstructionFinder is a tool to search for given instructions patterns, i.e., match sequences of instructions in an + * instruction list via regular expressions. This can be used, e.g., in order to implement a peep hole optimizer that + * looks for code patterns and replaces them with faster equivalents. * *

    - * This class internally uses the java.util.regex - * package to search for regular expressions. + * This class internally uses the java.util.regex package to search for regular expressions. * * A typical application would look like this: * @@ -68,73 +67,116 @@ */ public class InstructionFinder { - private static final int OFFSET = 32767; // char + OFFSET is outside of LATIN-1 - private static final int NO_OPCODES = 256; // Potential number, some are not used - private static final Map map = new HashMap<>(); - private final InstructionList il; - private String ilString; // instruction list as string - private InstructionHandle[] handles; // map instruction - - - // list to array /** - * @param il - * instruction list to search for given patterns + * Code patterns found may be checked using an additional user-defined constraint object whether they really match the + * needed criterion. I.e., check constraints that can not expressed with regular expressions. + * */ - public InstructionFinder(final InstructionList il) { - this.il = il; - reread(); - } - + public interface CodeConstraint { - /** - * Reread the instruction list, e.g., after you've altered the list upon a - * match. - */ - public final void reread() { - final int size = il.getLength(); - final char[] buf = new char[size]; // Create a string with length equal to il length - handles = il.getInstructionHandles(); - // Map opcodes to characters - for (int i = 0; i < size; i++) { - buf[i] = makeChar(handles[i].getInstruction().getOpcode()); - } - ilString = new String(buf); + /** + * @param match array of instructions matching the requested pattern + * @return true if the matched area is really useful + */ + boolean checkCode(InstructionHandle[] match); } + private static final int OFFSET = 32767; // char + OFFSET is outside of LATIN-1 + private static final int NO_OPCODES = 256; // Potential number, some are not used + private static final Map map = new HashMap<>(); - /** - * Map symbolic instruction names like "getfield" to a single character. - * - * @param pattern - * instruction pattern in lower case - * @return encoded string for a pattern such as "BranchInstruction". - */ - private static String mapName( final String pattern ) { - final String result = map.get(pattern); - if (result != null) { - return result; - } + // Initialize pattern map + static { + map.put("arithmeticinstruction", + "(irem|lrem|iand|ior|ineg|isub|lneg|fneg|fmul|ldiv|fadd|lxor|frem|idiv|land|ixor|ishr|fsub|lshl|fdiv|iadd|lor|dmul|lsub|ishl|imul|lmul|lushr|dneg|iushr|lshr|ddiv|drem|dadd|ladd|dsub)"); + map.put("invokeinstruction", "(invokevirtual|invokeinterface|invokestatic|invokespecial|invokedynamic)"); + map.put("arrayinstruction", + "(baload|aastore|saload|caload|fastore|lastore|iaload|castore|iastore|aaload|bastore|sastore|faload|laload|daload|dastore)"); + map.put("gotoinstruction", "(goto|goto_w)"); + map.put("conversioninstruction", "(d2l|l2d|i2s|d2i|l2i|i2b|l2f|d2f|f2i|i2d|i2l|f2d|i2c|f2l|i2f)"); + map.put("localvariableinstruction", "(fstore|iinc|lload|dstore|dload|iload|aload|astore|istore|fload|lstore)"); + map.put("loadinstruction", "(fload|dload|lload|iload|aload)"); + map.put("fieldinstruction", "(getfield|putstatic|getstatic|putfield)"); + map.put("cpinstruction", + "(ldc2_w|invokeinterface|invokedynamic|multianewarray|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|ldc_w|invokestatic|invokevirtual|putfield|ldc|new|anewarray)"); + map.put("stackinstruction", "(dup2|swap|dup2_x2|pop|pop2|dup|dup2_x1|dup_x2|dup_x1)"); + map.put("branchinstruction", + "(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)"); + map.put("returninstruction", "(lreturn|ireturn|freturn|dreturn|areturn|return)"); + map.put("storeinstruction", "(istore|fstore|dstore|astore|lstore)"); + map.put("select", "(tableswitch|lookupswitch)"); + map.put("ifinstruction", + "(ifeq|ifgt|if_icmpne|if_icmpeq|ifge|ifnull|ifne|if_icmple|if_icmpge|if_acmpeq|if_icmplt|if_acmpne|ifnonnull|iflt|if_icmpgt|ifle)"); + map.put("jsrinstruction", "(jsr|jsr_w)"); + map.put("variablelengthinstruction", "(tableswitch|jsr|goto|lookupswitch)"); + map.put("unconditionalbranch", "(goto|jsr|jsr_w|athrow|goto_w)"); + map.put("constantpushinstruction", "(dconst|bipush|sipush|fconst|iconst|lconst)"); + map.put("typedinstruction", + "(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dastore|ret|f2d|f2i|drem|iinc|i2c|checkcast|frem|lreturn|astore|lushr|daload|dneg|fastore|istore|lshl|ldiv|lstore|areturn|ishr|ldc_w|invokeinterface|invokedynamic|aastore|lxor|ishl|l2d|i2f|return|faload|sipush|iushr|caload|instanceof|invokespecial|putfield|fmul|ireturn|laload|d2f|lneg|ixor|i2l|fdiv|lastore|multianewarray|i2b|getstatic|i2d|putstatic|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|freturn|ldc|aconst_null|castore|lmul|ldc2_w|dadd|iconst|f2l|ddiv|dstore|land|jsr|anewarray|dmul|bipush|dsub|sastore|d2i|i2s|lshr|iadd|l2i|lload|bastore|fstore|fneg|iload|fadd|baload|fconst|ior|ineg|dreturn|l2f|lconst|getfield|invokevirtual|invokestatic|iastore)"); + map.put("popinstruction", "(fstore|dstore|pop|pop2|astore|putstatic|istore|lstore)"); + map.put("allocationinstruction", "(multianewarray|new|anewarray|newarray)"); + map.put("indexedinstruction", + "(lload|lstore|fload|ldc2_w|invokeinterface|invokedynamic|multianewarray|astore|dload|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|dstore|istore|iinc|ldc_w|ret|fstore|invokestatic|iload|putfield|invokevirtual|ldc|new|aload|anewarray)"); + map.put("pushinstruction", "(dup|lload|dup2|bipush|fload|ldc2_w|sipush|lconst|fconst|dload|getstatic|ldc_w|aconst_null|dconst|iload|ldc|iconst|aload)"); + map.put("stackproducer", + "(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dup|f2d|f2i|drem|i2c|checkcast|frem|lushr|daload|dneg|lshl|ldiv|ishr|ldc_w|invokeinterface|invokedynamic|lxor|ishl|l2d|i2f|faload|sipush|iushr|caload|instanceof|invokespecial|fmul|laload|d2f|lneg|ixor|i2l|fdiv|getstatic|i2b|swap|i2d|dup2|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|ldc|arraylength|aconst_null|tableswitch|lmul|ldc2_w|iconst|dadd|f2l|ddiv|land|jsr|anewarray|dmul|bipush|dsub|d2i|newarray|i2s|lshr|iadd|lload|l2i|fneg|iload|fadd|baload|fconst|lookupswitch|ior|ineg|lconst|l2f|getfield|invokevirtual|invokestatic)"); + map.put("stackconsumer", + "(imul|lsub|lor|iflt|fcmpg|if_icmpgt|iand|ifeq|if_icmplt|lrem|ifnonnull|idiv|d2l|isub|dcmpg|dastore|if_icmpeq|f2d|f2i|drem|i2c|checkcast|frem|lreturn|astore|lushr|pop2|monitorexit|dneg|fastore|istore|lshl|ldiv|lstore|areturn|if_icmpge|ishr|monitorenter|invokeinterface|invokedynamic|aastore|lxor|ishl|l2d|i2f|return|iushr|instanceof|invokespecial|fmul|ireturn|d2f|lneg|ixor|pop|i2l|ifnull|fdiv|lastore|i2b|if_acmpeq|ifge|swap|i2d|putstatic|fcmpl|ladd|irem|dcmpl|fsub|freturn|ifgt|castore|lmul|dadd|f2l|ddiv|dstore|land|if_icmpne|if_acmpne|dmul|dsub|sastore|ifle|d2i|i2s|lshr|iadd|l2i|bastore|fstore|fneg|fadd|ior|ineg|ifne|dreturn|l2f|if_icmple|getfield|invokevirtual|invokestatic|iastore)"); + map.put("exceptionthrower", + "(irem|lrem|laload|putstatic|baload|dastore|areturn|getstatic|ldiv|anewarray|iastore|castore|idiv|saload|lastore|fastore|putfield|lreturn|caload|getfield|return|aastore|freturn|newarray|instanceof|multianewarray|athrow|faload|iaload|aaload|dreturn|monitorenter|checkcast|bastore|arraylength|new|invokevirtual|sastore|ldc_w|ireturn|invokespecial|monitorexit|invokeinterface|invokedynamic|ldc|invokestatic|daload)"); + map.put("loadclass", + "(multianewarray|invokeinterface|invokedynamic|instanceof|invokespecial|putfield|checkcast|putstatic|invokevirtual|new|getstatic|invokestatic|getfield|anewarray)"); + map.put("instructiontargeter", + "(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)"); + // Some aliases + map.put("if_icmp", "(if_icmpne|if_icmpeq|if_icmple|if_icmpge|if_icmplt|if_icmpgt)"); + map.put("if_acmp", "(if_acmpeq|if_acmpne)"); + map.put("if", "(ifeq|ifne|iflt|ifge|ifgt|ifle)"); + // Precompile some aliases first + map.put("iconst", precompile(Const.ICONST_0, Const.ICONST_5, Const.ICONST_M1)); + map.put("lconst", new String(new char[] {'(', makeChar(Const.LCONST_0), '|', makeChar(Const.LCONST_1), ')'})); + map.put("dconst", new String(new char[] {'(', makeChar(Const.DCONST_0), '|', makeChar(Const.DCONST_1), ')'})); + map.put("fconst", new String(new char[] {'(', makeChar(Const.FCONST_0), '|', makeChar(Const.FCONST_1), '|', makeChar(Const.FCONST_2), ')'})); + map.put("lload", precompile(Const.LLOAD_0, Const.LLOAD_3, Const.LLOAD)); + map.put("iload", precompile(Const.ILOAD_0, Const.ILOAD_3, Const.ILOAD)); + map.put("dload", precompile(Const.DLOAD_0, Const.DLOAD_3, Const.DLOAD)); + map.put("fload", precompile(Const.FLOAD_0, Const.FLOAD_3, Const.FLOAD)); + map.put("aload", precompile(Const.ALOAD_0, Const.ALOAD_3, Const.ALOAD)); + map.put("lstore", precompile(Const.LSTORE_0, Const.LSTORE_3, Const.LSTORE)); + map.put("istore", precompile(Const.ISTORE_0, Const.ISTORE_3, Const.ISTORE)); + map.put("dstore", precompile(Const.DSTORE_0, Const.DSTORE_3, Const.DSTORE)); + map.put("fstore", precompile(Const.FSTORE_0, Const.FSTORE_3, Const.FSTORE)); + map.put("astore", precompile(Const.ASTORE_0, Const.ASTORE_3, Const.ASTORE)); + // Compile strings + map.forEach((key, value) -> { + final char ch = value.charAt(1); // Omit already precompiled patterns + if (ch < OFFSET) { + map.put(key, compilePattern(value)); // precompile all patterns + } + }); + // Add instruction alias to match anything + final StringBuilder buf = new StringBuilder("("); for (short i = 0; i < NO_OPCODES; i++) { - if (pattern.equals(Const.getOpcodeName(i))) { - return "" + makeChar(i); + if (Const.getNoOfOperands(i) != Const.UNDEFINED) { // Not an invalid opcode + buf.append(makeChar(i)); + if (i < NO_OPCODES - 1) { + buf.append('|'); + } } } - throw new IllegalArgumentException("Instruction unknown: " + pattern); + buf.append(')'); + map.put("instruction", buf.toString()); } - /** - * Replace symbolic names of instructions with the appropiate character and - * remove all white space from string. Meta characters such as +, * are - * ignored. + * Replace symbolic names of instructions with the appropriate character and remove all white space from string. Meta + * characters such as +, * are ignored. * - * @param pattern - * The pattern to compile + * @param pattern The pattern to compile * @return translated regular expression string */ - private static String compilePattern( final String pattern ) { - //Bug: BCEL-77 - Instructions are assumed to be english, to avoid odd Locale issues + private static String compilePattern(final String pattern) { + // Bug: BCEL-77 - Instructions are assumed to be english, to avoid odd Locale issues final String lower = pattern.toLowerCase(Locale.ENGLISH); final StringBuilder buf = new StringBuilder(); final int size = pattern.length(); @@ -144,11 +186,10 @@ private static String compilePattern( final String pattern ) { final StringBuilder name = new StringBuilder(); while ((Character.isLetterOrDigit(ch) || ch == '_') && i < size) { name.append(ch); - if (++i < size) { - ch = lower.charAt(i); - } else { + if (++i >= size) { break; } + ch = lower.charAt(i); } i--; buf.append(mapName(name.toString())); @@ -159,245 +200,172 @@ private static String compilePattern( final String pattern ) { return buf.toString(); } - /** - * @return the matched piece of code as an array of instruction (handles) + * Convert opcode number to char. */ - private InstructionHandle[] getMatch( final int matched_from, final int match_length ) { - final InstructionHandle[] match = new InstructionHandle[match_length]; - System.arraycopy(handles, matched_from, match, 0, match_length); - return match; + private static char makeChar(final short opcode) { + return (char) (opcode + OFFSET); } - /** - * Search for the given pattern in the instruction list. You can search for - * any valid opcode via its symbolic name, e.g. "istore". You can also use a - * super class or an interface name to match a whole set of instructions, e.g. - * "BranchInstruction" or "LoadInstruction". "istore" is also an alias for all - * "istore_x" instructions. Additional aliases are "if" for "ifxx", "if_icmp" - * for "if_icmpxx", "if_acmp" for "if_acmpxx". - * - * Consecutive instruction names must be separated by white space which will - * be removed during the compilation of the pattern. - * - * For the rest the usual pattern matching rules for regular expressions - * apply. - *

    - * Example pattern: - * - *

    -     * search("BranchInstruction NOP ((IfInstruction|GOTO)+ ISTORE Instruction)*");
    -     * 
    - * - *

    - * If you alter the instruction list upon a match such that other matching - * areas are affected, you should call reread() to update the finder and call - * search() again, because the matches are cached. + * Map symbolic instruction names like "getfield" to a single character. * - * @param pattern - * the instruction pattern to search for, where case is ignored - * @param from - * where to start the search in the instruction list - * @param constraint - * optional CodeConstraint to check the found code pattern for - * user-defined constraints - * @return iterator of matches where e.nextElement() returns an array of - * instruction handles describing the matched area + * @param pattern instruction pattern in lower case + * @return encoded string for a pattern such as "BranchInstruction". */ - public final Iterator search( final String pattern, - final InstructionHandle from, final CodeConstraint constraint ) { - final String search = compilePattern(pattern); - int start = -1; - for (int i = 0; i < handles.length; i++) { - if (handles[i] == from) { - start = i; // Where to start search from (index) - break; - } - } - if (start == -1) { - throw new ClassGenException("Instruction handle " + from - + " not found in instruction list."); + private static String mapName(final String pattern) { + final String result = map.get(pattern); + if (result != null) { + return result; } - final Pattern regex = Pattern.compile(search); - final List matches = new ArrayList<>(); - final Matcher matcher = regex.matcher(ilString); - while (start < ilString.length() && matcher.find(start)) { - final int startExpr = matcher.start(); - final int endExpr = matcher.end(); - final int lenExpr = endExpr - startExpr; - final InstructionHandle[] match = getMatch(startExpr, lenExpr); - if ((constraint == null) || constraint.checkCode(match)) { - matches.add(match); + for (short i = 0; i < NO_OPCODES; i++) { + if (pattern.equals(Const.getOpcodeName(i))) { + return String.valueOf(makeChar(i)); } - start = endExpr; } - return matches.iterator(); + throw new IllegalArgumentException("Instruction unknown: " + pattern); } + private static String precompile(final short from, final short to, final short extra) { + final StringBuilder buf = new StringBuilder("("); + for (short i = from; i <= to; i++) { + buf.append(makeChar(i)); + buf.append('|'); + } + buf.append(makeChar(extra)); + buf.append(")"); + return buf.toString(); + } + + private final InstructionList il; + + private String ilString; // instruction list as string + + private InstructionHandle[] handles; // map instruction + // list to array /** - * Start search beginning from the start of the given instruction list. - * - * @param pattern - * the instruction pattern to search for, where case is ignored - * @return iterator of matches where e.nextElement() returns an array of - * instruction handles describing the matched area + * @param il instruction list to search for given patterns */ - public final Iterator search( final String pattern ) { - return search(pattern, il.getStart(), null); + public InstructionFinder(final InstructionList il) { + this.il = il; + reread(); } - /** - * Start search beginning from `from'. - * - * @param pattern - * the instruction pattern to search for, where case is ignored - * @param from - * where to start the search in the instruction list - * @return iterator of matches where e.nextElement() returns an array of - * instruction handles describing the matched area + * @return the inquired instruction list */ - public final Iterator search( final String pattern, - final InstructionHandle from ) { - return search(pattern, from, null); + public final InstructionList getInstructionList() { + return il; } - /** - * Start search beginning from the start of the given instruction list. Check - * found matches with the constraint object. - * - * @param pattern - * the instruction pattern to search for, case is ignored - * @param constraint - * constraints to be checked on matching code - * @return instruction handle or `null' if the match failed + * @return the matched piece of code as an array of instruction (handles) */ - public final Iterator search( final String pattern, - final CodeConstraint constraint ) { - return search(pattern, il.getStart(), constraint); + private InstructionHandle[] getMatch(final int matchedFrom, final int matchLength) { + return Arrays.copyOfRange(handles, matchedFrom, matchedFrom + matchLength); } - /** - * Convert opcode number to char. + * Reread the instruction list, e.g., after you've altered the list upon a match. */ - private static char makeChar( final short opcode ) { - return (char) (opcode + OFFSET); + public final void reread() { + final int size = il.getLength(); + final char[] buf = new char[size]; // Create a string with length equal to il length + handles = il.getInstructionHandles(); + // Map opcodes to characters + for (int i = 0; i < size; i++) { + buf[i] = makeChar(handles[i].getInstruction().getOpcode()); + } + ilString = new String(buf); } - /** - * @return the inquired instruction list + * Start search beginning from the start of the given instruction list. + * + * @param pattern the instruction pattern to search for, where case is ignored + * @return iterator of matches where e.nextElement() returns an array of instruction handles describing the matched area */ - public final InstructionList getInstructionList() { - return il; + public final Iterator search(final String pattern) { + return search(pattern, il.getStart(), null); } /** - * Code patterns found may be checked using an additional user-defined - * constraint object whether they really match the needed criterion. I.e., - * check constraints that can not expressed with regular expressions. + * Start search beginning from the start of the given instruction list. Check found matches with the constraint object. * + * @param pattern the instruction pattern to search for, case is ignored + * @param constraint constraints to be checked on matching code + * @return instruction handle or 'null' if the match failed */ - public interface CodeConstraint { + public final Iterator search(final String pattern, final CodeConstraint constraint) { + return search(pattern, il.getStart(), constraint); + } - /** - * @param match - * array of instructions matching the requested pattern - * @return true if the matched area is really useful - */ - boolean checkCode( InstructionHandle[] match ); + /** + * Start search beginning from 'from'. + * + * @param pattern the instruction pattern to search for, where case is ignored + * @param from where to start the search in the instruction list + * @return iterator of matches where e.nextElement() returns an array of instruction handles describing the matched area + */ + public final Iterator search(final String pattern, final InstructionHandle from) { + return search(pattern, from, null); } - // Initialize pattern map - static { - map.put("arithmeticinstruction","(irem|lrem|iand|ior|ineg|isub|lneg|fneg|fmul|ldiv|fadd|lxor|frem|idiv|land|ixor|ishr|fsub|lshl|fdiv|iadd|lor|dmul|lsub|ishl|imul|lmul|lushr|dneg|iushr|lshr|ddiv|drem|dadd|ladd|dsub)"); - map.put("invokeinstruction", "(invokevirtual|invokeinterface|invokestatic|invokespecial|invokedynamic)"); - map.put("arrayinstruction", "(baload|aastore|saload|caload|fastore|lastore|iaload|castore|iastore|aaload|bastore|sastore|faload|laload|daload|dastore)"); - map.put("gotoinstruction", "(goto|goto_w)"); - map.put("conversioninstruction", "(d2l|l2d|i2s|d2i|l2i|i2b|l2f|d2f|f2i|i2d|i2l|f2d|i2c|f2l|i2f)"); - map.put("localvariableinstruction","(fstore|iinc|lload|dstore|dload|iload|aload|astore|istore|fload|lstore)"); - map.put("loadinstruction", "(fload|dload|lload|iload|aload)"); - map.put("fieldinstruction", "(getfield|putstatic|getstatic|putfield)"); - map.put("cpinstruction", "(ldc2_w|invokeinterface|invokedynamic|multianewarray|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|ldc_w|invokestatic|invokevirtual|putfield|ldc|new|anewarray)"); - map.put("stackinstruction", "(dup2|swap|dup2_x2|pop|pop2|dup|dup2_x1|dup_x2|dup_x1)"); - map.put("branchinstruction", "(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)"); - map.put("returninstruction", "(lreturn|ireturn|freturn|dreturn|areturn|return)"); - map.put("storeinstruction", "(istore|fstore|dstore|astore|lstore)"); - map.put("select", "(tableswitch|lookupswitch)"); - map.put("ifinstruction", "(ifeq|ifgt|if_icmpne|if_icmpeq|ifge|ifnull|ifne|if_icmple|if_icmpge|if_acmpeq|if_icmplt|if_acmpne|ifnonnull|iflt|if_icmpgt|ifle)"); - map.put("jsrinstruction", "(jsr|jsr_w)"); - map.put("variablelengthinstruction", "(tableswitch|jsr|goto|lookupswitch)"); - map.put("unconditionalbranch", "(goto|jsr|jsr_w|athrow|goto_w)"); - map.put("constantpushinstruction", "(dconst|bipush|sipush|fconst|iconst|lconst)"); - map.put("typedinstruction", "(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dastore|ret|f2d|f2i|drem|iinc|i2c|checkcast|frem|lreturn|astore|lushr|daload|dneg|fastore|istore|lshl|ldiv|lstore|areturn|ishr|ldc_w|invokeinterface|invokedynamic|aastore|lxor|ishl|l2d|i2f|return|faload|sipush|iushr|caload|instanceof|invokespecial|putfield|fmul|ireturn|laload|d2f|lneg|ixor|i2l|fdiv|lastore|multianewarray|i2b|getstatic|i2d|putstatic|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|freturn|ldc|aconst_null|castore|lmul|ldc2_w|dadd|iconst|f2l|ddiv|dstore|land|jsr|anewarray|dmul|bipush|dsub|sastore|d2i|i2s|lshr|iadd|l2i|lload|bastore|fstore|fneg|iload|fadd|baload|fconst|ior|ineg|dreturn|l2f|lconst|getfield|invokevirtual|invokestatic|iastore)"); - map.put("popinstruction", "(fstore|dstore|pop|pop2|astore|putstatic|istore|lstore)"); - map.put("allocationinstruction", "(multianewarray|new|anewarray|newarray)"); - map.put("indexedinstruction", "(lload|lstore|fload|ldc2_w|invokeinterface|invokedynamic|multianewarray|astore|dload|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|dstore|istore|iinc|ldc_w|ret|fstore|invokestatic|iload|putfield|invokevirtual|ldc|new|aload|anewarray)"); - map.put("pushinstruction", "(dup|lload|dup2|bipush|fload|ldc2_w|sipush|lconst|fconst|dload|getstatic|ldc_w|aconst_null|dconst|iload|ldc|iconst|aload)"); - map.put("stackproducer", "(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dup|f2d|f2i|drem|i2c|checkcast|frem|lushr|daload|dneg|lshl|ldiv|ishr|ldc_w|invokeinterface|invokedynamic|lxor|ishl|l2d|i2f|faload|sipush|iushr|caload|instanceof|invokespecial|fmul|laload|d2f|lneg|ixor|i2l|fdiv|getstatic|i2b|swap|i2d|dup2|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|ldc|arraylength|aconst_null|tableswitch|lmul|ldc2_w|iconst|dadd|f2l|ddiv|land|jsr|anewarray|dmul|bipush|dsub|d2i|newarray|i2s|lshr|iadd|lload|l2i|fneg|iload|fadd|baload|fconst|lookupswitch|ior|ineg|lconst|l2f|getfield|invokevirtual|invokestatic)"); - map.put("stackconsumer", "(imul|lsub|lor|iflt|fcmpg|if_icmpgt|iand|ifeq|if_icmplt|lrem|ifnonnull|idiv|d2l|isub|dcmpg|dastore|if_icmpeq|f2d|f2i|drem|i2c|checkcast|frem|lreturn|astore|lushr|pop2|monitorexit|dneg|fastore|istore|lshl|ldiv|lstore|areturn|if_icmpge|ishr|monitorenter|invokeinterface|invokedynamic|aastore|lxor|ishl|l2d|i2f|return|iushr|instanceof|invokespecial|fmul|ireturn|d2f|lneg|ixor|pop|i2l|ifnull|fdiv|lastore|i2b|if_acmpeq|ifge|swap|i2d|putstatic|fcmpl|ladd|irem|dcmpl|fsub|freturn|ifgt|castore|lmul|dadd|f2l|ddiv|dstore|land|if_icmpne|if_acmpne|dmul|dsub|sastore|ifle|d2i|i2s|lshr|iadd|l2i|bastore|fstore|fneg|fadd|ior|ineg|ifne|dreturn|l2f|if_icmple|getfield|invokevirtual|invokestatic|iastore)"); - map.put("exceptionthrower","(irem|lrem|laload|putstatic|baload|dastore|areturn|getstatic|ldiv|anewarray|iastore|castore|idiv|saload|lastore|fastore|putfield|lreturn|caload|getfield|return|aastore|freturn|newarray|instanceof|multianewarray|athrow|faload|iaload|aaload|dreturn|monitorenter|checkcast|bastore|arraylength|new|invokevirtual|sastore|ldc_w|ireturn|invokespecial|monitorexit|invokeinterface|invokedynamic|ldc|invokestatic|daload)"); - map.put("loadclass", "(multianewarray|invokeinterface|invokedynamic|instanceof|invokespecial|putfield|checkcast|putstatic|invokevirtual|new|getstatic|invokestatic|getfield|anewarray)"); - map.put("instructiontargeter", "(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)"); - // Some aliases - map.put("if_icmp", "(if_icmpne|if_icmpeq|if_icmple|if_icmpge|if_icmplt|if_icmpgt)"); - map.put("if_acmp", "(if_acmpeq|if_acmpne)"); - map.put("if", "(ifeq|ifne|iflt|ifge|ifgt|ifle)"); - // Precompile some aliases first - map.put("iconst", precompile(Const.ICONST_0, Const.ICONST_5, Const.ICONST_M1)); - map.put("lconst", new String(new char[] { '(', makeChar(Const.LCONST_0), '|', makeChar(Const.LCONST_1), ')' })); - map.put("dconst", new String(new char[] { '(', makeChar(Const.DCONST_0), '|', makeChar(Const.DCONST_1), ')' })); - map.put("fconst", new String(new char[] { '(', makeChar(Const.FCONST_0), '|', makeChar(Const.FCONST_1), '|', makeChar(Const.FCONST_2), ')' })); - map.put("lload", precompile(Const.LLOAD_0, Const.LLOAD_3, Const.LLOAD)); - map.put("iload", precompile(Const.ILOAD_0, Const.ILOAD_3, Const.ILOAD)); - map.put("dload", precompile(Const.DLOAD_0, Const.DLOAD_3, Const.DLOAD)); - map.put("fload", precompile(Const.FLOAD_0, Const.FLOAD_3, Const.FLOAD)); - map.put("aload", precompile(Const.ALOAD_0, Const.ALOAD_3, Const.ALOAD)); - map.put("lstore", precompile(Const.LSTORE_0, Const.LSTORE_3, Const.LSTORE)); - map.put("istore", precompile(Const.ISTORE_0, Const.ISTORE_3, Const.ISTORE)); - map.put("dstore", precompile(Const.DSTORE_0, Const.DSTORE_3, Const.DSTORE)); - map.put("fstore", precompile(Const.FSTORE_0, Const.FSTORE_3, Const.FSTORE)); - map.put("astore", precompile(Const.ASTORE_0, Const.ASTORE_3, Const.ASTORE)); - // Compile strings - for (final Map.Entry entry : map.entrySet()) { - final String key = entry.getKey(); - final String value = entry.getValue(); - final char ch = value.charAt(1); // Omit already precompiled patterns - if (ch < OFFSET) { - map.put(key, compilePattern(value)); // precompile all patterns + /** + * Search for the given pattern in the instruction list. You can search for any valid opcode via its symbolic name, e.g. + * "istore". You can also use a super class or an interface name to match a whole set of instructions, e.g. + * "BranchInstruction" or "LoadInstruction". "istore" is also an alias for all "istore_x" instructions. Additional + * aliases are "if" for "ifxx", "if_icmp" for "if_icmpxx", "if_acmp" for "if_acmpxx". + * + * Consecutive instruction names must be separated by white space which will be removed during the compilation of the + * pattern. + * + * For the rest the usual pattern matching rules for regular expressions apply. + *

    + * Example pattern: + * + *

    +     * search("BranchInstruction NOP ((IfInstruction|GOTO)+ ISTORE Instruction)*");
    +     * 
    + * + *

    + * If you alter the instruction list upon a match such that other matching areas are affected, you should call reread() + * to update the finder and call search() again, because the matches are cached. + * + * @param pattern the instruction pattern to search for, where case is ignored + * @param from where to start the search in the instruction list + * @param constraint optional CodeConstraint to check the found code pattern for user-defined constraints + * @return iterator of matches where e.nextElement() returns an array of instruction handles describing the matched area + */ + public final Iterator search(final String pattern, final InstructionHandle from, final CodeConstraint constraint) { + final String search = compilePattern(pattern); + int start = -1; + for (int i = 0; i < handles.length; i++) { + if (handles[i] == from) { + start = i; // Where to start search from (index) + break; } } - // Add instruction alias to match anything - final StringBuilder buf = new StringBuilder("("); - for (short i = 0; i < NO_OPCODES; i++) { - if (Const.getNoOfOperands(i) != Const.UNDEFINED) { // Not an invalid opcode - buf.append(makeChar(i)); - if (i < NO_OPCODES - 1) { - buf.append('|'); - } - } + if (start == -1) { + throw new ClassGenException("Instruction handle " + from + " not found in instruction list."); } - buf.append(')'); - map.put("instruction", buf.toString()); - } - - - private static String precompile( final short from, final short to, final short extra ) { - final StringBuilder buf = new StringBuilder("("); - for (short i = from; i <= to; i++) { - buf.append(makeChar(i)); - buf.append('|'); + final Pattern regex = Pattern.compile(search); + final List matches = new ArrayList<>(); + final Matcher matcher = regex.matcher(ilString); + while (start < ilString.length() && matcher.find(start)) { + final int startExpr = matcher.start(); + final int endExpr = matcher.end(); + final int lenExpr = endExpr - startExpr; + final InstructionHandle[] match = getMatch(startExpr, lenExpr); + if (constraint == null || constraint.checkCode(match)) { + matches.add(match); + } + start = endExpr; } - buf.append(makeChar(extra)); - buf.append(")"); - return buf.toString(); + return matches.iterator(); } - /* * Internal debugging routines. */ @@ -405,7 +373,6 @@ private static String precompile( final short from, final short to, final short // return pattern2string(pattern, true); // } - // private static final String pattern2string( String pattern, boolean make_string ) { // StringBuffer buf = new StringBuffer(); // for (int i = 0; i < pattern.length(); i++) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/MethodHTML.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/MethodHTML.java index 05f25ed775e..a75a58bedbf 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/MethodHTML.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/MethodHTML.java @@ -21,14 +21,14 @@ package com.sun.org.apache.bcel.internal.util; -import java.io.FileOutputStream; -import java.io.IOException; +import java.io.FileNotFoundException; import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.classfile.Attribute; import com.sun.org.apache.bcel.internal.classfile.Code; -import com.sun.org.apache.bcel.internal.classfile.ConstantValue; import com.sun.org.apache.bcel.internal.classfile.ExceptionTable; import com.sun.org.apache.bcel.internal.classfile.Field; import com.sun.org.apache.bcel.internal.classfile.Method; @@ -36,75 +36,69 @@ /** * Convert methods and fields into HTML file. - * - * */ final class MethodHTML { private final String className; // name of current class - private final PrintWriter file; // file to write to + private final PrintWriter printWriter; // file to write to private final ConstantHTML constantHtml; - private final AttributeHTML attribute_html; + private final AttributeHTML attributeHtml; - - MethodHTML(final String dir, final String class_name, final Method[] methods, final Field[] fields, - final ConstantHTML constant_html, final AttributeHTML attribute_html) throws IOException { - this.className = class_name; - this.attribute_html = attribute_html; - this.constantHtml = constant_html; - file = new PrintWriter(new FileOutputStream(dir + class_name + "_methods.html")); - file.println(""); - file.println("" - + ""); - for (final Field field : fields) { - writeField(field); - } - file.println("
    Access flagsTypeField name
    "); - file.println("" - + "" - + ""); - for (int i = 0; i < methods.length; i++) { - writeMethod(methods[i], i); + MethodHTML(final String dir, final String className, final Method[] methods, final Field[] fields, final ConstantHTML constantHtml, + final AttributeHTML attributeHtml, final Charset charset) throws FileNotFoundException, UnsupportedEncodingException { + this.className = className; + this.attributeHtml = attributeHtml; + this.constantHtml = constantHtml; + try (PrintWriter newPrintWriter = new PrintWriter(dir + className + "_methods.html", charset.name())) { + printWriter = newPrintWriter; + printWriter.print(""); + printWriter.println("
    Access flagsReturn typeMethod nameArguments
    "); + printWriter.println("" + ""); + for (final Field field : fields) { + writeField(field); + } + printWriter.println("
    Access flagsTypeField name
    "); + printWriter.println("" + + "" + ""); + for (int i = 0; i < methods.length; i++) { + writeMethod(methods[i], i); + } + printWriter.println("
    Access flagsReturn typeMethod nameArguments
    "); } - file.println(""); - file.close(); } - /** * Print field of class. * * @param field field to print - * @throws java.io.IOException */ - private void writeField( final Field field ) throws IOException { + private void writeField(final Field field) { final String type = Utility.signatureToString(field.getSignature()); final String name = field.getName(); String access = Utility.accessToString(field.getAccessFlags()); Attribute[] attributes; access = Utility.replace(access, " ", " "); - file.print("" + access + "\n" - + Class2HTML.referenceType(type) + "" + name - + ""); + printWriter.print("" + access + "\n" + Class2HTML.referenceType(type) + "" + name + ""); attributes = field.getAttributes(); // Write them to the Attributes.html file with anchor "[]" for (int i = 0; i < attributes.length; i++) { - attribute_html.writeAttribute(attributes[i], name + "@" + i); + attributeHtml.writeAttribute(attributes[i], name + "@" + i); } for (int i = 0; i < attributes.length; i++) { if (attributes[i].getTag() == Const.ATTR_CONSTANT_VALUE) { // Default value - final String str = ((ConstantValue) attributes[i]).toString(); + final String str = attributes[i].toString(); // Reference attribute in _attributes.html - file.print("= " + str + "\n"); + printWriter.print("= " + str + "\n"); break; } } - file.println(""); + printWriter.println(""); } - - private void writeMethod( final Method method, final int method_number ) { + private void writeMethod(final Method method, final int methodNumber) { // Get raw signature final String signature = method.getSignature(); // Get array of strings containing the argument types @@ -113,48 +107,44 @@ private void writeMethod( final Method method, final int method_number ) { final String type = Utility.methodSignatureReturnType(signature, false); // Get method name final String name = method.getName(); - String html_name; + String htmlName; // Get method's access flags String access = Utility.accessToString(method.getAccessFlags()); // Get the method's attributes, the Code Attribute in particular final Attribute[] attributes = method.getAttributes(); - /* HTML doesn't like names like and spaces are places to break - * lines. Both we don't want... + /* + * HTML doesn't like names like and spaces are places to break lines. Both we don't want... */ access = Utility.replace(access, " ", " "); - html_name = Class2HTML.toHTML(name); - file.print("" + access + ""); - file.print("" + Class2HTML.referenceType(type) + "" + "" + html_name - + "\n("); + htmlName = Class2HTML.toHTML(name); + printWriter.print("" + access + ""); + printWriter.print("" + Class2HTML.referenceType(type) + "" + "" + + htmlName + "\n("); for (int i = 0; i < args.length; i++) { - file.print(Class2HTML.referenceType(args[i])); + printWriter.print(Class2HTML.referenceType(args[i])); if (i < args.length - 1) { - file.print(", "); + printWriter.print(", "); } } - file.print(")"); + printWriter.print(")"); // Check for thrown exceptions for (int i = 0; i < attributes.length; i++) { - attribute_html.writeAttribute(attributes[i], "method" + method_number + "@" + i, - method_number); + attributeHtml.writeAttribute(attributes[i], "method" + methodNumber + "@" + i, methodNumber); final byte tag = attributes[i].getTag(); if (tag == Const.ATTR_EXCEPTIONS) { - file.print("throws"); + printWriter.print("throws"); final int[] exceptions = ((ExceptionTable) attributes[i]).getExceptionIndexTable(); for (int j = 0; j < exceptions.length; j++) { - file.print(constantHtml.referenceConstant(exceptions[j])); + printWriter.print(constantHtml.referenceConstant(exceptions[j])); if (j < exceptions.length - 1) { - file.print(", "); + printWriter.print(", "); } } - file.println(""); + printWriter.println(""); } else if (tag == Const.ATTR_CODE) { - final Attribute[] c_a = ((Code) attributes[i]).getAttributes(); - for (int j = 0; j < c_a.length; j++) { - attribute_html.writeAttribute(c_a[j], "method" + method_number + "@" + i + "@" - + j, method_number); + final Attribute[] attributeArray = ((Code) attributes[i]).getAttributes(); + for (int j = 0; j < attributeArray.length; j++) { + attributeHtml.writeAttribute(attributeArray[j], "method" + methodNumber + "@" + i + "@" + j, methodNumber); } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ModularRuntimeImage.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ModularRuntimeImage.java index 9958d0a1a62..fd7cd0d2dc3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ModularRuntimeImage.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ModularRuntimeImage.java @@ -35,7 +35,6 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.Map; @@ -54,28 +53,24 @@ public class ModularRuntimeImage implements Closeable { /** * Constructs a default instance. - * - * @throws IOException - * an I/O error occurs accessing the file system */ - public ModularRuntimeImage() throws IOException { + @SuppressWarnings("resource") // See #close() + public ModularRuntimeImage() { this(null, FileSystems.getFileSystem(URI.create("jrt:/"))); } /** * Constructs an instance using the JRT file system implementation from a specific Java Home. * - * @param javaHome - * Path to a Java 9 or greater home. + * @param javaHome Path to a Java 9 or greater home. * - * @throws IOException - * an I/O error occurs accessing the file system + * @throws IOException an I/O error occurs accessing the file system */ public ModularRuntimeImage(final String javaHome) throws IOException { final Map emptyMap = Collections.emptyMap(); final Path jrePath = Paths.get(javaHome); final Path jrtFsPath = jrePath.resolve("lib").resolve("jrt-fs.jar"); - this.classLoader = new URLClassLoader(new URL[] {jrtFsPath.toUri().toURL() }); + this.classLoader = URLClassLoader.newInstance(new URL[] {jrtFsPath.toUri().toURL()}); this.fileSystem = FileSystems.newFileSystem(URI.create("jrt:/"), emptyMap, classLoader); } @@ -94,22 +89,21 @@ public void close() throws IOException { } } + public FileSystem getFileSystem() { + return fileSystem; + } + /** * Lists all entries in the given directory. * - * @param dirPath - * directory path. + * @param dirPath directory path. * @return a list of dir entries if an I/O error occurs - * @throws IOException - * an I/O error occurs accessing the file system + * @throws IOException an I/O error occurs accessing the file system */ public List list(final Path dirPath) throws IOException { final List list = new ArrayList<>(); try (DirectoryStream ds = Files.newDirectoryStream(dirPath)) { - final Iterator iterator = ds.iterator(); - while (iterator.hasNext()) { - list.add(iterator.next()); - } + ds.forEach(list::add); } return list; } @@ -117,11 +111,9 @@ public List list(final Path dirPath) throws IOException { /** * Lists all entries in the given directory. * - * @param dirName - * directory path. + * @param dirName directory path. * @return a list of dir entries if an I/O error occurs - * @throws IOException - * an I/O error occurs accessing the file system + * @throws IOException an I/O error occurs accessing the file system */ public List list(final String dirName) throws IOException { return list(fileSystem.getPath(dirName)); @@ -131,8 +123,7 @@ public List list(final String dirName) throws IOException { * Lists all modules. * * @return a list of modules - * @throws IOException - * an I/O error occurs accessing the file system + * @throws IOException an I/O error occurs accessing the file system */ public List modules() throws IOException { return list(MODULES_PATH); @@ -142,15 +133,10 @@ public List modules() throws IOException { * Lists all packages. * * @return a list of modules - * @throws IOException - * an I/O error occurs accessing the file system + * @throws IOException an I/O error occurs accessing the file system */ public List packages() throws IOException { return list(PACKAGES_PATH); } - public FileSystem getFileSystem() { - return fileSystem; - } - } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java index cf2add7a506..8d1ddf493cd 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -22,42 +22,45 @@ import com.sun.org.apache.bcel.internal.classfile.JavaClass; /** - * Abstract definition of a class repository. Instances may be used - * to load classes from different sources and may be used in the - * Repository.setRepository method. + * Abstract definition of a class repository. Instances may be used to load classes from different sources and may be + * used in the Repository.setRepository method. * - * @see com.sun.org.apache.bcel.internal.Repository - * @LastModified: Jan 2020 + * @see org.apache.bcel.Repository + * @LastModified: Feb 2023 */ public interface Repository { /** - * Stores the provided class under "clazz.getClassName()" + * Clears all entries from cache. */ - void storeClass(JavaClass clazz); + void clear(); /** - * Removes class from repository + * Finds the class with the name provided, if the class isn't there, return NULL. */ - void removeClass(JavaClass clazz); + JavaClass findClass(String className); /** - * Finds the class with the name provided, if the class isn't there, return NULL. + * Finds the JavaClass instance for the given run-time class object. + * + * @throws ClassNotFoundException if the class can't be found. */ - JavaClass findClass(String className); + JavaClass loadClass(Class clazz) throws ClassNotFoundException; /** * Finds the class with the name provided, if the class isn't there, make an attempt to load it. + * + * @throws ClassNotFoundException if the class can't be found. */ - JavaClass loadClass(String className) throws java.lang.ClassNotFoundException; + JavaClass loadClass(String className) throws ClassNotFoundException; /** - * Finds the JavaClass instance for the given run-time class object + * Removes class from repository */ - JavaClass loadClass(Class clazz) throws java.lang.ClassNotFoundException; + void removeClass(JavaClass clazz); /** - * Clears all entries from cache. + * Stores the provided class under "clazz.getClassName()" */ - void clear(); + void storeClass(JavaClass clazz); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/SyntheticRepository.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/SyntheticRepository.java index c0c708235ec..470c6ea17b6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/SyntheticRepository.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/SyntheticRepository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -24,22 +24,23 @@ import com.sun.org.apache.bcel.internal.classfile.ClassParser; import com.sun.org.apache.bcel.internal.classfile.JavaClass; +import com.sun.org.apache.bcel.internal.classfile.Utility; import java.lang.ref.SoftReference; import java.util.HashMap; import java.util.Map; /** - * This repository is used in situations where a Class is created outside the - * realm of a ClassLoader. Classes are loaded from the file systems using the - * paths specified in the given class path. By default, this is the value - * returned by ClassPath.getClassPath().
    - * This repository uses a factory design, allowing it to maintain a collection - * of different classpaths, and as such It is designed to be used as a singleton - * per classpath. + * This repository is used in situations where a Class is created outside the realm of a ClassLoader. Classes are loaded + * from the file systems using the paths specified in the given class path. By default, this is the value returned by + * ClassPath.getClassPath(). + *

    + * This repository uses a factory design, allowing it to maintain a collection of different classpaths, and as such It + * is designed to be used as a singleton per classpath. + *

    * * @see com.sun.org.apache.bcel.internal.Repository * - * @LastModified: May 2021 + * @LastModified: Feb 2023 */ public class SyntheticRepository implements Repository { @@ -54,20 +55,11 @@ public static SyntheticRepository getInstance() { } /** - * Store a new JavaClass instance into this Repository. - */ - @Override - public void storeClass(final JavaClass clazz) { - loadedClasses.put(clazz.getClassName(), new SoftReference<>(clazz)); - clazz.setRepository(this); - } - - /** - * Remove class from repository + * Clear all entries from cache. */ @Override - public void removeClass(final JavaClass clazz) { - loadedClasses.remove(clazz.getClassName()); + public void clear() { + loadedClasses.clear(); } /** @@ -76,48 +68,36 @@ public void removeClass(final JavaClass clazz) { @Override public JavaClass findClass(final String className) { final SoftReference ref = loadedClasses.get(className); - if (ref == null) { - return null; -} - return ref.get(); + return ref == null ? null : ref.get(); } /** - * Finds a JavaClass object by name. If it is already in this Repository, the - * Repository version is returned. - * - * @param className the name of the class - * @return the JavaClass object - * @throws ClassNotFoundException if the class is not in the Repository + * Remove class from repository */ @Override - public JavaClass loadClass(String className) throws ClassNotFoundException { - if ((className == null) || className.isEmpty()) { - throw new IllegalArgumentException("Invalid class name " + className); + public void removeClass(final JavaClass clazz) { + loadedClasses.remove(clazz.getClassName()); } - className = className.replace('/', '.'); // Just in case, canonical form - final JavaClass clazz = findClass(className); - if (clazz != null) { - return clazz; - } - IOException e = new IOException("Couldn't find: " + className + ".class"); - throw new ClassNotFoundException("Exception while looking for class " + - className + ": " + e, e); + /** + * Store a new JavaClass instance into this Repository. + */ + @Override + public void storeClass(final JavaClass clazz) { + // Not calling super.storeClass because this subclass maintains the mapping. + loadedClasses.put(clazz.getClassName(), new SoftReference<>(clazz)); + clazz.setRepository(this); } /** - * Find the JavaClass object for a runtime Class object. If a class with the - * same name is already in this Repository, the Repository version is - * returned. Otherwise, getResourceAsStream() is called on the Class object - * to find the class's representation. If the representation is found, it is - * added to the Repository. + * Finds the JavaClass object for a runtime Class object. If a class with the same name is already in this Repository, + * the Repository version is returned. Otherwise, getResourceAsStream() is called on the Class object to find the + * class's representation. If the representation is found, it is added to the Repository. * * @see Class * @param clazz the runtime Class object * @return JavaClass object for given runtime class - * @throws ClassNotFoundException if the class is not in the Repository, and - * its representation could not be found + * @throws ClassNotFoundException if the class is not in the Repository, and its representation could not be found */ @Override public JavaClass loadClass(final Class clazz) throws ClassNotFoundException { @@ -125,52 +105,54 @@ public JavaClass loadClass(final Class clazz) throws ClassNotFoundException { final JavaClass repositoryClass = findClass(className); if (repositoryClass != null) { return repositoryClass; - } + } String name = className; final int i = name.lastIndexOf('.'); if (i > 0) { name = name.substring(i + 1); } - JavaClass cls = null; - try (InputStream clsStream = clazz.getResourceAsStream(name + ".class")) { - return cls = loadClass(clsStream, className); + + try (InputStream clsStream = clazz.getResourceAsStream(name + JavaClass.EXTENSION)) { + return loadClass(clsStream, className); } catch (final IOException e) { - return cls; + return null; } - } - - private JavaClass loadClass(final InputStream is, final String className) - throws ClassNotFoundException { + private JavaClass loadClass(final InputStream inputStream, final String className) throws ClassNotFoundException { try { - if (is != null) { - final ClassParser parser = new ClassParser(is, className); + if (inputStream != null) { + final ClassParser parser = new ClassParser(inputStream, className); final JavaClass clazz = parser.parse(); storeClass(clazz); return clazz; } } catch (final IOException e) { - throw new ClassNotFoundException("Exception while looking for class " - + className + ": " + e, e); - } finally { - if (is != null) { - try { - is.close(); - } catch (final IOException e) { - // ignored - } - } + throw new ClassNotFoundException("Exception while looking for class " + className + ": " + e, e); } - throw new ClassNotFoundException("SyntheticRepository could not load " - + className); + throw new ClassNotFoundException("ClassRepository could not load " + className); } /** - * Clear all entries from cache. + * Finds a JavaClass object by name. If it is already in this Repository, the Repository version is returned. Otherwise, + * the Repository's classpath is searched for the class (and it is added to the Repository if found). + * + * @param className the name of the class + * @return the JavaClass object + * @throws ClassNotFoundException if the class is not in the Repository, and could not be found on the classpath */ @Override - public void clear() { - loadedClasses.clear(); + public JavaClass loadClass(String className) throws ClassNotFoundException { + if (className == null || className.isEmpty()) { + throw new IllegalArgumentException("Invalid class name " + className); + } + className = Utility.pathToPackage(className); // Just in case, canonical form + final JavaClass clazz = findClass(className); + if (clazz != null) { + return clazz; + } + IOException e = new IOException("Couldn't find: " + className + ".class"); + throw new ClassNotFoundException("Exception while looking for class " + + className + ": " + e, e); } } 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 11c3508cd7e..6f48d1391f4 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -1420,32 +1420,23 @@ else if ( } } } - - // The next is kind of a hack to keep from escaping in the case - // of Shift_JIS and the like. - - /* - else if ((ch < m_maxCharacter) && (m_maxCharacter == 0xFFFF) - && (ch != 160)) - { - writer.write(ch); // no escaping in this case - } - else - */ - String outputStringForChar = m_charInfo.getOutputStringForChar(ch); - if (null != outputStringForChar) - { - writer.write(outputStringForChar); - } - else if (escapingNotNeeded(ch)) - { - writer.write(ch); // no escaping in this case - } else { - writer.write("&#"); - writer.write(Integer.toString(ch)); - writer.write(';'); + String outputStringForChar = m_charInfo.getOutputStringForChar(ch); + if (null != outputStringForChar) + { + writer.write(outputStringForChar); + } + else if (escapingNotNeeded(ch)) + { + writer.write(ch); // no escaping in this case + } + else + { + writer.write("&#"); + writer.write(Integer.toString(ch)); + writer.write(';'); + } } } cleanStart = i + 1; diff --git a/src/java.xml/share/classes/jdk/xml/internal/Utils.java b/src/java.xml/share/classes/jdk/xml/internal/Utils.java new file mode 100644 index 00000000000..439930be15d --- /dev/null +++ b/src/java.xml/share/classes/jdk/xml/internal/Utils.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.Arrays; + +/** + * General utility. Use JdkXmlUtils for XML processing related functions. + */ +public class Utils { + /** + * Creates a new array with copies of the original array and additional items + * appended to the end of it. + * + * @param original the original array + * @param items items to be appended to the original array + * @return a new array with copies of the original array and additional items + */ + public static Class[] arraysAppend(final Class[] original, final Class... items) { + if (original == null && items == null) { + return null; + } + if (items == null) { + return Arrays.copyOf(original, original.length); + } + if (original == null) { + return Arrays.copyOf(items, items.length); + } + + Class[] result = Arrays.copyOf(original, original.length + items.length); + System.arraycopy(items, 0, result, original.length, items.length); + return result; + } +} diff --git a/src/java.xml/share/legal/bcel.md b/src/java.xml/share/legal/bcel.md index 6dffd077c81..2c673d6b1af 100644 --- a/src/java.xml/share/legal/bcel.md +++ b/src/java.xml/share/legal/bcel.md @@ -1,10 +1,10 @@ -## Apache Commons Byte Code Engineering Library (BCEL) Version 6.5.0 +## Apache Commons Byte Code Engineering Library (BCEL) Version 6.7.0 ### Apache Commons BCEL Notice
     
         Apache Commons BCEL
    -    Copyright 2004-2020 The Apache Software Foundation
    +    Copyright 2004-2022 The Apache Software Foundation
     
         This product includes software developed at
         The Apache Software Foundation (https://www.apache.org/).
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties
    index 39fc113a7fd..0b82927dfe7 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties
    @@ -121,8 +121,6 @@ javac.opt.arg.profile=\
         
     javac.opt.arg.release=\
         
    -javac.opt.arg.release=\
    -    
     javac.opt.arg.number=\
         
     javac.opt.plugin=\
    diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java
    index 62fe41655d0..d54e27baa5c 100644
    --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java
    +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java
    @@ -90,6 +90,9 @@ abstract class P11Key implements Key, Length {
         // flags indicating whether the key is a token object, sensitive, extractable
         final boolean tokenObject, sensitive, extractable;
     
    +    // flag indicating whether the current token is NSS
    +    final transient boolean isNSS;
    +
         private final NativeKeyHolder keyIDHolder;
     
         private static final boolean DISABLE_NATIVE_KEYS_EXTRACTION;
    @@ -136,7 +139,7 @@ abstract class P11Key implements Key, Length {
             this.sensitive = sensitive;
             this.extractable = extractable;
             char[] tokenLabel = this.token.tokenInfo.label;
    -        boolean isNSS = (tokenLabel[0] == 'N' && tokenLabel[1] == 'S'
    +        isNSS = (tokenLabel[0] == 'N' && tokenLabel[1] == 'S'
                     && tokenLabel[2] == 'S');
             boolean extractKeyInfo = (!DISABLE_NATIVE_KEYS_EXTRACTION && isNSS &&
                     extractable && !tokenObject);
    @@ -237,7 +240,8 @@ protected Object writeReplace() throws ObjectStreamException {
             } else {
                 // XXX short term serialization for unextractable keys
                 throw new NotSerializableException
    -                ("Cannot serialize sensitive and unextractable keys");
    +                    ("Cannot serialize sensitive, unextractable " + (isNSS ?
    +                    ", and NSS token keys" : "keys"));
             }
             return new KeyRep(type, getAlgorithm(), format, getEncoded());
         }
    @@ -460,7 +464,7 @@ private static class P11SecretKey extends P11Key implements SecretKey {
             }
             public String getFormat() {
                 token.ensureValid();
    -            if (sensitive || (extractable == false)) {
    +            if (sensitive || !extractable || (isNSS && tokenObject)) {
                     return null;
                 } else {
                     return "RAW";
    diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java
    index b1af8d5aa05..c1cff261397 100644
    --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java
    +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java
    @@ -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
    @@ -32,6 +32,8 @@
     import java.security.spec.*;
     
     import sun.security.rsa.RSAPublicKeyImpl;
    +import sun.security.rsa.RSAPrivateCrtKeyImpl;
    +import sun.security.rsa.RSAUtil.KeyType;
     import static sun.security.pkcs11.TemplateManager.*;
     import sun.security.pkcs11.wrapper.*;
     import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
    @@ -58,14 +60,11 @@ PublicKey implTranslatePublicKey(PublicKey key) throws InvalidKeyException {
                         rsaKey.getModulus(),
                         rsaKey.getPublicExponent()
                     );
    -            } else if ("X.509".equals(key.getFormat())) {
    +            } else {
                     // let SunRsaSign provider parse for us, then recurse
    -                byte[] encoded = key.getEncoded();
    -                key = RSAPublicKeyImpl.newKey(encoded);
    +                key = RSAPublicKeyImpl.newKey(KeyType.RSA, key.getFormat(),
    +                        key.getEncoded());
                     return implTranslatePublicKey(key);
    -            } else {
    -                throw new InvalidKeyException("PublicKey must be instance "
    -                        + "of RSAPublicKey or have X.509 encoding");
                 }
             } catch (PKCS11Exception e) {
                 throw new InvalidKeyException("Could not create RSA public key", e);
    @@ -93,14 +92,11 @@ PrivateKey implTranslatePrivateKey(PrivateKey key)
                         rsaKey.getModulus(),
                         rsaKey.getPrivateExponent()
                     );
    -            } else if ("PKCS#8".equals(key.getFormat())) {
    +            } else {
                     // let SunRsaSign provider parse for us, then recurse
    -                byte[] encoded = key.getEncoded();
    -                key = sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(encoded);
    +                key = RSAPrivateCrtKeyImpl.newKey(KeyType.RSA, key.getFormat(),
    +                        key.getEncoded());
                     return implTranslatePrivateKey(key);
    -            } else {
    -                throw new InvalidKeyException("Private key must be instance "
    -                        + "of RSAPrivate(Crt)Key or have PKCS#8 encoding");
                 }
             } catch (PKCS11Exception e) {
                 throw new InvalidKeyException("Could not create RSA private key", e);
    @@ -113,8 +109,8 @@ protected PublicKey engineGeneratePublic(KeySpec keySpec)
             token.ensureValid();
             if (keySpec instanceof X509EncodedKeySpec) {
                 try {
    -                byte[] encoded = ((X509EncodedKeySpec)keySpec).getEncoded();
    -                PublicKey key = RSAPublicKeyImpl.newKey(encoded);
    +                PublicKey key = RSAPublicKeyImpl.newKey(KeyType.RSA, "X.509",
    +                        ((X509EncodedKeySpec)keySpec).getEncoded());
                     return implTranslatePublicKey(key);
                 } catch (InvalidKeyException e) {
                     throw new InvalidKeySpecException
    @@ -143,9 +139,8 @@ protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
             token.ensureValid();
             if (keySpec instanceof PKCS8EncodedKeySpec) {
                 try {
    -                byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
    -                PrivateKey key =
    -                        sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(encoded);
    +                PrivateKey key = RSAPrivateCrtKeyImpl.newKey(KeyType.RSA,
    +                        "PKCS#8", ((PKCS8EncodedKeySpec)keySpec).getEncoded());
                     return implTranslatePrivateKey(key);
                 } catch (GeneralSecurityException e) {
                     throw new InvalidKeySpecException
    diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
    index cf7cd19b689..ffbd671246a 100644
    --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
    +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
    @@ -46,6 +46,7 @@
     import sun.security.util.Debug;
     import sun.security.util.ResourcesMgr;
     import static sun.security.util.SecurityConstants.PROVIDER_VER;
    +import static sun.security.util.SecurityProviderConstants.getAliases;
     
     import sun.security.pkcs11.Secmod.*;
     
    @@ -408,19 +409,15 @@ public int hashCode() {
             return System.identityHashCode(this);
         }
     
    -    private static String[] s(String ...aliases) {
    -        return aliases;
    -    }
    -
         private static final class Descriptor {
             final String type;
             final String algorithm;
             final String className;
    -        final String[] aliases;
    +        final List aliases;
             final int[] mechanisms;
     
             private Descriptor(String type, String algorithm, String className,
    -                String[] aliases, int[] mechanisms) {
    +                List aliases, int[] mechanisms) {
                 this.type = type;
                 this.algorithm = algorithm;
                 this.className = className;
    @@ -463,10 +460,16 @@ private static void d(String type, String algorithm, String className,
         }
     
         private static void d(String type, String algorithm, String className,
    -            String[] aliases, int[] m) {
    +            List aliases, int[] m) {
             register(new Descriptor(type, algorithm, className, aliases, m));
         }
     
    +    private static void dA(String type, String algorithm, String className,
    +            int[] m) {
    +        register(new Descriptor(type, algorithm, className,
    +                getAliases(algorithm), m));
    +    }
    +
         private static void register(Descriptor d) {
             for (int i = 0; i < d.mechanisms.length; i++) {
                 int m = d.mechanisms[i];
    @@ -528,51 +531,37 @@ private static void register(Descriptor d) {
                     m(CKM_MD2));
             d(MD, "MD5",            P11Digest,
                     m(CKM_MD5));
    -        d(MD, "SHA1",           P11Digest,
    -                s("SHA", "SHA-1", "1.3.14.3.2.26", "OID.1.3.14.3.2.26"),
    +        dA(MD, "SHA-1",           P11Digest,
                     m(CKM_SHA_1));
     
    -        d(MD, "SHA-224",        P11Digest,
    -                s("2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4"),
    +        dA(MD, "SHA-224",        P11Digest,
                     m(CKM_SHA224));
    -        d(MD, "SHA-256",        P11Digest,
    -                s("2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"),
    +        dA(MD, "SHA-256",        P11Digest,
                     m(CKM_SHA256));
    -        d(MD, "SHA-384",        P11Digest,
    -                s("2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"),
    +        dA(MD, "SHA-384",        P11Digest,
                     m(CKM_SHA384));
    -        d(MD, "SHA-512",        P11Digest,
    -                s("2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"),
    +        dA(MD, "SHA-512",        P11Digest,
                     m(CKM_SHA512));
    -        d(MD, "SHA-512/224",        P11Digest,
    -                s("2.16.840.1.101.3.4.2.5", "OID.2.16.840.1.101.3.4.2.5"),
    +        dA(MD, "SHA-512/224",        P11Digest,
                     m(CKM_SHA512_224));
    -        d(MD, "SHA-512/256",        P11Digest,
    -                s("2.16.840.1.101.3.4.2.6", "OID.2.16.840.1.101.3.4.2.6"),
    +        dA(MD, "SHA-512/256",        P11Digest,
                     m(CKM_SHA512_256));
     
             d(MAC, "HmacMD5",       P11MAC,
                     m(CKM_MD5_HMAC));
    -        d(MAC, "HmacSHA1",      P11MAC,
    -                s("1.2.840.113549.2.7", "OID.1.2.840.113549.2.7"),
    +        dA(MAC, "HmacSHA1",      P11MAC,
                     m(CKM_SHA_1_HMAC));
    -        d(MAC, "HmacSHA224",    P11MAC,
    -                s("1.2.840.113549.2.8", "OID.1.2.840.113549.2.8"),
    +        dA(MAC, "HmacSHA224",    P11MAC,
                     m(CKM_SHA224_HMAC));
    -        d(MAC, "HmacSHA256",    P11MAC,
    -                s("1.2.840.113549.2.9", "OID.1.2.840.113549.2.9"),
    +        dA(MAC, "HmacSHA256",    P11MAC,
                     m(CKM_SHA256_HMAC));
    -        d(MAC, "HmacSHA384",    P11MAC,
    -                s("1.2.840.113549.2.10", "OID.1.2.840.113549.2.10"),
    +        dA(MAC, "HmacSHA384",    P11MAC,
                     m(CKM_SHA384_HMAC));
    -        d(MAC, "HmacSHA512",    P11MAC,
    -                s("1.2.840.113549.2.11", "OID.1.2.840.113549.2.11"),
    +        dA(MAC, "HmacSHA512",    P11MAC,
                     m(CKM_SHA512_HMAC));
    -        d(MAC, "HmacSHA512/224",    P11MAC,
    -                s("1.2.840.113549.2.12", "OID.1.2.840.113549.2.12"),
    +        dA(MAC, "HmacSHA512/224",    P11MAC,
                     m(CKM_SHA512_224_HMAC));
    -        d(MAC, "HmacSHA512/256",    P11MAC,
    -                s("1.2.840.113549.2.13", "OID.1.2.840.113549.2.13"),
    +        dA(MAC, "HmacSHA512/256",    P11MAC,
                     m(CKM_SHA512_256_HMAC));
     
             d(MAC, "SslMacMD5",     P11MAC,
    @@ -581,18 +570,20 @@ private static void register(Descriptor d) {
                     m(CKM_SSL3_SHA1_MAC));
     
             d(KPG, "RSA",           P11KeyPairGenerator,
    -                s("1.2.840.113549.1.1", "OID.1.2.840.113549.1.1"),
    +                getAliases("PKCS1"),
                     m(CKM_RSA_PKCS_KEY_PAIR_GEN));
     
    -        d(KPG, "DSA",           P11KeyPairGenerator,
    -                s("1.3.14.3.2.12", "1.2.840.10040.4.1", "OID.1.2.840.10040.4.1"),
    +        List dhAlias = List.of("DiffieHellman");
    +
    +        dA(KPG, "DSA",           P11KeyPairGenerator,
                     m(CKM_DSA_KEY_PAIR_GEN));
    -        d(KPG, "DH",            P11KeyPairGenerator,    s("DiffieHellman"),
    +        d(KPG, "DH",            P11KeyPairGenerator,
    +                dhAlias,
                     m(CKM_DH_PKCS_KEY_PAIR_GEN));
             d(KPG, "EC",            P11KeyPairGenerator,
                     m(CKM_EC_KEY_PAIR_GEN));
     
    -        d(KG,  "ARCFOUR",       P11KeyGenerator,        s("RC4"),
    +        dA(KG,  "ARCFOUR",       P11KeyGenerator,
                     m(CKM_RC4_KEY_GEN));
             d(KG,  "DES",           P11KeyGenerator,
                     m(CKM_DES_KEY_GEN));
    @@ -608,12 +599,12 @@ private static void register(Descriptor d) {
             // register (Secret)KeyFactories if there are any mechanisms
             // for a particular algorithm that we support
             d(KF, "RSA",            P11RSAKeyFactory,
    -                s("1.2.840.113549.1.1", "OID.1.2.840.113549.1.1"),
    +                getAliases("PKCS1"),
                     m(CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, CKM_RSA_X_509));
    -        d(KF, "DSA",            P11DSAKeyFactory,
    -                s("1.3.14.3.2.12", "1.2.840.10040.4.1", "OID.1.2.840.10040.4.1"),
    +        dA(KF, "DSA",            P11DSAKeyFactory,
                     m(CKM_DSA_KEY_PAIR_GEN, CKM_DSA, CKM_DSA_SHA1));
    -        d(KF, "DH",             P11DHKeyFactory,        s("DiffieHellman"),
    +        d(KF, "DH",             P11DHKeyFactory,
    +                dhAlias,
                     m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));
             d(KF, "EC",             P11DHKeyFactory,
                     m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
    @@ -621,8 +612,7 @@ private static void register(Descriptor d) {
     
             // AlgorithmParameters for EC.
             // Only needed until we have an EC implementation in the SUN provider.
    -        d(AGP, "EC",            "sun.security.util.ECParameters",
    -                s("1.2.840.10045.2.1"),
    +        dA(AGP, "EC",            "sun.security.util.ECParameters",
                     m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
                         CKM_ECDSA, CKM_ECDSA_SHA1));
     
    @@ -630,24 +620,23 @@ private static void register(Descriptor d) {
             d(AGP, "GCM",            "sun.security.util.GCMParameters",
                     m(CKM_AES_GCM));
     
    -        d(AGP, "ChaCha20-Poly1305",
    +        dA(AGP, "ChaCha20-Poly1305",
                     "com.sun.crypto.provider.ChaCha20Poly1305Parameters",
    -                s("1.2.840.113549.1.9.16.3.18", "OID.1.2.840.113549.1.9.16.3.18"),
                     m(CKM_CHACHA20_POLY1305));
     
    -        d(KA, "DH",             P11KeyAgreement,        s("DiffieHellman"),
    +        d(KA, "DH",             P11KeyAgreement,
    +                dhAlias,
                     m(CKM_DH_PKCS_DERIVE));
             d(KA, "ECDH",           "sun.security.pkcs11.P11ECDHKeyAgreement",
                     m(CKM_ECDH1_DERIVE));
     
    -        d(SKF, "ARCFOUR",       P11SecretKeyFactory,    s("RC4"),
    +        dA(SKF, "ARCFOUR",      P11SecretKeyFactory,
                     m(CKM_RC4));
             d(SKF, "DES",           P11SecretKeyFactory,
                     m(CKM_DES_CBC));
             d(SKF, "DESede",        P11SecretKeyFactory,
                     m(CKM_DES3_CBC));
    -        d(SKF, "AES",           P11SecretKeyFactory,
    -                s("2.16.840.1.101.3.4.1", "OID.2.16.840.1.101.3.4.1"),
    +        dA(SKF, "AES",          P11SecretKeyFactory,
                     m(CKM_AES_CBC));
             d(SKF, "Blowfish",      P11SecretKeyFactory,
                     m(CKM_BLOWFISH_CBC));
    @@ -655,7 +644,7 @@ private static void register(Descriptor d) {
                     m(CKM_CHACHA20_POLY1305));
     
             // XXX attributes for Ciphers (supported modes, padding)
    -        d(CIP, "ARCFOUR",                       P11Cipher,      s("RC4"),
    +        dA(CIP, "ARCFOUR",                      P11Cipher,
                     m(CKM_RC4));
             d(CIP, "DES/CBC/NoPadding",             P11Cipher,
                     m(CKM_DES_CBC));
    @@ -663,7 +652,8 @@ private static void register(Descriptor d) {
                     m(CKM_DES_CBC_PAD, CKM_DES_CBC));
             d(CIP, "DES/ECB/NoPadding",             P11Cipher,
                     m(CKM_DES_ECB));
    -        d(CIP, "DES/ECB/PKCS5Padding",          P11Cipher,      s("DES"),
    +        d(CIP, "DES/ECB/PKCS5Padding",          P11Cipher,
    +                List.of("DES"),
                     m(CKM_DES_ECB));
     
             d(CIP, "DESede/CBC/NoPadding",          P11Cipher,
    @@ -672,47 +662,40 @@ private static void register(Descriptor d) {
                     m(CKM_DES3_CBC_PAD, CKM_DES3_CBC));
             d(CIP, "DESede/ECB/NoPadding",          P11Cipher,
                     m(CKM_DES3_ECB));
    -        d(CIP, "DESede/ECB/PKCS5Padding",       P11Cipher,      s("DESede"),
    +        d(CIP, "DESede/ECB/PKCS5Padding",       P11Cipher,
    +                List.of("DESede"),
                     m(CKM_DES3_ECB));
             d(CIP, "AES/CBC/NoPadding",             P11Cipher,
                     m(CKM_AES_CBC));
    -        d(CIP, "AES_128/CBC/NoPadding",          P11Cipher,
    -                s("2.16.840.1.101.3.4.1.2", "OID.2.16.840.1.101.3.4.1.2"),
    +        dA(CIP, "AES_128/CBC/NoPadding",        P11Cipher,
                     m(CKM_AES_CBC));
    -        d(CIP, "AES_192/CBC/NoPadding",          P11Cipher,
    -                s("2.16.840.1.101.3.4.1.22", "OID.2.16.840.1.101.3.4.1.22"),
    +        dA(CIP, "AES_192/CBC/NoPadding",        P11Cipher,
                     m(CKM_AES_CBC));
    -        d(CIP, "AES_256/CBC/NoPadding",          P11Cipher,
    -                s("2.16.840.1.101.3.4.1.42", "OID.2.16.840.1.101.3.4.1.42"),
    +        dA(CIP, "AES_256/CBC/NoPadding",        P11Cipher,
                     m(CKM_AES_CBC));
             d(CIP, "AES/CBC/PKCS5Padding",          P11Cipher,
                     m(CKM_AES_CBC_PAD, CKM_AES_CBC));
             d(CIP, "AES/ECB/NoPadding",             P11Cipher,
                     m(CKM_AES_ECB));
    -        d(CIP, "AES_128/ECB/NoPadding",          P11Cipher,
    -                s("2.16.840.1.101.3.4.1.1", "OID.2.16.840.1.101.3.4.1.1"),
    +        dA(CIP, "AES_128/ECB/NoPadding",        P11Cipher,
                     m(CKM_AES_ECB));
    -        d(CIP, "AES_192/ECB/NoPadding",          P11Cipher,
    -                s("2.16.840.1.101.3.4.1.21", "OID.2.16.840.1.101.3.4.1.21"),
    +        dA(CIP, "AES_192/ECB/NoPadding",        P11Cipher,
                     m(CKM_AES_ECB));
    -        d(CIP, "AES_256/ECB/NoPadding",          P11Cipher,
    -                s("2.16.840.1.101.3.4.1.41", "OID.2.16.840.1.101.3.4.1.41"),
    +        dA(CIP, "AES_256/ECB/NoPadding",        P11Cipher,
                     m(CKM_AES_ECB));
    -        d(CIP, "AES/ECB/PKCS5Padding",          P11Cipher,      s("AES"),
    +        d(CIP, "AES/ECB/PKCS5Padding",          P11Cipher,
    +                List.of("AES"),
                     m(CKM_AES_ECB));
             d(CIP, "AES/CTR/NoPadding",             P11Cipher,
                     m(CKM_AES_CTR));
     
             d(CIP, "AES/GCM/NoPadding",             P11AEADCipher,
                     m(CKM_AES_GCM));
    -        d(CIP, "AES_128/GCM/NoPadding",          P11AEADCipher,
    -                s("2.16.840.1.101.3.4.1.6", "OID.2.16.840.1.101.3.4.1.6"),
    +        dA(CIP, "AES_128/GCM/NoPadding",        P11AEADCipher,
                     m(CKM_AES_GCM));
    -        d(CIP, "AES_192/GCM/NoPadding",          P11AEADCipher,
    -                s("2.16.840.1.101.3.4.1.26", "OID.2.16.840.1.101.3.4.1.26"),
    +        dA(CIP, "AES_192/GCM/NoPadding",        P11AEADCipher,
                     m(CKM_AES_GCM));
    -        d(CIP, "AES_256/GCM/NoPadding",          P11AEADCipher,
    -                s("2.16.840.1.101.3.4.1.46", "OID.2.16.840.1.101.3.4.1.46"),
    +        dA(CIP, "AES_256/GCM/NoPadding",        P11AEADCipher,
                     m(CKM_AES_GCM));
     
             d(CIP, "Blowfish/CBC/NoPadding",        P11Cipher,
    @@ -720,56 +703,46 @@ private static void register(Descriptor d) {
             d(CIP, "Blowfish/CBC/PKCS5Padding",     P11Cipher,
                     m(CKM_BLOWFISH_CBC));
     
    -        d(CIP, "ChaCha20-Poly1305",             P11AEADCipher,
    -                s("1.2.840.113549.1.9.16.3.18", "OID.1.2.840.113549.1.9.16.3.18"),
    +        dA(CIP, "ChaCha20-Poly1305",            P11AEADCipher,
                     m(CKM_CHACHA20_POLY1305));
     
    -        d(CIP, "RSA/ECB/PKCS1Padding",          P11RSACipher,   s("RSA"),
    +        d(CIP, "RSA/ECB/PKCS1Padding",          P11RSACipher,
    +                List.of("RSA"),
                     m(CKM_RSA_PKCS));
             d(CIP, "RSA/ECB/NoPadding",             P11RSACipher,
                     m(CKM_RSA_X_509));
     
    -        d(SIG, "RawDSA",        P11Signature,   s("NONEwithDSA"),
    +        d(SIG, "RawDSA",        P11Signature,
    +                List.of("NONEwithDSA"),
                     m(CKM_DSA));
    -        d(SIG, "DSA",           P11Signature,
    -                s("SHA1withDSA", "1.3.14.3.2.13", "1.3.14.3.2.27",
    -                  "1.2.840.10040.4.3", "OID.1.2.840.10040.4.3"),
    +        dA(SIG, "SHA1withDSA",           P11Signature,
                     m(CKM_DSA_SHA1, CKM_DSA));
    -        d(SIG, "SHA224withDSA", P11Signature,
    -                s("2.16.840.1.101.3.4.3.1", "OID.2.16.840.1.101.3.4.3.1"),
    +        dA(SIG, "SHA224withDSA", P11Signature,
                     m(CKM_DSA_SHA224));
    -        d(SIG, "SHA256withDSA", P11Signature,
    -                s("2.16.840.1.101.3.4.3.2", "OID.2.16.840.1.101.3.4.3.2"),
    +        dA(SIG, "SHA256withDSA", P11Signature,
                     m(CKM_DSA_SHA256));
    -        d(SIG, "SHA384withDSA", P11Signature,
    -                s("2.16.840.1.101.3.4.3.3", "OID.2.16.840.1.101.3.4.3.3"),
    +        dA(SIG, "SHA384withDSA", P11Signature,
                     m(CKM_DSA_SHA384));
    -        d(SIG, "SHA512withDSA", P11Signature,
    -                s("2.16.840.1.101.3.4.3.4", "OID.2.16.840.1.101.3.4.3.4"),
    +        dA(SIG, "SHA512withDSA", P11Signature,
                     m(CKM_DSA_SHA512));
             d(SIG, "RawDSAinP1363Format",   P11Signature,
    -                s("NONEwithDSAinP1363Format"),
    +                List.of("NONEwithDSAinP1363Format"),
                     m(CKM_DSA));
             d(SIG, "DSAinP1363Format",      P11Signature,
    -                s("SHA1withDSAinP1363Format"),
    +                List.of("SHA1withDSAinP1363Format"),
                     m(CKM_DSA_SHA1, CKM_DSA));
     
             d(SIG, "NONEwithECDSA", P11Signature,
                     m(CKM_ECDSA));
    -        d(SIG, "SHA1withECDSA", P11Signature,
    -                s("ECDSA", "1.2.840.10045.4.1", "OID.1.2.840.10045.4.1"),
    +        dA(SIG, "SHA1withECDSA", P11Signature,
                     m(CKM_ECDSA_SHA1, CKM_ECDSA));
    -        d(SIG, "SHA224withECDSA",       P11Signature,
    -                s("1.2.840.10045.4.3.1", "OID.1.2.840.10045.4.3.1"),
    +        dA(SIG, "SHA224withECDSA",       P11Signature,
                     m(CKM_ECDSA));
    -        d(SIG, "SHA256withECDSA",       P11Signature,
    -                s("1.2.840.10045.4.3.2", "OID.1.2.840.10045.4.3.2"),
    +        dA(SIG, "SHA256withECDSA",       P11Signature,
                     m(CKM_ECDSA));
    -        d(SIG, "SHA384withECDSA",       P11Signature,
    -                s("1.2.840.10045.4.3.3", "OID.1.2.840.10045.4.3.3"),
    +        dA(SIG, "SHA384withECDSA",       P11Signature,
                     m(CKM_ECDSA));
    -        d(SIG, "SHA512withECDSA",       P11Signature,
    -                s("1.2.840.10045.4.3.4", "OID.1.2.840.10045.4.3.4"),
    +        dA(SIG, "SHA512withECDSA",       P11Signature,
                     m(CKM_ECDSA));
             d(SIG, "NONEwithECDSAinP1363Format",   P11Signature,
                     m(CKM_ECDSA));
    @@ -783,30 +756,21 @@ private static void register(Descriptor d) {
                     m(CKM_ECDSA));
             d(SIG, "SHA512withECDSAinP1363Format", P11Signature,
                     m(CKM_ECDSA));
    -        d(SIG, "MD2withRSA",    P11Signature,
    -                s("1.2.840.113549.1.1.2", "OID.1.2.840.113549.1.1.2"),
    +        dA(SIG, "MD2withRSA",    P11Signature,
                     m(CKM_MD2_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
    -        d(SIG, "MD5withRSA",    P11Signature,
    -                s("1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4"),
    +        dA(SIG, "MD5withRSA",    P11Signature,
                     m(CKM_MD5_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
    -        d(SIG, "SHA1withRSA",   P11Signature,
    -                s("1.2.840.113549.1.1.5", "OID.1.2.840.113549.1.1.5",
    -                  "1.3.14.3.2.29"),
    +        dA(SIG, "SHA1withRSA",   P11Signature,
                     m(CKM_SHA1_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
    -        d(SIG, "SHA224withRSA", P11Signature,
    -                s("1.2.840.113549.1.1.14", "OID.1.2.840.113549.1.1.14"),
    +        dA(SIG, "SHA224withRSA", P11Signature,
                     m(CKM_SHA224_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
    -        d(SIG, "SHA256withRSA", P11Signature,
    -                s("1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11"),
    +        dA(SIG, "SHA256withRSA", P11Signature,
                     m(CKM_SHA256_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
    -        d(SIG, "SHA384withRSA", P11Signature,
    -                s("1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12"),
    +        dA(SIG, "SHA384withRSA", P11Signature,
                     m(CKM_SHA384_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
    -        d(SIG, "SHA512withRSA", P11Signature,
    -                s("1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13"),
    +        dA(SIG, "SHA512withRSA", P11Signature,
                     m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
    -        d(SIG, "RSASSA-PSS", P11PSSSignature,
    -                s("1.2.840.113549.1.1.10", "OID.1.2.840.113549.1.1.10"),
    +        dA(SIG, "RSASSA-PSS", P11PSSSignature,
                     m(CKM_RSA_PKCS_PSS));
             d(SIG, "SHA1withRSASSA-PSS", P11PSSSignature,
                     m(CKM_SHA1_RSA_PKCS_PSS));
    @@ -821,7 +785,7 @@ private static void register(Descriptor d) {
     
             d(KG, "SunTlsRsaPremasterSecret",
                         "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
    -                    s("SunTls12RsaPremasterSecret"),
    +                List.of("SunTls12RsaPremasterSecret"),
                     m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));
             d(KG, "SunTlsMasterSecret",
                         "sun.security.pkcs11.P11TlsMasterSecretGenerator",
    @@ -1128,7 +1092,7 @@ public Object run() {
                     if (config.isEnabled(PCKM_KEYSTORE)) {
                         putService(new P11Service(token, KS, "PKCS11",
                             "sun.security.pkcs11.P11KeyStore",
    -                        s("PKCS11-" + config.getName()),
    +                        List.of("PKCS11-" + config.getName()),
                             PCKM_KEYSTORE));
                     }
                     return null;
    @@ -1148,17 +1112,13 @@ private static final class P11Service extends Service {
             private final long mechanism;
     
             P11Service(Token token, String type, String algorithm,
    -                String className, String[] al, long mechanism) {
    -            super(token.provider, type, algorithm, className, toList(al),
    +                String className, List al, long mechanism) {
    +            super(token.provider, type, algorithm, className, al,
                         type.equals(SR) ? Map.of("ThreadSafe", "true") : null);
                 this.token = token;
                 this.mechanism = mechanism & 0xFFFFFFFFL;
             }
     
    -        private static List toList(String[] aliases) {
    -            return (aliases == null) ? null : Arrays.asList(aliases);
    -        }
    -
             public Object newInstance(Object param)
                     throws NoSuchAlgorithmException {
                 if (token.isValid() == false) {
    diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Token.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Token.java
    index 1d0c0a7fc22..dab1bb64b8a 100644
    --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Token.java
    +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Token.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -420,11 +420,26 @@ private synchronized byte[] getTokenId() {
     
         private Object writeReplace() throws ObjectStreamException {
             if (isValid() == false) {
    -            throw new NotSerializableException("Token has been removed");
    +            throw new InvalidObjectException("Token has been removed");
             }
             return new TokenRep(this);
         }
     
    +    /**
    +     * Restores the state of this object from the stream.
    +     * 

    + * Deserialization of this object is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "Tokens are not directly deserializable"); + } + // serialized representation of a token // tokens can only be de-serialized within the same VM invocation // and if the token has not been removed in the meantime @@ -447,7 +462,7 @@ private Object readResolve() throws ObjectStreamException { } } } - throw new NotSerializableException("Could not find token"); + throw new InvalidObjectException("Could not find token"); } } diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java index 81c992d62d3..a7aae0565e3 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPrivateKeyImpl.java @@ -26,6 +26,8 @@ package sun.security.ec; import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.math.BigInteger; import java.security.*; @@ -38,7 +40,7 @@ /** * Key implementation for EC private keys. - * + *

    * ASN.1 syntax for EC private keys from SEC 1 v1.5 (draft): * *

    @@ -208,4 +210,19 @@ protected void parseKeyBits() throws InvalidKeyException {
                 throw new InvalidKeyException("Invalid EC private key", e);
             }
         }
    +
    +    /**
    +     * Restores the state of this object from the stream.
    +     * 

    + * Deserialization of this object is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "ECPrivateKeyImpl keys are not directly deserializable"); + } } diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPublicKeyImpl.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPublicKeyImpl.java index bc403026c4d..b0c344d6e42 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPublicKeyImpl.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECPublicKeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,8 @@ import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.security.*; import java.security.interfaces.*; import java.security.spec.*; @@ -122,10 +124,25 @@ public String toString() { + "\n parameters: " + params; } - protected Object writeReplace() throws java.io.ObjectStreamException { + private Object writeReplace() throws java.io.ObjectStreamException { return new KeyRep(KeyRep.Type.PUBLIC, getAlgorithm(), getFormat(), getEncoded()); } + + /** + * Restores the state of this object from the stream. + *

    + * Deserialization of this object is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "ECPublicKeyImpl keys are not directly deserializable"); + } } diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java index 09be69ecc46..9ae8eee8597 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java @@ -27,11 +27,11 @@ import java.util.*; import java.security.*; -import java.util.regex.Pattern; import sun.security.util.CurveDB; import sun.security.util.NamedCurve; import static sun.security.util.SecurityConstants.PROVIDER_VER; +import static sun.security.util.SecurityProviderConstants.*; /** * Provider class for the Elliptic Curve provider. @@ -69,6 +69,13 @@ public Void run() { } } + private static class ProviderServiceA extends ProviderService { + ProviderServiceA(Provider p, String type, String algo, String cn, + HashMap attrs) { + super(p, type, algo, cn, getAliases(algo), attrs); + } + } + private static class ProviderService extends Provider.Service { ProviderService(Provider p, String type, String algo, String cn) { @@ -76,9 +83,8 @@ private static class ProviderService extends Provider.Service { } ProviderService(Provider p, String type, String algo, String cn, - String[] aliases, HashMap attrs) { - super(p, type, algo, cn, - (aliases == null? null : Arrays.asList(aliases)), attrs); + List aliases, HashMap attrs) { + super(p, type, algo, cn, aliases, attrs); } @Override @@ -184,7 +190,7 @@ void putEntries(boolean useFullImplementation) { */ putService(new ProviderService(this, "KeyFactory", "EC", "sun.security.ec.ECKeyFactory", - new String[] { "EllipticCurve" }, ATTRS)); + List.of("EllipticCurve"), ATTRS)); /* * Algorithm Parameter engine @@ -192,7 +198,6 @@ void putEntries(boolean useFullImplementation) { // "AlgorithmParameters.EC SupportedCurves" prop used by unit test boolean firstCurve = true; StringBuilder names = new StringBuilder(); - Pattern nameSplitPattern = Pattern.compile(CurveDB.SPLIT_PATTERN); Collection supportedCurves = CurveDB.getSupportedCurves(); @@ -204,10 +209,9 @@ void putEntries(boolean useFullImplementation) { } names.append("["); - - String[] commonNames = nameSplitPattern.split(namedCurve.getName()); + String[] commonNames = namedCurve.getNameAndAliases(); for (String commonName : commonNames) { - names.append(commonName.trim()); + names.append(commonName); names.append(","); } @@ -218,10 +222,8 @@ void putEntries(boolean useFullImplementation) { HashMap apAttrs = new HashMap<>(ATTRS); apAttrs.put("SupportedCurves", names.toString()); - putService(new ProviderService(this, "AlgorithmParameters", - "EC", "sun.security.util.ECParameters", - new String[] { "EllipticCurve", "1.2.840.10045.2.1", "OID.1.2.840.10045.2.1" }, - apAttrs)); + putService(new ProviderServiceA(this, "AlgorithmParameters", + "EC", "sun.security.util.ECParameters", apAttrs)); putXDHEntries(); @@ -239,25 +241,20 @@ void putEntries(boolean useFullImplementation) { putService(new ProviderService(this, "Signature", "NONEwithECDSA", "sun.security.ec.ECDSASignature$Raw", null, ATTRS)); - putService(new ProviderService(this, "Signature", + putService(new ProviderServiceA(this, "Signature", "SHA1withECDSA", "sun.security.ec.ECDSASignature$SHA1", - new String[] { "1.2.840.10045.4.1", "OID.1.2.840.10045.4.1" }, ATTRS)); - putService(new ProviderService(this, "Signature", + putService(new ProviderServiceA(this, "Signature", "SHA224withECDSA", "sun.security.ec.ECDSASignature$SHA224", - new String[] { "1.2.840.10045.4.3.1", "OID.1.2.840.10045.4.3.1"}, ATTRS)); - putService(new ProviderService(this, "Signature", + putService(new ProviderServiceA(this, "Signature", "SHA256withECDSA", "sun.security.ec.ECDSASignature$SHA256", - new String[] { "1.2.840.10045.4.3.2", "OID.1.2.840.10045.4.3.2"}, ATTRS)); - putService(new ProviderService(this, "Signature", + putService(new ProviderServiceA(this, "Signature", "SHA384withECDSA", "sun.security.ec.ECDSASignature$SHA384", - new String[] { "1.2.840.10045.4.3.3", "OID.1.2.840.10045.4.3.3" }, ATTRS)); - putService(new ProviderService(this, "Signature", + putService(new ProviderServiceA(this, "Signature", "SHA512withECDSA", "sun.security.ec.ECDSASignature$SHA512", - new String[] { "1.2.840.10045.4.3.4", "OID.1.2.840.10045.4.3.4" }, ATTRS)); putService(new ProviderService(this, "Signature", @@ -284,7 +281,7 @@ void putEntries(boolean useFullImplementation) { */ putService(new ProviderService(this, "KeyPairGenerator", "EC", "sun.security.ec.ECKeyPairGenerator", - new String[] { "EllipticCurve" }, ATTRS)); + List.of("EllipticCurve"), ATTRS)); /* * Key Agreement engine @@ -301,30 +298,29 @@ private void putXDHEntries() { /* XDH does not require native implementation */ putService(new ProviderService(this, "KeyFactory", "XDH", "sun.security.ec.XDHKeyFactory", null, ATTRS)); - putService(new ProviderService(this, "KeyFactory", + putService(new ProviderServiceA(this, "KeyFactory", "X25519", "sun.security.ec.XDHKeyFactory.X25519", - new String[]{"1.3.101.110", "OID.1.3.101.110"}, ATTRS)); - putService(new ProviderService(this, "KeyFactory", + ATTRS)); + putService(new ProviderServiceA(this, "KeyFactory", "X448", "sun.security.ec.XDHKeyFactory.X448", - new String[]{"1.3.101.111", "OID.1.3.101.111"}, ATTRS)); + ATTRS)); putService(new ProviderService(this, "KeyPairGenerator", "XDH", "sun.security.ec.XDHKeyPairGenerator", null, ATTRS)); - putService(new ProviderService(this, "KeyPairGenerator", + putService(new ProviderServiceA(this, "KeyPairGenerator", "X25519", "sun.security.ec.XDHKeyPairGenerator.X25519", - new String[]{"1.3.101.110", "OID.1.3.101.110"}, ATTRS)); - putService(new ProviderService(this, "KeyPairGenerator", + ATTRS)); + putService(new ProviderServiceA(this, "KeyPairGenerator", "X448", "sun.security.ec.XDHKeyPairGenerator.X448", - new String[]{"1.3.101.111", "OID.1.3.101.111"}, ATTRS)); + ATTRS)); putService(new ProviderService(this, "KeyAgreement", "XDH", "sun.security.ec.XDHKeyAgreement", null, ATTRS)); - putService(new ProviderService(this, "KeyAgreement", + putService(new ProviderServiceA(this, "KeyAgreement", "X25519", "sun.security.ec.XDHKeyAgreement.X25519", - new String[]{"1.3.101.110", "OID.1.3.101.110"}, ATTRS)); - putService(new ProviderService(this, "KeyAgreement", + ATTRS)); + putService(new ProviderServiceA(this, "KeyAgreement", "X448", "sun.security.ec.XDHKeyAgreement.X448", - new String[]{"1.3.101.111", "OID.1.3.101.111"}, ATTRS)); - + ATTRS)); } } diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPrivateKeyImpl.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPrivateKeyImpl.java index 2b93cfd17c7..bb4b732a0e7 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPrivateKeyImpl.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPrivateKeyImpl.java @@ -25,6 +25,9 @@ package sun.security.ec; +import java.io.ObjectInputStream; +import java.io.IOException; +import java.io.InvalidObjectException; import java.security.interfaces.XECPrivateKey; import java.util.Optional; import java.security.InvalidKeyException; @@ -87,5 +90,19 @@ public AlgorithmParameterSpec getParams() { public Optional getScalar() { return Optional.of(getK()); } -} + /** + * Restores the state of this object from the stream. + *

    + * Deserialization of this object is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "XDHPrivateKeyImpl keys are not directly deserializable"); + } +} diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPublicKeyImpl.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPublicKeyImpl.java index 0b9b6d93c04..b9118a19515 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPublicKeyImpl.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPublicKeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package sun.security.ec; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.KeyRep; @@ -107,7 +110,7 @@ public String getAlgorithm() { return "XDH"; } - protected Object writeReplace() throws java.io.ObjectStreamException { + private Object writeReplace() throws java.io.ObjectStreamException { return new KeyRep(KeyRep.Type.PUBLIC, getAlgorithm(), getFormat(), @@ -130,5 +133,20 @@ private static void reverse(byte [] arr) { j--; } } + + /** + * Restores the state of this object from the stream. + *

    + * Deserialization of this object is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "XDHPublicKeyImpl keys are not directly deserializable"); + } } diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XECParameters.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/XECParameters.java index 9d7bddb5edb..5868c17086b 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/XECParameters.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XECParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -120,8 +120,8 @@ public String getName() { // set up X25519 try { BigInteger p = TWO.pow(255).subtract(BigInteger.valueOf(19)); - addParameters(255, p, 121665, (byte) 0x09, 3, - new int[]{1, 3, 101, 110}, NamedParameterSpec.X25519.getName(), + addParameters(255, p, 121665, (byte)0x09, 3, + "1.3.101.110", NamedParameterSpec.X25519.getName(), bySize, byOid, byName); } catch (IOException ex) { @@ -132,8 +132,8 @@ public String getName() { try { BigInteger p = TWO.pow(448).subtract(TWO.pow(224)) .subtract(BigInteger.ONE); - addParameters(448, p, 39081, (byte) 0x05, 2, - new int[]{1, 3, 101, 111}, NamedParameterSpec.X448.getName(), + addParameters(448, p, 39081, (byte)0x05, 2, + "1.3.101.111", NamedParameterSpec.X448.getName(), bySize, byOid, byName); } catch (IOException ex) { @@ -146,12 +146,12 @@ public String getName() { } private static void addParameters(int bits, BigInteger p, int a24, - byte basePoint, int logCofactor, int[] oidBytes, String name, + byte basePoint, int logCofactor, String objectId, String name, Map bySize, Map byOid, Map byName) throws IOException { - ObjectIdentifier oid = new ObjectIdentifier(oidBytes); + ObjectIdentifier oid = ObjectIdentifier.of(objectId); XECParameters params = new XECParameters(bits, p, a24, basePoint, logCofactor, oid, name); bySize.put(bits, params); diff --git a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPrivateKey.java b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPrivateKey.java index a65ea445890..cea2f93ed5f 100644 --- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPrivateKey.java +++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPrivateKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package sun.security.mscapi; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.security.PrivateKey; /** @@ -74,6 +77,22 @@ public String toString() { // This class is not serializable private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { - throw new java.io.NotSerializableException(); + throw new java.io.InvalidObjectException( + "CPrivateKeys are not serializable"); + } + + /** + * Restores the state of this object from the stream. + *

    + * Deserialization of this object is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "CPrivateKeys are not deserializable"); } } diff --git a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPublicKey.java b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPublicKey.java index 35e25e90647..93c11c8d561 100644 --- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPublicKey.java +++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CPublicKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package sun.security.mscapi; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.math.BigInteger; import java.security.AlgorithmParameters; import java.security.KeyException; @@ -108,7 +111,7 @@ public ECParameterSpec getParams() { public String toString() { StringBuffer sb = new StringBuffer(); - sb.append(algorithm + "PublicKey [size=").append(keyLength) + sb.append(algorithm).append("PublicKey [size=").append(keyLength) .append("]\n ECPoint: ").append(getW()) .append("\n params: ").append(getParams()); return sb.toString(); @@ -127,7 +130,7 @@ public static class CRSAPublicKey extends CPublicKey implements RSAPublicKey { public String toString() { StringBuffer sb = new StringBuffer(); - sb.append(algorithm + "PublicKey [size=").append(keyLength) + sb.append(algorithm).append("PublicKey [size=").append(keyLength) .append(" bits, type="); if (handles.hCryptKey != 0) { sb.append(getKeyType(handles.hCryptKey)) @@ -221,6 +224,21 @@ protected Object writeReplace() throws java.io.ObjectStreamException { getEncoded()); } + /** + * Restores the state of this object from the stream. + *

    + * Deserialization of this object is not supported. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "CPublicKeys are not deserializable"); + } + // Returns the CAPI or CNG representation of the key. native byte[] getPublicKeyBlob(long hCryptProv, long hCryptKey) throws KeyException; diff --git a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java index 2721dc66068..d89c9ab3d6a 100644 --- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java +++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -32,9 +32,10 @@ import java.security.InvalidParameterException; import java.security.ProviderException; import java.util.HashMap; -import java.util.Arrays; +import java.util.List; import static sun.security.util.SecurityConstants.PROVIDER_VER; +import static sun.security.util.SecurityProviderConstants.getAliases; /** * A Cryptographic Service Provider for the Microsoft Crypto API. @@ -56,16 +57,21 @@ public Void run() { } }); } + private static class ProviderServiceA extends ProviderService { + ProviderServiceA(Provider p, String type, String algo, String cn, + HashMap attrs) { + super(p, type, algo, cn, getAliases(algo), attrs); + } + } - private static final class ProviderService extends Provider.Service { + private static class ProviderService extends Provider.Service { ProviderService(Provider p, String type, String algo, String cn) { super(p, type, algo, cn, null, null); } ProviderService(Provider p, String type, String algo, String cn, - String[] aliases, HashMap attrs) { - super(p, type, algo, cn, - (aliases == null? null : Arrays.asList(aliases)), attrs); + List aliases, HashMap attrs) { + super(p, type, algo, cn, aliases, attrs); } @Override @@ -188,48 +194,47 @@ public Void run() { putService(new ProviderService(p, "Signature", "SHA1withRSA", "sun.security.mscapi.CSignature$SHA1withRSA", null, attrs)); - putService(new ProviderService(p, "Signature", - "SHA256withRSA", "sun.security.mscapi.CSignature$SHA256withRSA", - new String[] { "1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11" }, + putService(new ProviderServiceA(p, "Signature", + "SHA256withRSA", + "sun.security.mscapi.CSignature$SHA256withRSA", attrs)); - putService(new ProviderService(p, "Signature", - "SHA384withRSA", "sun.security.mscapi.CSignature$SHA384withRSA", - new String[] { "1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12" }, + putService(new ProviderServiceA(p, "Signature", + "SHA384withRSA", + "sun.security.mscapi.CSignature$SHA384withRSA", attrs)); - putService(new ProviderService(p, "Signature", - "SHA512withRSA", "sun.security.mscapi.CSignature$SHA512withRSA", - new String[] { "1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13" }, + putService(new ProviderServiceA(p, "Signature", + "SHA512withRSA", + "sun.security.mscapi.CSignature$SHA512withRSA", + attrs)); + putService(new ProviderServiceA(p, "Signature", + "RSASSA-PSS", "sun.security.mscapi.CSignature$PSS", attrs)); - putService(new ProviderService(p, "Signature", - "RSASSA-PSS", "sun.security.mscapi.CSignature$PSS", - new String[] { "1.2.840.113549.1.1.10", "OID.1.2.840.113549.1.1.10" }, - attrs)); putService(new ProviderService(p, "Signature", "MD5withRSA", "sun.security.mscapi.CSignature$MD5withRSA", null, attrs)); putService(new ProviderService(p, "Signature", "MD2withRSA", "sun.security.mscapi.CSignature$MD2withRSA", null, attrs)); - putService(new ProviderService(p, "Signature", - "SHA1withECDSA", "sun.security.mscapi.CSignature$SHA1withECDSA", - new String[] { "1.2.840.10045.4.1", "OID.1.2.840.10045.4.1" }, - attrs)); - putService(new ProviderService(p, "Signature", - "SHA224withECDSA", "sun.security.mscapi.CSignature$SHA224withECDSA", - new String[] { "1.2.840.10045.4.3.1", "OID.1.2.840.10045.4.3.1"}, - attrs)); - putService(new ProviderService(p, "Signature", - "SHA256withECDSA", "sun.security.mscapi.CSignature$SHA256withECDSA", - new String[] { "1.2.840.10045.4.3.2", "OID.1.2.840.10045.4.3.2"}, - attrs)); - putService(new ProviderService(p, "Signature", - "SHA384withECDSA", "sun.security.mscapi.CSignature$SHA384withECDSA", - new String[] { "1.2.840.10045.4.3.3", "OID.1.2.840.10045.4.3.3"}, - attrs)); - putService(new ProviderService(p, "Signature", - "SHA512withECDSA", "sun.security.mscapi.CSignature$SHA512withECDSA", - new String[] { "1.2.840.10045.4.3.4", "OID.1.2.840.10045.4.3.4"}, - attrs)); + putService(new ProviderServiceA(p, "Signature", + "SHA1withECDSA", + "sun.security.mscapi.CSignature$SHA1withECDSA", + attrs)); + putService(new ProviderServiceA(p, "Signature", + "SHA224withECDSA", + "sun.security.mscapi.CSignature$SHA224withECDSA", + attrs)); + putService(new ProviderServiceA(p, "Signature", + "SHA256withECDSA", + "sun.security.mscapi.CSignature$SHA256withECDSA", + attrs)); + putService(new ProviderServiceA(p, "Signature", + "SHA384withECDSA", + "sun.security.mscapi.CSignature$SHA384withECDSA", + attrs)); + putService(new ProviderServiceA(p, "Signature", + "SHA512withECDSA", + "sun.security.mscapi.CSignature$SHA512withECDSA", + attrs)); /* * Key Pair Generator engines */ diff --git a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/LibMDMech.java b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/LibMDMech.java index 3b6b3f623f5..05a7af7edcc 100644 --- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/LibMDMech.java +++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/LibMDMech.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -25,6 +25,9 @@ package com.oracle.security.ucrypto; +import java.util.List; +import static sun.security.util.SecurityProviderConstants.getAliases; + /** * Enum for representing the ucrypto mechanisms. * @@ -36,25 +39,30 @@ public enum LibMDMech { { sd("MessageDigest", "MD5", "com.oracle.security.ucrypto.NativeDigestMD$MD5") }), SHA_1(new ServiceDesc[] - { sd("MessageDigest", "SHA", "com.oracle.security.ucrypto.NativeDigestMD$SHA1", - "SHA-1", "SHA1") + { sd("MessageDigest", "SHA-1", "com.oracle.security.ucrypto.NativeDigestMD$SHA1", + getAliases("SHA-1")) }), SHA_256(new ServiceDesc[] { sd("MessageDigest", "SHA-256", "com.oracle.security.ucrypto.NativeDigestMD$SHA256", - "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1") + getAliases("SHA-256")) }), SHA_384(new ServiceDesc[] { sd("MessageDigest", "SHA-384", "com.oracle.security.ucrypto.NativeDigestMD$SHA384", - "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2") + getAliases("SHA-384")) }), SHA_512(new ServiceDesc[] { sd("MessageDigest", "SHA-512", "com.oracle.security.ucrypto.NativeDigestMD$SHA512", - "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3") + getAliases("SHA-512")) }); ServiceDesc[] serviceDescs; - private static ServiceDesc sd(String type, String algo, String cn, String... aliases) { + private static ServiceDesc sd(String type, String algo, String cn) { + return new ServiceDesc(type, algo, cn, null); + } + + private static ServiceDesc sd(String type, String algo, String cn, + List aliases) { return new ServiceDesc(type, algo, cn, aliases); } diff --git a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/ServiceDesc.java b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/ServiceDesc.java index aa7eae1e000..8b915626ffb 100644 --- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/ServiceDesc.java +++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/ServiceDesc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -42,15 +42,11 @@ final class ServiceDesc { this(type, algo, cn, null); } - ServiceDesc(String type, String algo, String cn, String[] aliases) { + ServiceDesc(String type, String algo, String cn, List aliases) { this.type = type; this.algo = algo; this.cn = cn; - if (aliases != null) { - this.aliases = Arrays.asList(aliases); - } else { - this.aliases = null; - } + this.aliases = aliases; } String getType() { return type; diff --git a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java index 0e1c2849828..b853755a7a2 100644 --- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java +++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package com.oracle.security.ucrypto; +import java.util.List; +import static sun.security.util.SecurityProviderConstants.getAliases; + /** * Enum for representing the ucrypto mechanisms. * @@ -36,23 +39,23 @@ public enum UcryptoMech { CRYPTO_AES_ECB(new ServiceDesc[] { sd("Cipher", "AES/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding"), sd("Cipher", "AES/ECB/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesEcbPKCS5", - "AES"), - sd("Cipher", "AES_128/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding", - "2.16.840.1.101.3.4.1.1", "OID.2.16.840.1.101.3.4.1.1"), - sd("Cipher", "AES_192/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding", - "2.16.840.1.101.3.4.1.21", "OID.2.16.840.1.101.3.4.1.21"), - sd("Cipher", "AES_256/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding", - "2.16.840.1.101.3.4.1.41", "OID.2.16.840.1.101.3.4.1.41") + List.of("AES")), + sdA("Cipher", "AES_128/ECB/NoPadding", + "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding"), + sdA("Cipher", "AES_192/ECB/NoPadding", + "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding"), + sdA("Cipher", "AES_256/ECB/NoPadding", + "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding") }), CRYPTO_AES_CBC(new ServiceDesc[] { sd("Cipher", "AES/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding"), sd("Cipher", "AES/CBC/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCbcPKCS5"), - sd("Cipher", "AES_128/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding", - "2.16.840.1.101.3.4.1.2", "OID.2.16.840.1.101.3.4.1.2"), - sd("Cipher", "AES_192/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding", - "2.16.840.1.101.3.4.1.22", "OID.2.16.840.1.101.3.4.1.22"), - sd("Cipher", "AES_256/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding", - "2.16.840.1.101.3.4.1.42", "OID.2.16.840.1.101.3.4.1.42") + sdA("Cipher", "AES_128/CBC/NoPadding", + "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding"), + sdA("Cipher", "AES_192/CBC/NoPadding", + "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding"), + sdA("Cipher", "AES_256/CBC/NoPadding", + "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding") }), // CRYPTO_AES_CBC_PAD(null), // Support added since S11.1; however we still use CRYPTO_AES_CBC due to known bug CRYPTO_AES_CTR(new ServiceDesc[] @@ -60,12 +63,12 @@ public enum UcryptoMech { // CRYPTO_AES_CCM(null), // Need Java API for CK_AES_CCM_PARAMS CRYPTO_AES_GCM(new ServiceDesc[] { sd("Cipher", "AES/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding"), - sd("Cipher", "AES_128/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding", - "2.16.840.1.101.3.4.1.6", "OID.2.16.840.1.101.3.4.1.6"), - sd("Cipher", "AES_192/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding", - "2.16.840.1.101.3.4.1.26", "OID.2.16.840.1.101.3.4.1.26"), - sd("Cipher", "AES_256/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding", - "2.16.840.1.101.3.4.1.46", "OID.2.16.840.1.101.3.4.1.46") + sdA("Cipher", "AES_128/GCM/NoPadding", + "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding"), + sdA("Cipher", "AES_192/GCM/NoPadding", + "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding"), + sdA("Cipher", "AES_256/GCM/NoPadding", + "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding") }), // CRYPTO_AES_GMAC(null), // No support from Solaris CRYPTO_AES_CFB128(new ServiceDesc[] @@ -75,76 +78,87 @@ public enum UcryptoMech { CRYPTO_RSA_PKCS(new ServiceDesc[] { sd("Cipher", "RSA/ECB/PKCS1Padding", "com.oracle.security.ucrypto.NativeRSACipher$PKCS1Padding", - "RSA") + List.of("RSA")) }), CRYPTO_RSA_X_509(new ServiceDesc[] { sd("Cipher", "RSA/ECB/NoPadding", "com.oracle.security.ucrypto.NativeRSACipher$NoPadding") }), CRYPTO_MD5_RSA_PKCS(new ServiceDesc[] - { sd("Signature", "MD5withRSA", "com.oracle.security.ucrypto.NativeRSASignature$MD5", - "1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4") + { sdA("Signature", "MD5withRSA", + "com.oracle.security.ucrypto.NativeRSASignature$MD5") }), CRYPTO_SHA1_RSA_PKCS(new ServiceDesc[] - { sd("Signature", "SHA1withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA1", - "1.2.840.113549.1.1.5", "OID.1.2.840.113549.1.1.5", - "1.3.14.3.2.29") + { sdA("Signature", "SHA1withRSA", + "com.oracle.security.ucrypto.NativeRSASignature$SHA1") }), CRYPTO_SHA256_RSA_PKCS(new ServiceDesc[] - { sd("Signature", "SHA256withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA256", - "1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11") + { sdA("Signature", "SHA256withRSA", + "com.oracle.security.ucrypto.NativeRSASignature$SHA256") }), CRYPTO_SHA384_RSA_PKCS(new ServiceDesc[] - { sd("Signature", "SHA384withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA384", - "1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12") + { sdA("Signature", "SHA384withRSA", + "com.oracle.security.ucrypto.NativeRSASignature$SHA384") }), CRYPTO_SHA512_RSA_PKCS(new ServiceDesc[] - { sd("Signature", "SHA512withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA512", - "1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13") + { sdA("Signature", "SHA512withRSA", + "com.oracle.security.ucrypto.NativeRSASignature$SHA512") }), CRYPTO_MD5(new ServiceDesc[] - { sd("MessageDigest", "MD5", "com.oracle.security.ucrypto.NativeDigest$MD5") }), + { sd("MessageDigest", "MD5", "com.oracle.security.ucrypto.NativeDigest$MD5") + }), CRYPTO_SHA1(new ServiceDesc[] - { sd("MessageDigest", "SHA", "com.oracle.security.ucrypto.NativeDigest$SHA1", "SHA-1", "SHA1") }), + { sdA("MessageDigest", "SHA-1", + "com.oracle.security.ucrypto.NativeDigest$SHA1") + }), CRYPTO_SHA224(new ServiceDesc[] - { sd("MessageDigest", "SHA-224", "com.oracle.security.ucrypto.NativeDigest$SHA224", - "2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4") - }), + { sdA("MessageDigest", "SHA-224", + "com.oracle.security.ucrypto.NativeDigest$SHA224") + }), CRYPTO_SHA256(new ServiceDesc[] - { sd("MessageDigest", "SHA-256", "com.oracle.security.ucrypto.NativeDigest$SHA256", - "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1") - }), + { sdA("MessageDigest", "SHA-256", + "com.oracle.security.ucrypto.NativeDigest$SHA256") + }), CRYPTO_SHA384(new ServiceDesc[] - { sd("MessageDigest", "SHA-384", "com.oracle.security.ucrypto.NativeDigest$SHA384", - "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2") - }), + { sdA("MessageDigest", "SHA-384", + "com.oracle.security.ucrypto.NativeDigest$SHA384") + }), CRYPTO_SHA512(new ServiceDesc[] - { sd("MessageDigest", "SHA-512", "com.oracle.security.ucrypto.NativeDigest$SHA512", - "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3") - }), + { sdA("MessageDigest", "SHA-512", + "com.oracle.security.ucrypto.NativeDigest$SHA512") + }), CRYPTO_SHA3_224(new ServiceDesc[] - { sd("MessageDigest", "SHA3-224", "com.oracle.security.ucrypto.NativeDigest$SHA3_224", - "2.16.840.1.101.3.4.2.7", "OID.2.16.840.1.101.3.4.2.7") - }), + { sdA("MessageDigest", "SHA3-224", + "com.oracle.security.ucrypto.NativeDigest$SHA3_224") + }), CRYPTO_SHA3_256(new ServiceDesc[] - { sd("MessageDigest", "SHA3-256", "com.oracle.security.ucrypto.NativeDigest$SHA3_256", - "2.16.840.1.101.3.4.2.8", "OID.2.16.840.1.101.3.4.2.8") - }), + { sdA("MessageDigest", "SHA3-256", + "com.oracle.security.ucrypto.NativeDigest$SHA3_256") + }), CRYPTO_SHA3_384(new ServiceDesc[] - { sd("MessageDigest", "SHA3-384", "com.oracle.security.ucrypto.NativeDigest$SHA3_384", - "2.16.840.1.101.3.4.2.9", "OID.2.16.840.1.101.3.4.2.9") - }), + { sdA("MessageDigest", "SHA3-384", + "com.oracle.security.ucrypto.NativeDigest$SHA3_384") + }), CRYPTO_SHA3_512(new ServiceDesc[] - { sd("MessageDigest", "SHA3-512", "com.oracle.security.ucrypto.NativeDigest$SHA3_512", - "2.16.840.1.101.3.4.2.10", "OID.2.16.840.1.101.3.4.2.10") - }); + { sdA("MessageDigest", "SHA3-512", + "com.oracle.security.ucrypto.NativeDigest$SHA3_512") + }); private int mech = 0; private final ServiceDesc[] serviceDescs; - private static ServiceDesc sd(String type, String algo, String cn, String... aliases) { + private static ServiceDesc sd(String type, String algo, String cn) { + return new ServiceDesc(type, algo, cn, null); + } + + private static ServiceDesc sd(String type, String algo, String cn, + List aliases) { return new ServiceDesc(type, algo, cn, aliases); } + private static ServiceDesc sdA(String type, String algo, String cn) { + return new ServiceDesc(type, algo, cn, getAliases(algo)); + } + UcryptoMech(ServiceDesc[] serviceDescs) { this.serviceDescs = serviceDescs; } diff --git a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java index a1a7cc15508..0300547a7c3 100644 --- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java +++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ import java.security.*; import static sun.security.util.SecurityConstants.PROVIDER_VER; - /** * OracleUcrypto provider main class. * @@ -134,9 +133,8 @@ public HashMap run() { } } - private static ServiceDesc sd(String type, String algo, String cn, - String... aliases) { - return new ServiceDesc(type, algo, cn, aliases); + private static ServiceDesc sd(String type, String algo, String cn) { + return new ServiceDesc(type, algo, cn, null); } private static final class ProviderService extends Provider.Service { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java index 307598f47fc..ef8258525d5 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java @@ -121,6 +121,9 @@ public FileMapHeader(Address addr) { } public boolean inCopiedVtableSpace(Address vptrAddress) { + if (vptrAddress == null) { + return false; + } if (vptrAddress.greaterThan(mdRegionBaseAddress) && vptrAddress.lessThanOrEqual(mdRegionEndAddress)) { return true; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java index 850fcd0d5d3..6eae172f5e2 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -130,6 +130,7 @@ public class VM { private static Type intxType; private static Type uintxType; private static Type sizetType; + private static Type uint64tType; private static CIntegerType boolType; private Boolean sharingEnabled; private Boolean compressedOopsEnabled; @@ -231,6 +232,50 @@ public long getSizet() { return addr.getCIntegerAt(0, sizetType.getSize(), true); } + public boolean isCcstr() { + return type.equals("ccstr"); + } + + public String getCcstr() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(isCcstr(), "not a ccstr flag!"); + } + return CStringUtilities.getString(addr.getAddressAt(0)); + } + + public boolean isCcstrlist() { + return type.equals("ccstrlist"); + } + + public String getCcstrlist() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(isCcstrlist(), "not a ccstrlist flag!"); + } + return CStringUtilities.getString(addr.getAddressAt(0)); + } + + public boolean isDouble() { + return type.equals("double"); + } + + public double getDouble() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(isDouble(), "not a double flag!"); + } + return addr.getJDoubleAt(0); + } + + public boolean isUint64t() { + return type.equals("uint64_t"); + } + + public long getUint64t() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(isUint64t(), "not an uint64_t flag!"); + } + return addr.getCIntegerAt(0, uint64tType.getSize(), true); + } + public String getValue() { if (isBool()) { return Boolean.toString(getBool()); @@ -241,11 +286,27 @@ public String getValue() { } else if (isIntx()) { return Long.toString(getIntx()); } else if (isUIntx()) { - return Long.toString(getUIntx()); + return Long.toUnsignedString(getUIntx()); } else if (isSizet()) { - return Long.toString(getSizet()); + return Long.toUnsignedString(getSizet()); + } else if (isCcstr()) { + var str = getCcstr(); + if (str != null) { + str = "\"" + str + "\""; + } + return str; + } else if (isCcstrlist()) { + var str = getCcstrlist(); + if (str != null) { + str = "\"" + str + "\""; + } + return str; + } else if (isDouble()) { + return Double.toString(getDouble()); + } else if (isUint64t()) { + return Long.toUnsignedString(getUint64t()); } else { - return null; + throw new WrongTypeException("Unknown type: " + type + " (" + name + ")"); } } }; @@ -383,6 +444,7 @@ private VM(TypeDataBase db, JVMDebugger debugger, boolean isBigEndian) { intxType = db.lookupType("intx"); uintxType = db.lookupType("uintx"); sizetType = db.lookupType("size_t"); + uint64tType = db.lookupType("uint64_t"); boolType = (CIntegerType) db.lookupType("bool"); minObjAlignmentInBytes = getObjectAlignmentInBytes(); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java index 8ed5bc2d4b8..6a439716a83 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -293,6 +293,8 @@ private long getFlagValue(String name, Map flagMap) { if (f != null) { if (f.isBool()) { return f.getBool()? 1L : 0L; + } else if (f.isUIntx() || f.isSizet() || f.isUint64t()) { + return Long.parseUnsignedLong(f.getValue()); } else { return Long.parseLong(f.getValue()); } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java index ad10d1a773f..0070b55c22d 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java @@ -14,7 +14,7 @@ * @see Macro * @see Reference * @see Widget - * @see org.jline.keymap.KeyMap + * @see jdk.internal.org.jline.keymap.KeyMap * * @author Guillaume Nodet */ diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java index 51f449f20ee..0e95538492d 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java @@ -24,6 +24,7 @@ public class Candidate implements Comparable { private final String suffix; private final String key; private final boolean complete; + private final int sort; /** * Simple constructor with only a single String as an argument. @@ -31,7 +32,7 @@ public class Candidate implements Comparable { * @param value the candidate */ public Candidate(String value) { - this(value, value, null, null, null, null, true); + this(value, value, null, null, null, null, true, 0); } /** @@ -44,8 +45,9 @@ public Candidate(String value) { * @param suffix the suffix * @param key the key * @param complete the complete flag + * @param sort the sort flag */ - public Candidate(String value, String displ, String group, String descr, String suffix, String key, boolean complete) { + public Candidate(String value, String displ, String group, String descr, String suffix, String key, boolean complete, int sort) { this.value = Objects.requireNonNull(value); this.displ = Objects.requireNonNull(displ); this.group = group; @@ -53,6 +55,22 @@ public Candidate(String value, String displ, String group, String descr, String this.suffix = suffix; this.key = key; this.complete = complete; + this.sort = sort; + } + + /** + * Constructs a new Candidate. + * + * @param value the value + * @param displ the display string + * @param group the group + * @param descr the description + * @param suffix the suffix + * @param key the key + * @param complete the complete flag + */ + public Candidate(String value, String displ, String group, String descr, String suffix, String key, boolean complete) { + this(value, displ, group, descr, suffix, key, complete, 0); } /** @@ -133,9 +151,36 @@ public boolean complete() { return complete; } + /** + * Integer used to override default sort logic. + * @return the sort int + */ + public int sort() { + return sort; + } + + @Override public int compareTo(Candidate o) { - return value.compareTo(o.value); + // If both candidates have same sort, use default behavior + if( sort == o.sort() ) { + return value.compareTo(o.value); + } else { + return Integer.compare(sort, o.sort()); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Candidate candidate = (Candidate) o; + return Objects.equals(value, candidate.value); + } + + @Override + public int hashCode() { + return Objects.hash(value); } @Override diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java index 1f98d6168f0..52a36b83896 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java @@ -10,7 +10,7 @@ /** * An extension of {@link ParsedLine} that, being aware of the quoting and escaping rules - * of the {@link org.jline.reader.Parser} that produced it, knows if and how a completion candidate + * of the {@link jdk.internal.org.jline.reader.Parser} that produced it, knows if and how a completion candidate * should be escaped/quoted. * * @author Eric Bottard diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java index 3cfd73fa19a..58117c8f213 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java @@ -29,7 +29,7 @@ void compile(Map options, boolean prefix, Completing /** * * @param candidates list of candidates - * @return a map of candidates that completion matcher matches + * @return a list of candidates that completion matcher matches */ List matches(List candidates); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java index 81266c7cda5..136fb20324b 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2019, the original author or authors. + * Copyright (c) 2002-2021, the original author or authors. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -14,7 +14,28 @@ public interface Highlighter { + /** + * Highlight buffer + * @param reader LineReader + * @param buffer the buffer to be highlighted + * @return highlighted buffer + */ AttributedString highlight(LineReader reader, String buffer); - public void setErrorPattern(Pattern errorPattern); - public void setErrorIndex(int errorIndex); + + /** + * Refresh highlight configuration + */ + default void refresh(LineReader reader) {} + + /** + * Set error pattern to be highlighted + * @param errorPattern error pattern to be highlighted + */ + void setErrorPattern(Pattern errorPattern); + + /** + * Set error index to be highlighted + * @param errorIndex error index to be highlighted + */ + void setErrorIndex(int errorIndex); } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java index 3dd078cc745..7a669edddb5 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java @@ -61,12 +61,13 @@ public interface History extends Iterable void append(Path file, boolean incremental) throws IOException; /** - * Read history from the file. If incremental only the events that are not contained within the internal list are added. + * Read history from the file. If checkDuplicates is true only the events that + * are not contained within the internal list are added. * @param file History file - * @param incremental If true incremental read operation is performed. + * @param checkDuplicates If true, duplicate history entries will be discarded * @throws IOException if a problem occurs */ - void read(Path file, boolean incremental) throws IOException; + void read(Path file, boolean checkDuplicates) throws IOException; /** * Purge history. diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java index 07b72668721..03729853ca5 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java @@ -352,7 +352,7 @@ public interface LineReader { String AMBIGUOUS_BINDING = "ambiguous-binding"; /** - * Columns separated list of patterns that will not be saved in history. + * Colon separated list of patterns that will not be saved in history. */ String HISTORY_IGNORE = "history-ignore"; @@ -467,6 +467,9 @@ enum Option { /** Show command options tab completion candidates for zero length word */ EMPTY_WORD_OPTIONS(true), + + /** Disable the undo feature */ + DISABLE_UNDO ; private final boolean def; @@ -699,7 +702,7 @@ enum SuggestionType { void runMacro(String macro); /** - * Read a mouse event when the {@link org.jline.utils.InfoCmp.Capability#key_mouse} sequence + * Read a mouse event when the {@link jdk.internal.org.jline.utils.InfoCmp.Capability#key_mouse} sequence * has just been read on the input stream. * Compared to {@link Terminal#readMouseEvent()}, this method takes into account keys * that have been pushed back using {@link #runMacro(String)}. diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java index 422561a86c5..14d5a0e8b1c 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java @@ -118,6 +118,12 @@ public LineReader build() { throw new IOError(e); } } + + String appName = this.appName; + if (null == appName) { + appName = terminal.getName(); + } + LineReaderImpl reader = new LineReaderImpl(terminal, appName, variables); if (history != null) { reader.setHistory(history); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java index 2e2ad8c24bc..1f7df67d573 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2021, the original author or authors. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -12,8 +12,8 @@ import java.util.regex.Pattern; public interface Parser { - static final String REGEX_VARIABLE = "[a-zA-Z_]{1,}[a-zA-Z0-9_-]*"; - static final String REGEX_COMMAND = "[:]{0,1}[a-zA-Z]{1,}[a-zA-Z0-9_-]*"; + String REGEX_VARIABLE = "[a-zA-Z_]+[a-zA-Z0-9_-]*"; + String REGEX_COMMAND = "[:]?[a-zA-Z]+[a-zA-Z0-9_-]*"; ParsedLine parse(String line, int cursor, ParseContext context) throws SyntaxError; @@ -34,7 +34,7 @@ default boolean validVariableName(String name) { } default String getCommand(final String line) { - String out = ""; + String out; Pattern patternCommand = Pattern.compile("^\\s*" + REGEX_VARIABLE + "=(" + REGEX_COMMAND + ")(\\s+|$)"); Matcher matcher = patternCommand.matcher(line); if (matcher.find()) { @@ -68,7 +68,7 @@ enum ParseContext { /** Parsed words will have all characters present in input line * including quotes and escape chars. - * May throw EOFError in which case we have incomplete input. + * We should tolerate and ignore errors. */ SPLIT_LINE, diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java index 0d4ead5743d..f829f13d51b 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java @@ -54,7 +54,7 @@ public List matches(List candidates) { break; } } - return !matching.isEmpty() ? matching.entrySet().stream().flatMap(e -> e.getValue().stream()).collect(Collectors.toList()) + return !matching.isEmpty() ? matching.entrySet().stream().flatMap(e -> e.getValue().stream()).distinct().collect(Collectors.toList()) : new ArrayList<>(); } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java index 4fb616f61dc..d9b3a9948d5 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java @@ -27,6 +27,27 @@ public enum Bracket { ANGLE // <> } + public static class BlockCommentDelims { + private final String start; + private final String end; + public BlockCommentDelims(String start, String end) { + if (start == null || end == null + || start.isEmpty() || end.isEmpty() || start.equals(end)) { + throw new IllegalArgumentException("Bad block comment delimiter!"); + } + this.start = start; + this.end = end; + } + + public String getStart() { + return start; + } + + public String getEnd() { + return end; + } + } + private char[] quoteChars = {'\'', '"'}; private char[] escapeChars = {'\\'}; @@ -39,6 +60,10 @@ public enum Bracket { private char[] closingBrackets = null; + private String[] lineCommentDelims = null; + + private BlockCommentDelims blockCommentDelims = null; + private String regexVariable = "[a-zA-Z_]+[a-zA-Z0-9_-]*((\\.|\\['|\\[\"|\\[)[a-zA-Z0-9_-]*(|']|\"]|]))?"; private String regexCommand = "[:]?[a-zA-Z]+[a-zA-Z0-9_-]*"; private int commandGroup = 4; @@ -47,6 +72,16 @@ public enum Bracket { // Chainable setters // + public DefaultParser lineCommentDelims(final String[] lineCommentDelims) { + this.lineCommentDelims = lineCommentDelims; + return this; + } + + public DefaultParser blockCommentDelims(final BlockCommentDelims blockCommentDelims) { + this.blockCommentDelims = blockCommentDelims; + return this; + } + public DefaultParser quoteChars(final char[] chars) { this.quoteChars = chars; return this; @@ -107,6 +142,22 @@ public char[] getEscapeChars() { return this.escapeChars; } + public void setLineCommentDelims(String[] lineCommentDelims) { + this.lineCommentDelims = lineCommentDelims; + } + + public String[] getLineCommentDelims() { + return this.lineCommentDelims; + } + + public void setBlockCommentDelims(BlockCommentDelims blockCommentDelims) { + this.blockCommentDelims = blockCommentDelims; + } + + public BlockCommentDelims getBlockCommentDelims() { + return blockCommentDelims; + } + public void setEofOnUnclosedQuote(boolean eofOnUnclosedQuote) { this.eofOnUnclosedQuote = eofOnUnclosedQuote; } @@ -225,6 +276,11 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex int rawWordStart = 0; BracketChecker bracketChecker = new BracketChecker(cursor); boolean quotedWord = false; + boolean lineCommented = false; + boolean blockCommented = false; + boolean blockCommentInRightOrder = true; + final String blockCommentEnd = blockCommentDelims == null ? null : blockCommentDelims.end; + final String blockCommentStart = blockCommentDelims == null ? null : blockCommentDelims.start; for (int i = 0; (line != null) && (i < line.length()); i++) { // once we reach the cursor, set the @@ -237,7 +293,7 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex rawWordCursor = i - rawWordStart; } - if (quoteStart < 0 && isQuoteChar(line, i)) { + if (quoteStart < 0 && isQuoteChar(line, i) && !lineCommented && !blockCommented) { // Start a quote block quoteStart = i; if (current.length()==0) { @@ -258,17 +314,40 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex quoteStart = -1; quotedWord = false; } else if (quoteStart < 0 && isDelimiter(line, i)) { - // Delimiter - if (current.length() > 0) { - words.add(current.toString()); - current.setLength(0); // reset the arg - if (rawWordCursor >= 0 && rawWordLength < 0) { - rawWordLength = i - rawWordStart; + if (lineCommented) { + if (isCommentDelim(line, i, System.lineSeparator())) { + lineCommented = false; + } + } else if (blockCommented) { + if (isCommentDelim(line, i, blockCommentEnd)) { + blockCommented = false; } + } else { + // Delimiter + rawWordLength = handleDelimiterAndGetRawWordLength(current, words, rawWordStart, rawWordCursor, rawWordLength, i); + rawWordStart = i + 1; } - rawWordStart = i + 1; } else { - if (!isEscapeChar(line, i)) { + if (quoteStart < 0 && !blockCommented && (lineCommented || isLineCommentStarted(line, i))) { + lineCommented = true; + } else if (quoteStart < 0 && !lineCommented + && (blockCommented || isCommentDelim(line, i, blockCommentStart))) { + if (blockCommented) { + if (blockCommentEnd != null && isCommentDelim(line, i, blockCommentEnd)) { + blockCommented = false; + i += blockCommentEnd.length() - 1; + } + } else { + blockCommented = true; + rawWordLength = handleDelimiterAndGetRawWordLength(current, words, rawWordStart, rawWordCursor, rawWordLength, i); + i += blockCommentStart == null ? 0 : blockCommentStart.length() - 1; + rawWordStart = i + 1; + } + } else if (quoteStart < 0 && !lineCommented + && isCommentDelim(line, i, blockCommentEnd)) { + current.append(line.charAt(i)); + blockCommentInRightOrder = false; + } else if (!isEscapeChar(line, i)) { current.append(line.charAt(i)); if (quoteStart < 0) { bracketChecker.check(line, i); @@ -301,6 +380,14 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex throw new EOFError(-1, -1, "Missing closing quote", line.charAt(quoteStart) == '\'' ? "quote" : "dquote"); } + if (blockCommented) { + throw new EOFError(-1, -1, "Missing closing block comment delimiter", + "add: " + blockCommentEnd); + } + if (!blockCommentInRightOrder) { + throw new EOFError(-1, -1, "Missing opening block comment delimiter", + "missing: " + blockCommentStart); + } if (bracketChecker.isClosingBracketMissing() || bracketChecker.isOpeningBracketMissing()) { String message = null; String missing = null; @@ -333,6 +420,17 @@ public boolean isDelimiter(final CharSequence buffer, final int pos) { return !isQuoted(buffer, pos) && !isEscaped(buffer, pos) && isDelimiterChar(buffer, pos); } + private int handleDelimiterAndGetRawWordLength(StringBuilder current, List words, int rawWordStart, int rawWordCursor, int rawWordLength, int pos) { + if (current.length() > 0) { + words.add(current.toString()); + current.setLength(0); // reset the arg + if (rawWordCursor >= 0 && rawWordLength < 0) { + return pos - rawWordStart; + } + } + return rawWordLength; + } + public boolean isQuoted(final CharSequence buffer, final int pos) { return false; } @@ -351,6 +449,36 @@ public boolean isQuoteChar(final CharSequence buffer, final int pos) { return false; } + private boolean isCommentDelim(final CharSequence buffer, final int pos, final String pattern) { + if (pos < 0) { + return false; + } + + if (pattern != null) { + final int length = pattern.length(); + if (length <= buffer.length() - pos) { + for (int i = 0; i < length; i++) { + if (pattern.charAt(i) != buffer.charAt(pos + i)) { + return false; + } + } + return true; + } + } + return false; + } + + public boolean isLineCommentStarted(final CharSequence buffer, final int pos) { + if (lineCommentDelims != null) { + for (String comment: lineCommentDelims) { + if (isCommentDelim(buffer, pos, comment)) { + return true; + } + } + } + return false; + } + @Override public boolean isEscapeChar(char ch) { if (escapeChars != null) { diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java index b32dde1d902..ee8a434e1a2 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2022, the original author or authors. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -281,7 +281,7 @@ protected enum BellType { int candidateStartPosition = 0; public LineReaderImpl(Terminal terminal) throws IOException { - this(terminal, null, null); + this(terminal, terminal.getName(), null); } public LineReaderImpl(Terminal terminal, String appName) throws IOException { @@ -633,7 +633,8 @@ public String readLine(String prompt, String rightPrompt, MaskingCallback maskin callWidget(CALLBACK_INIT); - undo.newState(buf.copy()); + if (!isSet(Option.DISABLE_UNDO)) + undo.newState(buf.copy()); // Draw initial prompt redrawLine(); @@ -679,7 +680,7 @@ public String readLine(String prompt, String rightPrompt, MaskingCallback maskin if (!w.apply()) { beep(); } - if (!isUndo && copy != null && buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) + if (!isSet(Option.DISABLE_UNDO) && !isUndo && copy != null && buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) && !copy.toString().equals(buf.toString())) { undo.newState(buf.copy()); } @@ -739,8 +740,8 @@ public String readLine(String prompt, String rightPrompt, MaskingCallback maskin } } finally { lock.unlock(); + startedReading.set(false); } - startedReading.set(false); } } @@ -1082,18 +1083,18 @@ public void editAndAddInBuffer(File file) throws Exception { if (isSet(Option.BRACKETED_PASTE)) { terminal.writer().write(BRACKETED_PASTE_OFF); } - Constructor ctor = Class.forName("org.jline.builtins.Nano").getConstructor(Terminal.class, File.class); + Constructor ctor = Class.forName("jdk.internal.org.jline.builtins.Nano").getConstructor(Terminal.class, File.class); Editor editor = (Editor) ctor.newInstance(terminal, new File(file.getParent())); editor.setRestricted(true); editor.open(Collections.singletonList(file.getName())); editor.run(); - BufferedReader br = new BufferedReader(new FileReader(file)); - String line; - commandsBuffer.clear(); - while ((line = br.readLine()) != null) { - commandsBuffer.add(line); + try (BufferedReader br = new BufferedReader(new FileReader(file))) { + String line; + commandsBuffer.clear(); + while ((line = br.readLine()) != null) { + commandsBuffer.add(line); + } } - br.close(); } // @@ -3595,9 +3596,9 @@ protected boolean editAndExecute() { File file = null; try { file = File.createTempFile("jline-execute-", null); - FileWriter writer = new FileWriter(file); - writer.write(buf.toString()); - writer.close(); + try (FileWriter writer = new FileWriter(file)) { + writer.write(buf.toString()); + } editAndAddInBuffer(file); } catch (Exception e) { e.printStackTrace(terminal.writer()); @@ -3796,6 +3797,9 @@ protected void redisplay(boolean flush) { Status status = Status.getStatus(terminal, false); if (status != null) { + if (terminal.getType().startsWith(AbstractWindowsTerminal.TYPE_WINDOWS)) { + status.resize(); + } status.redraw(); } @@ -3947,7 +3951,8 @@ private String matchPreviousCommand(String buffer) { StringBuilder sb = new StringBuilder(); for (char c: buffer.replace("\\", "\\\\").toCharArray()) { if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || c == '^' || c == '*' - || c == '$' || c == '.' || c == '?' || c == '+') { + || c == '$' || c == '.' || c == '?' || c == '+' || c == '|' || c == '<' || c == '>' || c == '!' + || c == '-') { sb.append('\\'); } sb.append(c); @@ -4520,7 +4525,7 @@ else if (isSet(Option.RECOGNIZE_EXACT)) { } } - private CompletingParsedLine wrap(ParsedLine line) { + protected static CompletingParsedLine wrap(ParsedLine line) { if (line instanceof CompletingParsedLine) { return (CompletingParsedLine) line; } else { @@ -4625,6 +4630,11 @@ private int displayRows(Status status) { return size.getRows() - (status != null ? status.size() : 0); } + private int visibleDisplayRows() { + Status status = Status.getStatus(terminal, false); + return terminal.getSize().getRows() - (status != null ? status.size() : 0); + } + private int promptLines() { AttributedString text = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); return text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()).size(); @@ -5070,18 +5080,19 @@ protected PostResult computePost(List possible, Candidate selection, protected PostResult computePost(List possible, Candidate selection, List ordered, String completed, Function wcwidth, int width, boolean autoGroup, boolean groupName, boolean rowsFirst) { List strings = new ArrayList<>(); + boolean customOrder = possible.stream().anyMatch(c -> c.sort() != 0); if (groupName) { Comparator groupComparator = getGroupComparator(); - Map> sorted; + Map> sorted; sorted = groupComparator != null ? new TreeMap<>(groupComparator) : new LinkedHashMap<>(); for (Candidate cand : possible) { String group = cand.group(); sorted.computeIfAbsent(group != null ? group : "", s -> new LinkedHashMap<>()) - .put(cand.value(), cand); + .put((customOrder ? cand.sort() : cand.value()), cand); } - for (Map.Entry> entry : sorted.entrySet()) { + for (Map.Entry> entry : sorted.entrySet()) { String group = entry.getKey(); if (group.isEmpty() && sorted.size() > 1) { group = getOthersGroupName(); @@ -5096,13 +5107,13 @@ protected PostResult computePost(List possible, Candidate selection, } } else { Set groups = new LinkedHashSet<>(); - TreeMap sorted = new TreeMap<>(); + TreeMap sorted = new TreeMap<>(); for (Candidate cand : possible) { String group = cand.group(); if (group != null) { groups.add(group); } - sorted.put(cand.value(), cand); + sorted.put((customOrder ? cand.sort() : cand.value()), cand); } if (autoGroup) { strings.addAll(groups); @@ -5129,7 +5140,7 @@ public TerminalLine(String line, int startPos, int width) { this.startPos = startPos; endLine = line.substring(line.lastIndexOf('\n') + 1); boolean first = true; - while (endLine.length() + (first ? startPos : 0) > width) { + while (endLine.length() + (first ? startPos : 0) > width && width > 0) { if (first) { endLine = endLine.substring(width - startPos); } else { @@ -5207,7 +5218,7 @@ else if (item instanceof List) { AttributedStringBuilder sb = new AttributedStringBuilder(); if (listSize > 0) { if (isSet(Option.AUTO_MENU_LIST) - && listSize < Math.min(getInt(MENU_LIST_MAX, DEFAULT_MENU_LIST_MAX), displayRows() - promptLines())) { + && listSize < Math.min(getInt(MENU_LIST_MAX, DEFAULT_MENU_LIST_MAX), visibleDisplayRows() - promptLines())) { maxWidth = Math.max(maxWidth, MENU_LIST_WIDTH); sb.tabs(Math.max(Math.min(candidateStartPosition, width - maxWidth - 1), 1)); width = maxWidth + 2; diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java index 0ac3ad0b7e7..3d173f72ec7 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java @@ -41,7 +41,7 @@ * @author Marc Prud'hommeaux * @author Jason Dillon * @since 2.3 - * @deprecated use org.jline.builtins.Completers$FileNameCompleter instead + * @deprecated use jdk.internal.org.jline.builtins.Completers$FileNameCompleter instead */ @Deprecated public class FileNameCompleter implements Completer diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java index 691708e1389..a17a356bf0e 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java @@ -67,7 +67,7 @@ private String command(String cmd) { if (cmd != null) { if (completers.containsKey(cmd)) { out = cmd; - } else if (aliasCommand.containsKey(cmd)) { + } else { out = aliasCommand.get(cmd); } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java index a2a0f575136..cdd1bc520dd 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java @@ -97,14 +97,14 @@ public void load() throws IOException { } @Override - public void read(Path file, boolean incremental) throws IOException { + public void read(Path file, boolean checkDuplicates) throws IOException { Path path = file != null ? file : getPath(); if (path != null) { try { if (Files.exists(path)) { Log.trace("Reading history from: ", path); try (BufferedReader reader = Files.newBufferedReader(path)) { - reader.lines().forEach(line -> addHistoryLine(path, line, incremental)); + reader.lines().forEach(line -> addHistoryLine(path, line, checkDuplicates)); setHistoryFileData(path, new HistoryFileData(items.size(), offset + items.size())); maybeResize(); } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java index 88970b88592..8c047e37342 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2021, the original author or authors. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -16,22 +16,24 @@ import java.io.OutputStream; import java.lang.reflect.Method; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; import java.util.Optional; import java.util.ServiceLoader; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; import jdk.internal.org.jline.terminal.impl.AbstractPosixTerminal; import jdk.internal.org.jline.terminal.impl.AbstractTerminal; +import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal; import jdk.internal.org.jline.terminal.impl.DumbTerminal; -import jdk.internal.org.jline.terminal.impl.ExecPty; -import jdk.internal.org.jline.terminal.impl.ExternalTerminal; -import jdk.internal.org.jline.terminal.impl.PosixPtyTerminal; -import jdk.internal.org.jline.terminal.impl.PosixSysTerminal; -import jdk.internal.org.jline.terminal.spi.JansiSupport; -import jdk.internal.org.jline.terminal.spi.JnaSupport; -import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.Log; import jdk.internal.org.jline.utils.OSUtils; @@ -52,6 +54,11 @@ public final class TerminalBuilder { public static final String PROP_EXEC = "org.jline.terminal.exec"; public static final String PROP_DUMB = "org.jline.terminal.dumb"; public static final String PROP_DUMB_COLOR = "org.jline.terminal.dumb.color"; + public static final String PROP_OUTPUT = "org.jline.terminal.output"; + public static final String PROP_OUTPUT_OUT = "out"; + public static final String PROP_OUTPUT_ERR = "err"; + public static final String PROP_OUTPUT_OUT_ERR = "out-err"; + public static final String PROP_OUTPUT_ERR_OUT = "err-out"; // // Other system properties controlling various jline parts @@ -61,6 +68,16 @@ public final class TerminalBuilder { public static final String PROP_COLOR_DISTANCE = "org.jline.utils.colorDistance"; public static final String PROP_DISABLE_ALTERNATE_CHARSET = "org.jline.utils.disableAlternateCharset"; + // + // Terminal output control + // + public enum SystemOutput { + SysOut, + SysErr, + SysOutOrSysErr, + SysErrOrSysOut + } + /** * Returns the default system terminal. * Terminals should be closed properly using the {@link Terminal#close()} @@ -97,6 +114,7 @@ public static TerminalBuilder builder() { private Charset encoding; private int codepage; private Boolean system; + private SystemOutput systemOutput; private Boolean jna; private Boolean jansi; private Boolean exec; @@ -128,6 +146,20 @@ public TerminalBuilder system(boolean system) { return this; } + /** + * Indicates which standard stream should be used when displaying to the terminal. + * The default is to use the system output stream. + * Building a system terminal will fail if one of the stream specified is not linked + * to the controlling terminal. + * + * @param systemOutput The mode to choose the output stream. + * @return The builder. + */ + public TerminalBuilder systemOutput(SystemOutput systemOutput) { + this.systemOutput = systemOutput; + return this; + } + public TerminalBuilder jna(boolean jna) { this.jna = jna; return this; @@ -298,11 +330,18 @@ private Terminal doBuild() throws IOException { encoding = Charset.forName(charsetName); } } - int codepage = this.codepage; - if (codepage <= 0) { - String str = System.getProperty(PROP_CODEPAGE); - if (str != null) { - codepage = Integer.parseInt(str); + if (encoding == null) { + int codepage = this.codepage; + if (codepage <= 0) { + String str = System.getProperty(PROP_CODEPAGE); + if (str != null) { + codepage = Integer.parseInt(str); + } + } + if (codepage >= 0) { + encoding = getCodepageCharset(codepage); + } else { + encoding = StandardCharsets.UTF_8; } } String type = this.type; @@ -328,102 +367,112 @@ private Terminal doBuild() throws IOException { if (dumb == null) { dumb = getBoolean(PROP_DUMB, null); } + IllegalStateException exception = new IllegalStateException("Unable to create a terminal"); + List providers = new ArrayList<>(); + if (jna) { + try { + TerminalProvider provider = TerminalProvider.load("jna"); + providers.add(provider); + } catch (Throwable t) { + Log.debug("Unable to load JNA support: ", t); + exception.addSuppressed(t); + } + } + if (jansi) { + try { + TerminalProvider provider = TerminalProvider.load("jansi"); + providers.add(provider); + } catch (Throwable t) { + Log.debug("Unable to load JANSI support: ", t); + exception.addSuppressed(t); + } + } + if (exec) + { + try { + TerminalProvider provider = TerminalProvider.load("exec"); + providers.add(provider); + } catch (Throwable t) { + Log.debug("Unable to load EXEC support: ", t); + exception.addSuppressed(t); + } + } + + Terminal terminal = null; if ((system != null && system) || (system == null && in == null && out == null)) { - if (system != null && ((in != null && !in.equals(System.in)) || (out != null && !out.equals(System.out)))) { + if (system != null && ((in != null && !in.equals(System.in)) || + (out != null && !out.equals(System.out) && !out.equals(System.err)))) { throw new IllegalArgumentException("Cannot create a system terminal using non System streams"); } - Terminal terminal = null; - IllegalStateException exception = new IllegalStateException("Unable to create a system terminal"); - TerminalBuilderSupport tbs = new TerminalBuilderSupport(jna, jansi); - if (tbs.isConsoleInput() && tbs.isConsoleOutput()) { + if (attributes != null || size != null) { + Log.warn("Attributes and size fields are ignored when creating a system terminal"); + } + if (out != null) { + if (out.equals(System.out)) { + systemOutput = SystemOutput.SysOut; + } else if (out.equals(System.err)) { + systemOutput = SystemOutput.SysErr; + } + } + if (systemOutput == null) { + String str = System.getProperty(PROP_OUTPUT); + if (str != null) { + switch (str.trim().toLowerCase(Locale.ROOT)) { + case PROP_OUTPUT_OUT: systemOutput = SystemOutput.SysOut; break; + case PROP_OUTPUT_ERR: systemOutput = SystemOutput.SysErr; break; + case PROP_OUTPUT_OUT_ERR: systemOutput = SystemOutput.SysOutOrSysErr; break; + case PROP_OUTPUT_ERR_OUT: systemOutput = SystemOutput.SysErrOrSysOut; break; + default: + Log.debug("Unsupported value for " + PROP_OUTPUT + ": " + str + ". Supported values are: " + + String.join(", ", PROP_OUTPUT_OUT, PROP_OUTPUT_ERR, PROP_OUTPUT_OUT_ERR,PROP_OUTPUT_ERR_OUT) + + "."); + } + } + } + if (systemOutput == null) { + systemOutput = SystemOutput.SysOutOrSysErr; + } + Map system = Stream.of(TerminalProvider.Stream.values()) + .collect(Collectors.toMap(stream -> stream, stream -> providers.stream().anyMatch(p -> p.isSystemStream(stream)))); + TerminalProvider.Stream console = select(system, systemOutput); + + if (system.get(TerminalProvider.Stream.Input) && console != null) { if (attributes != null || size != null) { Log.warn("Attributes and size fields are ignored when creating a system terminal"); } - if (OSUtils.IS_WINDOWS) { - if (!OSUtils.IS_CYGWIN && !OSUtils.IS_MSYSTEM) { - boolean ansiPassThrough = OSUtils.IS_CONEMU; - if (tbs.hasJnaSupport()) { - try { - terminal = tbs.getJnaSupport().winSysTerminal(name, type, ansiPassThrough, encoding, codepage - , nativeSignals, signalHandler, paused, inputStreamWrapper); - } catch (Throwable t) { - Log.debug("Error creating JNA based terminal: ", t.getMessage(), t); - exception.addSuppressed(t); - } - } - if (terminal == null && tbs.hasJansiSupport()) { - try { - terminal = tbs.getJansiSupport().winSysTerminal(name, type, ansiPassThrough, encoding, codepage - , nativeSignals, signalHandler, paused); - } catch (Throwable t) { - Log.debug("Error creating JANSI based terminal: ", t.getMessage(), t); - exception.addSuppressed(t); - } - } - } else if (exec) { - // - // Cygwin support - // - try { - // Cygwin defaults to XTERM, but actually supports 256 colors, - // so if the value comes from the environment, change it to xterm-256color - if ("xterm".equals(type) && this.type == null && System.getProperty(PROP_TYPE) == null) { - type = "xterm-256color"; - } - Pty pty = tbs.getExecPty(); - terminal = new PosixSysTerminal(name, type, pty, inputStreamWrapper.apply(pty.getSlaveInput()), pty.getSlaveOutput(), encoding, nativeSignals, signalHandler); - } catch (IOException e) { - // Ignore if not a tty - Log.debug("Error creating EXEC based terminal: ", e.getMessage(), e); - exception.addSuppressed(e); - } - } - if (terminal == null && !jna && !jansi && (dumb == null || !dumb)) { - throw new IllegalStateException("Unable to create a system terminal. On windows, either " - + "JNA or JANSI library is required. Make sure to add one of those in the classpath."); - } - } else { - if (tbs.hasJnaSupport()) { - try { - Pty pty = tbs.getJnaSupport().current(); - terminal = new PosixSysTerminal(name, type, pty, inputStreamWrapper.apply(pty.getSlaveInput()), pty.getSlaveOutput(), encoding, nativeSignals, signalHandler); - } catch (Throwable t) { - // ignore - Log.debug("Error creating JNA based terminal: ", t.getMessage(), t); - exception.addSuppressed(t); - } - } - if (terminal == null && tbs.hasJansiSupport()) { - try { - Pty pty = tbs.getJansiSupport().current(); - terminal = new PosixSysTerminal(name, type, pty, inputStreamWrapper.apply(pty.getSlaveInput()), pty.getSlaveOutput(), encoding, nativeSignals, signalHandler); - } catch (Throwable t) { - Log.debug("Error creating JANSI based terminal: ", t.getMessage(), t); - exception.addSuppressed(t); - } - } - if (terminal == null && exec) { + boolean ansiPassThrough = OSUtils.IS_CONEMU; + // Cygwin defaults to XTERM, but actually supports 256 colors, + // so if the value comes from the environment, change it to xterm-256color + if ((OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) && "xterm".equals(type) + && this.type == null && System.getProperty(PROP_TYPE) == null) { + type = "xterm-256color"; + } + for ( TerminalProvider provider : providers) { + if (terminal == null) { try { - Pty pty = tbs.getExecPty(); - terminal = new PosixSysTerminal(name, type, pty, inputStreamWrapper.apply(pty.getSlaveInput()), pty.getSlaveOutput(), encoding, nativeSignals, signalHandler); + terminal = provider.sysTerminal(name, type, ansiPassThrough, encoding, + nativeSignals, signalHandler, paused, console, inputStreamWrapper); } catch (Throwable t) { - // Ignore if not a tty - Log.debug("Error creating EXEC based terminal: ", t.getMessage(), t); + Log.debug("Error creating " + provider.name() + " based terminal: ", t.getMessage(), t); exception.addSuppressed(t); } } } - if (terminal instanceof AbstractTerminal) { - AbstractTerminal t = (AbstractTerminal) terminal; - if (SYSTEM_TERMINAL.compareAndSet(null, t)) { - t.setOnClose(() -> SYSTEM_TERMINAL.compareAndSet(t, null)); - } else { - exception.addSuppressed(new IllegalStateException("A system terminal is already running. " + - "Make sure to use the created system Terminal on the LineReaderBuilder if you're using one " + - "or that previously created system Terminals have been correctly closed.")); - terminal.close(); - terminal = null; - } + if (terminal == null && OSUtils.IS_WINDOWS && !jna && !jansi && (dumb == null || !dumb)) { + throw new IllegalStateException("Unable to create a system terminal. On windows, either " + + "JNA or JANSI library is required. Make sure to add one of those in the classpath."); + } + } + if (terminal instanceof AbstractTerminal) { + AbstractTerminal t = (AbstractTerminal) terminal; + if (SYSTEM_TERMINAL.compareAndSet(null, t)) { + t.setOnClose(() -> SYSTEM_TERMINAL.compareAndSet(t, null)); + } else { + exception.addSuppressed(new IllegalStateException("A system terminal is already running. " + + "Make sure to use the created system Terminal on the LineReaderBuilder if you're using one " + + "or that previously created system Terminals have been correctly closed.")); + terminal.close(); + terminal = null; } } if (terminal == null && (dumb == null || dumb)) { @@ -433,7 +482,8 @@ private Terminal doBuild() throws IOException { color = getBoolean(PROP_DUMB_COLOR, false); // detect emacs using the env variable if (!color) { - color = System.getenv("INSIDE_EMACS") != null; + String emacs = System.getenv("INSIDE_EMACS"); + color = emacs != null && emacs.contains("comint"); } // detect Intellij Idea if (!color) { @@ -441,12 +491,13 @@ private Terminal doBuild() throws IOException { color = command != null && command.contains("idea"); } if (!color) { - color = tbs.isConsoleOutput() && System.getenv("TERM") != null; + color = system.get(TerminalProvider.Stream.Output) && System.getenv("TERM") != null; } if (!color && dumb == null) { if (Log.isDebugEnabled()) { - Log.warn("input is tty: {}", tbs.isConsoleInput()); - Log.warn("output is tty: {}", tbs.isConsoleOutput()); + Log.warn("input is tty: {}", system.get(TerminalProvider.Stream.Input)); + Log.warn("output is tty: {}", system.get(TerminalProvider.Stream.Output)); + Log.warn("error is tty: {}", system.get(TerminalProvider.Stream.Error)); Log.warn("Creating a dumb terminal", exception); } else { Log.warn("Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)"); @@ -454,33 +505,49 @@ private Terminal doBuild() throws IOException { } } terminal = new DumbTerminal(name, color ? Terminal.TYPE_DUMB_COLOR : Terminal.TYPE_DUMB, - inputStreamWrapper.apply(new FileInputStream(FileDescriptor.in)), - new FileOutputStream(FileDescriptor.out), + new FileInputStream(FileDescriptor.in), + new FileOutputStream(console == TerminalProvider.Stream.Output ? FileDescriptor.out : FileDescriptor.err), encoding, signalHandler); } - if (terminal == null) { - throw exception; - } - return terminal; } else { - if (jna) { - try { - Pty pty = load(JnaSupport.class).open(attributes, size); - return new PosixPtyTerminal(name, type, pty, inputStreamWrapper.apply(in), out, encoding, signalHandler, paused); - } catch (Throwable t) { - Log.debug("Error creating JNA based terminal: ", t.getMessage(), t); + for ( TerminalProvider provider : providers) { + if (terminal == null) { + try { + terminal = provider.newTerminal(name, type, inputStreamWrapper.apply(in), out, encoding, signalHandler, paused, attributes, size); + } catch (Throwable t) { + Log.debug("Error creating " + provider.name() + " based terminal: ", t.getMessage(), t); + exception.addSuppressed(t); + } } } - if (jansi) { - try { - Pty pty = load(JansiSupport.class).open(attributes, size); - return new PosixPtyTerminal(name, type, pty, inputStreamWrapper.apply(in), out, encoding, signalHandler, paused); - } catch (Throwable t) { - Log.debug("Error creating JANSI based terminal: ", t.getMessage(), t); - } + } + if (terminal == null) { + throw exception; + } + return terminal; + } + + private TerminalProvider.Stream select(Map system, SystemOutput systemOutput) { + switch (systemOutput) { + case SysOut: + return select(system, TerminalProvider.Stream.Output); + case SysErr: + return select(system, TerminalProvider.Stream.Error); + case SysOutOrSysErr: + return select(system, TerminalProvider.Stream.Output, TerminalProvider.Stream.Error); + case SysErrOrSysOut: + return select(system, TerminalProvider.Stream.Error, TerminalProvider.Stream.Output); + } + return null; + } + + private static TerminalProvider.Stream select(Map system, TerminalProvider.Stream... streams) { + for (TerminalProvider.Stream s : streams) { + if (system.get(s)) { + return s; } - return new ExternalTerminal(name, type, inputStreamWrapper.apply(in), out, encoding, signalHandler, paused, attributes, size); } + return null; } private static String getParentProcessCommand() { @@ -512,6 +579,24 @@ private static S load(Class clazz) { return ServiceLoader.load(clazz, clazz.getClassLoader()).iterator().next(); } + private static final int UTF8_CODE_PAGE = 65001; + + private static Charset getCodepageCharset(int codepage) { + //http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html + if (codepage == UTF8_CODE_PAGE) { + return StandardCharsets.UTF_8; + } + String charsetMS = "ms" + codepage; + if (Charset.isSupported(charsetMS)) { + return Charset.forName(charsetMS); + } + String charsetCP = "cp" + codepage; + if (Charset.isSupported(charsetCP)) { + return Charset.forName(charsetCP); + } + return Charset.defaultCharset(); + } + /** * Allows an application to override the result of {@link #build()}. The * intended use case is to allow a container or server application to control @@ -545,79 +630,4 @@ public static void setTerminalOverride(final Terminal terminal) { TERMINAL_OVERRIDE.set(terminal); } - private static class TerminalBuilderSupport { - private JansiSupport jansiSupport = null; - private JnaSupport jnaSupport = null; - private Pty pty = null; - private boolean consoleOutput; - - TerminalBuilderSupport(boolean jna, boolean jansi) { - if (jna) { - try { - jnaSupport = load(JnaSupport.class); - consoleOutput = jnaSupport.isConsoleOutput(); - } catch (Throwable e) { - jnaSupport = null; - Log.debug("jnaSupport.isConsoleOutput(): ", e); - } - } - if (jansi) { - try { - jansiSupport = load(JansiSupport.class); - consoleOutput = jansiSupport.isConsoleOutput(); - } catch (Throwable e) { - jansiSupport = null; - Log.debug("jansiSupport.isConsoleOutput(): ", e); - } - } - if (jnaSupport == null && jansiSupport == null) { - try { - pty = ExecPty.current(); - consoleOutput = true; - } catch (Exception e) { - Log.debug("ExecPty.current(): ", e); - } - } - } - - public boolean isConsoleOutput() { - return consoleOutput; - } - - public boolean isConsoleInput() { - if (pty != null) { - return true; - } else if (hasJnaSupport()) { - return jnaSupport.isConsoleInput(); - } else if (hasJansiSupport()) { - return jansiSupport.isConsoleInput(); - } else { - return false; - } - } - - public boolean hasJnaSupport() { - return jnaSupport != null; - } - - public boolean hasJansiSupport() { - return jansiSupport != null; - } - - public JnaSupport getJnaSupport() { - return jnaSupport; - } - - public JansiSupport getJansiSupport() { - return jansiSupport; - } - - public Pty getExecPty() throws IOException { - if (pty == null) { - pty = ExecPty.current(); - } - return pty; - } - - } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java index 9ed353f46d0..0feab84fc7e 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java @@ -86,11 +86,6 @@ public int read(long timeout, boolean isPeek) throws IOException { } } - @Override - public int readBuffered(byte[] b) throws IOException { - return in.read(b); - } - private void setNonBlocking() { if (current == null || current.getControlChar(Attributes.ControlChar.VMIN) != 0 diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java index 5e21f034530..57cfb5d50b4 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java @@ -81,8 +81,8 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { protected boolean focusTracking = false; private volatile boolean closing; - public AbstractWindowsTerminal(Writer writer, String name, String type, Charset encoding, int codepage, boolean nativeSignals, SignalHandler signalHandler, Function inputStreamWrapper) throws IOException { - super(name, type, selectCharset(encoding, codepage), signalHandler); + public AbstractWindowsTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler, Function inputStreamWrapper) throws IOException { + super(name, type, encoding, signalHandler); NonBlockingPumpReader reader = NonBlocking.nonBlockingPumpReader(); this.slaveInputPipe = reader.getWriter(); this.input = inputStreamWrapper.apply(NonBlocking.nonBlockingStream(reader, encoding())); @@ -116,35 +116,6 @@ public AbstractWindowsTerminal(Writer writer, String name, String type, Charset } } - private static Charset selectCharset(Charset encoding, int codepage) { - if (encoding != null) { - return encoding; - } - - if (codepage >= 0) { - return getCodepageCharset(codepage); - } - - // Use UTF-8 as default - return StandardCharsets.UTF_8; - } - - private static Charset getCodepageCharset(int codepage) { - //http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html - if (codepage == UTF8_CODE_PAGE) { - return StandardCharsets.UTF_8; - } - String charsetMS = "ms" + codepage; - if (Charset.isSupported(charsetMS)) { - return Charset.forName(charsetMS); - } - String charsetCP = "cp" + codepage; - if (Charset.isSupported(charsetCP)) { - return Charset.forName(charsetCP); - } - return Charset.defaultCharset(); - } - @Override public SignalHandler handle(Signal signal, SignalHandler handler) { SignalHandler prev = super.handle(signal, handler); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java new file mode 100644 index 00000000000..dfa784c29f3 --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2022, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.impl; + +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; +import java.util.ServiceLoader; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.TimeUnit; + +import jdk.internal.org.jline.terminal.Attributes; +import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; +import jdk.internal.org.jline.utils.OSUtils; + +public class Diag { + + public static void main(String[] args) { + diag(System.out); + } + + static void diag(PrintStream out) { + out.println("System properties"); + out.println("================="); + out.println("os.name = " + System.getProperty("os.name")); + out.println("OSTYPE = " + System.getenv("OSTYPE")); + out.println("MSYSTEM = " + System.getenv("MSYSTEM")); + out.println("PWD = " + System.getenv("PWD")); + out.println("ConEmuPID = " + System.getenv("ConEmuPID")); + out.println("WSL_DISTRO_NAME = " + System.getenv("WSL_DISTRO_NAME")); + out.println("WSL_INTEROP = " + System.getenv("WSL_INTEROP")); + out.println(); + + out.println("OSUtils"); + out.println("================="); + out.println("IS_WINDOWS = " + OSUtils.IS_WINDOWS); + out.println("IS_CYGWIN = " + OSUtils.IS_CYGWIN); + out.println("IS_MSYSTEM = " + OSUtils.IS_MSYSTEM); + out.println("IS_WSL = " + OSUtils.IS_WSL); + out.println("IS_WSL1 = " + OSUtils.IS_WSL1); + out.println("IS_WSL2 = " + OSUtils.IS_WSL2); + out.println("IS_CONEMU = " + OSUtils.IS_CONEMU); + out.println("IS_OSX = " + OSUtils.IS_OSX); + out.println(); + + out.println("JnaSupport"); + out.println("================="); + try { + TerminalProvider provider = TerminalProvider.load("jna"); + testProvider(out, provider); + } catch (Throwable t) { + out.println("JNA support not available: " + t); + } + out.println(); + + out.println("JansiSupport"); + out.println("================="); + try { + TerminalProvider provider = TerminalProvider.load("jansi"); + testProvider(out, provider); + } catch (Throwable t) { + out.println("Jansi support not available: " + t); + } + out.println(); + + // Exec + out.println("Exec Support"); + out.println("================="); + try { + TerminalProvider provider = TerminalProvider.load("exec"); + testProvider(out, provider); + } catch (Throwable t) { + out.println("Exec support not available: " + t); + } + } + + private static void testProvider(PrintStream out, TerminalProvider provider) { + try { + out.println("StdIn stream = " + provider.isSystemStream(TerminalProvider.Stream.Input)); + out.println("StdOut stream = " + provider.isSystemStream(TerminalProvider.Stream.Output)); + out.println("StdErr stream = " + provider.isSystemStream(TerminalProvider.Stream.Error)); + } catch (Throwable t2) { + out.println("Unable to check stream: " + t2); + } + try { + out.println("StdIn stream name = " + provider.systemStreamName(TerminalProvider.Stream.Input)); + out.println("StdOut stream name = " + provider.systemStreamName(TerminalProvider.Stream.Output)); + out.println("StdErr stream name = " + provider.systemStreamName(TerminalProvider.Stream.Error)); + } catch (Throwable t2) { + out.println("Unable to check stream names: " + t2); + } + try (Terminal terminal = provider.sysTerminal("diag", "xterm", false, StandardCharsets.UTF_8, + false, Terminal.SignalHandler.SIG_DFL, false, TerminalProvider.Stream.Output, input -> input) ) { + if (terminal != null) { + Attributes attr = terminal.enterRawMode(); + try { + out.println("Terminal size: " + terminal.getSize()); + ForkJoinTask t = new ForkJoinPool(1).submit(() -> terminal.reader().read(1) ); + int r = t.get(1000, TimeUnit.MILLISECONDS); + StringBuilder sb = new StringBuilder(); + sb.append("The terminal seems to work: "); + sb.append("terminal ").append(terminal.getClass().getName()); + if (terminal instanceof AbstractPosixTerminal) { + sb.append(" with pty ").append(((AbstractPosixTerminal) terminal).getPty().getClass().getName()); + } + out.println(sb); + } catch (Throwable t3) { + out.println("Unable to read from terminal: " + t3); + t3.printStackTrace(); + } finally { + terminal.setAttributes(attr); + } + } else { + out.println("Not supported by provider"); + } + } catch (Throwable t2) { + out.println("Unable to open terminal: " + t2); + t2.printStackTrace(); + } + } + + static S load(Class clazz) { + return ServiceLoader.load(clazz, clazz.getClassLoader()).iterator().next(); + } + +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java index a40484939dd..5377b4acdb8 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java @@ -26,6 +26,7 @@ import jdk.internal.org.jline.terminal.Attributes.LocalFlag; import jdk.internal.org.jline.terminal.Attributes.OutputFlag; import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.terminal.spi.Pty; import jdk.internal.org.jline.utils.OSUtils; @@ -34,20 +35,23 @@ public class ExecPty extends AbstractPty implements Pty { private final String name; - private final boolean system; + private final TerminalProvider.Stream console; - public static Pty current() throws IOException { + public static Pty current(TerminalProvider.Stream console) throws IOException { try { String result = exec(true, OSUtils.TTY_COMMAND); - return new ExecPty(result.trim(), true); + if (console != TerminalProvider.Stream.Output && console != TerminalProvider.Stream.Error) { + throw new IllegalArgumentException("console should be Output or Error: " + console); + } + return new ExecPty(result.trim(), console); } catch (IOException e) { throw new IOException("Not a tty", e); } } - protected ExecPty(String name, boolean system) { + protected ExecPty(String name, TerminalProvider.Stream console) { this.name = name; - this.system = system; + this.console = console; } @Override @@ -70,16 +74,18 @@ public OutputStream getMasterOutput() { @Override protected InputStream doGetSlaveInput() throws IOException { - return system + return console != null ? new FileInputStream(FileDescriptor.in) : new FileInputStream(getName()); } @Override public OutputStream getSlaveOutput() throws IOException { - return system + return console == TerminalProvider.Stream.Output ? new FileOutputStream(FileDescriptor.out) - : new FileOutputStream(getName()); + : console == TerminalProvider.Stream.Error + ? new FileOutputStream(FileDescriptor.err) + : new FileOutputStream(getName()); } @Override @@ -93,23 +99,11 @@ protected void doSetAttr(Attributes attr) throws IOException { List commands = getFlagsToSet(attr, getAttr()); if (!commands.isEmpty()) { commands.add(0, OSUtils.STTY_COMMAND); - if (!system) { + if (console == null) { commands.add(1, OSUtils.STTY_F_OPTION); commands.add(2, getName()); } - try { - exec(system, commands.toArray(new String[commands.size()])); - } catch (IOException e) { - // Handle partial failures with GNU stty, see #97 - if (e.toString().contains("unable to perform all requested operations")) { - commands = getFlagsToSet(attr, getAttr()); - if (!commands.isEmpty()) { - throw new IOException("Could not set the following flags: " + String.join(", ", commands), e); - } - } else { - throw e; - } - } + exec(console != null, commands.toArray(new String[0])); } } @@ -171,7 +165,7 @@ public Size getSize() throws IOException { } protected String doGetConfig() throws IOException { - return system + return console != null ? exec(true, OSUtils.STTY_COMMAND, "-a") : exec(false, OSUtils.STTY_COMMAND, OSUtils.STTY_F_OPTION, getName(), "-a"); } @@ -280,7 +274,7 @@ static int doGetInt(String name, String cfg) throws IOException { @Override public void setSize(Size size) throws IOException { - if (system) { + if (console != null) { exec(true, OSUtils.STTY_COMMAND, "columns", Integer.toString(size.getColumns()), @@ -296,7 +290,7 @@ OSUtils.STTY_F_OPTION, getName(), @Override public String toString() { - return "ExecPty[" + getName() + (system ? ", system]" : "]"); + return "ExecPty[" + getName() + (console != null ? ", system]" : "]"); } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java index 0dfcedf2700..f85e3fe0b0c 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java @@ -15,7 +15,6 @@ import java.io.PrintWriter; import java.nio.charset.Charset; import java.util.Objects; -import java.util.concurrent.atomic.AtomicBoolean; import jdk.internal.org.jline.terminal.spi.Pty; import jdk.internal.org.jline.utils.ClosedException; @@ -143,10 +142,10 @@ public boolean paused() { } } - private class InputStreamWrapper extends NonBlockingInputStream { + private static class InputStreamWrapper extends NonBlockingInputStream { private final NonBlockingInputStream in; - private final AtomicBoolean closed = new AtomicBoolean(); + private volatile boolean closed; protected InputStreamWrapper(NonBlockingInputStream in) { this.in = in; @@ -154,7 +153,7 @@ protected InputStreamWrapper(NonBlockingInputStream in) { @Override public int read(long timeout, boolean isPeek) throws IOException { - if (closed.get()) { + if (closed) { throw new ClosedException(); } return in.read(timeout, isPeek); @@ -162,7 +161,7 @@ public int read(long timeout, boolean isPeek) throws IOException { @Override public void close() throws IOException { - closed.set(true); + closed = true; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java index 2909032d59a..a55f3d4a748 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java @@ -16,6 +16,7 @@ import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; +import java.util.function.Function; import jdk.internal.org.jline.utils.NonBlocking; import jdk.internal.org.jline.terminal.spi.Pty; @@ -34,11 +35,12 @@ public class PosixSysTerminal extends AbstractPosixTerminal { protected final Map nativeHandlers = new HashMap<>(); protected final Task closer; - public PosixSysTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding, - boolean nativeSignals, SignalHandler signalHandler) throws IOException { + public PosixSysTerminal(String name, String type, Pty pty, Charset encoding, + boolean nativeSignals, SignalHandler signalHandler, + Function inputStreamWrapper) throws IOException { super(name, type, pty, encoding, signalHandler); - this.input = NonBlocking.nonBlocking(getName(), in); - this.output = out; + this.input = NonBlocking.nonBlocking(getName(), inputStreamWrapper.apply(pty.getSlaveInput())); + this.output = pty.getSlaveOutput(); this.reader = NonBlocking.nonBlocking(getName(), input, encoding()); this.writer = new PrintWriter(new OutputStreamWriter(output, encoding())); parseInfoCmp(); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java new file mode 100644 index 00000000000..8bdeede2e1b --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2022, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.impl.exec; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.nio.charset.Charset; +import java.util.function.Function; + +import jdk.internal.org.jline.terminal.Attributes; +import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.terminal.impl.ExecPty; +import jdk.internal.org.jline.terminal.impl.ExternalTerminal; +import jdk.internal.org.jline.terminal.impl.PosixSysTerminal; +import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; +import jdk.internal.org.jline.utils.ExecHelper; +import jdk.internal.org.jline.utils.OSUtils; + +public class ExecTerminalProvider implements TerminalProvider +{ + + public String name() { + return "exec"; + } + + public Pty current(Stream consoleStream) throws IOException { + return ExecPty.current(consoleStream); + } + + @Override + public Terminal sysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, + boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, + Stream consoleStream, Function inputStreamWrapper) throws IOException { + if (OSUtils.IS_WINDOWS) { + return winSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper ); + } else { + return posixSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper ); + } + } + + public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, + boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, + Stream consoleStream, Function inputStreamWrapper ) throws IOException { + if (OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) { + Pty pty = current(consoleStream); + return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper); + } else { + return null; + } + } + + public Terminal posixSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, + boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, + Stream consoleStream, Function inputStreamWrapper) throws IOException { + Pty pty = current(consoleStream); + return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper); + } + + @Override + public Terminal newTerminal(String name, String type, InputStream in, OutputStream out, + Charset encoding, Terminal.SignalHandler signalHandler, boolean paused, + Attributes attributes, Size size) throws IOException + { + return new ExternalTerminal(name, type, in, out, encoding, signalHandler, paused, attributes, size); + } + + @Override + public boolean isSystemStream(Stream stream) { + try { + return isWindowsSystemStream(stream) || isPosixSystemStream(stream); + } catch (Throwable t) { + return false; + } + } + + public boolean isWindowsSystemStream(Stream stream) { + return systemStreamName( stream ) != null; + } + + public boolean isPosixSystemStream(Stream stream) { + try { + Process p = new ProcessBuilder(OSUtils.TEST_COMMAND, "-t", Integer.toString(stream.ordinal())) + .inheritIO().start(); + return p.waitFor() == 0; + } catch (Throwable t) { + // ignore + } + return false; + } + + @Override + public String systemStreamName(Stream stream) { + try { + ProcessBuilder.Redirect input = stream == Stream.Input + ? ProcessBuilder.Redirect.INHERIT + : getRedirect(stream == Stream.Output ? FileDescriptor.out : FileDescriptor.err); + Process p = new ProcessBuilder(OSUtils.TTY_COMMAND).redirectInput(input).start(); + String result = ExecHelper.waitAndCapture(p); + if (p.exitValue() == 0) { + return result.trim(); + } + } catch (Throwable t) { + // ignore + } + return null; + } + + private ProcessBuilder.Redirect getRedirect(FileDescriptor fd) throws ReflectiveOperationException { + // This is not really allowed, but this is the only way to redirect the output or error stream + // to the input. This is definitely not something you'd usually want to do, but in the case of + // the `tty` utility, it provides a way to get + Class rpi = Class.forName("java.lang.ProcessBuilder$RedirectPipeImpl"); + Constructor cns = rpi.getDeclaredConstructor(); + cns.setAccessible(true); + ProcessBuilder.Redirect input = (ProcessBuilder.Redirect) cns.newInstance(); + Field f = rpi.getDeclaredField("fd"); + f.setAccessible(true); + f.set(input, fd); + return input; + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/JansiSupport.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/JansiSupport.java deleted file mode 100644 index 750c8fc0712..00000000000 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/JansiSupport.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2002-2020, the original author or authors. - * - * This software is distributable under the BSD license. See the terms of the - * BSD license in the documentation provided with this software. - * - * https://opensource.org/licenses/BSD-3-Clause - */ -package jdk.internal.org.jline.terminal.spi; - -import jdk.internal.org.jline.terminal.Attributes; -import jdk.internal.org.jline.terminal.Size; -import jdk.internal.org.jline.terminal.Terminal; - -import java.io.IOException; -import java.nio.charset.Charset; - -public interface JansiSupport { - - Pty current() throws IOException; - - Pty open(Attributes attributes, Size size) throws IOException; - - Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler) throws IOException; - - Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused) throws IOException; - - boolean isWindowsConsole(); - - boolean isConsoleOutput(); - - boolean isConsoleInput(); -} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/JnaSupport.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/JnaSupport.java deleted file mode 100644 index 35f71a603f8..00000000000 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/JnaSupport.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2002-2020, the original author or authors. - * - * This software is distributable under the BSD license. See the terms of the - * BSD license in the documentation provided with this software. - * - * https://opensource.org/licenses/BSD-3-Clause - */ -package jdk.internal.org.jline.terminal.spi; - -import jdk.internal.org.jline.terminal.Attributes; -import jdk.internal.org.jline.terminal.Size; -import jdk.internal.org.jline.terminal.Terminal; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.util.function.Function; - -public interface JnaSupport { - - Pty current() throws IOException; - - Pty open(Attributes attributes, Size size) throws IOException; - - Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler) throws IOException; - - Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused) throws IOException; - - Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, Function inputStreamWrapper) throws IOException; - - boolean isWindowsConsole(); - - boolean isConsoleOutput(); - - boolean isConsoleInput(); -} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java new file mode 100644 index 00000000000..69f353c5719 --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2022, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.spi; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.Properties; +import java.util.ServiceLoader; +import java.util.function.Function; + +import jdk.internal.org.jline.terminal.Attributes; +import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.terminal.impl.exec.ExecTerminalProvider; + +public interface TerminalProvider +{ + + enum Stream { + Input, + Output, + Error + } + + String name(); + + Terminal sysTerminal(String name, String type, boolean ansiPassThrough, + Charset encoding, boolean nativeSignals, + Terminal.SignalHandler signalHandler, boolean paused, + Stream consoleStream, Function inputStreamWrapper) throws IOException; + + Terminal newTerminal(String name, String type, + InputStream masterInput, OutputStream masterOutput, + Charset encoding, Terminal.SignalHandler signalHandler, + boolean paused, Attributes attributes, Size size) throws IOException; + + boolean isSystemStream(Stream stream); + + String systemStreamName(Stream stream); + + static TerminalProvider load(String name) throws IOException { + switch (name) { + case "exec": return new ExecTerminalProvider(); + case "jna": { + try { + return (TerminalProvider) Class.forName("jdk.internal.org.jline.terminal.impl.jna.JnaTerminalProvider").getConstructor().newInstance(); + } catch (ReflectiveOperationException t) { + throw new IOException(t); + } + } + } + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + if (cl == null) { + cl = ClassLoader.getSystemClassLoader(); + } + InputStream is = cl.getResourceAsStream( "META-INF/services/org/jline/terminal/provider/" + name); + if (is != null) { + Properties props = new Properties(); + try { + props.load(is); + String className = props.getProperty("class"); + if (className == null) { + throw new IOException("No class defined in terminal provider file " + name); + } + Class clazz = cl.loadClass( className ); + return (TerminalProvider) clazz.getConstructor().newInstance(); + } catch ( Exception e ) { + throw new IOException("Unable to load terminal provider " + name, e); + } + } else { + throw new IOException("Unable to find terminal provider " + name); + } + } + +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java index 19550366944..dc452e10364 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java @@ -534,7 +534,7 @@ private static double calculateH(double h) { H = 0; return H; } else { - throw new IllegalArgumentException("h outside assumed range 0..360: " + Double.toString(h)); + throw new IllegalArgumentException("h outside assumed range 0..360: " + h); } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java index 4589c6b79bd..bdfd4c37bc2 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java @@ -12,7 +12,7 @@ import java.io.IOError; import java.io.IOException; import java.io.StringWriter; -import java.util.Stack; +import java.util.ArrayDeque; /** * Curses helper methods. @@ -21,8 +21,8 @@ */ public final class Curses { - private static Object[] sv = new Object[26]; - private static Object[] dv = new Object[26]; + private static final Object[] sv = new Object[26]; + private static final Object[] dv = new Object[26]; private static final int IFTE_NONE = 0; private static final int IFTE_IF = 1; @@ -68,7 +68,7 @@ private static void doTputs(Appendable out, String str, Object... params) throws int length = str.length(); int ifte = IFTE_NONE; boolean exec = true; - Stack stack = new Stack<>(); + ArrayDeque stack = new ArrayDeque<>(); while (index < length) { char ch = str.charAt(index++); switch (ch) { @@ -197,7 +197,7 @@ private static void doTputs(Appendable out, String str, Object... params) throws int start = index; while (str.charAt(index++) != '}') ; if (exec) { - int v = Integer.valueOf(str.substring(start, index - 1)); + int v = Integer.parseInt(str.substring(start, index - 1)); stack.push(v); } break; @@ -470,7 +470,7 @@ private static int toInteger(Object pop) { } else if (pop instanceof Boolean) { return (Boolean) pop ? 1 : 0; } else { - return Integer.valueOf(pop.toString()); + return Integer.parseInt(pop.toString()); } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java index 61e0736b5b4..aaeab9b71ff 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java @@ -187,7 +187,7 @@ public void update(List newLines, int targetCursorPos, boolean int lineIndex = 0; int currentPos = 0; - int numLines = Math.max(oldLines.size(), newLines.size()); + int numLines = Math.min(rows, Math.max(oldLines.size(), newLines.size())); boolean wrapNeeded = false; while (lineIndex < numLines) { AttributedString oldLine = diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java index 68f77f638b7..23a76071486 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java @@ -503,7 +503,7 @@ public enum Capability { public String[] getNames() { return getCapabilitiesByName().entrySet().stream() .filter(e -> e.getValue() == this) - .map(Map.Entry::getValue) + .map(Map.Entry::getKey) .toArray(String[]::new); } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java index 6d37a20083e..f8cb53489f9 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java @@ -95,13 +95,9 @@ public void close() throws IOException { @Override public int read(long timeout, boolean isPeek) throws IOException { - boolean isInfinite = (timeout <= 0L); - while (!bytes.hasRemaining() && (isInfinite || timeout > 0L)) { - long start = 0; - if (!isInfinite) { - start = System.currentTimeMillis(); - } - int c = reader.read(timeout); + Timeout t = new Timeout(timeout); + while (!bytes.hasRemaining() && !t.elapsed()) { + int c = reader.read(t.timeout()); if (c == EOF) { return EOF; } @@ -117,9 +113,6 @@ public int read(long timeout, boolean isPeek) throws IOException { encoder.encode(chars, bytes, false); bytes.flip(); } - if (!isInfinite) { - timeout -= System.currentTimeMillis() - start; - } } if (bytes.hasRemaining()) { if (isPeek) { @@ -151,21 +144,17 @@ public NonBlockingInputStreamReader(NonBlockingInputStream inputStream, Charset public NonBlockingInputStreamReader(NonBlockingInputStream input, CharsetDecoder decoder) { this.input = input; this.decoder = decoder; - this.bytes = ByteBuffer.allocate(4); - this.chars = CharBuffer.allocate(2); + this.bytes = ByteBuffer.allocate(2048); + this.chars = CharBuffer.allocate(1024); this.bytes.limit(0); this.chars.limit(0); } @Override protected int read(long timeout, boolean isPeek) throws IOException { - boolean isInfinite = (timeout <= 0L); - while (!chars.hasRemaining() && (isInfinite || timeout > 0L)) { - long start = 0; - if (!isInfinite) { - start = System.currentTimeMillis(); - } - int b = input.read(timeout); + Timeout t = new Timeout(timeout); + while (!chars.hasRemaining() && !t.elapsed()) { + int b = input.read(t.timeout()); if (b == EOF) { return EOF; } @@ -181,10 +170,6 @@ protected int read(long timeout, boolean isPeek) throws IOException { decoder.decode(bytes, chars, false); chars.flip(); } - - if (!isInfinite) { - timeout -= System.currentTimeMillis() - start; - } } if (chars.hasRemaining()) { if (isPeek) { @@ -198,46 +183,37 @@ protected int read(long timeout, boolean isPeek) throws IOException { } @Override - public int readBuffered(char[] b) throws IOException { + public int readBuffered(char[] b, int off, int len, long timeout) throws IOException { if (b == null) { throw new NullPointerException(); - } else if (b.length == 0) { + } else if (off < 0 || len < 0 || off + len < b.length) { + throw new IllegalArgumentException(); + } else if (len == 0) { return 0; + } else if (chars.hasRemaining()) { + int r = Math.min(len, chars.remaining()); + chars.get(b, off, r); + return r; } else { - if (chars.hasRemaining()) { - int r = Math.min(b.length, chars.remaining()); - chars.get(b); - return r; - } else { - byte[] buf = new byte[b.length]; - int l = input.readBuffered(buf); - if (l < 0) { - return l; - } else { - ByteBuffer currentBytes; - if (bytes.hasRemaining()) { - int transfer = bytes.remaining(); - byte[] newBuf = new byte[l + transfer]; - bytes.get(newBuf, 0, transfer); - System.arraycopy(buf, 0, newBuf, transfer, l); - currentBytes = ByteBuffer.wrap(newBuf); - bytes.position(0); - bytes.limit(0); - } else { - currentBytes = ByteBuffer.wrap(buf, 0, l); - } - CharBuffer chars = CharBuffer.wrap(b); - decoder.decode(currentBytes, chars, false); - chars.flip(); - if (currentBytes.hasRemaining()) { - int pos = bytes.position(); - bytes.limit(bytes.limit() + currentBytes.remaining()); - bytes.put(currentBytes); - bytes.position(pos); - } - return chars.remaining(); + Timeout t = new Timeout(timeout); + while (!chars.hasRemaining() && !t.elapsed()) { + if (!bytes.hasRemaining()) { + bytes.position(0); + bytes.limit(0); + } + int nb = input.readBuffered(bytes.array(), bytes.limit(), + bytes.capacity() - bytes.limit(), t.timeout()); + if (nb < 0) { + return nb; } + bytes.limit(bytes.limit() + nb); + chars.clear(); + decoder.decode(bytes, chars, false); + chars.flip(); } + int nb = Math.min(len, chars.remaining()); + chars.get(b, off, nb); + return nb; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java index 1fb53bf5ef8..a4283eb7006 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java @@ -79,12 +79,34 @@ public int read(byte b[], int off, int len) throws IOException { } public int readBuffered(byte[] b) throws IOException { + return readBuffered(b, 0L); + } + + public int readBuffered(byte[] b, long timeout) throws IOException { + return readBuffered(b, 0, b.length, timeout); + } + + public int readBuffered(byte[] b, int off, int len, long timeout) throws IOException { if (b == null) { throw new NullPointerException(); - } else if (b.length == 0) { + } else if (off < 0 || len < 0 || off + len < b.length) { + throw new IllegalArgumentException(); + } else if (len == 0) { return 0; } else { - return super.read(b, 0, b.length); + Timeout t = new Timeout(timeout); + int nb = 0; + while (!t.elapsed()) { + int r = read(nb > 0 ? 1 : t.timeout()); + if (r < 0) { + return nb > 0 ? nb : r; + } + b[off + nb++] = (byte) r; + if (nb >= len || t.isInfinite()) { + break; + } + } + return nb; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java index 94c831c361d..680047fbe60 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java @@ -123,20 +123,17 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { notifyAll(); } - boolean isInfinite = (timeout <= 0L); - /* * So the thread is currently doing the reading for us. So * now we play the waiting game. */ - while (isInfinite || timeout > 0L) { - long start = System.currentTimeMillis (); - + Timeout t = new Timeout(timeout); + while (!t.elapsed()) { try { if (Thread.interrupted()) { throw new InterruptedException(); } - wait(timeout); + wait(t.timeout()); } catch (InterruptedException e) { exception = (IOException) new InterruptedIOException().initCause(e); @@ -155,10 +152,6 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { assert exception == null; break; } - - if (!isInfinite) { - timeout -= System.currentTimeMillis() - start; - } } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java index a48be007e24..5a361344350 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java @@ -45,24 +45,17 @@ public OutputStream getOutputStream() { } private int wait(ByteBuffer buffer, long timeout) throws IOException { - boolean isInfinite = (timeout <= 0L); - long end = 0; - if (!isInfinite) { - end = System.currentTimeMillis() + timeout; - } - while (!closed && !buffer.hasRemaining() && (isInfinite || timeout > 0L)) { + Timeout t = new Timeout(timeout); + while (!closed && !buffer.hasRemaining() && !t.elapsed()) { // Wake up waiting readers/writers notifyAll(); try { - wait(timeout); + wait(t.timeout()); checkIoException(); } catch (InterruptedException e) { checkIoException(); throw new InterruptedIOException(); } - if (!isInfinite) { - timeout = end - System.currentTimeMillis(); - } } return buffer.hasRemaining() ? 0 @@ -107,17 +100,25 @@ public synchronized int read(long timeout, boolean isPeek) throws IOException { } @Override - public synchronized int readBuffered(byte[] b) throws IOException { - checkIoException(); - int res = wait(readBuffer, 0L); - if (res >= 0) { - res = 0; - while (res < b.length && readBuffer.hasRemaining()) { - b[res++] = (byte) (readBuffer.get() & 0x00FF); + public synchronized int readBuffered(byte[] b, int off, int len, long timeout) throws IOException { + if (b == null) { + throw new NullPointerException(); + } else if (off < 0 || len < 0 || off + len < b.length) { + throw new IllegalArgumentException(); + } else if (len == 0) { + return 0; + } else { + checkIoException(); + int res = wait(readBuffer, timeout); + if (res >= 0) { + res = 0; + while (res < len && readBuffer.hasRemaining()) { + b[off + res++] = (byte) (readBuffer.get() & 0x00FF); + } } + rewind(readBuffer, writeBuffer); + return res; } - rewind(readBuffer, writeBuffer); - return res; } public synchronized void setIoException(IOException exception) { diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java index 5f152c16e64..f36423f03b8 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java @@ -106,10 +106,12 @@ protected int read(long timeout, boolean isPeek) throws IOException { } @Override - public int readBuffered(char[] b) throws IOException { + public int readBuffered(char[] b, int off, int len, long timeout) throws IOException { if (b == null) { throw new NullPointerException(); - } else if (b.length == 0) { + } else if (off < 0 || len < 0 || off + len < b.length) { + throw new IllegalArgumentException(); + } else if (len == 0) { return 0; } else { final ReentrantLock lock = this.lock; @@ -117,7 +119,13 @@ public int readBuffered(char[] b) throws IOException { try { if (!closed && count == 0) { try { - notEmpty.await(); + if (timeout > 0) { + if (!notEmpty.await(timeout, TimeUnit.MILLISECONDS)) { + throw new IOException( "Timeout reading" ); + } + } else { + notEmpty.await(); + } } catch (InterruptedException e) { throw (IOException) new InterruptedIOException().initCause(e); } @@ -127,9 +135,9 @@ public int readBuffered(char[] b) throws IOException { } else if (count == 0) { return READ_EXPIRED; } else { - int r = Math.min(b.length, count); + int r = Math.min(len, count); for (int i = 0; i < r; i++) { - b[i] = buffer[read++]; + b[off + i] = buffer[read++]; if (read == buffer.length) { read = 0; } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java index 0dd3a59e5b0..e2f664f2999 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java @@ -85,7 +85,15 @@ public int read(char[] b, int off, int len) throws IOException { return 1; } - public abstract int readBuffered(char[] b) throws IOException; + public int readBuffered(char[] b) throws IOException { + return readBuffered(b, 0L); + } + + public int readBuffered(char[] b, long timeout) throws IOException { + return readBuffered(b, 0, b.length, timeout); + } + + public abstract int readBuffered(char[] b, int off, int len, long timeout) throws IOException; public int available() { return 0; diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java index 7a53d123e9c..d384cc9a0dc 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java @@ -91,10 +91,12 @@ public synchronized boolean ready() throws IOException { } @Override - public int readBuffered(char[] b) throws IOException { + public int readBuffered(char[] b, int off, int len, long timeout) throws IOException { if (b == null) { throw new NullPointerException(); - } else if (b.length == 0) { + } else if (off < 0 || len < 0 || off + len < b.length) { + throw new IllegalArgumentException(); + } else if (len == 0) { return 0; } else if (exception != null) { assert ch == READ_EXPIRED; @@ -105,15 +107,16 @@ public int readBuffered(char[] b) throws IOException { b[0] = (char) ch; ch = READ_EXPIRED; return 1; - } else if (!threadIsReading) { - return in.read(b); + } else if (!threadIsReading && timeout <= 0) { + return in.read(b, off, len); } else { - int c = read(-1, false); + // TODO: rework implementation to read as much as possible + int c = read(timeout, false); if (c >= 0) { - b[0] = (char) c; + b[off] = (char) c; return 1; } else { - return -1; + return c; } } } @@ -158,20 +161,17 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { notifyAll(); } - boolean isInfinite = (timeout <= 0L); - /* * So the thread is currently doing the reading for us. So * now we play the waiting game. */ - while (isInfinite || timeout > 0L) { - long start = System.currentTimeMillis (); - + Timeout t = new Timeout(timeout); + while (!t.elapsed()) { try { if (Thread.interrupted()) { throw new InterruptedException(); } - wait(timeout); + wait(t.timeout()); } catch (InterruptedException e) { exception = (IOException) new InterruptedIOException().initCause(e); @@ -190,10 +190,6 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { assert exception == null; break; } - - if (!isInfinite) { - timeout -= System.currentTimeMillis() - start; - } } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java index 839a08704f3..97487731852 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java @@ -9,6 +9,8 @@ package jdk.internal.org.jline.utils; import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; public class OSUtils { @@ -28,6 +30,12 @@ public class OSUtils { && (System.getenv("MSYSTEM").startsWith("MINGW") || System.getenv("MSYSTEM").equals("MSYS")); + public static final boolean IS_WSL = System.getenv("WSL_DISTRO_NAME") != null; + + public static final boolean IS_WSL1 = IS_WSL && System.getenv("WSL_INTEROP") == null; + + public static final boolean IS_WSL2 = IS_WSL && !IS_WSL1; + public static final boolean IS_CONEMU = IS_WINDOWS && System.getenv("ConEmuPID") != null; @@ -38,17 +46,20 @@ public class OSUtils { public static String STTY_COMMAND; public static String STTY_F_OPTION; public static String INFOCMP_COMMAND; + public static String TEST_COMMAND; static { String tty; String stty; String sttyfopt; String infocmp; + String test; if (OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) { - tty = "tty.exe"; - stty = "stty.exe"; + tty = null; + stty = null; sttyfopt = null; - infocmp = "infocmp.exe"; + infocmp = null; + test = null; String path = System.getenv("PATH"); if (path != null) { String[] paths = path.split(";"); @@ -62,23 +73,39 @@ public class OSUtils { if (infocmp == null && new File(p, "infocmp.exe").exists()) { infocmp = new File(p, "infocmp.exe").getAbsolutePath(); } + if (test == null && new File(p, "test.exe").exists()) { + test = new File(p, "test.exe").getAbsolutePath(); + } } } + if (tty == null) { + tty = "tty.exe"; + } + if (stty == null) { + stty = "stty.exe"; + } + if (infocmp == null) { + infocmp = "infocmp.exe"; + } + if (test == null) { + test = "test.exe"; + } } else { tty = "tty"; - stty = "stty"; + stty = IS_OSX ? "/bin/stty" : "stty"; + sttyfopt = IS_OSX ? "-f" : "-F"; infocmp = "infocmp"; - if (IS_OSX) { - sttyfopt = "-f"; - } - else { - sttyfopt = "-F"; - } + test = isTestCommandValid("/usr/bin/test") ? "/usr/bin/test" + : "/bin/test"; } TTY_COMMAND = tty; STTY_COMMAND = stty; STTY_F_OPTION = sttyfopt; INFOCMP_COMMAND = infocmp; + TEST_COMMAND = test; } + private static boolean isTestCommandValid(String command) { + return Files.isExecutable(Paths.get(command)); + } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java index fa40360a689..a6894e7672c 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java @@ -36,7 +36,7 @@ public PumpReader() { } public PumpReader(int bufferSize) { - char[] buf = new char[bufferSize]; + char[] buf = new char[Math.max(bufferSize, 2)]; this.readBuffer = CharBuffer.wrap(buf); this.writeBuffer = CharBuffer.wrap(buf); this.writer = new Writer(this); @@ -53,13 +53,27 @@ public java.io.InputStream createInputStream(Charset charset) { return new InputStream(this, charset); } - private boolean wait(CharBuffer buffer) throws InterruptedIOException { - if (closed) { - return false; + /** + * Blocks until more input is available, even if {@link #readBuffer} already + * contains some chars; or until the reader is closed. + * + * @return true if more input is available, false if no additional input is + * available and the reader is closed + * @throws InterruptedIOException If {@link #wait()} is interrupted + */ + private boolean waitForMoreInput() throws InterruptedIOException { + if (!writeBuffer.hasRemaining()) { + throw new AssertionError("No space in write buffer"); } - while (!buffer.hasRemaining()) { - // Wake up waiting readers/writers + int oldRemaining = readBuffer.remaining(); + + do { + if (closed) { + return false; + } + + // Wake up waiting writers notifyAll(); try { @@ -67,19 +81,41 @@ private boolean wait(CharBuffer buffer) throws InterruptedIOException { } catch (InterruptedException e) { throw new InterruptedIOException(); } + } while (readBuffer.remaining() <= oldRemaining); + + return true; + } + /** + * Waits until {@code buffer.hasRemaining() == true}, or it is false and + * the reader is {@link #closed}. + * + * @return true if {@code buffer.hasRemaining() == true}; false otherwise + * when reader is closed + */ + private boolean wait(CharBuffer buffer) throws InterruptedIOException { + while (!buffer.hasRemaining()) { if (closed) { return false; } + + // Wake up waiting readers/writers + notifyAll(); + + try { + wait(); + } catch (InterruptedException e) { + throw new InterruptedIOException(); + } } return true; } /** - * Blocks until more input is available or the reader is closed. + * Blocks until input is available or the reader is closed. * - * @return true if more input is available, false if the reader is closed + * @return true if input is available, false if no input is available and the reader is closed * @throws InterruptedIOException If {@link #wait()} is interrupted */ private boolean waitForInput() throws InterruptedIOException { @@ -94,7 +130,8 @@ private boolean waitForInput() throws InterruptedIOException { * @throws ClosedException If the reader was closed */ private void waitForBufferSpace() throws InterruptedIOException, ClosedException { - if (!wait(writeBuffer)) { + // Check `closed` to throw even if writer buffer has space available + if (!wait(writeBuffer) || closed) { throw new ClosedException(); } } @@ -122,7 +159,9 @@ private static boolean rewind(CharBuffer buffer, CharBuffer other) { * @return If more input is available */ private boolean rewindReadBuffer() { - return rewind(readBuffer, writeBuffer) && readBuffer.hasRemaining(); + boolean rw = rewind(readBuffer, writeBuffer) && readBuffer.hasRemaining(); + notifyAll(); + return rw; } /** @@ -131,6 +170,7 @@ private boolean rewindReadBuffer() { */ private void rewindWriteBuffer() { rewind(writeBuffer, readBuffer); + notifyAll(); } @Override @@ -202,10 +242,33 @@ public synchronized int read(CharBuffer target) throws IOException { } private void encodeBytes(CharsetEncoder encoder, ByteBuffer output) throws IOException { + int oldPos = output.position(); CoderResult result = encoder.encode(readBuffer, output, false); - if (rewindReadBuffer() && result.isUnderflow()) { - encoder.encode(readBuffer, output, false); + int encodedCount = output.position() - oldPos; + + if (result.isUnderflow()) { + boolean hasMoreInput = rewindReadBuffer(); + boolean reachedEndOfInput = false; + + // If encoding did not make any progress must block for more input + if (encodedCount == 0 && !hasMoreInput) { + reachedEndOfInput = !waitForMoreInput(); + } + + result = encoder.encode(readBuffer, output, reachedEndOfInput); + if (result.isError()) { + result.throwException(); + } + if (!reachedEndOfInput && output.position() - oldPos == 0) { + throw new AssertionError("Failed to encode any chars"); + } rewindReadBuffer(); + } else if (result.isOverflow()) { + if (encodedCount == 0) { + throw new AssertionError("Output buffer has not enough space"); + } + } else { + result.throwException(); } } @@ -334,7 +397,7 @@ private InputStream(PumpReader reader, Charset charset) { this.encoder = charset.newEncoder() .onUnmappableCharacter(CodingErrorAction.REPLACE) .onMalformedInput(CodingErrorAction.REPLACE); - this.buffer = ByteBuffer.allocate((int) Math.ceil(encoder.maxBytesPerChar())); + this.buffer = ByteBuffer.allocate((int) Math.ceil(encoder.maxBytesPerChar() * 2)); // No input available after initialization buffer.limit(0); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java index f2cc61e80a5..be1659957b4 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java @@ -241,7 +241,7 @@ private AttributedStyle applyReference(final AttributedStyle style, final String if (spec.length() == 1) { // log.warning("Invalid style-reference; missing discriminator: " + spec); } else { - String name = spec.substring(1, spec.length()); + String name = spec.substring(1); String resolvedSpec = source.apply(name); if (resolvedSpec != null) { return apply(style, resolvedSpec); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java new file mode 100644 index 00000000000..edea89cf2d9 --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2002-2018, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.utils; + +/** + * Helper class ti use during I/O operations with an eventual timeout. + */ +public class Timeout { + + private final long timeout; + private long cur = 0; + private long end = Long.MAX_VALUE; + + public Timeout(long timeout) { + this.timeout = timeout; + } + + public boolean isInfinite() { + return timeout <= 0; + } + + public boolean isFinite() { + return timeout > 0; + } + + public boolean elapsed() { + if (timeout > 0) { + cur = System.currentTimeMillis(); + if (end == Long.MAX_VALUE) { + end = cur + timeout; + } + return cur >= end; + } else { + return false; + } + } + + public long timeout() { + return timeout > 0 ? Math.max(1, end - cur) : timeout; + } + +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java index d20b2e89785..db3a8d3d990 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java @@ -70,6 +70,7 @@ public static int wcwidth(int ucs) (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ (ucs >= 0xffe0 && ucs <= 0xffe6) || + (ucs >= 0x1f000 && ucs <= 0x1feee) || (ucs >= 0x20000 && ucs <= 0x2fffd) || (ucs >= 0x30000 && ucs <= 0x3fffd))) ? 1 : 0); } @@ -123,8 +124,8 @@ public static int wcwidth(int ucs) new Interval( 0x10A01, 0x10A03 ), new Interval( 0x10A05, 0x10A06 ), new Interval( 0x10A0C, 0x10A0F ), new Interval( 0x10A38, 0x10A3A ), new Interval( 0x10A3F, 0x10A3F ), new Interval( 0x1D167, 0x1D169 ), new Interval( 0x1D173, 0x1D182 ), new Interval( 0x1D185, 0x1D18B ), new Interval( 0x1D1AA, 0x1D1AD ), - new Interval( 0x1D242, 0x1D244 ), new Interval( 0xE0001, 0xE0001 ), new Interval( 0xE0020, 0xE007F ), - new Interval( 0xE0100, 0xE01EF ) + new Interval( 0x1D242, 0x1D244 ), new Interval( 0x1F3FB, 0x1F3FF ), new Interval( 0xE0001, 0xE0001 ), + new Interval( 0xE0020, 0xE007F ), new Interval( 0xE0100, 0xE01EF ) }; private static class Interval { diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-vtp.caps b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-vtp.caps index 39e0623eef3..4ce80158751 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-vtp.caps +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-vtp.caps @@ -2,7 +2,7 @@ windows-vtp|windows with virtual terminal processing, am, mc5i, mir, msgr, colors#256, cols#80, it#8, lines#24, ncv#3, pairs#64, bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, clear=\E[H\E[J, - cr=^M, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\E[B, + cr=^M, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\n, cuf=\E[%p1%dC, cuf1=\E[C, cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\E[A, il=\E[%p1%dL, il1=\E[L, diff --git a/src/jdk.internal.le/share/classes/module-info.java b/src/jdk.internal.le/share/classes/module-info.java index 1ece112f1e3..c51ca6ce5cd 100644 --- a/src/jdk.internal.le/share/classes/module-info.java +++ b/src/jdk.internal.le/share/classes/module-info.java @@ -56,8 +56,5 @@ exports jdk.internal.org.jline.terminal.spi to jdk.scripting.nashorn.shell, jdk.jshell; - - uses jdk.internal.org.jline.terminal.spi.JnaSupport; - } diff --git a/src/jdk.internal.le/share/legal/jline.md b/src/jdk.internal.le/share/legal/jline.md index dc3c460b7ea..4e5d344b4d1 100644 --- a/src/jdk.internal.le/share/legal/jline.md +++ b/src/jdk.internal.le/share/legal/jline.md @@ -1,4 +1,4 @@ -## JLine v3.20.0 +## JLine v3.22.0 ### JLine License
    @@ -41,10 +41,10 @@ OF THE POSSIBILITY OF SUCH DAMAGE.
     
     4th Party Dependency
     =============
    -org.fusesource.jansi version 1.17.1
    -org.apache.sshd 2.1 to 3
    -org.apache.felix.gogo.runtime 1.1.2
    -org.apache.felix.gogo.jline 1.1.4
    +org.fusesource.jansi version 2.4.0
    +org.apache.sshd 2.9.2
    +org.apache.felix.gogo.runtime 1.1.6
    +org.apache.felix.gogo.jline 1.1.8
     =============
     Apache License
                               Version 2.0, January 2004
    @@ -262,7 +262,7 @@ slf4j
     SLF4J source code and binaries are distributed under the MIT license.
     
     
    -Copyright (c) 2004-2017 QOS.ch
    +Copyright (c) 2004-2023 QOS.ch
     All rights reserved.
     
     Permission is hereby granted, free of charge, to any person obtaining
    diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaSupportImpl.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaSupportImpl.java
    deleted file mode 100644
    index 061952063cf..00000000000
    --- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaSupportImpl.java
    +++ /dev/null
    @@ -1,77 +0,0 @@
    -/*
    - * Copyright (c) 2002-2019, the original author or authors.
    - *
    - * This software is distributable under the BSD license. See the terms of the
    - * BSD license in the documentation provided with this software.
    - *
    - * https://opensource.org/licenses/BSD-3-Clause
    - */
    -package jdk.internal.org.jline.terminal.impl.jna;
    -
    -import jdk.internal.org.jline.terminal.Attributes;
    -import jdk.internal.org.jline.terminal.Size;
    -import jdk.internal.org.jline.terminal.Terminal;
    -import jdk.internal.org.jline.terminal.impl.jna.win.JnaWinSysTerminal;
    -import jdk.internal.org.jline.terminal.spi.JnaSupport;
    -import jdk.internal.org.jline.terminal.spi.Pty;
    -import jdk.internal.org.jline.utils.OSUtils;
    -
    -import java.io.IOException;
    -import java.io.InputStream;
    -import java.nio.charset.Charset;
    -import java.util.function.Function;
    -
    -public class JnaSupportImpl implements JnaSupport {
    -    @Override
    -    public Pty current() throws IOException {
    -//        return JnaNativePty.current();
    -        throw new UnsupportedOperationException();
    -    }
    -
    -    @Override
    -    public Pty open(Attributes attributes, Size size) throws IOException {
    -//        return JnaNativePty.open(attributes, size);
    -        throw new UnsupportedOperationException();
    -    }
    -
    -    @Override
    -    public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler) throws IOException {
    -        return winSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, false);
    -    }
    -
    -    @Override
    -    public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused) throws IOException {
    -        return winSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, paused, input -> input);
    -    }
    -
    -    @Override
    -    public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, Function inputStreamWrapper) throws IOException {
    -        return JnaWinSysTerminal.createTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, paused, inputStreamWrapper);
    -    }
    -
    -    @Override
    -    public boolean isWindowsConsole() {
    -        return JnaWinSysTerminal.isWindowsConsole();
    -    }
    -
    -    @Override
    -    public boolean isConsoleOutput() {
    -        if (OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) {
    -            throw new UnsupportedOperationException();
    -        } else if (OSUtils.IS_WINDOWS) {
    -            return JnaWinSysTerminal.isConsoleOutput();
    -        }
    -        throw new UnsupportedOperationException();
    -    }
    -
    -    @Override
    -    public boolean isConsoleInput() {
    -        if (OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) {
    -            throw new UnsupportedOperationException();
    -        } else if (OSUtils.IS_WINDOWS) {
    -            return JnaWinSysTerminal.isConsoleInput();
    -        }
    -        throw new UnsupportedOperationException();
    -    }
    -
    -}
    diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java
    new file mode 100644
    index 00000000000..b820ce2187e
    --- /dev/null
    +++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java
    @@ -0,0 +1,106 @@
    +/*
    + * Copyright (c) 2002-2020, the original author or authors.
    + *
    + * This software is distributable under the BSD license. See the terms of the
    + * BSD license in the documentation provided with this software.
    + *
    + * https://opensource.org/licenses/BSD-3-Clause
    + */
    +package jdk.internal.org.jline.terminal.impl.jna;
    +
    +import jdk.internal.org.jline.terminal.Attributes;
    +import jdk.internal.org.jline.terminal.Size;
    +import jdk.internal.org.jline.terminal.Terminal;
    +import jdk.internal.org.jline.terminal.impl.PosixPtyTerminal;
    +import jdk.internal.org.jline.terminal.impl.PosixSysTerminal;
    +import jdk.internal.org.jline.terminal.impl.jna.win.JnaWinSysTerminal;
    +import jdk.internal.org.jline.terminal.spi.TerminalProvider;
    +import jdk.internal.org.jline.terminal.spi.Pty;
    +import jdk.internal.org.jline.utils.OSUtils;
    +
    +import java.io.IOException;
    +import java.io.InputStream;
    +import java.io.OutputStream;
    +import java.nio.charset.Charset;
    +import java.util.function.Function;
    +
    +public class JnaTerminalProvider implements TerminalProvider
    +{
    +    @Override
    +    public String name() {
    +        return "jna";
    +    }
    +
    +//    public Pty current(TerminalProvider.Stream console) throws IOException {
    +//        return JnaNativePty.current(console);
    +//    }
    +//
    +//    public Pty open(Attributes attributes, Size size) throws IOException {
    +//        return JnaNativePty.open(attributes, size);
    +//    }
    +
    +    @Override
    +    public Terminal sysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
    +                                boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
    +                                Stream consoleStream, Function inputStreamWrapper) throws IOException {
    +        if (OSUtils.IS_WINDOWS) {
    +            return winSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper );
    +        } else {
    +            return null;
    +        }
    +    }
    +
    +    public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
    +                                   boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
    +                                   Stream console, Function inputStreamWrapper) throws IOException {
    +        return JnaWinSysTerminal.createTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, console, inputStreamWrapper);
    +    }
    +
    +//    public Terminal posixSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
    +//                                     boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
    +//                                     Stream consoleStream) throws IOException {
    +//        Pty pty = current(consoleStream);
    +//        return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler);
    +//    }
    +
    +    @Override
    +    public Terminal newTerminal(String name, String type, InputStream in, OutputStream out,
    +                                Charset encoding, Terminal.SignalHandler signalHandler, boolean paused,
    +                                Attributes attributes, Size size) throws IOException
    +    {
    +//        Pty pty = open(attributes, size);
    +//        return new PosixPtyTerminal(name, type, pty, in, out, encoding, signalHandler, paused);
    +        return null;
    +    }
    +
    +    @Override
    +    public boolean isSystemStream(Stream stream) {
    +        try {
    +            if (OSUtils.IS_WINDOWS) {
    +                return isWindowsSystemStream(stream);
    +            } else {
    +//                return isPosixSystemStream(stream);
    +                return false;
    +            }
    +        } catch (Throwable t) {
    +            return false;
    +        }
    +    }
    +
    +    public boolean isWindowsSystemStream(Stream stream) {
    +        return JnaWinSysTerminal.isWindowsSystemStream(stream);
    +    }
    +
    +//    public boolean isPosixSystemStream(Stream stream) {
    +//        return JnaNativePty.isPosixSystemStream(stream);
    +//    }
    +
    +    @Override
    +    public String systemStreamName(Stream stream) {
    +//        if (OSUtils.IS_WINDOWS) {
    +            return null;
    +//        } else {
    +//            return JnaNativePty.posixSystemStreamName(stream);
    +//        }
    +    }
    +}
    diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java
    index d2dc21286ac..a4469003c16 100644
    --- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java
    +++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java
    @@ -17,17 +17,17 @@
     
     class JnaWinConsoleWriter extends AbstractWindowsConsoleWriter {
     
    -    private final Pointer consoleHandle;
    +    private final Pointer console;
         private final IntByReference writtenChars = new IntByReference();
     
    -    JnaWinConsoleWriter(Pointer consoleHandle) {
    -        this.consoleHandle = consoleHandle;
    +    JnaWinConsoleWriter(Pointer console) {
    +        this.console = console;
         }
     
         @Override
         protected void writeConsole(char[] text, int len) throws IOException {
             try {
    -            Kernel32.INSTANCE.WriteConsoleW(this.consoleHandle, text, len, this.writtenChars, null);
    +            Kernel32.INSTANCE.WriteConsoleW(this.console, text, len, this.writtenChars, null);
             } catch (LastErrorException e) {
                 throw new IOException("Failed to write to console", e);
             }
    diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java
    index 39e4d219f17..5ffc5d714ed 100644
    --- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java
    +++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002-2019, the original author or authors.
    + * Copyright (c) 2002-2020, the original author or authors.
      *
      * This software is distributable under the BSD license. See the terms of the
      * BSD license in the documentation provided with this software.
    @@ -19,11 +19,10 @@
     //import com.sun.jna.LastErrorException;
     //import com.sun.jna.Pointer;
     //import com.sun.jna.ptr.IntByReference;
    -
     import jdk.internal.org.jline.terminal.Cursor;
     import jdk.internal.org.jline.terminal.Size;
    -import jdk.internal.org.jline.terminal.Terminal;
     import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
    +import jdk.internal.org.jline.terminal.spi.TerminalProvider;
     import jdk.internal.org.jline.utils.InfoCmp;
     import jdk.internal.org.jline.utils.OSUtils;
     
    @@ -31,38 +30,50 @@ public class JnaWinSysTerminal extends AbstractWindowsTerminal {
     
         private static final Pointer consoleIn = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_INPUT_HANDLE);
         private static final Pointer consoleOut = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_OUTPUT_HANDLE);
    -
    -    public static JnaWinSysTerminal createTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, SignalHandler signalHandler, boolean paused, Function inputStreamWrapper) throws IOException {
    +    private static final Pointer consoleErr = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_ERROR_HANDLE);
    +
    +    public static JnaWinSysTerminal createTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, boolean nativeSignals, SignalHandler signalHandler, boolean paused, TerminalProvider.Stream consoleStream, Function inputStreamWrapper) throws IOException {
    +        Pointer console;
    +        switch (consoleStream) {
    +            case Output:
    +                console = JnaWinSysTerminal.consoleOut;
    +                break;
    +            case Error:
    +                console = JnaWinSysTerminal.consoleErr;
    +                break;
    +            default:
    +                throw new IllegalArgumentException("Unsupport stream for console: " + consoleStream);
    +        }
             Writer writer;
             if (ansiPassThrough) {
                 if (type == null) {
                     type = OSUtils.IS_CONEMU ? TYPE_WINDOWS_CONEMU : TYPE_WINDOWS;
                 }
    -            writer = new JnaWinConsoleWriter(consoleOut);
    +            writer = new JnaWinConsoleWriter(console);
             } else {
                 IntByReference mode = new IntByReference();
    -            Kernel32.INSTANCE.GetConsoleMode(consoleOut, mode);
    +            Kernel32.INSTANCE.GetConsoleMode(console, mode);
                 try {
    -                Kernel32.INSTANCE.SetConsoleMode(consoleOut, mode.getValue() | AbstractWindowsTerminal.ENABLE_VIRTUAL_TERMINAL_PROCESSING);
    +                Kernel32.INSTANCE.SetConsoleMode(console, mode.getValue() | AbstractWindowsTerminal.ENABLE_VIRTUAL_TERMINAL_PROCESSING);
                     if (type == null) {
                         type = TYPE_WINDOWS_VTP;
                     }
    -                writer = new JnaWinConsoleWriter(consoleOut);
    +                writer = new JnaWinConsoleWriter(console);
                 } catch (LastErrorException e) {
                     if (OSUtils.IS_CONEMU) {
                         if (type == null) {
                             type = TYPE_WINDOWS_CONEMU;
                         }
    -                    writer = new JnaWinConsoleWriter(consoleOut);
    +                    writer = new JnaWinConsoleWriter(console);
                     } else {
                         if (type == null) {
                             type = TYPE_WINDOWS;
                         }
    -                    writer = new WindowsAnsiWriter(new BufferedWriter(new JnaWinConsoleWriter(consoleOut)), consoleOut);
    +                    writer = new WindowsAnsiWriter(new BufferedWriter(new JnaWinConsoleWriter(console)), console);
                     }
                 }
             }
    -        JnaWinSysTerminal terminal = new JnaWinSysTerminal(writer, name, type, encoding, codepage, nativeSignals, signalHandler, inputStreamWrapper);
    +        JnaWinSysTerminal terminal = new JnaWinSysTerminal(writer, name, type, encoding, nativeSignals, signalHandler, inputStreamWrapper);
             // Start input pump thread
             if (!paused) {
                 terminal.resume();
    @@ -70,39 +81,26 @@ public static JnaWinSysTerminal createTerminal(String name, String type, boolean
             return terminal;
         }
     
    -    public static boolean isWindowsConsole() {
    +    public static boolean isWindowsSystemStream(TerminalProvider.Stream stream) {
             try {
                 IntByReference mode = new IntByReference();
    -            Kernel32.INSTANCE.GetConsoleMode(consoleOut, mode);
    -            Kernel32.INSTANCE.GetConsoleMode(consoleIn, mode);
    -            return true;
    -        } catch (LastErrorException e) {
    -            return false;
    -        }
    -    }
    -
    -    public static boolean isConsoleOutput() {
    -        try {
    -            IntByReference mode = new IntByReference();
    -            Kernel32.INSTANCE.GetConsoleMode(consoleOut, mode);
    -            return true;
    -        } catch (LastErrorException e) {
    -            return false;
    -        }
    -    }
    -
    -    public static boolean isConsoleInput() {
    -        try {
    -            IntByReference mode = new IntByReference();
    -            Kernel32.INSTANCE.GetConsoleMode(consoleIn, mode);
    +            Pointer console;
    +            switch (stream) {
    +                case Input: console = consoleIn; break;
    +                case Output: console = consoleOut; break;
    +                case Error: console = consoleErr; break;
    +                default: return false;
    +            }
    +            Kernel32.INSTANCE.GetConsoleMode(console, mode);
                 return true;
             } catch (LastErrorException e) {
                 return false;
             }
         }
     
    -    JnaWinSysTerminal(Writer writer, String name, String type, Charset encoding, int codepage, boolean nativeSignals, SignalHandler signalHandler, Function inputStreamWrapper) throws IOException {
    -        super(writer, name, type, encoding, codepage, nativeSignals, signalHandler, inputStreamWrapper);
    +    JnaWinSysTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler,
    +            Function inputStreamWrapper) throws IOException {
    +        super(writer, name, type, encoding, nativeSignals, signalHandler, inputStreamWrapper);
             strings.put(InfoCmp.Capability.key_mouse, "\\E[M");
         }
     
    diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/TimestampedSigner.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/TimestampedSigner.java
    index c11a719d6fd..b2a996b94d0 100644
    --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/TimestampedSigner.java
    +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/TimestampedSigner.java
    @@ -48,25 +48,11 @@
     @SuppressWarnings("deprecation")
     public final class TimestampedSigner extends ContentSigner {
     
    -    /*
    -     * Object identifier for the subject information access X.509 certificate
    -     * extension.
    -     */
    -    private static final String SUBJECT_INFO_ACCESS_OID = "1.3.6.1.5.5.7.1.11";
    -
         /*
          * Object identifier for the timestamping access descriptors.
          */
    -    private static final ObjectIdentifier AD_TIMESTAMPING_Id;
    -    static {
    -        ObjectIdentifier tmp = null;
    -        try {
    -            tmp = new ObjectIdentifier("1.3.6.1.5.5.7.48.3");
    -        } catch (IOException e) {
    -            // ignore
    -        }
    -        AD_TIMESTAMPING_Id = tmp;
    -    }
    +    private static final ObjectIdentifier AD_TIMESTAMPING_Id =
    +            ObjectIdentifier.of(KnownOIDs.AD_TimeStamping);
     
         /**
          * Instantiates a content signer that supports timestamped signatures.
    @@ -155,8 +141,8 @@ public static URI getTimestampingURI(X509Certificate tsaCertificate) {
             }
             // Parse the extensions
             try {
    -            byte[] extensionValue =
    -                tsaCertificate.getExtensionValue(SUBJECT_INFO_ACCESS_OID);
    +            byte[] extensionValue = tsaCertificate.getExtensionValue
    +                    (KnownOIDs.SubjectInfoAccess.value());
                 if (extensionValue == null) {
                     return null;
                 }
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
    index 0e2f041175d..61872571ee8 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
    @@ -1628,7 +1628,8 @@ protected DocPath defaultAction(Element e, Void p) {
             if (!(lower.startsWith("mailto:")
                     || lower.startsWith("http:")
                     || lower.startsWith("https:")
    -                || lower.startsWith("file:"))) {
    +                || lower.startsWith("file:")
    +                || lower.startsWith("ftp:"))) {
                 text = "{@" + (new DocRootTaglet()).getName() + "}/"
                         + redirectPathFromRoot.resolve(text).getPath();
                 text = replaceDocRootDir(text);
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java
    index a8cc7f7b2ec..5fa8157a121 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -29,6 +29,7 @@
     import jdk.javadoc.internal.doclets.toolkit.Content;
     import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
     import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
    +import jdk.javadoc.internal.doclets.toolkit.util.Extern;
     
     /**
      * Factory for HTML A elements, both links (with a {@code href} attribute)
    @@ -334,44 +335,7 @@ public String getName(String name) {
                 return name.replaceAll(" +", "");
             }
     
    -        StringBuilder sb = new StringBuilder();
    -        for (int i = 0; i < name.length(); i++) {
    -            char ch = name.charAt(i);
    -            switch (ch) {
    -                case '(':
    -                case ')':
    -                case '<':
    -                case '>':
    -                case ',':
    -                    sb.append('-');
    -                    break;
    -                case ' ':
    -                case '[':
    -                    break;
    -                case ']':
    -                    sb.append(":A");
    -                    break;
    -                // Any appearance of $ needs to be substituted with ":D" and not with hyphen
    -                // since a field name "P$$ and a method P(), both valid member names, can end
    -                // up as "P--". A member name beginning with $ needs to be substituted with
    -                // "Z:Z:D".
    -                case '$':
    -                    if (i == 0)
    -                        sb.append("Z:Z");
    -                    sb.append(":D");
    -                    break;
    -                // A member name beginning with _ needs to be prefixed with "Z:Z" since valid anchor
    -                // names can only begin with a letter.
    -                case '_':
    -                    if (i == 0)
    -                        sb.append("Z:Z");
    -                    sb.append(ch);
    -                    break;
    -                default:
    -                    sb.append(ch);
    -            }
    -        }
    -        return sb.toString();
    +        return Extern.getOldFormHtmlName(name);
         }
     
     }
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.css
    index e7cb731793f..dfef26182b0 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.css
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.css
    @@ -1,4 +1,4 @@
    -/*! jQuery UI - v1.13.1 - 2022-05-12
    +/*! jQuery UI - v1.13.2 - 2023-02-27
     * http://jqueryui.com
     * Includes: core.css, autocomplete.css, menu.css
     * Copyright jQuery Foundation and other contributors; Licensed MIT */
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.js b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.js
    index 27c0b2dfb09..95ec9f04fd2 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.js
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.js
    @@ -1,4 +1,4 @@
    -/*! jQuery UI - v1.13.1 - 2022-05-12
    +/*! jQuery UI - v1.13.2 - 2023-02-27
     * http://jqueryui.com
     * Includes: widget.js, position.js, keycode.js, unique-id.js, widgets/autocomplete.js, widgets/menu.js
     * Copyright jQuery Foundation and other contributors; Licensed MIT */
    @@ -20,11 +20,11 @@
     
     $.ui = $.ui || {};
     
    -var version = $.ui.version = "1.13.1";
    +var version = $.ui.version = "1.13.2";
     
     
     /*!
    - * jQuery UI Widget 1.13.1
    + * jQuery UI Widget 1.13.2
      * http://jqueryui.com
      *
      * Copyright jQuery Foundation and other contributors
    @@ -766,7 +766,7 @@ var widget = $.widget;
     
     
     /*!
    - * jQuery UI Position 1.13.1
    + * jQuery UI Position 1.13.2
      * http://jqueryui.com
      *
      * Copyright jQuery Foundation and other contributors
    @@ -1263,7 +1263,7 @@ var position = $.ui.position;
     
     
     /*!
    - * jQuery UI Keycode 1.13.1
    + * jQuery UI Keycode 1.13.2
      * http://jqueryui.com
      *
      * Copyright jQuery Foundation and other contributors
    @@ -1298,7 +1298,7 @@ var keycode = $.ui.keyCode = {
     
     
     /*!
    - * jQuery UI Unique ID 1.13.1
    + * jQuery UI Unique ID 1.13.2
      * http://jqueryui.com
      *
      * Copyright jQuery Foundation and other contributors
    @@ -1366,7 +1366,7 @@ var safeActiveElement = $.ui.safeActiveElement = function( document ) {
     
     
     /*!
    - * jQuery UI Menu 1.13.1
    + * jQuery UI Menu 1.13.2
      * http://jqueryui.com
      *
      * Copyright jQuery Foundation and other contributors
    @@ -1385,7 +1385,7 @@ var safeActiveElement = $.ui.safeActiveElement = function( document ) {
     
     
     var widgetsMenu = $.widget( "ui.menu", {
    -	version: "1.13.1",
    +	version: "1.13.2",
     	defaultElement: "
      ", delay: 300, options: { @@ -2057,7 +2057,7 @@ var widgetsMenu = $.widget( "ui.menu", { /*! - * jQuery UI Autocomplete 1.13.1 + * jQuery UI Autocomplete 1.13.2 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -2076,7 +2076,7 @@ var widgetsMenu = $.widget( "ui.menu", { $.widget( "ui.autocomplete", { - version: "1.13.1", + version: "1.13.2", defaultElement: "", options: { appendTo: null, diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.min.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.min.css index d64539cb3c9..693327f0148 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.min.css +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.min.css @@ -1,4 +1,4 @@ -/*! jQuery UI - v1.13.1 - 2022-05-12 +/*! jQuery UI - v1.13.2 - 2023-02-27 * http://jqueryui.com * Includes: core.css, autocomplete.css, menu.css * Copyright jQuery Foundation and other contributors; Licensed MIT */ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.min.js b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.min.js index 55c283294e5..8166a15ee23 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.min.js +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-ui.min.js @@ -1,6 +1,6 @@ -/*! jQuery UI - v1.13.1 - 2022-05-12 +/*! jQuery UI - v1.13.2 - 2023-02-27 * http://jqueryui.com * Includes: widget.js, position.js, keycode.js, unique-id.js, widgets/autocomplete.js, widgets/menu.js * Copyright jQuery Foundation and other contributors; Licensed MIT */ -!function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)}(function(x){"use strict";x.ui=x.ui||{};x.ui.version="1.13.1";var n,i=0,l=Array.prototype.hasOwnProperty,a=Array.prototype.slice;x.cleanData=(n=x.cleanData,function(t){for(var e,i,s=0;null!=(i=t[s]);s++)(e=x._data(i,"events"))&&e.remove&&x(i).triggerHandler("remove");n(t)}),x.widget=function(t,i,e){var s,n,o,l={},a=t.split(".")[0],r=a+"-"+(t=t.split(".")[1]);return e||(e=i,i=x.Widget),Array.isArray(e)&&(e=x.extend.apply(null,[{}].concat(e))),x.expr.pseudos[r.toLowerCase()]=function(t){return!!x.data(t,r)},x[a]=x[a]||{},s=x[a][t],n=x[a][t]=function(t,e){if(!this||!this._createWidget)return new n(t,e);arguments.length&&this._createWidget(t,e)},x.extend(n,s,{version:e.version,_proto:x.extend({},e),_childConstructors:[]}),(o=new i).options=x.widget.extend({},o.options),x.each(e,function(e,s){function n(){return i.prototype[e].apply(this,arguments)}function o(t){return i.prototype[e].apply(this,t)}l[e]="function"==typeof s?function(){var t,e=this._super,i=this._superApply;return this._super=n,this._superApply=o,t=s.apply(this,arguments),this._super=e,this._superApply=i,t}:s}),n.prototype=x.widget.extend(o,{widgetEventPrefix:s&&o.widgetEventPrefix||t},l,{constructor:n,namespace:a,widgetName:t,widgetFullName:r}),s?(x.each(s._childConstructors,function(t,e){var i=e.prototype;x.widget(i.namespace+"."+i.widgetName,n,e._proto)}),delete s._childConstructors):i._childConstructors.push(n),x.widget.bridge(t,n),n},x.widget.extend=function(t){for(var e,i,s=a.call(arguments,1),n=0,o=s.length;n",options:{classes:{},disabled:!1,create:null},_createWidget:function(t,e){e=x(e||this.defaultElement||this)[0],this.element=x(e),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=x(),this.hoverable=x(),this.focusable=x(),this.classesElementLookup={},e!==this&&(x.data(e,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===e&&this.destroy()}}),this.document=x(e.style?e.ownerDocument:e.document||e),this.window=x(this.document[0].defaultView||this.document[0].parentWindow)),this.options=x.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:x.noop,_create:x.noop,_init:x.noop,destroy:function(){var i=this;this._destroy(),x.each(this.classesElementLookup,function(t,e){i._removeClass(e,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:x.noop,widget:function(){return this.element},option:function(t,e){var i,s,n,o=t;if(0===arguments.length)return x.widget.extend({},this.options);if("string"==typeof t)if(o={},t=(i=t.split(".")).shift(),i.length){for(s=o[t]=x.widget.extend({},this.options[t]),n=0;n
      "),i=e.children()[0];return x("body").append(e),t=i.offsetWidth,e.css("overflow","scroll"),t===(i=i.offsetWidth)&&(i=e[0].clientWidth),e.remove(),s=t-i},getScrollInfo:function(t){var e=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),i=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),e="scroll"===e||"auto"===e&&t.widthC(E(s),E(n))?o.important="horizontal":o.important="vertical",c.using.call(this,t,o)}),l.offset(x.extend(u,{using:t}))})},x.ui.position={fit:{left:function(t,e){var i=e.within,s=i.isWindow?i.scrollLeft:i.offset.left,n=i.width,o=t.left-e.collisionPosition.marginLeft,l=s-o,a=o+e.collisionWidth-n-s;e.collisionWidth>n?0n?0",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.lastMousePosition={x:null,y:null},this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault(),this._activateItem(t)},"click .ui-menu-item":function(t){var e=x(t.target),i=x(x.ui.safeActiveElement(this.document[0]));!this.mouseHandled&&e.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),e.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&i.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":"_activateItem","mousemove .ui-menu-item":"_activateItem",mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this._menuItems().first();e||this.focus(t,i)},blur:function(t){this._delay(function(){x.contains(this.element[0],x.ui.safeActiveElement(this.document[0]))||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t,!0),this.mouseHandled=!1}})},_activateItem:function(t){var e,i;this.previousFilter||t.clientX===this.lastMousePosition.x&&t.clientY===this.lastMousePosition.y||(this.lastMousePosition={x:t.clientX,y:t.clientY},e=x(t.target).closest(".ui-menu-item"),i=x(t.currentTarget),e[0]===i[0]&&(i.is(".ui-state-active")||(this._removeClass(i.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(t,i))))},_destroy:function(){var t=this.element.find(".ui-menu-item").removeAttr("role aria-disabled").children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),t.children().each(function(){var t=x(this);t.data("ui-menu-submenu-caret")&&t.remove()})},_keydown:function(t){var e,i,s,n=!0;switch(t.keyCode){case x.ui.keyCode.PAGE_UP:this.previousPage(t);break;case x.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case x.ui.keyCode.HOME:this._move("first","first",t);break;case x.ui.keyCode.END:this._move("last","last",t);break;case x.ui.keyCode.UP:this.previous(t);break;case x.ui.keyCode.DOWN:this.next(t);break;case x.ui.keyCode.LEFT:this.collapse(t);break;case x.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case x.ui.keyCode.ENTER:case x.ui.keyCode.SPACE:this._activate(t);break;case x.ui.keyCode.ESCAPE:this.collapse(t);break;default:e=this.previousFilter||"",s=n=!1,i=96<=t.keyCode&&t.keyCode<=105?(t.keyCode-96).toString():String.fromCharCode(t.keyCode),clearTimeout(this.filterTimer),i===e?s=!0:i=e+i,e=this._filterMenuItems(i),(e=s&&-1!==e.index(this.active.next())?this.active.nextAll(".ui-menu-item"):e).length||(i=String.fromCharCode(t.keyCode),e=this._filterMenuItems(i)),e.length?(this.focus(t,e),this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}n&&t.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var t,e,s=this,n=this.options.icons.submenu,i=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),e=i.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=x(this),e=t.prev(),i=x("").data("ui-menu-submenu-caret",!0);s._addClass(i,"ui-menu-icon","ui-icon "+n),e.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",e.attr("id"))}),this._addClass(e,"ui-menu","ui-widget ui-widget-content ui-front"),(t=i.add(this.element).find(this.options.items)).not(".ui-menu-item").each(function(){var t=x(this);s._isDivider(t)&&s._addClass(t,"ui-menu-divider","ui-widget-content")}),i=(e=t.not(".ui-menu-item, .ui-menu-divider")).children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(e,"ui-menu-item")._addClass(i,"ui-menu-item-wrapper"),t.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!x.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){var i;"icons"===t&&(i=this.element.find(".ui-menu-icon"),this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",String(t)),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),i=this.active.children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",i.attr("id")),i=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),(i=e.children(".ui-menu")).length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(t){var e,i,s;this._hasScroll()&&(i=parseFloat(x.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(x.css(this.activeMenu[0],"paddingTop"))||0,e=t.offset().top-this.activeMenu.offset().top-i-s,i=this.activeMenu.scrollTop(),s=this.activeMenu.height(),t=t.outerHeight(),e<0?this.activeMenu.scrollTop(i+e):s",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,liveRegionTimer:null,_create:function(){var i,s,n,t=this.element[0].nodeName.toLowerCase(),e="textarea"===t,t="input"===t;this.isMultiLine=e||!t&&this._isContentEditable(this.element),this.valueMethod=this.element[e||t?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(t){if(this.element.prop("readOnly"))s=n=i=!0;else{s=n=i=!1;var e=x.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:i=!0,this._move("previousPage",t);break;case e.PAGE_DOWN:i=!0,this._move("nextPage",t);break;case e.UP:i=!0,this._keyEvent("previous",t);break;case e.DOWN:i=!0,this._keyEvent("next",t);break;case e.ENTER:this.menu.active&&(i=!0,t.preventDefault(),this.menu.select(t));break;case e.TAB:this.menu.active&&this.menu.select(t);break;case e.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(t),t.preventDefault());break;default:s=!0,this._searchTimeout(t)}}},keypress:function(t){if(i)return i=!1,void(this.isMultiLine&&!this.menu.element.is(":visible")||t.preventDefault());if(!s){var e=x.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:this._move("previousPage",t);break;case e.PAGE_DOWN:this._move("nextPage",t);break;case e.UP:this._keyEvent("previous",t);break;case e.DOWN:this._keyEvent("next",t)}}},input:function(t){if(n)return n=!1,void t.preventDefault();this._searchTimeout(t)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){clearTimeout(this.searching),this.close(t),this._change(t)}}),this._initSource(),this.menu=x("
        ").appendTo(this._appendTo()).menu({role:null}).hide().attr({unselectable:"on"}).menu("instance"),this._addClass(this.menu.element,"ui-autocomplete","ui-front"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault()},menufocus:function(t,e){var i,s;if(this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type)))return this.menu.blur(),void this.document.one("mousemove",function(){x(t.target).trigger(t.originalEvent)});s=e.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",t,{item:s})&&t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(s.value),(i=e.item.attr("aria-label")||s.value)&&String.prototype.trim.call(i).length&&(clearTimeout(this.liveRegionTimer),this.liveRegionTimer=this._delay(function(){this.liveRegion.html(x("
        ").text(i))},100))},menuselect:function(t,e){var i=e.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==x.ui.safeActiveElement(this.document[0])&&(this.element.trigger("focus"),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",t,{item:i})&&this._value(i.value),this.term=this._value(),this.close(t),this.selectedItem=i}}),this.liveRegion=x("
        ",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(t,e){this._super(t,e),"source"===t&&this._initSource(),"appendTo"===t&&this.menu.element.appendTo(this._appendTo()),"disabled"===t&&e&&this.xhr&&this.xhr.abort()},_isEventTargetInWidget:function(t){var e=this.menu.element[0];return t.target===this.element[0]||t.target===e||x.contains(e,t.target)},_closeOnClickOutside:function(t){this._isEventTargetInWidget(t)||this.close()},_appendTo:function(){var t=this.options.appendTo;return t=!(t=!(t=t&&(t.jquery||t.nodeType?x(t):this.document.find(t).eq(0)))||!t[0]?this.element.closest(".ui-front, dialog"):t).length?this.document[0].body:t},_initSource:function(){var i,s,n=this;Array.isArray(this.options.source)?(i=this.options.source,this.source=function(t,e){e(x.ui.autocomplete.filter(i,t.term))}):"string"==typeof this.options.source?(s=this.options.source,this.source=function(t,e){n.xhr&&n.xhr.abort(),n.xhr=x.ajax({url:s,data:t,dataType:"json",success:function(t){e(t)},error:function(){e([])}})}):this.source=this.options.source},_searchTimeout:function(s){clearTimeout(this.searching),this.searching=this._delay(function(){var t=this.term===this._value(),e=this.menu.element.is(":visible"),i=s.altKey||s.ctrlKey||s.metaKey||s.shiftKey;t&&(e||i)||(this.selectedItem=null,this.search(null,s))},this.options.delay)},search:function(t,e){return t=null!=t?t:this._value(),this.term=this._value(),t.length").append(x("
        ").text(e.label)).appendTo(t)},_move:function(t,e){if(this.menu.element.is(":visible"))return this.menu.isFirstItem()&&/^previous/.test(t)||this.menu.isLastItem()&&/^next/.test(t)?(this.isMultiLine||this._value(this.term),void this.menu.blur()):void this.menu[t](e);this.search(null,e)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(t,e){this.isMultiLine&&!this.menu.element.is(":visible")||(this._move(t,e),e.preventDefault())},_isContentEditable:function(t){if(!t.length)return!1;var e=t.prop("contentEditable");return"inherit"===e?this._isContentEditable(t.parent()):"true"===e}}),x.extend(x.ui.autocomplete,{escapeRegex:function(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,e){var i=new RegExp(x.ui.autocomplete.escapeRegex(e),"i");return x.grep(t,function(t){return i.test(t.label||t.value||t)})}}),x.widget("ui.autocomplete",x.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(t){return t+(1").text(e))},100))}});x.ui.autocomplete}); \ No newline at end of file +!function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)}(function(x){"use strict";x.ui=x.ui||{};x.ui.version="1.13.2";var n,i=0,l=Array.prototype.hasOwnProperty,a=Array.prototype.slice;x.cleanData=(n=x.cleanData,function(t){for(var e,i,s=0;null!=(i=t[s]);s++)(e=x._data(i,"events"))&&e.remove&&x(i).triggerHandler("remove");n(t)}),x.widget=function(t,i,e){var s,n,o,l={},a=t.split(".")[0],r=a+"-"+(t=t.split(".")[1]);return e||(e=i,i=x.Widget),Array.isArray(e)&&(e=x.extend.apply(null,[{}].concat(e))),x.expr.pseudos[r.toLowerCase()]=function(t){return!!x.data(t,r)},x[a]=x[a]||{},s=x[a][t],n=x[a][t]=function(t,e){if(!this||!this._createWidget)return new n(t,e);arguments.length&&this._createWidget(t,e)},x.extend(n,s,{version:e.version,_proto:x.extend({},e),_childConstructors:[]}),(o=new i).options=x.widget.extend({},o.options),x.each(e,function(e,s){function n(){return i.prototype[e].apply(this,arguments)}function o(t){return i.prototype[e].apply(this,t)}l[e]="function"==typeof s?function(){var t,e=this._super,i=this._superApply;return this._super=n,this._superApply=o,t=s.apply(this,arguments),this._super=e,this._superApply=i,t}:s}),n.prototype=x.widget.extend(o,{widgetEventPrefix:s&&o.widgetEventPrefix||t},l,{constructor:n,namespace:a,widgetName:t,widgetFullName:r}),s?(x.each(s._childConstructors,function(t,e){var i=e.prototype;x.widget(i.namespace+"."+i.widgetName,n,e._proto)}),delete s._childConstructors):i._childConstructors.push(n),x.widget.bridge(t,n),n},x.widget.extend=function(t){for(var e,i,s=a.call(arguments,1),n=0,o=s.length;n",options:{classes:{},disabled:!1,create:null},_createWidget:function(t,e){e=x(e||this.defaultElement||this)[0],this.element=x(e),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=x(),this.hoverable=x(),this.focusable=x(),this.classesElementLookup={},e!==this&&(x.data(e,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===e&&this.destroy()}}),this.document=x(e.style?e.ownerDocument:e.document||e),this.window=x(this.document[0].defaultView||this.document[0].parentWindow)),this.options=x.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:x.noop,_create:x.noop,_init:x.noop,destroy:function(){var i=this;this._destroy(),x.each(this.classesElementLookup,function(t,e){i._removeClass(e,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:x.noop,widget:function(){return this.element},option:function(t,e){var i,s,n,o=t;if(0===arguments.length)return x.widget.extend({},this.options);if("string"==typeof t)if(o={},t=(i=t.split(".")).shift(),i.length){for(s=o[t]=x.widget.extend({},this.options[t]),n=0;n
        "),i=e.children()[0];return x("body").append(e),t=i.offsetWidth,e.css("overflow","scroll"),t===(i=i.offsetWidth)&&(i=e[0].clientWidth),e.remove(),s=t-i},getScrollInfo:function(t){var e=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),i=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),e="scroll"===e||"auto"===e&&t.widthC(E(s),E(n))?o.important="horizontal":o.important="vertical",c.using.call(this,t,o)}),l.offset(x.extend(u,{using:t}))})},x.ui.position={fit:{left:function(t,e){var i=e.within,s=i.isWindow?i.scrollLeft:i.offset.left,n=i.width,o=t.left-e.collisionPosition.marginLeft,l=s-o,a=o+e.collisionWidth-n-s;e.collisionWidth>n?0n?0",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.lastMousePosition={x:null,y:null},this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault(),this._activateItem(t)},"click .ui-menu-item":function(t){var e=x(t.target),i=x(x.ui.safeActiveElement(this.document[0]));!this.mouseHandled&&e.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),e.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&i.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":"_activateItem","mousemove .ui-menu-item":"_activateItem",mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this._menuItems().first();e||this.focus(t,i)},blur:function(t){this._delay(function(){x.contains(this.element[0],x.ui.safeActiveElement(this.document[0]))||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t,!0),this.mouseHandled=!1}})},_activateItem:function(t){var e,i;this.previousFilter||t.clientX===this.lastMousePosition.x&&t.clientY===this.lastMousePosition.y||(this.lastMousePosition={x:t.clientX,y:t.clientY},e=x(t.target).closest(".ui-menu-item"),i=x(t.currentTarget),e[0]===i[0]&&(i.is(".ui-state-active")||(this._removeClass(i.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(t,i))))},_destroy:function(){var t=this.element.find(".ui-menu-item").removeAttr("role aria-disabled").children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),t.children().each(function(){var t=x(this);t.data("ui-menu-submenu-caret")&&t.remove()})},_keydown:function(t){var e,i,s,n=!0;switch(t.keyCode){case x.ui.keyCode.PAGE_UP:this.previousPage(t);break;case x.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case x.ui.keyCode.HOME:this._move("first","first",t);break;case x.ui.keyCode.END:this._move("last","last",t);break;case x.ui.keyCode.UP:this.previous(t);break;case x.ui.keyCode.DOWN:this.next(t);break;case x.ui.keyCode.LEFT:this.collapse(t);break;case x.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case x.ui.keyCode.ENTER:case x.ui.keyCode.SPACE:this._activate(t);break;case x.ui.keyCode.ESCAPE:this.collapse(t);break;default:e=this.previousFilter||"",s=n=!1,i=96<=t.keyCode&&t.keyCode<=105?(t.keyCode-96).toString():String.fromCharCode(t.keyCode),clearTimeout(this.filterTimer),i===e?s=!0:i=e+i,e=this._filterMenuItems(i),(e=s&&-1!==e.index(this.active.next())?this.active.nextAll(".ui-menu-item"):e).length||(i=String.fromCharCode(t.keyCode),e=this._filterMenuItems(i)),e.length?(this.focus(t,e),this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}n&&t.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var t,e,s=this,n=this.options.icons.submenu,i=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),e=i.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=x(this),e=t.prev(),i=x("").data("ui-menu-submenu-caret",!0);s._addClass(i,"ui-menu-icon","ui-icon "+n),e.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",e.attr("id"))}),this._addClass(e,"ui-menu","ui-widget ui-widget-content ui-front"),(t=i.add(this.element).find(this.options.items)).not(".ui-menu-item").each(function(){var t=x(this);s._isDivider(t)&&s._addClass(t,"ui-menu-divider","ui-widget-content")}),i=(e=t.not(".ui-menu-item, .ui-menu-divider")).children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(e,"ui-menu-item")._addClass(i,"ui-menu-item-wrapper"),t.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!x.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){var i;"icons"===t&&(i=this.element.find(".ui-menu-icon"),this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",String(t)),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),i=this.active.children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",i.attr("id")),i=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),(i=e.children(".ui-menu")).length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(t){var e,i,s;this._hasScroll()&&(i=parseFloat(x.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(x.css(this.activeMenu[0],"paddingTop"))||0,e=t.offset().top-this.activeMenu.offset().top-i-s,i=this.activeMenu.scrollTop(),s=this.activeMenu.height(),t=t.outerHeight(),e<0?this.activeMenu.scrollTop(i+e):s",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,liveRegionTimer:null,_create:function(){var i,s,n,t=this.element[0].nodeName.toLowerCase(),e="textarea"===t,t="input"===t;this.isMultiLine=e||!t&&this._isContentEditable(this.element),this.valueMethod=this.element[e||t?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(t){if(this.element.prop("readOnly"))s=n=i=!0;else{s=n=i=!1;var e=x.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:i=!0,this._move("previousPage",t);break;case e.PAGE_DOWN:i=!0,this._move("nextPage",t);break;case e.UP:i=!0,this._keyEvent("previous",t);break;case e.DOWN:i=!0,this._keyEvent("next",t);break;case e.ENTER:this.menu.active&&(i=!0,t.preventDefault(),this.menu.select(t));break;case e.TAB:this.menu.active&&this.menu.select(t);break;case e.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(t),t.preventDefault());break;default:s=!0,this._searchTimeout(t)}}},keypress:function(t){if(i)return i=!1,void(this.isMultiLine&&!this.menu.element.is(":visible")||t.preventDefault());if(!s){var e=x.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:this._move("previousPage",t);break;case e.PAGE_DOWN:this._move("nextPage",t);break;case e.UP:this._keyEvent("previous",t);break;case e.DOWN:this._keyEvent("next",t)}}},input:function(t){if(n)return n=!1,void t.preventDefault();this._searchTimeout(t)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){clearTimeout(this.searching),this.close(t),this._change(t)}}),this._initSource(),this.menu=x("
          ").appendTo(this._appendTo()).menu({role:null}).hide().attr({unselectable:"on"}).menu("instance"),this._addClass(this.menu.element,"ui-autocomplete","ui-front"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault()},menufocus:function(t,e){var i,s;if(this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type)))return this.menu.blur(),void this.document.one("mousemove",function(){x(t.target).trigger(t.originalEvent)});s=e.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",t,{item:s})&&t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(s.value),(i=e.item.attr("aria-label")||s.value)&&String.prototype.trim.call(i).length&&(clearTimeout(this.liveRegionTimer),this.liveRegionTimer=this._delay(function(){this.liveRegion.html(x("
          ").text(i))},100))},menuselect:function(t,e){var i=e.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==x.ui.safeActiveElement(this.document[0])&&(this.element.trigger("focus"),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",t,{item:i})&&this._value(i.value),this.term=this._value(),this.close(t),this.selectedItem=i}}),this.liveRegion=x("
          ",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(t,e){this._super(t,e),"source"===t&&this._initSource(),"appendTo"===t&&this.menu.element.appendTo(this._appendTo()),"disabled"===t&&e&&this.xhr&&this.xhr.abort()},_isEventTargetInWidget:function(t){var e=this.menu.element[0];return t.target===this.element[0]||t.target===e||x.contains(e,t.target)},_closeOnClickOutside:function(t){this._isEventTargetInWidget(t)||this.close()},_appendTo:function(){var t=this.options.appendTo;return t=!(t=!(t=t&&(t.jquery||t.nodeType?x(t):this.document.find(t).eq(0)))||!t[0]?this.element.closest(".ui-front, dialog"):t).length?this.document[0].body:t},_initSource:function(){var i,s,n=this;Array.isArray(this.options.source)?(i=this.options.source,this.source=function(t,e){e(x.ui.autocomplete.filter(i,t.term))}):"string"==typeof this.options.source?(s=this.options.source,this.source=function(t,e){n.xhr&&n.xhr.abort(),n.xhr=x.ajax({url:s,data:t,dataType:"json",success:function(t){e(t)},error:function(){e([])}})}):this.source=this.options.source},_searchTimeout:function(s){clearTimeout(this.searching),this.searching=this._delay(function(){var t=this.term===this._value(),e=this.menu.element.is(":visible"),i=s.altKey||s.ctrlKey||s.metaKey||s.shiftKey;t&&(e||i)||(this.selectedItem=null,this.search(null,s))},this.options.delay)},search:function(t,e){return t=null!=t?t:this._value(),this.term=this._value(),t.length").append(x("
          ").text(e.label)).appendTo(t)},_move:function(t,e){if(this.menu.element.is(":visible"))return this.menu.isFirstItem()&&/^previous/.test(t)||this.menu.isLastItem()&&/^next/.test(t)?(this.isMultiLine||this._value(this.term),void this.menu.blur()):void this.menu[t](e);this.search(null,e)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(t,e){this.isMultiLine&&!this.menu.element.is(":visible")||(this._move(t,e),e.preventDefault())},_isContentEditable:function(t){if(!t.length)return!1;var e=t.prop("contentEditable");return"inherit"===e?this._isContentEditable(t.parent()):"true"===e}}),x.extend(x.ui.autocomplete,{escapeRegex:function(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,e){var i=new RegExp(x.ui.autocomplete.escapeRegex(e),"i");return x.grep(t,function(t){return i.test(t.label||t.value||t)})}}),x.widget("ui.autocomplete",x.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(t){return t+(1").text(e))},100))}});x.ui.autocomplete}); \ No newline at end of file diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java index 9007bf8ed88..aa35b2cd9d7 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,6 +98,11 @@ private static class Item { */ final boolean relative; + /** + * Indicates that docs use old-form of anchors. + */ + final boolean useOldFormId; + /** * Constructor to build a Extern Item object and map it with the element name. * If the same element name is found in the map, then the first mapped @@ -108,10 +113,11 @@ private static class Item { * file is picked. * @param relative True if path is URL, false if directory path. */ - Item(String elementName, DocPath path, boolean relative) { + Item(String elementName, DocPath path, boolean relative, boolean useOldFormId) { this.elementName = elementName; this.path = path; this.relative = relative; + this.useOldFormId = useOldFormId; } /** @@ -179,7 +185,7 @@ public DocLink getExternalLink(Element element, DocPath relativepath, String fil DocPath p = fnd.relative ? relativepath.resolve(fnd.path).resolve(filename) : fnd.path.resolve(filename); - return new DocLink(p, "is-external=true", memberName); + return new DocLink(p, "is-external=true", fnd.useOldFormId ? getOldFormHtmlName(memberName) : memberName); } /** @@ -212,6 +218,18 @@ public boolean link(String url, String elemlisturl, Reporter reporter) throws Do return link(url, elemlisturl, reporter, true); } + /** + * Checks if platform docs for the specified version use old-form anchors. + * Old-form anchors are used by Oracle docs for JDKs 8 and 9. + * It can be checked on https://docs.oracle.com/javase//docs/api + * + * @param version + * @return True if docs use old-form anchors + */ + private boolean isOldFormPlatformDocs(int version) { + return 8 == version || 9 == version; + } + /* * Build the extern element list from given URL or the directory path. * Flag error if the "-link" or "-linkoffline" option is already used. @@ -292,7 +310,7 @@ private String adjustEndFileSeparator(String url) { private void readElementListFromURL(String urlpath, URL elemlisturlpath) throws Fault { try { URL link = elemlisturlpath.toURI().resolve(DocPaths.ELEMENT_LIST.getPath()).toURL(); - readElementList(link.openStream(), urlpath, false); + readElementList(link.openStream(), urlpath, false, false); } catch (URISyntaxException | MalformedURLException exc) { throw new Fault(configuration.getText("doclet.MalformedURL", elemlisturlpath.toString()), exc); } catch (IOException exc) { @@ -309,7 +327,7 @@ private void readElementListFromURL(String urlpath, URL elemlisturlpath) throws private void readAlternateURL(String urlpath, URL elemlisturlpath) throws Fault { try { URL link = elemlisturlpath.toURI().resolve(DocPaths.PACKAGE_LIST.getPath()).toURL(); - readElementList(link.openStream(), urlpath, false); + readElementList(link.openStream(), urlpath, false, true); } catch (URISyntaxException | MalformedURLException exc) { throw new Fault(configuration.getText("doclet.MalformedURL", elemlisturlpath.toString()), exc); } catch (IOException exc) { @@ -332,27 +350,27 @@ private void readElementListFromFile(String path, DocFile elemListPath) file = file.resolveAgainst(DocumentationTool.Location.DOCUMENTATION_OUTPUT); } if (file.exists()) { - readElementList(file, path); + readElementList(file, path, false); } else { DocFile file1 = elemListPath.resolve(DocPaths.PACKAGE_LIST); if (!(file1.isAbsolute() || linkoffline)) { file1 = file1.resolveAgainst(DocumentationTool.Location.DOCUMENTATION_OUTPUT); } if (file1.exists()) { - readElementList(file1, path); + readElementList(file1, path, true); } else { throw new Fault(configuration.getText("doclet.File_error", file.getPath()), null); } } } - private void readElementList(DocFile file, String path) throws Fault, DocFileIOException { + private void readElementList(DocFile file, String path, boolean isOldFormDoc) throws Fault, DocFileIOException { try { if (file.canRead()) { boolean pathIsRelative = !isUrl(path) && !DocFile.createFileForInput(configuration, path).isAbsolute(); - readElementList(file.openInputStream(), path, pathIsRelative); + readElementList(file.openInputStream(), path, pathIsRelative, isOldFormDoc); } else { throw new Fault(configuration.getText("doclet.File_error", file.getPath()), null); } @@ -370,7 +388,7 @@ private void readElementList(DocFile file, String path) throws Fault, DocFileIOE * @param relative Is path relative? * @throws IOException if there is a problem reading or closing the stream */ - private void readElementList(InputStream input, String path, boolean relative) + private void readElementList(InputStream input, String path, boolean relative, boolean isOldFormDoc) throws IOException { try (BufferedReader in = new BufferedReader(new InputStreamReader(input))) { String elemname = null; @@ -382,7 +400,7 @@ private void readElementList(InputStream input, String path, boolean relative) elempath = basePath; if (elemname.startsWith(DocletConstants.MODULE_PREFIX)) { moduleName = elemname.replace(DocletConstants.MODULE_PREFIX, ""); - Item item = new Item(moduleName, elempath, relative); + Item item = new Item(moduleName, elempath, relative, isOldFormDoc); moduleItems.put(moduleName, item); } else { DocPath pkgPath = DocPath.create(elemname.replace('.', '/')); @@ -392,7 +410,7 @@ private void readElementList(InputStream input, String path, boolean relative) elempath = elempath.resolve(pkgPath); } String actualModuleName = checkLinkCompatibility(elemname, moduleName, path); - Item item = new Item(elemname, elempath, relative); + Item item = new Item(elemname, elempath, relative, isOldFormDoc); packageItems.computeIfAbsent(actualModuleName, k -> new TreeMap<>()) .put(elemname, item); } @@ -455,4 +473,65 @@ private String checkLinkCompatibility(String packageName, String moduleName, Str } return moduleName == null ? DocletConstants.DEFAULT_ELEMENT_NAME : moduleName; } + + /** + * Converts a name to an old-form HTML name (old-form id). + * + * @param name the string that needs to be converted to a valid HTML name + * @return old-form HTML name + */ + public static String getOldFormHtmlName(String name) { + /* The HTML 4 spec at http://www.w3.org/TR/html4/types.html#h-6.2 mentions + * that the name/id should begin with a letter followed by other valid characters. + * The HTML 5 spec (draft) is more permissive on names/ids where the only restriction + * is that it should be at least one character long and should not contain spaces. + * The spec draft is @ http://www.w3.org/html/wg/drafts/html/master/dom.html#the-id-attribute. + * + * For HTML 4, we need to check for non-characters at the beginning of the name and + * substitute it accordingly, "_" and "$" can appear at the beginning of a member name. + * The method substitutes "$" with "Z:Z:D" and will prefix "_" with "Z:Z". + */ + + if (null == name) + return name; + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < name.length(); i++) { + char ch = name.charAt(i); + switch (ch) { + case '(': + case ')': + case '<': + case '>': + case ',': + sb.append('-'); + break; + case ' ': + case '[': + break; + case ']': + sb.append(":A"); + break; + // Any appearance of $ needs to be substituted with ":D" and not with hyphen + // since a field name "P$$ and a method P(), both valid member names, can end + // up as "P--". A member name beginning with $ needs to be substituted with + // "Z:Z:D". + case '$': + if (i == 0) + sb.append("Z:Z"); + sb.append(":D"); + break; + // A member name beginning with _ needs to be prefixed with "Z:Z" since valid anchor + // names can only begin with a letter. + case '_': + if (i == 0) + sb.append("Z:Z"); + sb.append(ch); + break; + default: + sb.append(ch); + } + } + return sb.toString(); + } } diff --git a/src/jdk.javadoc/share/legal/jqueryUI.md b/src/jdk.javadoc/share/legal/jqueryUI.md index 8031bdb56ef..8bda9d7a85e 100644 --- a/src/jdk.javadoc/share/legal/jqueryUI.md +++ b/src/jdk.javadoc/share/legal/jqueryUI.md @@ -1,4 +1,4 @@ -## jQuery UI v1.12.1 +## jQuery UI v1.13.2 ### jQuery UI License ``` diff --git a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Env.java b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Env.java index 1af357322a9..f195ad5fc44 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Env.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Env.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -57,8 +57,8 @@ class Env { private static HashMap savedValues = new HashMap(); private static Method atExitMethod; - static void init(String connectSpec, boolean openNow, int flags) { - connection = new VMConnection(connectSpec, flags); + static void init(String connectSpec, boolean openNow, int flags, String extraOptions) { + connection = new VMConnection(connectSpec, flags, extraOptions); if (!connection.isLaunch() || openNow) { connection.open(); } diff --git a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java index 4f7a0551a93..884fe86dfc4 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -1047,8 +1047,8 @@ public static void main(String argv[]) throws MissingResourceException { /* * Here are examples of jdb command lines and how the options * are interpreted as arguments to the program being debugged. - * arg1 arg2 - * ---- ---- + * arg1 arg2 + * ---- ---- * jdb hello a b a b * jdb hello "a b" a b * jdb hello a,b a,b @@ -1085,14 +1085,10 @@ public static void main(String argv[]) throws MissingResourceException { connectSpec); return; } - connectSpec += "options=" + javaArgs + ","; } try { - if (! connectSpec.endsWith(",")) { - connectSpec += ","; // (Bug ID 4285874) - } - Env.init(connectSpec, launchImmediately, traceFlags); + Env.init(connectSpec, launchImmediately, traceFlags, javaArgs); new TTY(); } catch(Exception e) { MessageOutput.printException("Internal exception:", e); diff --git a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/VMConnection.java b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/VMConnection.java index db48b3f8357..de355ba5d82 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/VMConnection.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/VMConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -78,7 +78,8 @@ private Connector findConnector(String name) { return null; } - private Map parseConnectorArgs(Connector connector, String argString) { + private Map + parseConnectorArgs(Connector connector, String argString, String extraOptions) { Map arguments = connector.defaultArguments(); /* @@ -121,10 +122,20 @@ private Map parseConnectorArgs( */ if (name.equals("options")) { StringBuilder sb = new StringBuilder(); + if (extraOptions != null) { + sb.append(extraOptions).append(" "); + // set extraOptions to null to avoid appending it again + extraOptions = null; + } for (String s : splitStringAtNonEnclosedWhiteSpace(value)) { + boolean wasEnclosed = false; while (isEnclosed(s, "\"") || isEnclosed(s, "'")) { + wasEnclosed = true; s = s.substring(1, s.length() - 1); } + if (wasEnclosed && hasWhitespace(s)) { + s = "\"" + s + "\""; + } sb.append(s); sb.append(" "); } @@ -150,9 +161,26 @@ private Map parseConnectorArgs( throw new IllegalArgumentException (MessageOutput.format("Illegal connector argument", argString)); } + if (extraOptions != null) { + // there was no "options" specified in argString + Connector.Argument argument = arguments.get("options"); + if (argument != null) { + argument.setValue(extraOptions); + } + } return arguments; } + private static boolean hasWhitespace(String string) { + int length = string.length(); + for (int i = 0; i < length; i++) { + if (Character.isWhitespace(string.charAt(i))) { + return true; + } + } + return false; + } + private static boolean isEnclosed(String value, String enclosingChar) { if (value.indexOf(enclosingChar) == 0) { int lastIndex = value.lastIndexOf(enclosingChar); @@ -299,7 +327,7 @@ static private boolean isLastChar(char[] arr, int pos) { return (pos + 1 == arr.length); } - VMConnection(String connectSpec, int traceFlags) { + VMConnection(String connectSpec, int traceFlags, String extraOptions) { String nameString; String argString; int index = connectSpec.indexOf(':'); @@ -317,7 +345,7 @@ static private boolean isLastChar(char[] arr, int pos) { (MessageOutput.format("No connector named:", nameString)); } - connectorArgs = parseConnectorArgs(connector, argString); + connectorArgs = parseConnectorArgs(connector, argString, extraOptions); this.traceFlags = traceFlags; } diff --git a/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java b/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java index 8d2031f888b..ff937e44c92 100644 --- a/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java +++ b/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.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 @@ -902,9 +902,6 @@ public ServerSocket createServerSocket(int port) throws IOException { private static class HostAwareSslSocketFactory extends SslRMIServerSocketFactory { private final String bindAddress; - private final String[] enabledCipherSuites; - private final String[] enabledProtocols; - private final boolean needClientAuth; private final SSLContext context; private HostAwareSslSocketFactory(String[] enabledCipherSuites, @@ -919,11 +916,9 @@ private HostAwareSslSocketFactory(SSLContext ctx, String[] enabledProtocols, boolean sslNeedClientAuth, String bindAddress) throws IllegalArgumentException { - this.context = ctx; + super(ctx, enabledCipherSuites, enabledProtocols, sslNeedClientAuth); this.bindAddress = bindAddress; - this.enabledProtocols = enabledProtocols; - this.enabledCipherSuites = enabledCipherSuites; - this.needClientAuth = sslNeedClientAuth; + this.context = ctx; checkValues(ctx, enabledCipherSuites, enabledProtocols); } @@ -933,14 +928,15 @@ public ServerSocket createServerSocket(int port) throws IOException { try { InetAddress addr = InetAddress.getByName(bindAddress); return new SslServerSocket(port, 0, addr, context, - enabledCipherSuites, enabledProtocols, needClientAuth); + this.getEnabledCipherSuites(), this.getEnabledProtocols(), + this.getNeedClientAuth()); } catch (UnknownHostException e) { return new SslServerSocket(port, context, - enabledCipherSuites, enabledProtocols, needClientAuth); + this.getEnabledCipherSuites(), this.getEnabledProtocols(), this.getNeedClientAuth()); } } else { return new SslServerSocket(port, context, - enabledCipherSuites, enabledProtocols, needClientAuth); + this.getEnabledCipherSuites(), this.getEnabledProtocols(), this.getNeedClientAuth()); } } diff --git a/src/jdk.pack/share/native/libunpack/jni.cpp b/src/jdk.pack/share/native/libunpack/jni.cpp index 069df3f3a35..b0ff3eacfb7 100644 --- a/src/jdk.pack/share/native/libunpack/jni.cpp +++ b/src/jdk.pack/share/native/libunpack/jni.cpp @@ -314,9 +314,12 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_getUnusedInput(JNIEnv *env, jobject JNIEXPORT jlong JNICALL Java_com_sun_java_util_jar_pack_NativeUnpack_finish(JNIEnv *env, jobject pObj) { - unpacker* uPtr = get_unpacker(env, pObj, false); + // There's no need to create a new unpacker here if we don't already have one + // just to immediatly free it afterwards. + unpacker* uPtr = get_unpacker(env, pObj, /* noCreate= */ true); CHECK_EXCEPTION_RETURN_VALUE(uPtr, 0); size_t consumed = uPtr->input_consumed(); + // free_unpacker() will set the unpacker field on 'pObj' to null free_unpacker(env, pObj, uPtr); return consumed; } diff --git a/src/jdk.security.auth/share/classes/com/sun/security/auth/LdapPrincipal.java b/src/jdk.security.auth/share/classes/com/sun/security/auth/LdapPrincipal.java index 6af39422d5f..04e79414247 100644 --- a/src/jdk.security.auth/share/classes/com/sun/security/auth/LdapPrincipal.java +++ b/src/jdk.security.auth/share/classes/com/sun/security/auth/LdapPrincipal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package com.sun.security.auth; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.security.Principal; import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; @@ -135,4 +138,30 @@ public String toString() { private LdapName getLdapName(String name) throws InvalidNameException { return new LdapName(name); } + + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if ((name == null) || (nameString == null)) { + throw new InvalidObjectException( + "null name/nameString is illegal"); + } + try { + if (!name.equals(getLdapName(nameString))) { + throw new InvalidObjectException("Inconsistent names"); + } + } catch (InvalidNameException e) { + InvalidObjectException nse = new InvalidObjectException( + "Invalid Name"); + nse.initCause(e); + throw nse; + } + } } diff --git a/src/jdk.security.auth/share/classes/com/sun/security/auth/NTDomainPrincipal.java b/src/jdk.security.auth/share/classes/com/sun/security/auth/NTDomainPrincipal.java index ed9c2eff568..44330647da9 100644 --- a/src/jdk.security.auth/share/classes/com/sun/security/auth/NTDomainPrincipal.java +++ b/src/jdk.security.auth/share/classes/com/sun/security/auth/NTDomainPrincipal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package com.sun.security.auth; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.security.Principal; /** @@ -120,9 +123,7 @@ public boolean equals(Object o) { return false; NTDomainPrincipal that = (NTDomainPrincipal)o; - if (name.equals(that.getName())) - return true; - return false; + return name.equals(that.getName()); } /** @@ -133,4 +134,23 @@ public boolean equals(Object o) { public int hashCode() { return this.getName().hashCode(); } + + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if (name == null) { + java.text.MessageFormat form = new java.text.MessageFormat + (sun.security.util.ResourcesMgr.getAuthResourceString + ("invalid.null.input.value")); + Object[] source = {"name"}; + throw new InvalidObjectException(form.format(source)); + } + } } diff --git a/src/jdk.security.auth/share/classes/com/sun/security/auth/NTSid.java b/src/jdk.security.auth/share/classes/com/sun/security/auth/NTSid.java index b5e2dc7d6d6..1cc8731fa95 100644 --- a/src/jdk.security.auth/share/classes/com/sun/security/auth/NTSid.java +++ b/src/jdk.security.auth/share/classes/com/sun/security/auth/NTSid.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package com.sun.security.auth; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.security.Principal; /** @@ -80,7 +83,7 @@ public NTSid (String stringSid) { (sun.security.util.ResourcesMgr.getAuthResourceString ("Invalid.NTSid.value")); } - sid = new String(stringSid); + sid = stringSid; } /** @@ -128,10 +131,7 @@ public boolean equals(Object o) { return false; NTSid that = (NTSid)o; - if (sid.equals(that.sid)) { - return true; - } - return false; + return sid.equals(that.sid); } /** @@ -142,4 +142,28 @@ public boolean equals(Object o) { public int hashCode() { return sid.hashCode(); } + + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if (sid == null) { + java.text.MessageFormat form = new java.text.MessageFormat + (sun.security.util.ResourcesMgr.getAuthResourceString + ("invalid.null.input.value")); + Object[] source = {"stringSid"}; + throw new InvalidObjectException(form.format(source)); + } + if (sid.length() == 0) { + throw new InvalidObjectException + (sun.security.util.ResourcesMgr.getAuthResourceString + ("Invalid.NTSid.value")); + } + } } diff --git a/src/jdk.security.auth/share/classes/com/sun/security/auth/NTUserPrincipal.java b/src/jdk.security.auth/share/classes/com/sun/security/auth/NTUserPrincipal.java index a7c2ce97cd0..c236b9a780c 100644 --- a/src/jdk.security.auth/share/classes/com/sun/security/auth/NTUserPrincipal.java +++ b/src/jdk.security.auth/share/classes/com/sun/security/auth/NTUserPrincipal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package com.sun.security.auth; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.security.Principal; /** @@ -114,9 +117,7 @@ public boolean equals(Object o) { return false; NTUserPrincipal that = (NTUserPrincipal)o; - if (name.equals(that.getName())) - return true; - return false; + return name.equals(that.getName()); } /** @@ -127,4 +128,24 @@ public boolean equals(Object o) { public int hashCode() { return this.getName().hashCode(); } + + + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if (name == null) { + java.text.MessageFormat form = new java.text.MessageFormat + (sun.security.util.ResourcesMgr.getAuthResourceString + ("invalid.null.input.value")); + Object[] source = {"name"}; + throw new InvalidObjectException(form.format(source)); + } + } } diff --git a/src/jdk.security.auth/share/classes/com/sun/security/auth/UnixNumericGroupPrincipal.java b/src/jdk.security.auth/share/classes/com/sun/security/auth/UnixNumericGroupPrincipal.java index 2780f56ff3b..24f5c87be66 100644 --- a/src/jdk.security.auth/share/classes/com/sun/security/auth/UnixNumericGroupPrincipal.java +++ b/src/jdk.security.auth/share/classes/com/sun/security/auth/UnixNumericGroupPrincipal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package com.sun.security.auth; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.security.Principal; import java.util.Objects; @@ -184,10 +187,8 @@ public boolean equals(Object o) { return false; UnixNumericGroupPrincipal that = (UnixNumericGroupPrincipal)o; - if (this.getName().equals(that.getName()) && - this.isPrimaryGroup() == that.isPrimaryGroup()) - return true; - return false; + return this.getName().equals(that.getName()) && + this.isPrimaryGroup() == that.isPrimaryGroup(); } /** @@ -198,4 +199,23 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(name, isPrimaryGroup()); } + + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if (name == null) { + java.text.MessageFormat form = new java.text.MessageFormat + (sun.security.util.ResourcesMgr.getAuthResourceString + ("invalid.null.input.value")); + Object[] source = {"name"}; + throw new InvalidObjectException(form.format(source)); + } + } } diff --git a/src/jdk.security.auth/share/classes/com/sun/security/auth/UnixNumericUserPrincipal.java b/src/jdk.security.auth/share/classes/com/sun/security/auth/UnixNumericUserPrincipal.java index 30a1e9ca81d..4b38d31b201 100644 --- a/src/jdk.security.auth/share/classes/com/sun/security/auth/UnixNumericUserPrincipal.java +++ b/src/jdk.security.auth/share/classes/com/sun/security/auth/UnixNumericUserPrincipal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package com.sun.security.auth; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.security.Principal; /** @@ -146,9 +149,7 @@ public boolean equals(Object o) { return false; UnixNumericUserPrincipal that = (UnixNumericUserPrincipal)o; - if (this.getName().equals(that.getName())) - return true; - return false; + return this.getName().equals(that.getName()); } /** @@ -159,4 +160,23 @@ public boolean equals(Object o) { public int hashCode() { return name.hashCode(); } + + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if (name == null) { + java.text.MessageFormat form = new java.text.MessageFormat + (sun.security.util.ResourcesMgr.getAuthResourceString + ("invalid.null.input.value")); + Object[] source = {"name"}; + throw new InvalidObjectException(form.format(source)); + } + } } diff --git a/src/jdk.security.auth/share/classes/com/sun/security/auth/UnixPrincipal.java b/src/jdk.security.auth/share/classes/com/sun/security/auth/UnixPrincipal.java index fde93a62a53..d6660f02d41 100644 --- a/src/jdk.security.auth/share/classes/com/sun/security/auth/UnixPrincipal.java +++ b/src/jdk.security.auth/share/classes/com/sun/security/auth/UnixPrincipal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package com.sun.security.auth; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.security.Principal; /** @@ -115,9 +118,7 @@ public boolean equals(Object o) { return false; UnixPrincipal that = (UnixPrincipal)o; - if (this.getName().equals(that.getName())) - return true; - return false; + return this.getName().equals(that.getName()); } /** @@ -128,4 +129,23 @@ public boolean equals(Object o) { public int hashCode() { return name.hashCode(); } + + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if (name == null) { + java.text.MessageFormat form = new java.text.MessageFormat + (sun.security.util.ResourcesMgr.getAuthResourceString + ("invalid.null.input.value")); + Object[] source = {"name"}; + throw new InvalidObjectException(form.format(source)); + } + } } diff --git a/src/jdk.security.auth/share/classes/com/sun/security/auth/UserPrincipal.java b/src/jdk.security.auth/share/classes/com/sun/security/auth/UserPrincipal.java index 04b133e4004..5813f974a77 100644 --- a/src/jdk.security.auth/share/classes/com/sun/security/auth/UserPrincipal.java +++ b/src/jdk.security.auth/share/classes/com/sun/security/auth/UserPrincipal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package com.sun.security.auth; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.security.Principal; /** @@ -109,4 +112,19 @@ public String getName() { public String toString() { return name; } + + /** + * Restores the state of this object from the stream. + * + * @param stream the {@code ObjectInputStream} from which data is read + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if (name == null) { + throw new InvalidObjectException("null name is illegal"); + } + } } diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java index abd96c42cfd..c9cbf6b4744 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java @@ -2575,10 +2575,22 @@ void readExtra(ZipFileSystem zipfs) throws IOException { int sz = SH(extra, pos + 2); pos += 4; if (pos + sz > elen) { // invalid data - throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)"); + throw new ZipException(String.format( + "Invalid CEN header (invalid extra data field size for " + + "tag: 0x%04x size: %d)", + tag, sz)); } switch (tag) { case EXTID_ZIP64 : + // if ZIP64_EXTID blocksize == 0, which may occur with some older + // versions of Apache Ant and Commons Compress, validate csize + // size, and locoff to make sure the fields != ZIP64_MAGICVAL + if (sz == 0) { + if (csize == ZIP64_MINVAL || size == ZIP64_MINVAL || locoff == ZIP64_MINVAL) { + throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)"); + } + break; + } // Check to see if we have a valid block size if (!isZip64ExtBlockSizeValid(sz)) { throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)"); diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index d0daea4a718..7385ba25693 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -40,13 +40,67 @@ # :hotspot_compiler +compiler/aot/DeoptimizationTest.java 8310619 macosx-x64 +compiler/aot/RecompilationTest.java 8310619 macosx-x64 +compiler/aot/SharedUsageTest.java 8310619 macosx-x64 +compiler/aot/TestHeapBase.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeDynamic2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeDynamic2CompiledTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeDynamic2InterpretedTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeDynamic2NativeTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeInterface2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeInterface2CompiledTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeInterface2InterpretedTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeInterface2NativeTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeSpecial2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeSpecial2CompiledTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeSpecial2InterpretedTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeSpecial2NativeTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeStatic2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeStatic2CompiledTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeStatic2InterpretedTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeStatic2NativeTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeVirtual2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeVirtual2CompiledTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeVirtual2InterpretedTest.java 8310619 macosx-x64 +compiler/aot/calls/fromAot/AotInvokeVirtual2NativeTest.java 8310619 macosx-x64 +compiler/aot/calls/fromCompiled/CompiledInvokeDynamic2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromCompiled/CompiledInvokeInterface2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromCompiled/CompiledInvokeSpecial2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromCompiled/CompiledInvokeStatic2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromCompiled/CompiledInvokeVirtual2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromInterpreted/InterpretedInvokeDynamic2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromInterpreted/InterpretedInvokeInterface2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromInterpreted/InterpretedInvokeSpecial2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromInterpreted/InterpretedInvokeStatic2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromInterpreted/InterpretedInvokeVirtual2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromNative/NativeInvokeSpecial2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromNative/NativeInvokeStatic2AotTest.java 8310619 macosx-x64 +compiler/aot/calls/fromNative/NativeInvokeVirtual2AotTest.java 8310619 macosx-x64 +compiler/aot/cli/DisabledAOTWithLibraryTest.java 8310619 macosx-x64 +compiler/aot/cli/MultipleAOTLibraryTest.java 8310619 macosx-x64 +compiler/aot/cli/SingleAOTLibraryTest.java 8310619 macosx-x64 +compiler/aot/cli/SingleAOTOptionTest.java 8310619 macosx-x64 +compiler/aot/cli/jaotc/AtFileTest.java 8310619 macosx-x64 +compiler/aot/cli/jaotc/CompileClassTest.java 8310619 macosx-x64 +compiler/aot/cli/jaotc/CompileClassWithDebugTest.java 8303074,8310619 linux-aarch64,macosx-x64 +compiler/aot/cli/jaotc/CompileDirectoryTest.java 8310619 macosx-x64 +compiler/aot/cli/jaotc/CompileJarTest.java 8310619 macosx-x64 +compiler/aot/cli/jaotc/CompileModuleTest.java 8310619 macosx-x64 +compiler/aot/cli/jaotc/IgnoreErrorsTest.java 8310619 macosx-x64 +compiler/aot/cli/jaotc/ListOptionTest.java 8310619 macosx-x64 +compiler/aot/cli/jaotc/ListOptionWrongFileTest.java 8310619 macosx-x64 +compiler/aot/fingerprint/SelfChanged.java 8310619 macosx-x64 +compiler/aot/fingerprint/SelfChangedCDS.java 8310619 macosx-x64 +compiler/aot/fingerprint/SuperChanged.java 8310619 macosx-x64 +compiler/aot/verification/ClassAndLibraryNotMatchTest.java 8310619 macosx-x64 compiler/aot/verification/vmflags/TrackedFlagTest.java 8215224 generic-all compiler/aot/verification/vmflags/NotTrackedFlagTest.java 8215224 generic-all -compiler/aot/cli/jaotc/CompileClassWithDebugTest.java 8303074 linux-aarch64 compiler/ciReplay/TestSAServer.java 8029528 generic-all compiler/codecache/stress/OverloadCompileQueueTest.java 8166554 generic-all compiler/codegen/Test6896617.java 8193479 generic-all compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java 8140405 generic-all +compiler/gcbarriers/UnsafeIntrinsicsTest.java#z 8315528 linux-x64 compiler/jvmci/compilerToVM/GetFlagValueTest.java 8204459 generic-all compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java 8158860 generic-all compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java 8163894 generic-all @@ -65,13 +119,13 @@ compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java 8190680 generic-all compiler/runtime/Test8168712.java 8211769,8211771 generic-ppc64,generic-ppc64le,linux-s390x compiler/rtm/locking/TestRTMAbortRatio.java 8183263 generic-x64,generic-i586 -compiler/rtm/locking/TestRTMAbortThreshold.java 8183263 generic-x64,generic-i586 +compiler/rtm/locking/TestRTMAbortThreshold.java 8183263,8313877 generic-x64,generic-i586,generic-ppc64le compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java 8183263 generic-x64,generic-i586 compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java 8183263 generic-x64,generic-i586 compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java 8183263 generic-x64,generic-i586 compiler/rtm/locking/TestRTMLockingCalculationDelay.java 8183263 generic-x64,generic-i586 compiler/rtm/locking/TestRTMLockingThreshold.java 8183263 generic-x64,generic-i586 -compiler/rtm/locking/TestRTMSpinLoopCount.java 8183263 generic-x64,generic-i586 +compiler/rtm/locking/TestRTMSpinLoopCount.java 8183263,8313877 generic-x64,generic-i586,generic-ppc64le compiler/rtm/locking/TestUseRTMDeopt.java 8183263 generic-x64,generic-i586 compiler/rtm/locking/TestUseRTMXendForLockBusy.java 8183263 generic-x64,generic-i586 compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java 8183263 generic-x64,generic-i586 @@ -96,11 +150,13 @@ gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8193639 solaris-all gc/stress/gcbasher/TestGCBasherWithCMS.java 8272195 generic-i586 gc/cms/TestBubbleUpRef.java 8272195 generic-i586 gc/stress/gcold/TestGCOldWithCMS.java 8272195 generic-i586 +gc/stress/gcold/TestGCOldWithZ.java 8315531 linux-x64 ############################################################################# # :hotspot_runtime +runtime/CompressedOops/CompressedClassPointers.java 8305765 generic-all runtime/CompressedOops/UseCompressedOops.java 8079353 generic-all runtime/handshake/HandshakeWalkSuspendExitTest.java 8214174 generic-all runtime/SharedArchiveFile/SASymbolTableTest.java 8193639 solaris-all diff --git a/test/hotspot/jtreg/compiler/aot/verification/ClassAndLibraryNotMatchTest.java b/test/hotspot/jtreg/compiler/aot/verification/ClassAndLibraryNotMatchTest.java index 23acef2236c..e1640841cd1 100644 --- a/test/hotspot/jtreg/compiler/aot/verification/ClassAndLibraryNotMatchTest.java +++ b/test/hotspot/jtreg/compiler/aot/verification/ClassAndLibraryNotMatchTest.java @@ -92,7 +92,7 @@ private void compileAotLibrary() { private void runAndCheckHelloWorld(String checkString) { ProcessBuilder pb; try { - pb = ProcessTools.createJavaProcessBuilder(true, "-cp", ".", + pb = ProcessTools.createTestJvm("-cp", ".", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseAOT", "-XX:AOTLibrary=./" + LIB_NAME, HELLO_WORLD_CLASS_NAME); } catch (Exception e) { diff --git a/test/hotspot/jtreg/compiler/aot/verification/vmflags/BasicFlagsChange.java b/test/hotspot/jtreg/compiler/aot/verification/vmflags/BasicFlagsChange.java index c52a6f5f7f9..e2ca3784913 100644 --- a/test/hotspot/jtreg/compiler/aot/verification/vmflags/BasicFlagsChange.java +++ b/test/hotspot/jtreg/compiler/aot/verification/vmflags/BasicFlagsChange.java @@ -87,7 +87,7 @@ private static void runAndCheck(String option, String libName, so, a message like "skipped $pathTolibrary aot library" or "loaded $pathToLibrary aot library" is present for cases of incompatible or compatible flags respectively */ - pb = ProcessTools.createJavaProcessBuilder(true, "-XX:+UnlockExperimentalVMOptions", + pb = ProcessTools.createTestJvm("-XX:+UnlockExperimentalVMOptions", "-XX:+UseAOT", "-XX:+PrintAOT", "-XX:AOTLibrary=./" + libName, option, HelloWorldPrinter.class.getName()); } catch (Exception ex) { diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyIntrinsicWithUCT.java b/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyIntrinsicWithUCT.java new file mode 100644 index 00000000000..1ce5e19cbf2 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyIntrinsicWithUCT.java @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8297730 + * @summary Test taking UCT between array allocation and array copy to report correct exception. + * @library /test/lib + * @run main/othervm -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.arraycopy.TestArrayCopyIntrinsicWithUCT::test* + * compiler.arraycopy.TestArrayCopyIntrinsicWithUCT + */ + +package compiler.arraycopy; + +import jdk.test.lib.Asserts; + +import java.util.function.Function; +import java.util.function.Supplier; + +public class TestArrayCopyIntrinsicWithUCT { + static int zero = 0; + static int zero2 = 0; + static int minusOne = -1; + static int iFld; + static int iFld2; + static boolean flag; + static byte[] byArrNull = null; + static A aFld = null; + + static public void main(String[] args) { + System.out.println("Start"); // Ensure loaded. + new A(); // Ensure loaded + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSize); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSize2); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeFldSize); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeFldSize2); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeStore); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeStore2); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZero); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZero2); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZero3); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZero4); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZero5); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZero6); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZero7); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZeroFld); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZeroFld2); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZeroFld3); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZeroFld4); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZeroFld5); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZeroFld6); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZeroFld7); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeDivZeroNullPointer); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeSizeComplex); + runNegativeSize(TestArrayCopyIntrinsicWithUCT::testNegativeControlFlowNotAllowed); + flag = false; + runNegativeSizeHalf(); + runNegativeSizeHalf(); + } + + static void runNegativeSize(Supplier testMethod) { + try { + testMethod.get(); + Asserts.fail("should throw exception"); + } catch (NegativeArraySizeException e) { + // Expected + } + } + + static void runNegativeSize(Function testMethod) { + try { + testMethod.apply(null); + Asserts.fail("should throw exception"); + } catch (NegativeArraySizeException e) { + // Expected + } + } + + static byte[] testNegativeSize(byte[] byArr) { + byte[] b = new byte[-1]; // throws NegativeArraySizeException + int len = byArr.length; // null check trap would fail + System.arraycopy(byArr, 0, b, 0, len); + return b; + } + + static byte[] testNegativeSize2() { + byte[] byArr = new byte[8]; + byte[] b = new byte[-1]; // throws NegativeArraySizeException + int len = byArrNull.length; // null check trap would fail + System.arraycopy(byArr, 0, b, 0, len); + return b; + } + + static byte[] testNegativeFldSize(byte[] byArr) { + byte[] b = new byte[minusOne]; // throws NegativeArraySizeException + int len = byArr.length; // null check trap would fail + System.arraycopy(byArr, 0, b, 0, len); + return b; + } + static byte[] testNegativeFldSize2() { + byte[] byArr = new byte[8]; + byte[] b = new byte[minusOne]; // throws NegativeArraySizeException + int len = byArrNull.length; // null check trap would fail + System.arraycopy(byArr, 0, b, 0, len); + return b; + } + + static byte[] testNegativeSizeStore(byte[] byArr) { + byte[] b = new byte[minusOne]; // throws NegativeArraySizeException + iFld++; // Since we have a store here, we do not move the allocation down + int len = byArr.length; // null check trap would fail + System.arraycopy(byArr, 0, b, 0, len); + return b; + } + + static byte[] testNegativeSizeStore2() { + byte[] byArr = new byte[8]; + byte[] b = new byte[minusOne]; // throws NegativeArraySizeException + iFld++; // Since we have a store here, we do not move the allocation down + int len = byArrNull.length; // null check trap would fail + System.arraycopy(byArr, 0, b, 0, len); + return b; + } + + static byte[] testNegativeSizeDivZero(byte[] byArr) { + byte[] b = new byte[-1]; // throws NegativeArraySizeException + int len = 8 / zero; // div by zero trap would fail + System.arraycopy(byArr, 0, b, 0, len); + return b; + } + + static byte[] testNegativeSizeDivZero2() { + byte[] byArr = new byte[8]; + byte[] b = new byte[-1]; // throws NegativeArraySizeException + int len = 8 / zero; // div by zero trap would fail + System.arraycopy(byArr, 0, b, 0, len); + return b; + } + + static byte[] testNegativeSizeDivZero3(byte[] byArr) { + byte[] b = new byte[-1]; // throws NegativeArraySizeException + int len = 8 / zero; // div by zero trap would fail + System.arraycopy(byArr, 0, b, 0, iFld2); + iFld = len; + return b; + } + + static byte[] testNegativeSizeDivZero4(byte[] byArr) { + byte[] b = new byte[-1]; // throws NegativeArraySizeException + int len = 8 / zero / zero2; // 2 div by zero traps would fail + System.arraycopy(byArr, 0, b, 0, iFld2); + iFld = len; + return b; + } + + static byte[] testNegativeSizeDivZero5(byte[] byArr) { + byte[] b = new byte[minusOne]; // throws NegativeArraySizeException + int len = 8 / zero / zero2; // 2 div by zero traps would fail + System.arraycopy(byArr, 0, b, 0, iFld2); + iFld = len; + return b; + } + + static byte[] testNegativeSizeDivZero6(byte[] byArr) { + byte[] b = new byte[minusOne]; // throws NegativeArraySizeException + int len = 8 / zero / zero2; // 2 div by zero traps would fail + System.arraycopy(byArr, 0, b, 0, 8); + iFld = len; + return b; + } + + static byte[] testNegativeSizeDivZero7(byte[] byArr) { + byte[] b = new byte[-1]; // throws NegativeArraySizeException + int len = 8 / zero / zero2; // 2 div by zero traps would fail + System.arraycopy(byArr, 0, b, 0, 8); + iFld = len; + return b; + } + + static byte[] testNegativeSizeDivZeroFld(byte[] byArr) { + byte[] b = new byte[-1]; // throws NegativeArraySizeException + int len = minusOne / zero; // div by zero trap would fail + System.arraycopy(byArr, 0, b, 0, len); + return b; + } + + static byte[] testNegativeSizeDivZeroFld2() { + byte[] byArr = new byte[8]; + byte[] b = new byte[-1]; // throws NegativeArraySizeException + int len = minusOne / zero; // div by zero trap would fail + System.arraycopy(byArr, 0, b, 0, len); + return b; + } + + static byte[] testNegativeSizeDivZeroFld3(byte[] byArr) { + byte[] b = new byte[-1]; // throws NegativeArraySizeException + int len = minusOne / zero; // div by zero trap would fail + System.arraycopy(byArr, 0, b, 0, iFld2); + iFld = len; + return b; + } + + static byte[] testNegativeSizeDivZeroFld4(byte[] byArr) { + byte[] b = new byte[-1]; // throws NegativeArraySizeException + int len = minusOne / zero / zero2; // div by zero trap would fail + System.arraycopy(byArr, 0, b, 0, iFld2); + iFld = len; + return b; + } + + static byte[] testNegativeSizeDivZeroFld5(byte[] byArr) { + byte[] b = new byte[minusOne]; // throws NegativeArraySizeException + int len = minusOne / zero / zero2; // div by zero trap would fail + System.arraycopy(byArr, 0, b, 0, iFld2); + iFld = len; + return b; + } + + static byte[] testNegativeSizeDivZeroFld6(byte[] byArr) { + byte[] b = new byte[minusOne]; // throws NegativeArraySizeException + int len = minusOne / zero / zero2; // div by zero trap would fail + System.arraycopy(byArr, 0, b, 0, 8); + iFld = len; + return b; + } + + static byte[] testNegativeSizeDivZeroFld7(byte[] byArr) { + byte[] b = new byte[-1]; // throws NegativeArraySizeException + int len = minusOne / zero / zero2; // div by zero trap would fail + System.arraycopy(byArr, 0, b, 0, 8); + iFld = len; + return b; + } + + static byte[] testNegativeSizeDivZeroNullPointer(byte[] byArr) { + byte[] b = new byte[minusOne]; // throws NegativeArraySizeException + int x = minusOne / zero / zero2; // div by zero trap would fail + int len = byArr.length; + System.arraycopy(byArr, 0, b, 0, len); + iFld = x; + return b; + } + + static byte[] testNegativeSizeComplex(byte[] byArr) { + byte[] b = new byte[minusOne]; // throws NegativeArraySizeException + int x = minusOne / zero; // div by zero trap would fail + int y = aFld.i; + int len = byArr.length; + x = x + aFld.i2 / zero2; + System.arraycopy(byArr, 0, b, 0, x); + iFld = x + y; + return b; + } + + // Optimization not applied because of additional control flow that is not considered safe. + static byte[] testNegativeControlFlowNotAllowed(byte[] byArr) { + int x = 23; + byte[] b = new byte[minusOne]; // throws NegativeArraySizeException + if (flag) { + x = 34; + } + int len = x / zero; + System.arraycopy(byArr, 0, b, 0, 8); + iFld = len; + return b; + } + + static void runNegativeSizeHalf() { + try { + testNegativeSizeHalf(null); + Asserts.fail("should throw exception"); + } catch (NegativeArraySizeException e) { + Asserts.assertTrue(flag, "wrongly caught NegativeArraySizeException"); + } catch (NullPointerException e) { + Asserts.assertFalse(flag, "wrongly caught NullPointerException"); + } + flag = !flag; + } + + static byte[] testNegativeSizeHalf(byte[] byArr) { + int size = flag ? -1 : 1; + byte[] b = new byte[size]; // throws NegativeArraySizeException if size == -1 + int len = byArr.length; // throws NullPointerException if size == 1 + System.arraycopy(byArr, 0, b, 0, len); + return b; + } +} + +class A { + int i, i2; +} diff --git a/test/hotspot/jtreg/compiler/arraycopy/stress/TestStressArrayCopy.java b/test/hotspot/jtreg/compiler/arraycopy/stress/TestStressArrayCopy.java index e3c4e7f78ae..282f75ae638 100644 --- a/test/hotspot/jtreg/compiler/arraycopy/stress/TestStressArrayCopy.java +++ b/test/hotspot/jtreg/compiler/arraycopy/stress/TestStressArrayCopy.java @@ -172,7 +172,7 @@ public static void main(String... args) throws Exception { for (String className : classNames) { // Start a new job { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, mix(c, "-Xmx256m", className).toArray(new String[0])); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(mix(c, "-Xmx256m", className).toArray(new String[0])); Process p = pb.start(); OutputAnalyzer oa = new OutputAnalyzer(p); forks.add(new Fork(p, oa)); diff --git a/test/hotspot/jtreg/compiler/c2/Test6905845.java b/test/hotspot/jtreg/compiler/c2/Test6905845.java index bd11140dee0..4208790706f 100644 --- a/test/hotspot/jtreg/compiler/c2/Test6905845.java +++ b/test/hotspot/jtreg/compiler/c2/Test6905845.java @@ -26,6 +26,7 @@ * @bug 6905845 * @summary Server VM improperly optimizing away loop. * + * @requires vm.opt.TieredStopAtLevel != 3 * @run main/timeout=480 compiler.c2.Test6905845 */ diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestIntrinsicsRegStress.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestIntrinsicsRegStress.java new file mode 100644 index 00000000000..960661b975a --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestIntrinsicsRegStress.java @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2023, 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 8307572 + * @summary Verify vector register clobbering in some aarch64 intrinsics + * @library /compiler/patches /test/lib + * @build java.base/java.lang.Helper + * @run main/othervm -Xbatch -XX:CompileThreshold=100 -XX:-TieredCompilation compiler.c2.aarch64.TestIntrinsicsRegStress + */ + +package compiler.c2.aarch64; + +import java.util.Arrays; + +public class TestIntrinsicsRegStress { + + final int LENGTH = 1024; + final int ITER = 10000; + final int NUM = 32; + + byte[] ba; + char[] ca; + char[] cb; + float[] fv; + + String str; + String[] strings; + String needle = "01234567890123456789"; + + public void init() { + ca = new char[LENGTH]; + fv = new float[NUM]; + strings = new String[NUM]; + for (int i = 0; i < LENGTH; i++) { + ca[i] = (char) ('a' + i % NUM); + } + cb = ca.clone(); + str = new String(ca); + for (int i = 0; i < NUM; i++) { + fv[i] = 1; + } + for (int i = 0; i < NUM; i++) { + strings[i] = str.substring(i) + needle; + } + } + + public void checkIndexOf(int iter) { + float t0 = 0; + float t1 = fv[1] * fv[0]; + float t2 = fv[2] * fv[0]; + float t3 = fv[3] * fv[0]; + float t4 = fv[4] * fv[0]; + float t5 = fv[5] * fv[0]; + float t6 = fv[6] * fv[0]; + float t7 = fv[7] * fv[0]; + float t8 = fv[8] * fv[0]; + float t9 = fv[9] * fv[0]; + float t10 = fv[10] * fv[0]; + float t11 = fv[11] * fv[0]; + float t12 = fv[12] * fv[0]; + float t13 = fv[13] * fv[0]; + float t14 = fv[14] * fv[0]; + float t15 = fv[15] * fv[0]; + float t16 = fv[16] * fv[0]; + float t17 = fv[17] * fv[0]; + float t18 = fv[18] * fv[0]; + float t19 = fv[19] * fv[0]; + float t20 = fv[20] * fv[0]; + float t21 = fv[21] * fv[0]; + float t22 = fv[22] * fv[0]; + float t23 = fv[23] * fv[0]; + float t24 = fv[24] * fv[0]; + float t25 = fv[25] * fv[0]; + float t26 = fv[26] * fv[0]; + float t27 = fv[27] * fv[0]; + float t28 = fv[28] * fv[0]; + float t29 = fv[29] * fv[0]; + float t30 = fv[30] * fv[0]; + + int result = strings[iter % NUM].indexOf(needle); + + if (result > LENGTH - NUM / 2) { + // Use fp registers as many as possible and try to make them + // live across above intrinsic function. + t0 += t1 - t2 + t3 - t4 + t5 - t6 + t7 - t8 + t9 - t10 + t11 - t12 + t13 - t14 + t15 + - t16 + t17 - t18 + t19 - t20 + t21 - t22 + t23 - t24 + t25 - t26 + t27 - t28 + + t29 - t30; // 0 + } + fv[31] += t0 + t2 - t11 + t16 - t29; + } + + public void testIndexOf() { + for (int i = 0; i < ITER; i++) { + checkIndexOf(i); + } + } + + public void checkArraysEquals() { + float t0 = 0; + float t1 = fv[1] * fv[0]; + float t2 = fv[2] * fv[0]; + float t3 = fv[3] * fv[0]; + float t4 = fv[4] * fv[0]; + float t5 = fv[5] * fv[0]; + float t6 = fv[6] * fv[0]; + float t7 = fv[7] * fv[0]; + float t8 = fv[8] * fv[0]; + float t9 = fv[9] * fv[0]; + float t10 = fv[10] * fv[0]; + float t11 = fv[11] * fv[0]; + float t12 = fv[12] * fv[0]; + float t13 = fv[13] * fv[0]; + float t14 = fv[14] * fv[0]; + float t15 = fv[15] * fv[0]; + float t16 = fv[16] * fv[0]; + float t17 = fv[17] * fv[0]; + float t18 = fv[18] * fv[0]; + float t19 = fv[19] * fv[0]; + float t20 = fv[20] * fv[0]; + float t21 = fv[21] * fv[0]; + float t22 = fv[22] * fv[0]; + float t23 = fv[23] * fv[0]; + float t24 = fv[24] * fv[0]; + float t25 = fv[25] * fv[0]; + float t26 = fv[26] * fv[0]; + float t27 = fv[27] * fv[0]; + float t28 = fv[28] * fv[0]; + float t29 = fv[29] * fv[0]; + float t30 = fv[30] * fv[0]; + + if (Arrays.equals(ca, cb)) { + // Use fp registers as many as possible and try to make them + // live across above intrinsic function. + t0 += t1 - t2 + t3 - t4 + t5 - t6 + t7 - t8 + t9 - t10 + t11 - t12 + t13 - t14 + t15 + - t16 + t17 - t18 + t19 - t20 + t21 - t22 + t23 - t24 + t25 - t26 + t27 - t28 + + t29 - t30; // 0 + } + fv[31] += t0 + t2 - t11 + t16 - t29; + } + + public void testArraysEquals() { + for (int i = 0; i < ITER; i++) { + checkArraysEquals(); + } + } + + public void checkCompress(int iter) { + float t0 = 0; + float t1 = fv[1] * fv[0]; + float t2 = fv[2] * fv[0]; + float t3 = fv[3] * fv[0]; + float t4 = fv[4] * fv[0]; + float t5 = fv[5] * fv[0]; + float t6 = fv[6] * fv[0]; + float t7 = fv[7] * fv[0]; + float t8 = fv[8] * fv[0]; + float t9 = fv[9] * fv[0]; + float t10 = fv[10] * fv[0]; + float t11 = fv[11] * fv[0]; + float t12 = fv[12] * fv[0]; + float t13 = fv[13] * fv[0]; + float t14 = fv[14] * fv[0]; + float t15 = fv[15] * fv[0]; + float t16 = fv[16] * fv[0]; + float t17 = fv[17] * fv[0]; + float t18 = fv[18] * fv[0]; + float t19 = fv[19] * fv[0]; + float t20 = fv[20] * fv[0]; + float t21 = fv[21] * fv[0]; + float t22 = fv[22] * fv[0]; + float t23 = fv[23] * fv[0]; + float t24 = fv[24] * fv[0]; + float t25 = fv[25] * fv[0]; + float t26 = fv[26] * fv[0]; + float t27 = fv[27] * fv[0]; + float t28 = fv[28] * fv[0]; + float t29 = fv[29] * fv[0]; + float t30 = fv[30] * fv[0]; + + ba = Helper.compressChar(ca, 0, LENGTH, 0, LENGTH); + + if (ba[iter % LENGTH] > (byte) ('a' + 5)) { + // Use fp registers as many as possible and try to make them + // live across above intrinsic function. + t0 += t1 - t2 + t3 - t4 + t5 - t6 + t7 - t8 + t9 - t10 + t11 - t12 + t13 - t14 + t15 + - t16 + t17 - t18 + t19 - t20 + t21 - t22 + t23 - t24 + t25 - t26 + t27 - t28 + + t29 - t30; // 0 + } + fv[31] += t0 + t2 - t11 + t16 - t29; + } + + public void testCompress() { + for (int i = 0; i < ITER; i++) { + checkCompress(i); + } + } + + public void checkInflate(int iter) { + float t0 = 0; + float t1 = fv[1] * fv[0]; + float t2 = fv[2] * fv[0]; + float t3 = fv[3] * fv[0]; + float t4 = fv[4] * fv[0]; + float t5 = fv[5] * fv[0]; + float t6 = fv[6] * fv[0]; + float t7 = fv[7] * fv[0]; + float t8 = fv[8] * fv[0]; + float t9 = fv[9] * fv[0]; + float t10 = fv[10] * fv[0]; + float t11 = fv[11] * fv[0]; + float t12 = fv[12] * fv[0]; + float t13 = fv[13] * fv[0]; + float t14 = fv[14] * fv[0]; + float t15 = fv[15] * fv[0]; + float t16 = fv[16] * fv[0]; + float t17 = fv[17] * fv[0]; + float t18 = fv[18] * fv[0]; + float t19 = fv[19] * fv[0]; + float t20 = fv[20] * fv[0]; + float t21 = fv[21] * fv[0]; + float t22 = fv[22] * fv[0]; + float t23 = fv[23] * fv[0]; + float t24 = fv[24] * fv[0]; + float t25 = fv[25] * fv[0]; + float t26 = fv[26] * fv[0]; + float t27 = fv[27] * fv[0]; + float t28 = fv[28] * fv[0]; + float t29 = fv[29] * fv[0]; + float t30 = fv[30] * fv[0]; + + str.getChars(0, LENGTH, ca, 0); + + if (ca[iter % LENGTH] > (byte) ('a' + NUM / 2)) { + // Use fp registers as many as possible and try to make them + // live across above intrinsic function. + t0 += t1 - t2 + t3 - t4 + t5 - t6 + t7 - t8 + t9 - t10 + t11 - t12 + t13 - t14 + t15 + - t16 + t17 - t18 + t19 - t20 + t21 - t22 + t23 - t24 + t25 - t26 + t27 - t28 + + t29 - t30; // 0 + } + fv[31] += t0 + t2 - t11 + t16 - t29; + } + + public void testInflate() { + for (int i = 0; i < ITER; i++) { + checkInflate(i); + } + } + + public void verifyAndReset() { + if (fv[31] != 1.0) { + throw new RuntimeException("Failed with " + Float.toString(fv[31])); + } else { + System.out.println("Success!"); + } + fv[31] = 1.0f; + } + + public static void main(String[] args) { + TestIntrinsicsRegStress t = new TestIntrinsicsRegStress(); + t.init(); + + t.testIndexOf(); + t.verifyAndReset(); + + t.testArraysEquals(); + t.verifyAndReset(); + + t.testCompress(); + t.verifyAndReset(); + + t.testInflate(); + t.verifyAndReset(); + } +} diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestDebugInfo.java b/test/hotspot/jtreg/compiler/c2/irTests/TestDebugInfo.java new file mode 100644 index 00000000000..bf9c5694411 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestDebugInfo.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2.irTests; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @ignore + * @bug 8201516 + * @summary Verify that debug information in C2 compiled code is correct. + * @library /test/lib / + * @requires vm.compiler2.enabled + * @run driver compiler.c2.irTests.TestDebugInfo + */ +// ignore -- as ir_framework is not in 11. +public class TestDebugInfo { + + public static void main(String[] args) { + TestFramework.runWithFlags("-XX:+UnlockDiagnosticVMOptions", "-XX:+DebugNonSafepoints"); + } + + static class MyClass { + final int val; + + @ForceInline + public MyClass(int val) { + this.val = val; + } + + @ForceInline + synchronized void synchronizedMethod(boolean throwIt) { + if (throwIt) { + throw new RuntimeException(); // Make sure there is an exception state + } + } + } + + static Object[] array = new Object[3]; + static MyClass myVal = new MyClass(42); + + // Verify that the MemBarRelease emitted at the MyClass constructor exit + // does not incorrectly reference the caller method in its debug information. + @Test + @IR(failOn = {"MemBarRelease.*testFinalFieldInit.*bci:-1"}, phase = CompilePhase.BEFORE_MATCHING) + public static void testFinalFieldInit() { + array[0] = new MyClass(42); + array[1] = new MyClass(42); + array[2] = new MyClass(42); + } + + // Verify that the MemBarReleaseLock emitted at the synchronizedMethod exit + // does not incorrectly reference the caller method in its debug information. + @Test + @IR(failOn = {"MemBarReleaseLock.*testSynchronized.*bci:-1"}, phase = CompilePhase.BEFORE_MATCHING) + public static void testSynchronized() { + try { + myVal.synchronizedMethod(false); + myVal.synchronizedMethod(true); + } catch (Exception e) { + // Ignore + } + } + + static byte b0 = 0; + static byte b1 = 0; + static byte b2 = 0; + static byte b3 = 0; + + @ForceInline + public static Integer useless3(Integer val) { + return ++val; + } + + @ForceInline + public static Integer useless2(Integer val) { + return useless3(useless3(useless3(useless3(useless3(useless3(useless3(useless3(val)))))))); + } + + @ForceInline + public static Integer useless1(Integer val) { + return useless2(useless2(useless2(useless2(useless2(useless2(useless2(useless2(val)))))))); + } + + @ForceInline + public static void useful3() { + b3 = 3; + } + + @ForceInline + public static void useful2() { + useful3(); + b2 = 2; + } + + @ForceInline + public static void useful1() { + useful2(); + b1 = 1; + } + + // Verify that RenumberLiveNodes preserves the debug information side table. + @Test + @IR(counts = {"StoreB.*name=b3.*useful3.*bci:1.*useful2.*bci:0.*useful1.*bci:0.*testRenumberLiveNodes.*bci:9", "= 1"}, phase = CompilePhase.BEFORE_MATCHING) + @IR(counts = {"StoreB.*name=b2.*useful2.*bci:4.*useful1.*bci:0.*testRenumberLiveNodes.*bci:9", "= 1"}, phase = CompilePhase.BEFORE_MATCHING) + @IR(counts = {"StoreB.*name=b1.*useful1.*bci:4.*testRenumberLiveNodes.*bci:9", "= 1"}, phase = CompilePhase.BEFORE_MATCHING) + @IR(counts = {"StoreB.*name=b0.*testRenumberLiveNodes.*bci:13", "= 1"}, phase = CompilePhase.BEFORE_MATCHING) + public static void testRenumberLiveNodes() { + // This generates ~3700 useless nodes to trigger RenumberLiveNodes + useless1(42); + + // Do something useful + useful1(); + b0 = 0; + } +} diff --git a/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java b/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java index 4fd20f6434c..d81375c0404 100644 --- a/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java +++ b/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java @@ -137,11 +137,10 @@ public boolean generateReplay(boolean needCoreDump, String... vmopts) { options.add(needCoreDump ? ENABLE_COREDUMP_ON_CRASH : DISABLE_COREDUMP_ON_CRASH); options.add(VERSION_OPTION); if (needCoreDump) { - crashOut = ProcessTools.executeProcess(getTestJavaCommandlineWithPrefix( + crashOut = ProcessTools.executeProcess(getTestJvmCommandlineWithPrefix( RUN_SHELL_NO_LIMIT, options.toArray(new String[0]))); } else { - crashOut = ProcessTools.executeProcess(ProcessTools.createJavaProcessBuilder(true, - options)); + crashOut = ProcessTools.executeProcess(ProcessTools.createTestJvm(options)); } crashOutputString = crashOut.getOutput(); Asserts.assertNotEquals(crashOut.getExitValue(), 0, "Crash JVM exits gracefully"); @@ -185,7 +184,7 @@ public int startTest(String... additionalVmOpts) { List allAdditionalOpts = new ArrayList<>(); allAdditionalOpts.addAll(Arrays.asList(REPLAY_OPTIONS)); allAdditionalOpts.addAll(Arrays.asList(additionalVmOpts)); - OutputAnalyzer oa = ProcessTools.executeProcess(getTestJavaCommandlineWithPrefix( + OutputAnalyzer oa = ProcessTools.executeProcess(getTestJvmCommandlineWithPrefix( RUN_SHELL_ZERO_LIMIT, allAdditionalOpts.toArray(new String[0]))); return oa.getExitValue(); } catch (Throwable t) { @@ -285,9 +284,9 @@ private String getCoreFileLocation(String crashOutputString) { return null; } - private String[] getTestJavaCommandlineWithPrefix(String prefix, String... args) { + private String[] getTestJvmCommandlineWithPrefix(String prefix, String... args) { try { - String cmd = ProcessTools.getCommandLine(ProcessTools.createJavaProcessBuilder(true, args)); + String cmd = ProcessTools.getCommandLine(ProcessTools.createTestJvm(args)); return new String[]{"sh", "-c", prefix + (Platform.isWindows() ? cmd.replace('\\', '/').replace(";", "\\;").replace("|", "\\|") : cmd)}; } catch(Throwable t) { diff --git a/test/hotspot/jtreg/compiler/ciReplay/SABase.java b/test/hotspot/jtreg/compiler/ciReplay/SABase.java index bf0340d731e..017226185dd 100644 --- a/test/hotspot/jtreg/compiler/ciReplay/SABase.java +++ b/test/hotspot/jtreg/compiler/ciReplay/SABase.java @@ -57,7 +57,7 @@ public void testAction() { } ProcessBuilder pb; try { - pb = ProcessTools.createJavaProcessBuilder(true, "--add-modules", "jdk.hotspot.agent", + pb = ProcessTools.createTestJvm("--add-modules", "jdk.hotspot.agent", "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED", "sun.jvm.hotspot.CLHSDB", JDKToolFinder.getTestJDKTool("java"), TEST_CORE_FILE_NAME); diff --git a/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java b/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java index e68a3fdef11..4b5a957eb7e 100644 --- a/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java +++ b/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java @@ -112,7 +112,7 @@ static ArrayList getListOfTestsByPrefix(String testPrefix, Set e String classPath = String.join(File.pathSeparator, System.getProperty("java.class.path"), String.join(File.separator, libsDir, MXTOOL_JARFILE)); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(false, + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-cp", classPath, "com.oracle.mxtool.junit.FindClassesByAnnotatedMethods", graalUnitTestFilePath, testAnnotationName); @@ -263,8 +263,7 @@ public static void main(String... args) throws Exception { javaFlags.add("@"+GENERATED_TESTCLASSES_FILENAME); - ProcessBuilder javaPB = ProcessTools.createJavaProcessBuilder(true, - javaFlags); + ProcessBuilder javaPB = ProcessTools.createTestJvm(javaFlags); System.out.println("INFO: run command: " + String.join(" ", javaPB.command())); OutputAnalyzer outputAnalyzer = new OutputAnalyzer(javaPB.start()); diff --git a/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIndexOfCharIntrinsics.java b/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIndexOfCharIntrinsics.java new file mode 100644 index 00000000000..a02b4918140 --- /dev/null +++ b/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIndexOfCharIntrinsics.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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. + */ + +/* + * @test + * @bug 8301491 + * @summary Check for correct return value when calling indexOfChar intrinsics with negative value. + * @library /test/lib + * + * @run main/othervm -XX:CompileCommand=quiet + * -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.intrinsics.string.TestStringIndexOfCharIntrinsics::testIndexOfChar* + * -XX:CompileCommand=inline,java.lang.String*::indexOf* + * -XX:PerBytecodeTrapLimit=20000 + * -XX:PerMethodTrapLimit=20000 + * compiler.intrinsics.string.TestStringIndexOfCharIntrinsics + */ + +package compiler.intrinsics.string; + +import jdk.test.lib.Asserts; + +public class TestStringIndexOfCharIntrinsics { + + static byte byArr[] = new byte[500]; + + public static void main(String[] args) { + for (int j = 0; j < byArr.length; j++) { + byArr[j] = (byte)j; + } + // Test value for aarch64 + byArr[24] = 0x7; + byArr[23] = -0x80; + // Warmup + for (int i = 0; i < 10000; i++) { + testIndexOfCharArg(i); + testIndexOfCharConst(); + } + Asserts.assertEquals(testIndexOfCharConst() , -1, "must be -1 (character not found)"); + Asserts.assertEquals(testIndexOfCharArg(-2147483641) , -1, "must be -1 (character not found)"); + } + + static int testIndexOfCharConst() { + String s = new String(byArr); + return s.indexOf(-2147483641); + } + + static int testIndexOfCharArg(int ch) { + String s = new String(byArr); + return s.indexOf(ch); + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestRemoveEmptyCountedLoop.java b/test/hotspot/jtreg/compiler/loopopts/TestRemoveEmptyCountedLoop.java new file mode 100644 index 00000000000..71612cbc9d2 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestRemoveEmptyCountedLoop.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8289748 + * @summary SIGFPE caused by C2 IdealLoopTree::do_remove_empty_loop + * @key stress randomness + * + * @run main/othervm -XX:-TieredCompilation -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM + * -XX:CompileCommand=compileonly,compiler.loopopts.TestRemoveEmptyCountedLoop::test* + * compiler.loopopts.TestRemoveEmptyCountedLoop + */ + +package compiler.loopopts; + +public class TestRemoveEmptyCountedLoop { + + public static void test1() { + int k = 3; + for (int i=9; i>0; i--) { + for (int j=2; j0; i--) { + int j = 2; + do { + try { + k = k; + k = (1 % j); + } catch (Exception e) {} + } while (++j < i); + } + } + + public static void main(String[] args) { + test1(); + test2(); + System.out.println("Test passed."); + } +} diff --git a/test/hotspot/jtreg/compiler/loopstripmining/TestAddPAtOuterLoopHead.java b/test/hotspot/jtreg/compiler/loopstripmining/TestAddPAtOuterLoopHead.java new file mode 100644 index 00000000000..358622f2080 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopstripmining/TestAddPAtOuterLoopHead.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2023, 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 8303511 + * @summary C2: assert(get_ctrl(n) == cle_out) during unrolling + * @requires vm.gc.Parallel + * @run main/othervm -XX:-BackgroundCompilation -XX:+UseParallelGC TestAddPAtOuterLoopHead + */ + + +import java.util.Arrays; + +public class TestAddPAtOuterLoopHead { + public static void main(String[] args) { + boolean[] flags1 = new boolean[1000]; + boolean[] flags2 = new boolean[1000]; + Arrays.fill(flags2, true); + for (int i = 0; i < 20_000; i++) { + testHelper(42, 42, 43); + test(flags1); + test(flags2); + } + } + + private static int test(boolean[] flags) { + int[] array = new int[1000]; + + int k; + for (k = 0; k < 10; k++) { + for (int i = 0; i < 2; i++) { + } + } + k = k / 10; + int m; + for (m = 0; m < 2; m++) { + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + } + } + } + + + int v = 0; + for (int j = 0; j < 2; j++) { + for (int i = 0; i < 998; i += k) { + int l = testHelper(m, j, i); + v = array[i + l]; + if (flags[i]) { + return v; + } + } + } + + return v; + } + + private static int testHelper(int m, int j, int i) { + return m == 2 ? j : i; + } +} diff --git a/test/hotspot/jtreg/compiler/runtime/cr8015436/Driver8015436.java b/test/hotspot/jtreg/compiler/runtime/cr8015436/Driver8015436.java index 79c4eb8971a..36f4266c7d5 100644 --- a/test/hotspot/jtreg/compiler/runtime/cr8015436/Driver8015436.java +++ b/test/hotspot/jtreg/compiler/runtime/cr8015436/Driver8015436.java @@ -30,8 +30,8 @@ public class Driver8015436 { public static void main(String args[]) { OutputAnalyzer oa; try { - oa = ProcessTools.executeProcess(ProcessTools.createJavaProcessBuilder( - /* add test vm options */ true, Test8015436.class.getName())); + oa = ProcessTools.executeProcess(ProcessTools.createTestJvm( + Test8015436.class.getName())); } catch (Exception ex) { throw new Error("TESTBUG: exception while running child process: " + ex, ex); } diff --git a/test/hotspot/jtreg/compiler/startup/NumCompilerThreadsCheck.java b/test/hotspot/jtreg/compiler/startup/NumCompilerThreadsCheck.java index 0491e1c69fd..7f74264f941 100644 --- a/test/hotspot/jtreg/compiler/startup/NumCompilerThreadsCheck.java +++ b/test/hotspot/jtreg/compiler/startup/NumCompilerThreadsCheck.java @@ -46,11 +46,6 @@ public static void main(String[] args) throws Exception { String expectedOutput = "outside the allowed range"; out.shouldContain(expectedOutput); - - if (Platform.isZero()) { - String expectedLowWaterMarkText = "must be at least 0"; - out.shouldContain(expectedLowWaterMarkText); - } } } diff --git a/test/hotspot/jtreg/compiler/types/correctness/OffTest.java b/test/hotspot/jtreg/compiler/types/correctness/OffTest.java index e53a7252f83..e022b1ab0a2 100644 --- a/test/hotspot/jtreg/compiler/types/correctness/OffTest.java +++ b/test/hotspot/jtreg/compiler/types/correctness/OffTest.java @@ -87,7 +87,7 @@ private static void runTest() throws Exception { OPTIONS[TYPE_PROFILE_INDEX] = typeProfileLevel; OPTIONS[USE_TYPE_SPECULATION_INDEX] = useTypeSpeculation; OPTIONS[PROFILING_TYPE_INDEX] = type.name(); - ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(/* addTestVmOptions= */ true, OPTIONS); + ProcessBuilder processBuilder = ProcessTools.createTestJvm(OPTIONS); OutputAnalyzer outputAnalyzer = new OutputAnalyzer(processBuilder.start()); outputAnalyzer.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java index 75c33c9984c..b3fa7c49a8d 100644 --- a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java +++ b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.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 @@ -212,9 +212,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetBooleanPlain(base, offset, true, false); } - assertEquals(success, true, "weakCompareAndSetPlain boolean"); + assertEquals(success, true, "success weakCompareAndSetPlain boolean"); boolean x = UNSAFE.getBoolean(base, offset); - assertEquals(x, false, "weakCompareAndSetPlain boolean value"); + assertEquals(x, false, "success weakCompareAndSetPlain boolean value"); + } + + { + boolean success = UNSAFE.weakCompareAndSetBooleanPlain(base, offset, true, false); + assertEquals(success, false, "failing weakCompareAndSetPlain boolean"); + boolean x = UNSAFE.getBoolean(base, offset); + assertEquals(x, false, "failing weakCompareAndSetPlain boolean value"); } { @@ -222,9 +229,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetBooleanAcquire(base, offset, false, true); } - assertEquals(success, true, "weakCompareAndSetAcquire boolean"); + assertEquals(success, true, "success weakCompareAndSetAcquire boolean"); + boolean x = UNSAFE.getBoolean(base, offset); + assertEquals(x, true, "success weakCompareAndSetAcquire boolean"); + } + + { + boolean success = UNSAFE.weakCompareAndSetBooleanAcquire(base, offset, false, false); + assertEquals(success, false, "failing weakCompareAndSetAcquire boolean"); boolean x = UNSAFE.getBoolean(base, offset); - assertEquals(x, true, "weakCompareAndSetAcquire boolean"); + assertEquals(x, true, "failing weakCompareAndSetAcquire boolean value"); } { @@ -232,9 +246,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetBooleanRelease(base, offset, true, false); } - assertEquals(success, true, "weakCompareAndSetRelease boolean"); + assertEquals(success, true, "success weakCompareAndSetRelease boolean"); boolean x = UNSAFE.getBoolean(base, offset); - assertEquals(x, false, "weakCompareAndSetRelease boolean"); + assertEquals(x, false, "success weakCompareAndSetRelease boolean"); + } + + { + boolean success = UNSAFE.weakCompareAndSetBooleanRelease(base, offset, true, false); + assertEquals(success, false, "failing weakCompareAndSetRelease boolean"); + boolean x = UNSAFE.getBoolean(base, offset); + assertEquals(x, false, "failing weakCompareAndSetRelease boolean value"); } { @@ -242,9 +263,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetBoolean(base, offset, false, true); } - assertEquals(success, true, "weakCompareAndSet boolean"); + assertEquals(success, true, "success weakCompareAndSet boolean"); + boolean x = UNSAFE.getBoolean(base, offset); + assertEquals(x, true, "success weakCompareAndSet boolean"); + } + + { + boolean success = UNSAFE.weakCompareAndSetBoolean(base, offset, false, false); + assertEquals(success, false, "failing weakCompareAndSet boolean"); boolean x = UNSAFE.getBoolean(base, offset); - assertEquals(x, true, "weakCompareAndSet boolean"); + assertEquals(x, true, "failing weakCompareAndSet boolean value"); } UNSAFE.putBoolean(base, offset, false); diff --git a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java index 30ffae395df..0ce54ce877e 100644 --- a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java +++ b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.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 @@ -241,9 +241,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetBytePlain(base, offset, (byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetPlain byte"); + assertEquals(success, true, "success weakCompareAndSetPlain byte"); byte x = UNSAFE.getByte(base, offset); - assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value"); + assertEquals(x, (byte)0x23, "success weakCompareAndSetPlain byte value"); + } + + { + boolean success = UNSAFE.weakCompareAndSetBytePlain(base, offset, (byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetPlain byte"); + byte x = UNSAFE.getByte(base, offset); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetPlain byte value"); } { @@ -251,9 +258,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetByteAcquire(base, offset, (byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSetAcquire byte"); + assertEquals(success, true, "success weakCompareAndSetAcquire byte"); + byte x = UNSAFE.getByte(base, offset); + assertEquals(x, (byte)0x01, "success weakCompareAndSetAcquire byte"); + } + + { + boolean success = UNSAFE.weakCompareAndSetByteAcquire(base, offset, (byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetAcquire byte"); byte x = UNSAFE.getByte(base, offset); - assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte"); + assertEquals(x, (byte)0x01, "failing weakCompareAndSetAcquire byte value"); } { @@ -261,9 +275,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetByteRelease(base, offset, (byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetRelease byte"); + assertEquals(success, true, "success weakCompareAndSetRelease byte"); byte x = UNSAFE.getByte(base, offset); - assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte"); + assertEquals(x, (byte)0x23, "success weakCompareAndSetRelease byte"); + } + + { + boolean success = UNSAFE.weakCompareAndSetByteRelease(base, offset, (byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetRelease byte"); + byte x = UNSAFE.getByte(base, offset); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetRelease byte value"); } { @@ -271,9 +292,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetByte(base, offset, (byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSet byte"); + assertEquals(success, true, "success weakCompareAndSet byte"); + byte x = UNSAFE.getByte(base, offset); + assertEquals(x, (byte)0x01, "success weakCompareAndSet byte"); + } + + { + boolean success = UNSAFE.weakCompareAndSetByte(base, offset, (byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSet byte"); byte x = UNSAFE.getByte(base, offset); - assertEquals(x, (byte)0x01, "weakCompareAndSet byte"); + assertEquals(x, (byte)0x01, "failing weakCompareAndSet byte value"); } UNSAFE.putByte(base, offset, (byte)0x23); diff --git a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java index 817af4b18c1..bcc8a481800 100644 --- a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java +++ b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.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 @@ -259,9 +259,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetCharPlain(base, offset, '\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetPlain char"); + assertEquals(success, true, "success weakCompareAndSetPlain char"); char x = UNSAFE.getChar(base, offset); - assertEquals(x, '\u4567', "weakCompareAndSetPlain char value"); + assertEquals(x, '\u4567', "success weakCompareAndSetPlain char value"); + } + + { + boolean success = UNSAFE.weakCompareAndSetCharPlain(base, offset, '\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetPlain char"); + char x = UNSAFE.getChar(base, offset); + assertEquals(x, '\u4567', "failing weakCompareAndSetPlain char value"); } { @@ -269,9 +276,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetCharAcquire(base, offset, '\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSetAcquire char"); + assertEquals(success, true, "success weakCompareAndSetAcquire char"); + char x = UNSAFE.getChar(base, offset); + assertEquals(x, '\u0123', "success weakCompareAndSetAcquire char"); + } + + { + boolean success = UNSAFE.weakCompareAndSetCharAcquire(base, offset, '\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetAcquire char"); char x = UNSAFE.getChar(base, offset); - assertEquals(x, '\u0123', "weakCompareAndSetAcquire char"); + assertEquals(x, '\u0123', "failing weakCompareAndSetAcquire char value"); } { @@ -279,9 +293,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetCharRelease(base, offset, '\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetRelease char"); + assertEquals(success, true, "success weakCompareAndSetRelease char"); char x = UNSAFE.getChar(base, offset); - assertEquals(x, '\u4567', "weakCompareAndSetRelease char"); + assertEquals(x, '\u4567', "success weakCompareAndSetRelease char"); + } + + { + boolean success = UNSAFE.weakCompareAndSetCharRelease(base, offset, '\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetRelease char"); + char x = UNSAFE.getChar(base, offset); + assertEquals(x, '\u4567', "failing weakCompareAndSetRelease char value"); } { @@ -289,9 +310,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetChar(base, offset, '\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSet char"); + assertEquals(success, true, "success weakCompareAndSet char"); + char x = UNSAFE.getChar(base, offset); + assertEquals(x, '\u0123', "success weakCompareAndSet char"); + } + + { + boolean success = UNSAFE.weakCompareAndSetChar(base, offset, '\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSet char"); char x = UNSAFE.getChar(base, offset); - assertEquals(x, '\u0123', "weakCompareAndSet char"); + assertEquals(x, '\u0123', "failing weakCompareAndSet char value"); } UNSAFE.putChar(base, offset, '\u4567'); diff --git a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java index 37c15e57a6a..ec68b3a52b9 100644 --- a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java +++ b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.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 @@ -241,9 +241,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetDoublePlain(base, offset, 1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetPlain double"); + assertEquals(success, true, "success weakCompareAndSetPlain double"); double x = UNSAFE.getDouble(base, offset); - assertEquals(x, 2.0d, "weakCompareAndSetPlain double value"); + assertEquals(x, 2.0d, "success weakCompareAndSetPlain double value"); + } + + { + boolean success = UNSAFE.weakCompareAndSetDoublePlain(base, offset, 1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetPlain double"); + double x = UNSAFE.getDouble(base, offset); + assertEquals(x, 2.0d, "failing weakCompareAndSetPlain double value"); } { @@ -251,9 +258,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetDoubleAcquire(base, offset, 2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSetAcquire double"); + assertEquals(success, true, "success weakCompareAndSetAcquire double"); + double x = UNSAFE.getDouble(base, offset); + assertEquals(x, 1.0d, "success weakCompareAndSetAcquire double"); + } + + { + boolean success = UNSAFE.weakCompareAndSetDoubleAcquire(base, offset, 2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetAcquire double"); double x = UNSAFE.getDouble(base, offset); - assertEquals(x, 1.0d, "weakCompareAndSetAcquire double"); + assertEquals(x, 1.0d, "failing weakCompareAndSetAcquire double value"); } { @@ -261,9 +275,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetDoubleRelease(base, offset, 1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetRelease double"); + assertEquals(success, true, "success weakCompareAndSetRelease double"); double x = UNSAFE.getDouble(base, offset); - assertEquals(x, 2.0d, "weakCompareAndSetRelease double"); + assertEquals(x, 2.0d, "success weakCompareAndSetRelease double"); + } + + { + boolean success = UNSAFE.weakCompareAndSetDoubleRelease(base, offset, 1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetRelease double"); + double x = UNSAFE.getDouble(base, offset); + assertEquals(x, 2.0d, "failing weakCompareAndSetRelease double value"); } { @@ -271,9 +292,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetDouble(base, offset, 2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSet double"); + assertEquals(success, true, "success weakCompareAndSet double"); + double x = UNSAFE.getDouble(base, offset); + assertEquals(x, 1.0d, "success weakCompareAndSet double"); + } + + { + boolean success = UNSAFE.weakCompareAndSetDouble(base, offset, 2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSet double"); double x = UNSAFE.getDouble(base, offset); - assertEquals(x, 1.0d, "weakCompareAndSet double"); + assertEquals(x, 1.0d, "failing weakCompareAndSet double value"); } UNSAFE.putDouble(base, offset, 2.0d); diff --git a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java index 0ac9fa1e55a..73da36c8355 100644 --- a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java +++ b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.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 @@ -241,9 +241,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetFloatPlain(base, offset, 1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetPlain float"); + assertEquals(success, true, "success weakCompareAndSetPlain float"); float x = UNSAFE.getFloat(base, offset); - assertEquals(x, 2.0f, "weakCompareAndSetPlain float value"); + assertEquals(x, 2.0f, "success weakCompareAndSetPlain float value"); + } + + { + boolean success = UNSAFE.weakCompareAndSetFloatPlain(base, offset, 1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetPlain float"); + float x = UNSAFE.getFloat(base, offset); + assertEquals(x, 2.0f, "failing weakCompareAndSetPlain float value"); } { @@ -251,9 +258,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetFloatAcquire(base, offset, 2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSetAcquire float"); + assertEquals(success, true, "success weakCompareAndSetAcquire float"); + float x = UNSAFE.getFloat(base, offset); + assertEquals(x, 1.0f, "success weakCompareAndSetAcquire float"); + } + + { + boolean success = UNSAFE.weakCompareAndSetFloatAcquire(base, offset, 2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetAcquire float"); float x = UNSAFE.getFloat(base, offset); - assertEquals(x, 1.0f, "weakCompareAndSetAcquire float"); + assertEquals(x, 1.0f, "failing weakCompareAndSetAcquire float value"); } { @@ -261,9 +275,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetFloatRelease(base, offset, 1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetRelease float"); + assertEquals(success, true, "success weakCompareAndSetRelease float"); float x = UNSAFE.getFloat(base, offset); - assertEquals(x, 2.0f, "weakCompareAndSetRelease float"); + assertEquals(x, 2.0f, "success weakCompareAndSetRelease float"); + } + + { + boolean success = UNSAFE.weakCompareAndSetFloatRelease(base, offset, 1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetRelease float"); + float x = UNSAFE.getFloat(base, offset); + assertEquals(x, 2.0f, "failing weakCompareAndSetRelease float value"); } { @@ -271,9 +292,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetFloat(base, offset, 2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSet float"); + assertEquals(success, true, "success weakCompareAndSet float"); + float x = UNSAFE.getFloat(base, offset); + assertEquals(x, 1.0f, "success weakCompareAndSet float"); + } + + { + boolean success = UNSAFE.weakCompareAndSetFloat(base, offset, 2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSet float"); float x = UNSAFE.getFloat(base, offset); - assertEquals(x, 1.0f, "weakCompareAndSet float"); + assertEquals(x, 1.0f, "failing weakCompareAndSet float value"); } UNSAFE.putFloat(base, offset, 2.0f); diff --git a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java index 0f0f1f101d3..a62fede83d7 100644 --- a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java +++ b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.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 @@ -259,9 +259,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetIntPlain(base, offset, 0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetPlain int"); + assertEquals(success, true, "success weakCompareAndSetPlain int"); int x = UNSAFE.getInt(base, offset); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value"); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetPlain int value"); + } + + { + boolean success = UNSAFE.weakCompareAndSetIntPlain(base, offset, 0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetPlain int"); + int x = UNSAFE.getInt(base, offset); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetPlain int value"); } { @@ -269,9 +276,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetIntAcquire(base, offset, 0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSetAcquire int"); + assertEquals(success, true, "success weakCompareAndSetAcquire int"); + int x = UNSAFE.getInt(base, offset); + assertEquals(x, 0x01234567, "success weakCompareAndSetAcquire int"); + } + + { + boolean success = UNSAFE.weakCompareAndSetIntAcquire(base, offset, 0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetAcquire int"); int x = UNSAFE.getInt(base, offset); - assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int"); + assertEquals(x, 0x01234567, "failing weakCompareAndSetAcquire int value"); } { @@ -279,9 +293,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetIntRelease(base, offset, 0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetRelease int"); + assertEquals(success, true, "success weakCompareAndSetRelease int"); int x = UNSAFE.getInt(base, offset); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int"); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetRelease int"); + } + + { + boolean success = UNSAFE.weakCompareAndSetIntRelease(base, offset, 0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetRelease int"); + int x = UNSAFE.getInt(base, offset); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetRelease int value"); } { @@ -289,9 +310,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetInt(base, offset, 0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSet int"); + assertEquals(success, true, "success weakCompareAndSet int"); + int x = UNSAFE.getInt(base, offset); + assertEquals(x, 0x01234567, "success weakCompareAndSet int"); + } + + { + boolean success = UNSAFE.weakCompareAndSetInt(base, offset, 0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSet int"); int x = UNSAFE.getInt(base, offset); - assertEquals(x, 0x01234567, "weakCompareAndSet int"); + assertEquals(x, 0x01234567, "failing weakCompareAndSet int value"); } UNSAFE.putInt(base, offset, 0x89ABCDEF); diff --git a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java index 69a51bb698b..f7ab52cb04e 100644 --- a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java +++ b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.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 @@ -259,9 +259,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetLongPlain(base, offset, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetPlain long"); + assertEquals(success, true, "success weakCompareAndSetPlain long"); long x = UNSAFE.getLong(base, offset); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetPlain long value"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetPlain long value"); + } + + { + boolean success = UNSAFE.weakCompareAndSetLongPlain(base, offset, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetPlain long"); + long x = UNSAFE.getLong(base, offset); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetPlain long value"); } { @@ -269,9 +276,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetLongAcquire(base, offset, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSetAcquire long"); + assertEquals(success, true, "success weakCompareAndSetAcquire long"); + long x = UNSAFE.getLong(base, offset); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSetAcquire long"); + } + + { + boolean success = UNSAFE.weakCompareAndSetLongAcquire(base, offset, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetAcquire long"); long x = UNSAFE.getLong(base, offset); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSetAcquire long"); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSetAcquire long value"); } { @@ -279,9 +293,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetLongRelease(base, offset, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetRelease long"); + assertEquals(success, true, "success weakCompareAndSetRelease long"); long x = UNSAFE.getLong(base, offset); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetRelease long"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetRelease long"); + } + + { + boolean success = UNSAFE.weakCompareAndSetLongRelease(base, offset, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetRelease long"); + long x = UNSAFE.getLong(base, offset); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetRelease long value"); } { @@ -289,9 +310,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetLong(base, offset, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSet long"); + assertEquals(success, true, "success weakCompareAndSet long"); + long x = UNSAFE.getLong(base, offset); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSet long"); + } + + { + boolean success = UNSAFE.weakCompareAndSetLong(base, offset, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSet long"); long x = UNSAFE.getLong(base, offset); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSet long"); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSet long value"); } UNSAFE.putLong(base, offset, 0xCAFEBABECAFEBABEL); diff --git a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java index b2e5fc57e1e..04797707ff8 100644 --- a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java +++ b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.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 @@ -212,9 +212,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetObjectPlain(base, offset, "foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetPlain Object"); + assertEquals(success, true, "success weakCompareAndSetPlain Object"); Object x = UNSAFE.getObject(base, offset); - assertEquals(x, "bar", "weakCompareAndSetPlain Object value"); + assertEquals(x, "bar", "success weakCompareAndSetPlain Object value"); + } + + { + boolean success = UNSAFE.weakCompareAndSetObjectPlain(base, offset, "foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetPlain Object"); + Object x = UNSAFE.getObject(base, offset); + assertEquals(x, "bar", "failing weakCompareAndSetPlain Object value"); } { @@ -222,9 +229,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetObjectAcquire(base, offset, "bar", "foo"); } - assertEquals(success, true, "weakCompareAndSetAcquire Object"); + assertEquals(success, true, "success weakCompareAndSetAcquire Object"); + Object x = UNSAFE.getObject(base, offset); + assertEquals(x, "foo", "success weakCompareAndSetAcquire Object"); + } + + { + boolean success = UNSAFE.weakCompareAndSetObjectAcquire(base, offset, "bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSetAcquire Object"); Object x = UNSAFE.getObject(base, offset); - assertEquals(x, "foo", "weakCompareAndSetAcquire Object"); + assertEquals(x, "foo", "failing weakCompareAndSetAcquire Object value"); } { @@ -232,9 +246,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetObjectRelease(base, offset, "foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetRelease Object"); + assertEquals(success, true, "success weakCompareAndSetRelease Object"); Object x = UNSAFE.getObject(base, offset); - assertEquals(x, "bar", "weakCompareAndSetRelease Object"); + assertEquals(x, "bar", "success weakCompareAndSetRelease Object"); + } + + { + boolean success = UNSAFE.weakCompareAndSetObjectRelease(base, offset, "foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetRelease Object"); + Object x = UNSAFE.getObject(base, offset); + assertEquals(x, "bar", "failing weakCompareAndSetRelease Object value"); } { @@ -242,9 +263,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetObject(base, offset, "bar", "foo"); } - assertEquals(success, true, "weakCompareAndSet Object"); + assertEquals(success, true, "success weakCompareAndSet Object"); + Object x = UNSAFE.getObject(base, offset); + assertEquals(x, "foo", "success weakCompareAndSet Object"); + } + + { + boolean success = UNSAFE.weakCompareAndSetObject(base, offset, "bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSet Object"); Object x = UNSAFE.getObject(base, offset); - assertEquals(x, "foo", "weakCompareAndSet Object"); + assertEquals(x, "foo", "failing weakCompareAndSet Object value"); } UNSAFE.putObject(base, offset, "bar"); diff --git a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java index a6b845eec6b..5b3b006308b 100644 --- a/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java +++ b/test/hotspot/jtreg/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.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 @@ -259,9 +259,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetShortPlain(base, offset, (short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetPlain short"); + assertEquals(success, true, "success weakCompareAndSetPlain short"); short x = UNSAFE.getShort(base, offset); - assertEquals(x, (short)0x4567, "weakCompareAndSetPlain short value"); + assertEquals(x, (short)0x4567, "success weakCompareAndSetPlain short value"); + } + + { + boolean success = UNSAFE.weakCompareAndSetShortPlain(base, offset, (short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetPlain short"); + short x = UNSAFE.getShort(base, offset); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetPlain short value"); } { @@ -269,9 +276,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetShortAcquire(base, offset, (short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSetAcquire short"); + assertEquals(success, true, "success weakCompareAndSetAcquire short"); + short x = UNSAFE.getShort(base, offset); + assertEquals(x, (short)0x0123, "success weakCompareAndSetAcquire short"); + } + + { + boolean success = UNSAFE.weakCompareAndSetShortAcquire(base, offset, (short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetAcquire short"); short x = UNSAFE.getShort(base, offset); - assertEquals(x, (short)0x0123, "weakCompareAndSetAcquire short"); + assertEquals(x, (short)0x0123, "failing weakCompareAndSetAcquire short value"); } { @@ -279,9 +293,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetShortRelease(base, offset, (short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetRelease short"); + assertEquals(success, true, "success weakCompareAndSetRelease short"); short x = UNSAFE.getShort(base, offset); - assertEquals(x, (short)0x4567, "weakCompareAndSetRelease short"); + assertEquals(x, (short)0x4567, "success weakCompareAndSetRelease short"); + } + + { + boolean success = UNSAFE.weakCompareAndSetShortRelease(base, offset, (short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetRelease short"); + short x = UNSAFE.getShort(base, offset); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetRelease short value"); } { @@ -289,9 +310,16 @@ static void testAccess(Object base, long offset) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSetShort(base, offset, (short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSet short"); + assertEquals(success, true, "success weakCompareAndSet short"); + short x = UNSAFE.getShort(base, offset); + assertEquals(x, (short)0x0123, "success weakCompareAndSet short"); + } + + { + boolean success = UNSAFE.weakCompareAndSetShort(base, offset, (short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSet short"); short x = UNSAFE.getShort(base, offset); - assertEquals(x, (short)0x0123, "weakCompareAndSet short"); + assertEquals(x, (short)0x0123, "failing weakCompareAndSet short value"); } UNSAFE.putShort(base, offset, (short)0x4567); diff --git a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestBoolean.java b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestBoolean.java index a1b68c7305d..6de29f5b39c 100644 --- a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestBoolean.java +++ b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestBoolean.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 diff --git a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestByte.java b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestByte.java index c086315cb8a..87aa8c66a57 100644 --- a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestByte.java +++ b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestByte.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 diff --git a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestChar.java b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestChar.java index 3a55939826d..8e10d4334e4 100644 --- a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestChar.java +++ b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestChar.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 diff --git a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestDouble.java b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestDouble.java index 52bde3f08d6..878336db8a1 100644 --- a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestDouble.java +++ b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestDouble.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 diff --git a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestFloat.java b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestFloat.java index 478efa4dbc3..616919f09f4 100644 --- a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestFloat.java +++ b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestFloat.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 diff --git a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestInt.java b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestInt.java index 0bf8b641066..05e9a467a89 100644 --- a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestInt.java +++ b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestInt.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 diff --git a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestLong.java b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestLong.java index 64014df3340..38b0a83296a 100644 --- a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestLong.java +++ b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestLong.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 diff --git a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestObject.java b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestObject.java index 0145124c7bd..8782995957b 100644 --- a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestObject.java +++ b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestObject.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 diff --git a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestShort.java b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestShort.java index 9a815670595..c16761daaac 100644 --- a/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestShort.java +++ b/test/hotspot/jtreg/compiler/unsafe/SunMiscUnsafeAccessTestShort.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 diff --git a/test/hotspot/jtreg/compiler/unsafe/X-UnsafeAccessTest.java.template b/test/hotspot/jtreg/compiler/unsafe/X-UnsafeAccessTest.java.template index f28791765a1..8e1da7f63c8 100644 --- a/test/hotspot/jtreg/compiler/unsafe/X-UnsafeAccessTest.java.template +++ b/test/hotspot/jtreg/compiler/unsafe/X-UnsafeAccessTest.java.template @@ -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 @@ -303,9 +303,16 @@ public class $Qualifier$UnsafeAccessTest$Type$ { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSet$Type$Plain(base, offset, $value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetPlain $type$"); + assertEquals(success, true, "success weakCompareAndSetPlain $type$"); $type$ x = UNSAFE.get$Type$(base, offset); - assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value"); + assertEquals(x, $value2$, "success weakCompareAndSetPlain $type$ value"); + } + + { + boolean success = UNSAFE.weakCompareAndSet$Type$Plain(base, offset, $value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetPlain $type$"); + $type$ x = UNSAFE.get$Type$(base, offset); + assertEquals(x, $value2$, "failing weakCompareAndSetPlain $type$ value"); } { @@ -313,9 +320,16 @@ public class $Qualifier$UnsafeAccessTest$Type$ { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSet$Type$Acquire(base, offset, $value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSetAcquire $type$"); + assertEquals(success, true, "success weakCompareAndSetAcquire $type$"); + $type$ x = UNSAFE.get$Type$(base, offset); + assertEquals(x, $value1$, "success weakCompareAndSetAcquire $type$"); + } + + { + boolean success = UNSAFE.weakCompareAndSet$Type$Acquire(base, offset, $value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetAcquire $type$"); $type$ x = UNSAFE.get$Type$(base, offset); - assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); + assertEquals(x, $value1$, "failing weakCompareAndSetAcquire $type$ value"); } { @@ -323,9 +337,16 @@ public class $Qualifier$UnsafeAccessTest$Type$ { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSet$Type$Release(base, offset, $value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetRelease $type$"); + assertEquals(success, true, "success weakCompareAndSetRelease $type$"); $type$ x = UNSAFE.get$Type$(base, offset); - assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); + assertEquals(x, $value2$, "success weakCompareAndSetRelease $type$"); + } + + { + boolean success = UNSAFE.weakCompareAndSet$Type$Release(base, offset, $value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetRelease $type$"); + $type$ x = UNSAFE.get$Type$(base, offset); + assertEquals(x, $value2$, "failing weakCompareAndSetRelease $type$ value"); } { @@ -333,9 +354,16 @@ public class $Qualifier$UnsafeAccessTest$Type$ { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = UNSAFE.weakCompareAndSet$Type$(base, offset, $value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSet $type$"); + assertEquals(success, true, "success weakCompareAndSet $type$"); + $type$ x = UNSAFE.get$Type$(base, offset); + assertEquals(x, $value1$, "success weakCompareAndSet $type$"); + } + + { + boolean success = UNSAFE.weakCompareAndSet$Type$(base, offset, $value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSet $type$"); $type$ x = UNSAFE.get$Type$(base, offset); - assertEquals(x, $value1$, "weakCompareAndSet $type$"); + assertEquals(x, $value1$, "failing weakCompareAndSet $type$ value"); } #end[JdkInternalMisc] diff --git a/test/hotspot/jtreg/compiler/unsafe/generate-unsafe-access-tests.sh b/test/hotspot/jtreg/compiler/unsafe/generate-unsafe-access-tests.sh index b78b7923ad5..131861732c3 100644 --- a/test/hotspot/jtreg/compiler/unsafe/generate-unsafe-access-tests.sh +++ b/test/hotspot/jtreg/compiler/unsafe/generate-unsafe-access-tests.sh @@ -1,7 +1,7 @@ #!/bin/bash # -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 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 @@ -23,7 +23,7 @@ # questions. # -javac -d . ../../../../jdk/make/src/classes/build/tools/spp/Spp.java +javac -d . ../../../../../make/jdk/src/classes/build/tools/spp/Spp.java SPP=build.tools.spp.Spp @@ -123,8 +123,10 @@ function generate { args="$args -Dvalue1=$value1 -Dvalue2=$value2 -Dvalue3=$value3" echo $args + out=${Qualifier}UnsafeAccessTest${Type}.java + rm -rf "$out" java $SPP -nel -K$Qualifier -Dpackage=$package -DQualifier=$Qualifier -Dmodule=$module \ - $args -iX-UnsafeAccessTest.java.template -o${Qualifier}UnsafeAccessTest${Type}.java + $args -iX-UnsafeAccessTest.java.template -o$out done } diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java b/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java index 9e7d062e860..ae364bb37b6 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,23 +35,26 @@ * jdk.jartool/sun.tools.jar * @build AttemptOOM sun.hotspot.WhiteBox PrintContainerInfo CheckOperatingSystemMXBean * @run driver ClassFileInstaller -jar whitebox.jar sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission - * @run driver TestMemoryAwareness + * @run main/othervm -Xbootclasspath/a:whitebox.jar -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestMemoryAwareness */ import jdk.test.lib.containers.docker.Common; import jdk.test.lib.containers.docker.DockerRunOptions; import jdk.test.lib.containers.docker.DockerTestUtils; +import sun.hotspot.WhiteBox; import jdk.test.lib.process.OutputAnalyzer; import static jdk.test.lib.Asserts.assertNotNull; public class TestMemoryAwareness { private static final String imageName = Common.imageName("memory"); + private static final WhiteBox wb = WhiteBox.getWhiteBox(); - private static String getHostMaxMemory() throws Exception { - DockerRunOptions opts = Common.newOpts(imageName); - String goodMem = Common.run(opts).firstMatch("total physical memory: (\\d+)", 1); - assertNotNull(goodMem, "no match for 'total physical memory' in trace output"); - return goodMem; + private static String getHostMaxMemory() { + return Long.valueOf(wb.hostPhysicalMemory()).toString(); + } + + private static String getHostSwap() { + return Long.valueOf(wb.hostPhysicalSwap()).toString(); } public static void main(String[] args) throws Exception { @@ -92,10 +95,9 @@ public static void main(String[] args) throws Exception { "200M", Integer.toString(((int) Math.pow(2, 20)) * (200 - 100)), true /* additional cgroup fs mounts */ ); - final String hostMaxMem = getHostMaxMemory(); - testOperatingSystemMXBeanIgnoresMemLimitExceedingPhysicalMemory(hostMaxMem); - testMetricsIgnoresMemLimitExceedingPhysicalMemory(hostMaxMem); - testContainerMemExceedsPhysical(hostMaxMem); + testOSMXBeanIgnoresMemLimitExceedingPhysicalMemory(); + testMetricsExceedingPhysicalMemory(); + testContainerMemExceedsPhysical(); } finally { if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) { DockerTestUtils.removeDockerImage(imageName); @@ -122,9 +124,10 @@ private static void testMemoryLimit(String valueToSet, String expectedTraceValue // JDK-8292083 // Ensure that Java ignores container memory limit values above the host's physical memory. - private static void testContainerMemExceedsPhysical(final String hostMaxMem) + private static void testContainerMemExceedsPhysical() throws Exception { Common.logNewTestCase("container memory limit exceeds physical memory"); + String hostMaxMem = getHostMaxMemory(); String badMem = hostMaxMem + "0"; // set a container memory limit to the bad value DockerRunOptions opts = Common.newOpts(imageName) @@ -204,12 +207,17 @@ private static void testOperatingSystemMXBeanAwareness(String memoryAllocation, .shouldMatch("OperatingSystemMXBean\\.getFreePhysicalMemorySize: [1-9][0-9]+"); // in case of warnings like : "Your kernel does not support swap limit capabilities // or the cgroup is not mounted. Memory limited without swap." - // the getTotalSwapSpaceSize and getFreeSwapSpaceSize return the system - // values as the container setup isn't supported in that case. + // the getTotalSwapSpaceSize either returns the system (or host) values, or 0 + // if a container memory limit is in place and gets detected. A value of 0 is because, + // Metrics.getMemoryLimit() returns the same value as Metrics.getMemoryAndSwapLimit(). + // + // getFreeSwapSpaceSize() are a function of what getTotalSwapSpaceSize() returns. Either + // a number > 0, or 0 if getTotalSwapSpaceSize() == 0. try { out.shouldContain("OperatingSystemMXBean.getTotalSwapSpaceSize: " + expectedSwap); } catch(RuntimeException ex) { - out.shouldMatch("OperatingSystemMXBean.getTotalSwapSpaceSize: [0-9]+"); + String hostSwap = getHostSwap(); + out.shouldMatch("OperatingSystemMXBean.getTotalSwapSpaceSize: (0|" + hostSwap + ")"); } try { out.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: [1-9][0-9]+"); @@ -220,17 +228,18 @@ private static void testOperatingSystemMXBeanAwareness(String memoryAllocation, // JDK-8292541: Ensure OperatingSystemMXBean ignores container memory limits above the host's physical memory. - private static void testOperatingSystemMXBeanIgnoresMemLimitExceedingPhysicalMemory(final String hostMaxMem) + private static void testOSMXBeanIgnoresMemLimitExceedingPhysicalMemory() throws Exception { + String hostMaxMem = getHostMaxMemory(); String badMem = hostMaxMem + "0"; testOperatingSystemMXBeanAwareness(badMem, hostMaxMem, badMem, hostMaxMem); } // JDK-8292541: Ensure Metrics ignores container memory limits above the host's physical memory. - private static void testMetricsIgnoresMemLimitExceedingPhysicalMemory(final String hostMaxMem) + private static void testMetricsExceedingPhysicalMemory() throws Exception { Common.logNewTestCase("Metrics ignore container memory limit exceeding physical memory"); - String badMem = hostMaxMem + "0"; + String badMem = getHostMaxMemory() + "0"; DockerRunOptions opts = Common.newOpts(imageName) .addJavaOpts("-XshowSettings:system") .addDockerOpts("--memory", badMem); diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java b/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java index 5adf8160b10..d5f0b4bc621 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java @@ -85,10 +85,14 @@ private static void testMemoryLimitWithSwappiness(String dockerMemLimit, String // capabilities or the cgroup is not mounted. Memory limited without swap." // we only have Memory and Swap Limit is: in the output try { - out.shouldContain("Memory and Swap Limit is: " + expectedReadLimit) - .shouldContain( + if (out.getOutput().contains("memory_and_swap_limit_in_bytes: not supported")) { + System.out.println("memory_and_swap_limit_in_bytes not supported, avoiding Memory and Swap Limit check"); + } else { + out.shouldContain("Memory and Swap Limit is: " + expectedReadLimit) + .shouldContain( "Memory and Swap Limit has been reset to " + expectedResetLimit + " because swappiness is 0") - .shouldContain("Memory & Swap Limit: " + expectedLimit); + .shouldContain("Memory & Swap Limit: " + expectedLimit); + } } catch (RuntimeException ex) { System.out.println("Expected Memory and Swap Limit output missing."); System.out.println("You may need to add 'cgroup_enable=memory swapaccount=1' to the Linux kernel boot parameters."); diff --git a/test/hotspot/jtreg/gc/TestAllocateHeapAt.java b/test/hotspot/jtreg/gc/TestAllocateHeapAt.java index 2d519fe66bd..1cf46fc1021 100644 --- a/test/hotspot/jtreg/gc/TestAllocateHeapAt.java +++ b/test/hotspot/jtreg/gc/TestAllocateHeapAt.java @@ -40,8 +40,7 @@ public class TestAllocateHeapAt { public static void main(String args[]) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-XX:AllocateHeapAt=" + System.getProperty("test.dir", "."), "-Xlog:gc+heap=info", "-Xmx32m", diff --git a/test/hotspot/jtreg/gc/TestAllocateHeapAtError.java b/test/hotspot/jtreg/gc/TestAllocateHeapAtError.java index fe6e62b7f62..64f08cb6149 100644 --- a/test/hotspot/jtreg/gc/TestAllocateHeapAtError.java +++ b/test/hotspot/jtreg/gc/TestAllocateHeapAtError.java @@ -46,8 +46,7 @@ public static void main(String args[]) throws Exception { f = new File(test_dir, UUID.randomUUID().toString()); } while(f.exists()); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-XX:AllocateHeapAt=" + f.getName(), "-Xlog:gc+heap=info", "-Xmx32m", diff --git a/test/hotspot/jtreg/gc/TestAllocateHeapAtMultiple.java b/test/hotspot/jtreg/gc/TestAllocateHeapAtMultiple.java index 6ff7c95e217..3419dc3d668 100644 --- a/test/hotspot/jtreg/gc/TestAllocateHeapAtMultiple.java +++ b/test/hotspot/jtreg/gc/TestAllocateHeapAtMultiple.java @@ -62,7 +62,7 @@ public static void main(String args[]) throws Exception { "-Xlog:gc+heap=info", "-version"}); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, flags); + ProcessBuilder pb = ProcessTools.createTestJvm(flags); OutputAnalyzer output = new OutputAnalyzer(pb.start()); System.out.println("Output:\n" + output.getOutput()); diff --git a/test/hotspot/jtreg/gc/TestVerifyDuringStartup.java b/test/hotspot/jtreg/gc/TestVerifyDuringStartup.java index 9ba8c0b13b2..8db65490a1e 100644 --- a/test/hotspot/jtreg/gc/TestVerifyDuringStartup.java +++ b/test/hotspot/jtreg/gc/TestVerifyDuringStartup.java @@ -38,8 +38,7 @@ public class TestVerifyDuringStartup { public static void main(String args[]) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-XX:-UseTLAB", "-XX:+UnlockDiagnosticVMOptions", "-XX:+VerifyDuringStartup", diff --git a/test/hotspot/jtreg/gc/arguments/GCArguments.java b/test/hotspot/jtreg/gc/arguments/GCArguments.java index 2c9dcdf11b7..b2610da0c4e 100644 --- a/test/hotspot/jtreg/gc/arguments/GCArguments.java +++ b/test/hotspot/jtreg/gc/arguments/GCArguments.java @@ -67,22 +67,18 @@ static private String[] withDefaults(String[] arguments) { } static public ProcessBuilder createJavaProcessBuilder(List arguments) { - return createJavaProcessBuilder(false, arguments); + return createJavaProcessBuilder(arguments.toArray(String[]::new)); } - static public ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOptions, - List arguments) { - return createJavaProcessBuilder(addTestVmAndJavaOptions, - arguments.toArray(String[]::new)); + static public ProcessBuilder createJavaProcessBuilder(String... arguments) { + return ProcessTools.createJavaProcessBuilder(withDefaults(arguments)); } - static public ProcessBuilder createJavaProcessBuilder(String... arguments) { - return createJavaProcessBuilder(false, arguments); + static public ProcessBuilder createTestJvm(List arguments) { + return createTestJvm(arguments.toArray(String[]::new)); } - static public ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOptions, - String... arguments) { - return ProcessTools.createJavaProcessBuilder(addTestVmAndJavaOptions, - withDefaults(arguments)); + static public ProcessBuilder createTestJvm(String... arguments) { + return ProcessTools.createTestJvm(withDefaults(arguments)); } } diff --git a/test/hotspot/jtreg/gc/arguments/TestUseNUMAInterleaving.java b/test/hotspot/jtreg/gc/arguments/TestUseNUMAInterleaving.java index 9ca7049e1b0..cd632d6ea3a 100644 --- a/test/hotspot/jtreg/gc/arguments/TestUseNUMAInterleaving.java +++ b/test/hotspot/jtreg/gc/arguments/TestUseNUMAInterleaving.java @@ -41,8 +41,7 @@ public class TestUseNUMAInterleaving { public static void main(String[] args) throws Exception { - ProcessBuilder pb = GCArguments.createJavaProcessBuilder( - true, + ProcessBuilder pb = GCArguments.createTestJvm( "-XX:+UseNUMA", "-XX:+PrintFlagsFinal", "-version"); diff --git a/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData.java b/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData.java index f553cbc3efa..c52cd0a4f62 100644 --- a/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData.java +++ b/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData.java @@ -104,7 +104,7 @@ protected void test() throws Exception { } private void performTest(List opts) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, opts); + ProcessBuilder pb = ProcessTools.createTestJvm(opts); OutputAnalyzer output = new OutputAnalyzer(pb.start()); System.out.println(output.getStdout()); diff --git a/test/hotspot/jtreg/gc/g1/TestStringDeduplicationTableRehashFullGC.java b/test/hotspot/jtreg/gc/g1/TestStringDeduplicationTableRehashFullGC.java new file mode 100644 index 00000000000..fc5e4f13f4b --- /dev/null +++ b/test/hotspot/jtreg/gc/g1/TestStringDeduplicationTableRehashFullGC.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package gc.g1; + +/* + * @test TestStringDeduplicationTableRehashFullGC + * @summary Test string deduplication table rehash during full GC + * @bug 8310176 + * @key gc + * @requires vm.gc.G1 + * @library /test/lib + * @library / + * @modules java.base/jdk.internal.misc:open + * @modules java.base/java.lang:open + * java.management + * @run main gc.g1.TestStringDeduplicationTableRehashFullGC + */ + +public class TestStringDeduplicationTableRehashFullGC { + public static void main(String[] args) throws Exception { + TestStringDeduplicationTools.testTableRehashFullGC(); + } +} diff --git a/test/hotspot/jtreg/gc/g1/TestStringDeduplicationTools.java b/test/hotspot/jtreg/gc/g1/TestStringDeduplicationTools.java index 70d4a452d53..79a21e49d88 100644 --- a/test/hotspot/jtreg/gc/g1/TestStringDeduplicationTools.java +++ b/test/hotspot/jtreg/gc/g1/TestStringDeduplicationTools.java @@ -383,6 +383,23 @@ public static void testTableRehash() throws Exception { output.shouldHaveExitValue(0); } + public static void testTableRehashFullGC() throws Exception { + // Test with StringDeduplicationRehashALot using full GCs + // Table resizing prevents table rehashing from happening, thus we use + // SmallNumberOfStrings to limit the number of table resizes. + OutputAnalyzer output = DeduplicationTest.run(SmallNumberOfStrings, + DefaultAgeThreshold, + FullGC, + "-Xlog:gc,gc+stringdedup=trace", + "-XX:+StringDeduplicationRehashALot"); + output.shouldContain("Concurrent String Deduplication"); + output.shouldContain("Deduplicated:"); + output.shouldContain("Full GC"); + output.shouldMatch("Rehash Count: [1-9]"); + output.shouldNotContain("Hash Seed: 0x0"); + output.shouldHaveExitValue(0); + } + public static void testAgeThreshold() throws Exception { OutputAnalyzer output; diff --git a/test/hotspot/jtreg/gc/g1/mixedgc/TestLogging.java b/test/hotspot/jtreg/gc/g1/mixedgc/TestLogging.java index e53723891f7..12cb2335e84 100644 --- a/test/hotspot/jtreg/gc/g1/mixedgc/TestLogging.java +++ b/test/hotspot/jtreg/gc/g1/mixedgc/TestLogging.java @@ -95,8 +95,7 @@ private static OutputAnalyzer spawnMixedGCProvoker(String... extraFlags) Collections.addAll(testOpts, extraFlags); testOpts.add(MixedGCProvoker.class.getName()); System.out.println(testOpts); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(false, - testOpts); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(testOpts); return new OutputAnalyzer(pb.start()); } } diff --git a/test/hotspot/jtreg/gc/whitebox/TestWBGC.java b/test/hotspot/jtreg/gc/whitebox/TestWBGC.java index 2667896208f..2d1cdbf26c4 100644 --- a/test/hotspot/jtreg/gc/whitebox/TestWBGC.java +++ b/test/hotspot/jtreg/gc/whitebox/TestWBGC.java @@ -43,8 +43,7 @@ public class TestWBGC { public static void main(String args[]) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-Xbootclasspath/a:.", "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", diff --git a/test/hotspot/jtreg/runtime/BootstrapMethod/BSMCalledTwice.java b/test/hotspot/jtreg/runtime/BootstrapMethod/BSMCalledTwice.java index da16c05e793..a8a8aa060bf 100644 --- a/test/hotspot/jtreg/runtime/BootstrapMethod/BSMCalledTwice.java +++ b/test/hotspot/jtreg/runtime/BootstrapMethod/BSMCalledTwice.java @@ -107,7 +107,7 @@ public Class loadClass(String name) throws ClassNotFoundException { }; cl.loadClass(classTestCName); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-cp", ".", classTestCName); + ProcessBuilder pb = ProcessTools.createTestJvm("-cp", ".", classTestCName); OutputAnalyzer output = new OutputAnalyzer(pb.start()); String test_output = output.getOutput(); if (test_output == null) { diff --git a/test/hotspot/jtreg/runtime/ClassFile/UnsupportedClassFileVersion.java b/test/hotspot/jtreg/runtime/ClassFile/UnsupportedClassFileVersion.java index 486bba9717c..255e5e402cc 100644 --- a/test/hotspot/jtreg/runtime/ClassFile/UnsupportedClassFileVersion.java +++ b/test/hotspot/jtreg/runtime/ClassFile/UnsupportedClassFileVersion.java @@ -42,7 +42,7 @@ public class UnsupportedClassFileVersion implements Opcodes { public static void main(String... args) throws Exception { writeClassFile(); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-cp", ".", "ClassFile"); + ProcessBuilder pb = ProcessTools.createTestJvm("-cp", ".", "ClassFile"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("ClassFile has been compiled by a more recent version of the " + "Java Runtime (class file version 99.0), this version of " + diff --git a/test/hotspot/jtreg/runtime/SharedArchiveFile/SharedArchiveFile.java b/test/hotspot/jtreg/runtime/SharedArchiveFile/SharedArchiveFile.java index 0ad543bfab7..9dea549c307 100644 --- a/test/hotspot/jtreg/runtime/SharedArchiveFile/SharedArchiveFile.java +++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/SharedArchiveFile.java @@ -41,20 +41,20 @@ // methods to form command line to create/use shared archive. public class SharedArchiveFile { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-XX:SharedArchiveFile=./SharedArchiveFile.jsa", "-Xshare:dump"); OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "SharedArchiveFile"); CDSTestUtils.checkDump(out); // -XX:+DumpSharedSpaces should behave the same as -Xshare:dump - pb = ProcessTools.createJavaProcessBuilder(true, + pb = ProcessTools.createTestJvm( "-XX:SharedArchiveFile=./SharedArchiveFile.jsa", "-XX:+DumpSharedSpaces"); out = CDSTestUtils.executeAndLog(pb, "SharedArchiveFile"); CDSTestUtils.checkDump(out); - pb = ProcessTools.createJavaProcessBuilder(true, + pb = ProcessTools.createTestJvm( "-XX:SharedArchiveFile=./SharedArchiveFile.jsa", "-Xshare:on", "-version"); out = CDSTestUtils.executeAndLog(pb, "SharedArchiveFile"); diff --git a/test/hotspot/jtreg/runtime/StackTrace/LargeClassTest.java b/test/hotspot/jtreg/runtime/StackTrace/LargeClassTest.java index 79bb139a680..3909c159a41 100644 --- a/test/hotspot/jtreg/runtime/StackTrace/LargeClassTest.java +++ b/test/hotspot/jtreg/runtime/StackTrace/LargeClassTest.java @@ -46,7 +46,7 @@ public class LargeClassTest implements Opcodes { public static void main(String... args) throws Exception { writeClassFile(); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-cp", ".", "Large"); + ProcessBuilder pb = ProcessTools.createTestJvm("-cp", ".", "Large"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/runtime/Unsafe/RangeCheck.java b/test/hotspot/jtreg/runtime/Unsafe/RangeCheck.java index dc899e45c05..3101a7db1ea 100644 --- a/test/hotspot/jtreg/runtime/Unsafe/RangeCheck.java +++ b/test/hotspot/jtreg/runtime/Unsafe/RangeCheck.java @@ -44,8 +44,7 @@ public static void main(String args[]) throws Exception { return; } - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-Xmx128m", "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", "-XX:-TransmitErrorReport", diff --git a/test/hotspot/jtreg/runtime/appcds/DumpClassList.java b/test/hotspot/jtreg/runtime/appcds/DumpClassList.java index f112173ecdd..695afb693f7 100644 --- a/test/hotspot/jtreg/runtime/appcds/DumpClassList.java +++ b/test/hotspot/jtreg/runtime/appcds/DumpClassList.java @@ -76,8 +76,7 @@ public static void main(String[] args) throws Exception { String appendJar = JarBuilder.build("bootappend", "boot/append/Foo"); // dump class list - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-XX:DumpLoadedClassList=" + classList, "--patch-module=java.base=" + patchJar, "-Xbootclasspath/a:" + appendJar, diff --git a/test/hotspot/jtreg/runtime/appcds/GraalWithLimitedMetaspace.java b/test/hotspot/jtreg/runtime/appcds/GraalWithLimitedMetaspace.java index aae4c8df093..2db66f67bf2 100644 --- a/test/hotspot/jtreg/runtime/appcds/GraalWithLimitedMetaspace.java +++ b/test/hotspot/jtreg/runtime/appcds/GraalWithLimitedMetaspace.java @@ -86,7 +86,7 @@ public static List toClassNames(String filename) throws IOException { } static void dumpLoadedClasses(String[] expectedClasses) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, + ProcessBuilder pb = ProcessTools.createTestJvm( TestCommon.makeCommandLineForAppCDS( "-XX:DumpLoadedClassList=" + CLASSLIST_FILE, // trigger JVMCI runtime init so that JVMCI classes will be @@ -114,7 +114,7 @@ static void dumpLoadedClasses(String[] expectedClasses) throws Exception { } static void dumpArchive() throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, + ProcessBuilder pb = ProcessTools.createTestJvm( TestCommon.makeCommandLineForAppCDS( "-cp", TESTJAR, diff --git a/test/hotspot/jtreg/runtime/appcds/TestCommon.java b/test/hotspot/jtreg/runtime/appcds/TestCommon.java index c45c87012b4..a457c0dea86 100644 --- a/test/hotspot/jtreg/runtime/appcds/TestCommon.java +++ b/test/hotspot/jtreg/runtime/appcds/TestCommon.java @@ -149,7 +149,7 @@ public static OutputAnalyzer createArchive(AppCDSOptions opts) for (String s : opts.suffix) cmd.add(s); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmd); + ProcessBuilder pb = ProcessTools.createTestJvm(cmd); return executeAndLog(pb, "dump"); } @@ -199,8 +199,12 @@ public static OutputAnalyzer runWithArchive(AppCDSOptions opts) } } +<<<<<<< HEAD String[] cmdLine = cmd.toArray(new String[cmd.size()]); ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, makeCommandLineForAppCDS(cmdLine)); +======= + ProcessBuilder pb = ProcessTools.createTestJvm(cmd); +>>>>>>> dragonwell_extended_upstream/master return executeAndLog(pb, "exec"); } diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsBasic.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsBasic.java index d6049014dbd..ea3491999a2 100644 --- a/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsBasic.java +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SharedStringsBasic.java @@ -46,7 +46,7 @@ public static void main(String[] args) throws Exception { String sharedArchiveConfigFile = TestCommon.getSourceFile("SharedStringsBasic.txt").toString(); - ProcessBuilder dumpPb = ProcessTools.createJavaProcessBuilder(true, + ProcessBuilder dumpPb = ProcessTools.createTestJvm( TestCommon.makeCommandLineForAppCDS( "-cp", appJar, "-XX:SharedArchiveConfigFile=" + sharedArchiveConfigFile, @@ -58,7 +58,7 @@ public static void main(String[] args) throws Exception { .shouldContain("Shared string table stats") .shouldHaveExitValue(0); - ProcessBuilder runPb = ProcessTools.createJavaProcessBuilder(true, + ProcessBuilder runPb = ProcessTools.createTestJvm( TestCommon.makeCommandLineForAppCDS( "-cp", appJar, "-XX:SharedArchiveFile=./SharedStringsBasic.jsa", diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/SysDictCrash.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SysDictCrash.java index 3aa9d5467ca..145fdb1afae 100644 --- a/test/hotspot/jtreg/runtime/appcds/sharedStrings/SysDictCrash.java +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SysDictCrash.java @@ -41,7 +41,7 @@ public class SysDictCrash { public static void main(String[] args) throws Exception { // SharedBaseAddress=0 puts the archive at a very high address on solaris, // which provokes the crash. - ProcessBuilder dumpPb = ProcessTools.createJavaProcessBuilder(true, + ProcessBuilder dumpPb = ProcessTools.createTestJvm( TestCommon.makeCommandLineForAppCDS( "-XX:+UseG1GC", "-XX:MaxRAMPercentage=12.5", "-cp", ".", @@ -51,7 +51,7 @@ public static void main(String[] args) throws Exception { TestCommon.checkDump(TestCommon.executeAndLog(dumpPb, "dump")); - ProcessBuilder runPb = ProcessTools.createJavaProcessBuilder(true, + ProcessBuilder runPb = ProcessTools.createTestJvm( TestCommon.makeCommandLineForAppCDS( "-XX:+UseG1GC", "-XX:MaxRAMPercentage=12.5", "-XX:SharedArchiveFile=./SysDictCrash.jsa", diff --git a/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java b/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java index 21859e86ac9..1676c46a9e0 100644 --- a/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java +++ b/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java @@ -53,8 +53,7 @@ public static void main(String[] args) throws Exception { useJVMCICompilerStr = "-XX:+UnlockExperimentalVMOptions"; } ProcessBuilder pb = - ProcessTools.createJavaProcessBuilder( - true, + ProcessTools.createTestJvm( "-Djava.library.path=" + Utils.TEST_NATIVE_PATH, "-XX:+SafepointALot", "-XX:GuaranteedSafepointInterval=20", diff --git a/test/hotspot/jtreg/runtime/modules/ModuleOptionsTest.java b/test/hotspot/jtreg/runtime/modules/ModuleOptionsTest.java index e526e06abe1..bb3688f2a06 100644 --- a/test/hotspot/jtreg/runtime/modules/ModuleOptionsTest.java +++ b/test/hotspot/jtreg/runtime/modules/ModuleOptionsTest.java @@ -28,6 +28,7 @@ * options but accumulates --add-module values. * @modules java.base/jdk.internal.misc * @library /test/lib + * @run driver ModuleOptionsTest */ import jdk.test.lib.process.OutputAnalyzer; diff --git a/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleClassList.java b/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleClassList.java index 2c4442c7c91..85bb2f8b7c8 100644 --- a/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleClassList.java +++ b/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleClassList.java @@ -63,8 +63,7 @@ public static void main(String args[]) throws Throwable { String moduleJar = BasicJarBuilder.getTestJar("javanaming.jar"); String classList = "javanaming.list"; - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-XX:DumpLoadedClassList=" + classList, "--patch-module=java.naming=" + moduleJar, "PatchModuleMain", BOOT_CLASS.replace('/', '.')); @@ -98,8 +97,7 @@ public static void main(String args[]) throws Throwable { moduleJar = BasicJarBuilder.getTestJar("javasql.jar"); classList = "javasql.list"; - pb = ProcessTools.createJavaProcessBuilder( - true, + pb = ProcessTools.createTestJvm( "-XX:DumpLoadedClassList=" + classList, "--patch-module=java.sql=" + moduleJar, "PatchModuleMain", PLATFORM_CLASS.replace('/', '.')); @@ -131,8 +129,7 @@ public static void main(String args[]) throws Throwable { moduleJar = BasicJarBuilder.getTestJar("hello.jar"); classList = "hello.list"; - pb = ProcessTools.createJavaProcessBuilder( - true, + pb = ProcessTools.createTestJvm( "-XX:DumpLoadedClassList=" + classList, "-Xbootclasspath/a:" + moduleJar, "Hello"); diff --git a/test/hotspot/jtreg/runtime/os/AvailableProcessors.java b/test/hotspot/jtreg/runtime/os/AvailableProcessors.java index 8d88e0e6292..ef258f4c87d 100644 --- a/test/hotspot/jtreg/runtime/os/AvailableProcessors.java +++ b/test/hotspot/jtreg/runtime/os/AvailableProcessors.java @@ -68,8 +68,7 @@ public static void main(String[] args) throws Exception { // Get the java command we want to execute // Enable logging for easier failure diagnosis ProcessBuilder master = - ProcessTools.createJavaProcessBuilder(false, - "-Xlog:os=trace", + ProcessTools.createJavaProcessBuilder("-Xlog:os=trace", "AvailableProcessors"); int[] expected = new int[] { 1, available/2, available-1, available }; diff --git a/test/hotspot/jtreg/runtime/os/TestUseCpuAllocPath.java b/test/hotspot/jtreg/runtime/os/TestUseCpuAllocPath.java index 76eb73d8085..546203ad913 100644 --- a/test/hotspot/jtreg/runtime/os/TestUseCpuAllocPath.java +++ b/test/hotspot/jtreg/runtime/os/TestUseCpuAllocPath.java @@ -41,8 +41,7 @@ public class TestUseCpuAllocPath { public static void main(String[] args) throws Exception { ProcessBuilder pb = - ProcessTools.createJavaProcessBuilder(false, - "-Xlog:os=trace", + ProcessTools.createJavaProcessBuilder("-Xlog:os=trace", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UseCpuAllocPath", "-version"); diff --git a/test/hotspot/jtreg/runtime/verifier/OverriderMsg.java b/test/hotspot/jtreg/runtime/verifier/OverriderMsg.java index 8e484da4b39..d90012d0fba 100644 --- a/test/hotspot/jtreg/runtime/verifier/OverriderMsg.java +++ b/test/hotspot/jtreg/runtime/verifier/OverriderMsg.java @@ -125,7 +125,7 @@ public static void dump_Overrider () throws Exception { public static void main(String... args) throws Exception { dump_HasFinal(); dump_Overrider(); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-cp", ".", "Overrider"); + ProcessBuilder pb = ProcessTools.createTestJvm("-cp", ".", "Overrider"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain( "java.lang.VerifyError: class Overrider overrides final method HasFinal.m(Ljava/lang/String;)V"); diff --git a/test/hotspot/jtreg/runtime/verifier/TestANewArray.java b/test/hotspot/jtreg/runtime/verifier/TestANewArray.java index a5f9b5a1008..880d945dffa 100644 --- a/test/hotspot/jtreg/runtime/verifier/TestANewArray.java +++ b/test/hotspot/jtreg/runtime/verifier/TestANewArray.java @@ -69,7 +69,7 @@ public static void main(String... args) throws Exception { byte[] classFile_254 = dumpClassFile(cfv, test_Dimension_254, array_Dimension_254); writeClassFileFromByteArray(classFile_254); System.err.println("Running with cfv: " + cfv + ", test_Dimension_254"); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-verify", "-cp", ".", classCName); + ProcessBuilder pb = ProcessTools.createTestJvm("-verify", "-cp", ".", classCName); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldNotContain("java.lang.VerifyError"); output.shouldHaveExitValue(0); @@ -78,7 +78,7 @@ public static void main(String... args) throws Exception { byte[] classFile_255 = dumpClassFile(cfv, test_Dimension_255, array_Dimension_255); writeClassFileFromByteArray(classFile_255); System.err.println("Running with cfv: " + cfv + ", test_Dimension_255"); - pb = ProcessTools.createJavaProcessBuilder(true, "-verify", "-cp", ".", classCName); + pb = ProcessTools.createTestJvm("-verify", "-cp", ".", classCName); output = new OutputAnalyzer(pb.start()); // If anewarray has an operand with 255 array dimensions then VerifyError should // be thrown because the resulting array would have 256 dimensions. @@ -95,7 +95,7 @@ public static void main(String... args) throws Exception { byte[] classFile_264 = dumpClassFile(cfv, test_Dimension_264, array_Dimension_264); writeClassFileFromByteArray(classFile_264); System.err.println("Running with cfv: " + cfv + ", test_Dimension_264"); - pb = ProcessTools.createJavaProcessBuilder(true, "-verify", "-cp", ".", classCName); + pb = ProcessTools.createTestJvm("-verify", "-cp", ".", classCName); output = new OutputAnalyzer(pb.start()); output.shouldContain("java.lang.ClassFormatError"); output.shouldHaveExitValue(1); diff --git a/test/hotspot/jtreg/runtime/verifier/TestMultiANewArray.java b/test/hotspot/jtreg/runtime/verifier/TestMultiANewArray.java index 7e53ce27734..ba3734d889a 100644 --- a/test/hotspot/jtreg/runtime/verifier/TestMultiANewArray.java +++ b/test/hotspot/jtreg/runtime/verifier/TestMultiANewArray.java @@ -48,7 +48,7 @@ public static void main(String... args) throws Exception { int cfv = Integer.parseInt(args[0]); writeClassFile(cfv); System.err.println("Running with cfv: " + cfv); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-cp", ".", "ClassFile"); + ProcessBuilder pb = ProcessTools.createTestJvm("-cp", ".", "ClassFile"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("VerifyError"); output.shouldHaveExitValue(1); diff --git a/test/hotspot/jtreg/sanity/MismatchedWhiteBox/WhiteBox.java b/test/hotspot/jtreg/sanity/MismatchedWhiteBox/WhiteBox.java index e45cf846eb8..4d7ad5f81bc 100644 --- a/test/hotspot/jtreg/sanity/MismatchedWhiteBox/WhiteBox.java +++ b/test/hotspot/jtreg/sanity/MismatchedWhiteBox/WhiteBox.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,15 @@ package sun.hotspot; public class WhiteBox { + @SuppressWarnings("serial") + public static class WhiteBoxPermission extends java.security.BasicPermission { + // ClassFileInstaller is hard-coded to copy WhiteBox$WhiteBoxPermission, so let's + // make a fake one here as well. + public WhiteBoxPermission(String s) { + super(s); + } + } + private static native void registerNatives(); static { registerNatives(); } public native int notExistedMethod(); diff --git a/test/hotspot/jtreg/serviceability/jvmti/GetObjectSizeClass.java b/test/hotspot/jtreg/serviceability/jvmti/GetObjectSizeClass.java index e54fee726bc..c0a5041fdf2 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/GetObjectSizeClass.java +++ b/test/hotspot/jtreg/serviceability/jvmti/GetObjectSizeClass.java @@ -50,7 +50,7 @@ public static void main(String[] args) throws Exception { pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", "agent.jar", "GetObjectSizeClassAgent.class"}); pb.start().waitFor(); - ProcessBuilder pt = ProcessTools.createJavaProcessBuilder(true, "-javaagent:agent.jar", "GetObjectSizeClassAgent"); + ProcessBuilder pt = ProcessTools.createTestJvm("-javaagent:agent.jar", "GetObjectSizeClassAgent"); OutputAnalyzer output = new OutputAnalyzer(pt.start()); output.stdoutShouldContain("GetObjectSizeClass passed"); diff --git a/test/hotspot/jtreg/serviceability/jvmti/GetObjectSizeOverflow.java b/test/hotspot/jtreg/serviceability/jvmti/GetObjectSizeOverflow.java index 1f3cf82b296..5395e7c7790 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/GetObjectSizeOverflow.java +++ b/test/hotspot/jtreg/serviceability/jvmti/GetObjectSizeOverflow.java @@ -57,7 +57,7 @@ public static void main(String[] args) throws Exception { pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", "agent.jar", "GetObjectSizeOverflowAgent.class"}); pb.start().waitFor(); - ProcessBuilder pt = ProcessTools.createJavaProcessBuilder(true, "-Xmx4000m", "-javaagent:agent.jar", "GetObjectSizeOverflowAgent"); + ProcessBuilder pt = ProcessTools.createTestJvm("-Xmx4000m", "-javaagent:agent.jar", "GetObjectSizeOverflowAgent"); OutputAnalyzer output = new OutputAnalyzer(pt.start()); if (output.getStdout().contains("Could not reserve enough space") || output.getStderr().contains("java.lang.OutOfMemoryError")) { diff --git a/test/hotspot/jtreg/serviceability/logging/TestLogRotation.java b/test/hotspot/jtreg/serviceability/logging/TestLogRotation.java index 853cef8f14b..fbcaa40de04 100644 --- a/test/hotspot/jtreg/serviceability/logging/TestLogRotation.java +++ b/test/hotspot/jtreg/serviceability/logging/TestLogRotation.java @@ -72,8 +72,7 @@ public static void cleanLogs() { public static void runTest(int numberOfFiles) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-cp", System.getProperty("java.class.path"), "-Xlog:gc=debug:" + logFileName + "::filesize=" + logFileSizeK + "k" diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java index e6728ed0211..e93776b3b09 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java @@ -95,7 +95,7 @@ public static void main(String[] args) throws Exception { List options = new ArrayList<>(); options.addAll(Arrays.asList(jArgs)); crashOut = - ProcessTools.executeProcess(getTestJavaCommandlineWithPrefix( + ProcessTools.executeProcess(getTestJvmCommandlineWithPrefix( RUN_SHELL_NO_LIMIT, options.toArray(new String[0]))); } catch (Throwable t) { throw new Error("Can't execute the java cds process.", t); @@ -258,9 +258,9 @@ private static String getCoreFileLocation(String crashOutputString) { return null; } - private static String[] getTestJavaCommandlineWithPrefix(String prefix, String... args) { + private static String[] getTestJvmCommandlineWithPrefix(String prefix, String... args) { try { - String cmd = ProcessTools.getCommandLine(ProcessTools.createJavaProcessBuilder(true, args)); + String cmd = ProcessTools.getCommandLine(ProcessTools.createTestJvm(args)); return new String[]{"sh", "-c", prefix + cmd}; } catch (Throwable t) { throw new Error("Can't create process builder: " + t, t); diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java index 089ad615d8f..ac48b9f9ea2 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -33,6 +33,7 @@ /** * @test * @bug 8190198 + * @bug 8217612 * @summary Test clhsdb flags command * @requires vm.hasSA * @library /test/lib @@ -41,8 +42,8 @@ public class ClhsdbFlags { - public static void main(String[] args) throws Exception { - System.out.println("Starting ClhsdbFlags test"); + public static void runBasicTest() throws Exception { + System.out.println("Starting ClhsdbFlags basic test"); LingeredApp theApp = null; try { @@ -90,4 +91,54 @@ public static void main(String[] args) throws Exception { } System.out.println("Test PASSED"); } + + public static void runAllTypesTest() throws Exception { + System.out.println("Starting ClhsdbFlags all types test"); + + LingeredApp theApp = null; + try { + ClhsdbLauncher test = new ClhsdbLauncher(); + List vmArgs = new ArrayList(); + vmArgs.add("-XX:+UnlockDiagnosticVMOptions"); // bool + vmArgs.add("-XX:ActiveProcessorCount=1"); // int + vmArgs.add("-XX:ParallelGCThreads=1"); // uint + vmArgs.add("-XX:MaxJavaStackTraceDepth=1024"); // intx + vmArgs.add("-XX:LogEventsBufferEntries=10"); // uintx + vmArgs.add("-XX:HeapSizePerGCThread=32m"); // size_t + vmArgs.add("-XX:NativeMemoryTracking=off"); // ccstr + vmArgs.add("-XX:OnError='echo error'"); // ccstrlist + vmArgs.add("-XX:CompileThresholdScaling=1.0"); // double + vmArgs.add("-XX:ErrorLogTimeout=120"); // uint64_t + vmArgs.addAll(Utils.getVmOptions()); + theApp = LingeredApp.startApp(vmArgs); + System.out.println("Started LingeredApp with pid " + theApp.getPid()); + + List cmds = List.of("flags"); + + Map> expStrMap = new HashMap<>(); + expStrMap.put("flags", List.of( + "UnlockDiagnosticVMOptions = true", + "ActiveProcessorCount = 1", + "ParallelGCThreads = 1", + "MaxJavaStackTraceDepth = 1024", + "LogEventsBufferEntries = 10", + "HeapSizePerGCThread = 3", + "NativeMemoryTracking = \"off\"", + "OnError = \"'echo error'\"", + "CompileThresholdScaling = 1.0", + "ErrorLogTimeout = 120")); + + test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); + } finally { + LingeredApp.stopApp(theApp); + } + System.out.println("Test PASSED"); + } + + public static void main(String[] args) throws Exception { + runBasicTest(); + runAllTypesTest(); + } } diff --git a/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java b/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java index 84d05b1420f..67b356b38cd 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java @@ -87,7 +87,7 @@ static boolean useDefaultUlimit() { } static void test(String type) throws Throwable { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-XX:+CreateCoredumpOnCrash", + ProcessBuilder pb = ProcessTools.createTestJvm("-XX:+CreateCoredumpOnCrash", "-Xmx512m", "-XX:MaxMetaspaceSize=64m", "-XX:+CrashOnOutOfMemoryError", "-XX:-TransmitErrorReport", TestJmapCore.class.getName(), type); diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java index fabf95b61b0..d57a103f041 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java @@ -174,9 +174,7 @@ private void startCtwforAllClasses() { while (!done) { String[] cmd = cmd(classStart, classStop); try { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - /* addTestVmAndJavaOptions = */ true, - cmd); + ProcessBuilder pb = ProcessTools.createTestJvm(cmd); String commandLine = pb.command() .stream() .collect(Collectors.joining(" ")); diff --git a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/jtreg/JitTesterDriver.java b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/jtreg/JitTesterDriver.java index b0177849bd2..e350d5cf121 100644 --- a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/jtreg/JitTesterDriver.java +++ b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/jtreg/JitTesterDriver.java @@ -47,7 +47,7 @@ public static void main(String[] args) { } OutputAnalyzer oa; try { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, args); + ProcessBuilder pb = ProcessTools.createTestJvm(args); oa = new OutputAnalyzer(pb.start()); } catch (Exception e) { throw new Error("Unexpected exception on test jvm start :" + e, e); diff --git a/test/hotspot/jtreg/testlibrary_tests/ctw/CtwTest.java b/test/hotspot/jtreg/testlibrary_tests/ctw/CtwTest.java index a8ca32ee6ca..4fb45c0c592 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ctw/CtwTest.java +++ b/test/hotspot/jtreg/testlibrary_tests/ctw/CtwTest.java @@ -102,7 +102,7 @@ protected void compile(String[] args) throws Exception { } } } - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmd); + ProcessBuilder pb = ProcessTools.createTestJvm(cmd); OutputAnalyzer output = new OutputAnalyzer(pb.start()); dump(output, "compile"); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/vmTestbase/gc/huge/quicklook/largeheap/MemOptions/MemOptionsTest.java b/test/hotspot/jtreg/vmTestbase/gc/huge/quicklook/largeheap/MemOptions/MemOptionsTest.java index 1a0814e1dac..f8f213d733e 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/huge/quicklook/largeheap/MemOptions/MemOptionsTest.java +++ b/test/hotspot/jtreg/vmTestbase/gc/huge/quicklook/largeheap/MemOptions/MemOptionsTest.java @@ -94,7 +94,7 @@ private void positive(String name, String... opts) throws IOException { var cmd = new ArrayList(); Collections.addAll(cmd, opts); cmd.add(MemStat.class.getName()); - var pb = ProcessTools.createJavaProcessBuilder(true, cmd); + var pb = ProcessTools.createTestJvm(cmd); var output = new OutputAnalyzer(pb.start()); if (output.getExitValue() != 0) { output.reportDiagnosticSummary(); @@ -107,7 +107,7 @@ private void negative(String name, String... opts) throws IOException { var cmd = new ArrayList(); Collections.addAll(cmd, opts); cmd.add(MemStat.class.getName()); - var pb = ProcessTools.createJavaProcessBuilder(true, cmd); + var pb = ProcessTools.createTestJvm(cmd); var output = new OutputAnalyzer(pb.start()); if (output.getExitValue() == 0) { output.reportDiagnosticSummary(); diff --git a/test/hotspot/jtreg/vmTestbase/jit/tiered/Test.java b/test/hotspot/jtreg/vmTestbase/jit/tiered/Test.java index a4acb7663cb..51b45e94abf 100644 --- a/test/hotspot/jtreg/vmTestbase/jit/tiered/Test.java +++ b/test/hotspot/jtreg/vmTestbase/jit/tiered/Test.java @@ -51,7 +51,7 @@ public class Test { public static void main(String[] args) throws Exception { { System.out.println("TieredCompilation is enabled"); - var pb = ProcessTools.createJavaProcessBuilder(true, + var pb = ProcessTools.createTestJvm( "-XX:+TieredCompilation", "-XX:+PrintTieredEvents", "-version"); @@ -64,7 +64,7 @@ public static void main(String[] args) throws Exception { } { System.out.println("TieredCompilation is disabled"); - var pb = ProcessTools.createJavaProcessBuilder(true, + var pb = ProcessTools.createTestJvm( "-XX:-TieredCompilation", "-XX:+PrintTieredEvents", "-version"); diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/flags/maxMetaspaceSize/TestMaxMetaspaceSize.java b/test/hotspot/jtreg/vmTestbase/metaspace/flags/maxMetaspaceSize/TestMaxMetaspaceSize.java index d67d77e5b08..1cdfbd4e361 100644 --- a/test/hotspot/jtreg/vmTestbase/metaspace/flags/maxMetaspaceSize/TestMaxMetaspaceSize.java +++ b/test/hotspot/jtreg/vmTestbase/metaspace/flags/maxMetaspaceSize/TestMaxMetaspaceSize.java @@ -39,8 +39,8 @@ public class TestMaxMetaspaceSize { public static void main(String[] args) throws Exception { ProcessBuilder pb = - ProcessTools.createJavaProcessBuilder(true, "-XX:MaxMetaspaceSize=100m", - maxMetaspaceSize.class.getName()); + ProcessTools.createTestJvm("-XX:MaxMetaspaceSize=100m", + maxMetaspaceSize.class.getName()); OutputAnalyzer out = new OutputAnalyzer(pb.start()); if (out.getExitValue() == 0) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat001/thrstat001.cpp b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat001/thrstat001.cpp index fee4f58a417..1458c6ed920 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat001/thrstat001.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat001/thrstat001.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -39,177 +39,87 @@ static jvmtiEnv *jvmti = NULL; static jvmtiCapabilities caps; static jvmtiEventCallbacks callbacks; static jrawMonitorID access_lock; +static jrawMonitorID wait_lock; static jint result = PASSED; -static jboolean printdump = JNI_FALSE; static jthread thr_ptr = NULL; + static jint state[] = { JVMTI_THREAD_STATE_RUNNABLE, JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER, JVMTI_THREAD_STATE_IN_OBJECT_WAIT }; -static int entry_count = 0; -static int entry_error_count = 0; -static int exit_count = 0; -static int exit_error_count = 0; - -void JNICALL VMInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thr) { - jvmtiError err; - - err = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, - JVMTI_EVENT_THREAD_START, NULL); +static void +lock(const char* func_name, jrawMonitorID lock) { + jvmtiError err = jvmti->RawMonitorEnter(lock); if (err != JVMTI_ERROR_NONE) { - printf("Failed to enable THREAD_START event: %s (%d)\n", - TranslateError(err), err); + printf("%s: unexpected error in RawMonitorEnter: %s (%d)\n", + func_name, TranslateError(err), err); result = STATUS_FAILED; } - - if (caps.can_generate_method_entry_events) { - err = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, - JVMTI_EVENT_METHOD_ENTRY, NULL); - if (err != JVMTI_ERROR_NONE) { - printf("Failed to enable METHOD_ENTRY event: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } - } - - if (caps.can_generate_method_exit_events) { - err = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, - JVMTI_EVENT_METHOD_EXIT, NULL); - if (err != JVMTI_ERROR_NONE) { - printf("Failed to enable METHOD_EXIT event: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } - } } -void JNICALL -ThreadStart(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) { - jvmtiError err; - jvmtiThreadInfo thrInfo; - - err = jvmti_env->RawMonitorEnter(access_lock); - if (err != JVMTI_ERROR_NONE) { - printf("(RawMonitorEnter#TS) unexpected error: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } - - err = jvmti_env->GetThreadInfo(thread, &thrInfo); - if (err != JVMTI_ERROR_NONE) { - printf("(GetThreadInfo#TS) unexpected error: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } - if (thrInfo.name != NULL && strcmp(thrInfo.name, "thr1") == 0) { - thr_ptr = env->NewGlobalRef(thread); - if (printdump == JNI_TRUE) { - printf(">>> ThreadStart: \"%s\", 0x%p\n", thrInfo.name, thr_ptr); - } - } - - err = jvmti_env->RawMonitorExit(access_lock); +static void +unlock(const char* func_name, jrawMonitorID lock) { + jvmtiError err = jvmti->RawMonitorExit(lock); if (err != JVMTI_ERROR_NONE) { - printf("(RawMonitorExit#TS) unexpected error: %s (%d)\n", - TranslateError(err), err); + printf("%s: unexpected error in RawMonitorExit: %s (%d)\n", + func_name, TranslateError(err), err); result = STATUS_FAILED; } } -void JNICALL MethodEntry(jvmtiEnv *jvmti_env, JNIEnv *env, - jthread thread, jmethodID mid) { - jvmtiError err; - jvmtiThreadInfo thrInfo; - jint thrState; - - err = jvmti_env->RawMonitorEnter(access_lock); +static void +wait(const char* func_name, jrawMonitorID lock, jint millis) { + jvmtiError err = jvmti->RawMonitorWait(lock, (jlong)millis); if (err != JVMTI_ERROR_NONE) { - printf("(RawMonitorEnter#ME) unexpected error: %s (%d)\n", - TranslateError(err), err); + printf("%s: unexpected error in RawMonitorWait: %s (%d)\n", + func_name, TranslateError(err), err); result = STATUS_FAILED; } +} - entry_count++; - err = jvmti_env->GetThreadState(thread, &thrState); - if (err != JVMTI_ERROR_NONE) { - printf("(GetThreadState#ME) unexpected error: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } - if ((thrState & JVMTI_THREAD_STATE_RUNNABLE) == 0) { - if (entry_error_count == 0) { - err = jvmti_env->GetThreadInfo(thread, &thrInfo); - if (err != JVMTI_ERROR_NONE) { - printf("(GetThreadInfo#ME) unexpected error: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } - printf("Wrong thread \"%s\" state on MethodEntry event:\n", - thrInfo.name); - printf(" expected: JVMTI_THREAD_STATE_RUNNABLE\n"); - printf(" got: %s (%d)\n", - TranslateState(thrState), thrState); - } - entry_error_count++; - result = STATUS_FAILED; - } +static void +set_notification_mode(const char* event_name, + jvmtiEventMode mode, + jvmtiEvent event_type, + jthread event_thread) { + const char* action = (mode == JVMTI_ENABLE) ? "enable" : "disable"; + jvmtiError err = jvmti->SetEventNotificationMode(mode, event_type, event_thread); - err = jvmti_env->RawMonitorExit(access_lock); if (err != JVMTI_ERROR_NONE) { - printf("(RawMonitorExit#ME) unexpected error: %s (%d)\n", - TranslateError(err), err); + printf("Failed to %s %s event: %s (%d)\n", + action, event_name, TranslateError(err), err); result = STATUS_FAILED; } +} +void JNICALL VMInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thr) { + set_notification_mode("JVMTI_EVENT_THREAD_START", JVMTI_ENABLE, + JVMTI_EVENT_THREAD_START, NULL); } -void JNICALL MethodExit(jvmtiEnv *jvmti_env, JNIEnv *env, - jthread thread, jmethodID mid, - jboolean was_poped_by_exception, jvalue return_value) { +void JNICALL +ThreadStart(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) { jvmtiError err; jvmtiThreadInfo thrInfo; - jint thrState; - err = jvmti_env->RawMonitorEnter(access_lock); - if (err != JVMTI_ERROR_NONE) { - printf("(RawMonitorEnter#MX) unexpected error: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } + lock("ThreadStart", access_lock); - exit_count++; - err = jvmti_env->GetThreadState(thread, &thrState); + err = jvmti_env->GetThreadInfo(thread, &thrInfo); if (err != JVMTI_ERROR_NONE) { - printf("(GetThreadState#MX) unexpected error: %s (%d)\n", - TranslateError(err), err); + printf("(GetThreadInfo#TS) unexpected error: %s (%d)\n", + TranslateError(err), err); result = STATUS_FAILED; } - if ((thrState & JVMTI_THREAD_STATE_RUNNABLE) == 0) { - if (exit_error_count == 0) { - err = jvmti_env->GetThreadInfo(thread, &thrInfo); - if (err != JVMTI_ERROR_NONE) { - printf("(GetThreadInfo#MX) unexpected error: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } - printf("Wrong thread \"%s\" state on MethodExit event:\n", - thrInfo.name); - printf(" expected: JVMTI_THREAD_STATE_RUNNABLE\n"); - printf(" got: %s (%d)\n", - TranslateState(thrState), thrState); - } - exit_error_count++; - result = STATUS_FAILED; + if (thrInfo.name != NULL && strcmp(thrInfo.name, "thr1") == 0) { + thr_ptr = env->NewGlobalRef(thread); + printf(">>> ThreadStart: \"%s\", 0x%p\n", thrInfo.name, thr_ptr); + set_notification_mode("JVMTI_EVENT_THREAD_START", JVMTI_DISABLE, + JVMTI_EVENT_THREAD_START, NULL); } - err = jvmti_env->RawMonitorExit(access_lock); - if (err != JVMTI_ERROR_NONE) { - printf("(RawMonitorExit#MX) unexpected error: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } + unlock("ThreadStart", access_lock); } #ifdef STATIC_BUILD @@ -223,13 +133,12 @@ JNIEXPORT jint JNI_OnLoad_thrstat001(JavaVM *jvm, char *options, void *reserved) return JNI_VERSION_1_8; } #endif + jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { jint res; jvmtiError err; - if (options != NULL && strcmp(options, "printdump") == 0) { - printdump = JNI_TRUE; - } + printf("Agent_Initialize started\n"); res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1); if (res != JNI_OK || jvmti == NULL) { @@ -260,23 +169,20 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { err = jvmti->CreateRawMonitor("_access_lock", &access_lock); if (err != JVMTI_ERROR_NONE) { - printf("(CreateRawMonitor) unexpected error: %s (%d)\n", + printf("(CreateRawMonitor)#access_lock unexpected error: %s (%d)\n", + TranslateError(err), err); + return JNI_ERR; + } + + err = jvmti->CreateRawMonitor("_wait_lock", &wait_lock); + if (err != JVMTI_ERROR_NONE) { + printf("(CreateRawMonitor#wait_lock) unexpected error: %s (%d)\n", TranslateError(err), err); return JNI_ERR; } callbacks.VMInit = &VMInit; callbacks.ThreadStart = &ThreadStart; - if (caps.can_generate_method_entry_events) { - callbacks.MethodEntry = &MethodEntry; - } else { - printf("Warning: MethodEntry event is not implemented\n"); - } - if (caps.can_generate_method_exit_events) { - callbacks.MethodExit = &MethodExit; - } else { - printf("Warning: MethodExit event is not implemented\n"); - } err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)); if (err != JVMTI_ERROR_NONE) { printf("(SetEventCallbacks) unexpected error: %s (%d)\n", @@ -284,14 +190,10 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { return JNI_ERR; } - err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, - JVMTI_EVENT_VM_INIT, NULL); - if (err != JVMTI_ERROR_NONE) { - printf("Failed to enable VM_INIT event: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } + set_notification_mode("JVMTI_EVENT_VM_INIT", JVMTI_ENABLE, + JVMTI_EVENT_VM_INIT, NULL); + printf("Agent_Initialize finished\n\n"); return JNI_OK; } @@ -299,10 +201,10 @@ JNIEXPORT void JNICALL Java_nsk_jvmti_GetThreadState_thrstat001_checkStatus(JNIEnv *env, jclass cls, jint statInd) { jvmtiError err; - jrawMonitorID wait_lock; jint thrState; jint millis; + printf("native method checkStatus started\n"); if (jvmti == NULL) { printf("JVMTI client was not properly loaded!\n"); result = STATUS_FAILED; @@ -316,12 +218,6 @@ Java_nsk_jvmti_GetThreadState_thrstat001_checkStatus(JNIEnv *env, } /* wait until thread gets an expected state */ - err = jvmti->CreateRawMonitor("_wait_lock", &wait_lock); - if (err != JVMTI_ERROR_NONE) { - printf("(CreateRawMonitor) unexpected error: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } for (millis = WAIT_START; millis < WAIT_TIME; millis <<= 1) { err = jvmti->GetThreadState(thr_ptr, &thrState); if (err != JVMTI_ERROR_NONE) { @@ -332,36 +228,13 @@ Java_nsk_jvmti_GetThreadState_thrstat001_checkStatus(JNIEnv *env, if ((thrState & state[statInd]) != 0) { break; } - err = jvmti->RawMonitorEnter(wait_lock); - if (err != JVMTI_ERROR_NONE) { - printf("(RawMonitorEnter) unexpected error: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } - err = jvmti->RawMonitorWait(wait_lock, (jlong)millis); - if (err != JVMTI_ERROR_NONE) { - printf("(RawMonitorWait) unexpected error: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } - err = jvmti->RawMonitorExit(wait_lock); - if (err != JVMTI_ERROR_NONE) { - printf("(RawMonitorExit) unexpected error: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } - } - err = jvmti->DestroyRawMonitor(wait_lock); - if (err != JVMTI_ERROR_NONE) { - printf("(DestroyRawMonitor) unexpected error: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; + lock("checkStatus", wait_lock); + wait("checkStatus", wait_lock, millis); + unlock("checkStatus", wait_lock); } - if (printdump == JNI_TRUE) { - printf(">>> thread \"thr1\" (0x%p) state: %s (%d)\n", + printf(">>> thread \"thr1\" (0x%p) state: %s (%d)\n", thr_ptr, TranslateState(thrState), thrState); - } if ((thrState & state[statInd]) == 0) { printf("Wrong thread \"thr1\" (0x%p) state:\n", thr_ptr); @@ -371,55 +244,12 @@ Java_nsk_jvmti_GetThreadState_thrstat001_checkStatus(JNIEnv *env, TranslateState(thrState), thrState); result = STATUS_FAILED; } + printf("native method checkStatus finished\n\n"); } JNIEXPORT jint JNICALL Java_nsk_jvmti_GetThreadState_thrstat001_getRes(JNIEnv *env, jclass cls) { - jvmtiError err; - - err = jvmti->SetEventNotificationMode(JVMTI_DISABLE, - JVMTI_EVENT_THREAD_START, NULL); - if (err != JVMTI_ERROR_NONE) { - printf("Failed to disable THREAD_START event: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } - - if (caps.can_generate_method_entry_events) { - err = jvmti->SetEventNotificationMode(JVMTI_DISABLE, - JVMTI_EVENT_METHOD_ENTRY, NULL); - if (err != JVMTI_ERROR_NONE) { - printf("Failed to disable METHOD_ENTRY event: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } - } - - if (caps.can_generate_method_exit_events) { - err = jvmti->SetEventNotificationMode(JVMTI_DISABLE, - JVMTI_EVENT_METHOD_EXIT, NULL); - if (err != JVMTI_ERROR_NONE) { - printf("Failed to disable METHOD_EXIT event: %s (%d)\n", - TranslateError(err), err); - result = STATUS_FAILED; - } - } - - if (printdump == JNI_TRUE) { - printf(">>> total number of method entry events = %d\n", entry_count); - printf(">>> total number of method exit events = %d\n", exit_count); - } - - if (entry_error_count != 0) { - printf("Total number of errors on METHOD_ENTRY: %d of %d events\n", - entry_error_count, entry_count); - } - - if (exit_error_count != 0) { - printf("Total number of errors on METHOD_EXIT: %d of %d events\n", - exit_error_count, exit_count); - } - + printf("native method getRes: result: %d\n\n", result); return result; } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RetransformClasses/retransform003/TestDriver.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RetransformClasses/retransform003/TestDriver.java index 1fcaeffc33e..739659b019c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RetransformClasses/retransform003/TestDriver.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RetransformClasses/retransform003/TestDriver.java @@ -69,8 +69,7 @@ public class TestDriver { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-agentlib:retransform003-01=id=1 can_retransform_classes=1", "-agentlib:retransform003-02=id=2 can_retransform_classes=0", "-agentlib:retransform003-03=id=3 can_retransform_classes=1", diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetNativeMethodPrefix/SetNativeMethodPrefix001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetNativeMethodPrefix/SetNativeMethodPrefix001/TestDescription.java index 15f00657096..2caadcbca19 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetNativeMethodPrefix/SetNativeMethodPrefix001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetNativeMethodPrefix/SetNativeMethodPrefix001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -47,7 +47,7 @@ * /test/lib * @run driver jdk.test.lib.FileInstaller . . * @run main/othervm/native - * -agentlib:SetNativeMethodPrefix001= + * -agentlib:SetNativeMethodPrefix001 * nsk.jvmti.SetNativeMethodPrefix.SetNativeMethodPrefix001 */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetNativeMethodPrefix/SetNativeMethodPrefix002/TestDriver.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetNativeMethodPrefix/SetNativeMethodPrefix002/TestDriver.java index c8218922815..5e74b95db8c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetNativeMethodPrefix/SetNativeMethodPrefix002/TestDriver.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetNativeMethodPrefix/SetNativeMethodPrefix002/TestDriver.java @@ -58,8 +58,7 @@ public class TestDriver { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-agentlib:SetNativeMethodPrefix001=trace=all", "-agentlib:SetNativeMethodPrefix002-01=trace=all prefix=wa_", "-agentlib:SetNativeMethodPrefix002-02=trace=all prefix=wb_", diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/jvmti_tools.cpp b/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/jvmti_tools.cpp index 7aa0e13f939..d56e4f71c9b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/jvmti_tools.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/jvmti_tools.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -48,7 +48,6 @@ extern "C" { #define NSK_JVMTI_MAX_OPTIONS 10 #define NSK_JVMTI_OPTION_START '-' -#define NSK_JVMTI_OPTION_VAL_SEP '=' #define NSK_JVMTI_OPT_PATH_TO_NEW_BYTE_CODE "pathToNewByteCode" #define PATH_FORMAT "%s%02d/%s" @@ -191,23 +190,29 @@ static void nsk_jvmti_free() { } } -int isOptSep(char c) { - return isspace(c) || c == '~'; -} +/* + * Tokenize a string based on a list of delimiters. + */ +static char* token(char **s, const char *delim) { + char *p; + char *start = *s; + if (s == NULL || *s == NULL) { + return NULL; + } -/** - * - * The current option will not perform more than one - * single option which given, this is due to places explained - * in this question. - * - **/ + p = strpbrk(*s, delim); + if (p != NULL) { + /* Advance to next token. */ + *p = '\0'; + *s = p + 1; + } else { + /* End of tokens. */ + *s = NULL; + } - /* - * This whole play can be reduced with simple StringTokenizer (strtok). - * - */ + return start; +} #if !defined(__clang_major__) && defined(__GNUC__) && (__GNUC__ >= 8) _Pragma("GCC diagnostic push") @@ -215,82 +220,41 @@ _Pragma("GCC diagnostic ignored \"-Wstringop-truncation\"") #endif int nsk_jvmti_parseOptions(const char options[]) { - size_t len; - const char* opt; int success = NSK_TRUE; - context.options.string = NULL; - context.options.count = 0; - context.waittime = 2; - + char *str = NULL; + char *name = NULL; + char *value = NULL; + const char *delimiters = " ,~"; if (options == NULL) - return NSK_TRUE; + return success; - len = strlen(options); - context.options.string = (char*)malloc(len + 2); + /* + * Save a copy of the full options string for + * ArgumentHandler.getAgentOptionsString(). + */ + context.options.string = strdup(options); - if (context.options.string == NULL) { - nsk_complain("nsk_jvmti_parseOptions(): out of memory\n"); - return NSK_FALSE; - } - strncpy(context.options.string, options, len); - context.options.string[len] = '\0'; - context.options.string[len+1] = '\0'; - - for (opt = context.options.string; ; ) { - const char* opt_end; - const char* val_sep; - int opt_len=0; - int val_len=0; - int exit=1; - - while (*opt != '\0' && isOptSep(*opt)) opt++; - if (*opt == '\0') break; - - val_sep = NULL; - /* - This should break when the first option it encounters other wise - */ - for (opt_end = opt, opt_len=0; !(*opt_end == '\0' || isOptSep(*opt_end)); opt_end++,opt_len++) { - if (*opt_end == NSK_JVMTI_OPTION_VAL_SEP) { - val_sep = opt_end; - exit=0; - break; - } - } + /* Create a temporary copy of the options string to be tokenized. */ + str = strdup(options); + while ((name = token(&str, delimiters)) != NULL) { + value = strchr(name, '='); - if (exit == 1) break; - - /* now scan for the search for the option value end. - - */ - exit =1; - opt_end++; - val_sep++; - /** - * I was expecting this jvmti_parseOptions(), - * should be for multiple options as well. - * If this break is not there then It will expects - * to have. so a space should be sufficient as well. - */ - for(val_len=0; !(*opt_end == '\0' || isOptSep(*opt_end)); opt_end++,val_len++) { - //if (*opt_end == NSK_JVMTI_OPTION_START) { - // break; - //} + if (value != NULL) { + *value++ = '\0'; } - - if (!add_option(opt, opt_len, val_sep, val_len)) { + if (!add_option(name, (int)strlen(name), value, + value ? (int)strlen(value) : 0)) { success = NSK_FALSE; break; } - opt_end++; - opt = opt_end; } - if (!success) { nsk_jvmti_free(); } - + if (str != NULL) { + free(str); + } return success; } diff --git a/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfo/Test.java b/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfo/Test.java index 4475f42a462..557fa5001bb 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfo/Test.java +++ b/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfo/Test.java @@ -53,7 +53,7 @@ public class Test { public static void main(String[] args) throws Exception { { System.out.println("SegmentedCodeCache is enabled"); - var pb = ProcessTools.createJavaProcessBuilder(true, + var pb = ProcessTools.createTestJvm( "-XX:+SegmentedCodeCache", "-XX:+PrintCodeCache", "-version"); @@ -63,7 +63,7 @@ public static void main(String[] args) throws Exception { } { System.out.println("SegmentedCodeCache is disabled"); - var pb = ProcessTools.createJavaProcessBuilder(true, + var pb = ProcessTools.createTestJvm( "-XX:-SegmentedCodeCache", "-XX:+PrintCodeCache", "-version"); diff --git a/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfoOnCompilation/Test.java b/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfoOnCompilation/Test.java index 852032c2aea..4580e7f0ec8 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfoOnCompilation/Test.java +++ b/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfoOnCompilation/Test.java @@ -46,7 +46,7 @@ public class Test { private static String REGEXP = "^(CodeCache|(CodeHeap.*)): size=\\d+Kb used=\\d+Kb max_used=\\d+Kb free=\\d+Kb"; public static void main(String[] args) throws Exception { - var pb = ProcessTools.createJavaProcessBuilder(true, + var pb = ProcessTools.createTestJvm( "-XX:-PrintCodeCache", "-XX:+PrintCodeCacheOnCompilation", "-XX:-Inline", diff --git a/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest.java b/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest.java new file mode 100644 index 00000000000..1dc1f9a2388 --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package transform; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import static jaxp.library.JAXPTestUtilities.compareWithGold; +import static jaxp.library.JAXPTestUtilities.compareLinesWithGold; +import org.testng.Assert; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +/* + * @test + * @bug 8268457 + * @library /javax/xml/jaxp/libs + * @run testng transform.SurrogateTest + * @summary XML Transformer outputs Unicode supplementary character incorrectly to HTML + */ +@Listeners({jaxp.library.FilePolicy.class}) +public class SurrogateTest { + + final static String TEST_SRC = System.getProperty("test.src", "."); + + @Test + public void toHTMLTest() throws Exception { + String out = "SurrogateTest1out.html"; + String expected = TEST_SRC + File.separator + "SurrogateTest1.html"; + String xml = TEST_SRC + File.separator + "SurrogateTest1.xml"; + String xsl = TEST_SRC + File.separator + "SurrogateTest1.xsl"; + + try (FileInputStream tFis = new FileInputStream(xsl); + InputStream fis = new FileInputStream(xml); + FileOutputStream fos = new FileOutputStream(out)) { + + Source tSrc = new StreamSource(tFis); + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer t = tf.newTransformer(tSrc); + t.setOutputProperty("method", "html"); + + Source src = new StreamSource(fis); + Result res = new StreamResult(fos); + t.transform(src, res); + } + Assert.assertTrue(compareWithGold(expected, out)); + } + + @Test + public void handlerTest() throws Exception { + File xmlFile = new File(TEST_SRC, "SurrogateTest2.xml"); + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setNamespaceAware(true); + SAXParser sp = spf.newSAXParser(); + TestHandler th = new TestHandler(); + sp.parse(xmlFile, th); + Assert.assertTrue(compareLinesWithGold(TEST_SRC + File.separator + "SurrogateTest2.txt", th.lines)); + } + + private static class TestHandler extends DefaultHandler { + private List lines = new ArrayList<>(); + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + lines.add( localName + "@attr:" + attributes.getValue("attr")); + } + } +} diff --git a/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest1.html b/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest1.html new file mode 100644 index 00000000000..03205499e91 --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest1.html @@ -0,0 +1,12 @@ + + + + + + + +
          + +
          + + diff --git a/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest1.xml b/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest1.xml new file mode 100644 index 00000000000..bb346086b05 --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest1.xml @@ -0,0 +1,4 @@ + + + 𠮟 + diff --git a/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest1.xsl b/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest1.xsl new file mode 100644 index 00000000000..200a1291ba9 --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest1.xsl @@ -0,0 +1,26 @@ + + + + + + + + + + +
          + + + + + + + +
          +
          + + +
          +
          diff --git a/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest2.txt b/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest2.txt new file mode 100644 index 00000000000..0e3ce0062c7 --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest2.txt @@ -0,0 +1,4 @@ +root@attr:null +tag1@attr:𠮟 +tag2@attr:𠀋 +tag3@attr:𣱿 diff --git a/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest2.xml b/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest2.xml new file mode 100644 index 00000000000..3f91e3c82ae --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/transform/SurrogateTest2.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathAncestorsTest.java b/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathAncestorsTest.java new file mode 100644 index 00000000000..5f489a2fe7b --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathAncestorsTest.java @@ -0,0 +1,186 @@ +/* + * 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 xpath; + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/* + * @test + * @bug 8289508 + * @library /javax/xml/jaxp/unittest + * @run testng/othervm xpath.XPathAncestorsTest + * @summary Tests for XPath ancestor and ancestor-or-self axis specifiers. + */ +public class XPathAncestorsTest { + + private static final String XML = + "\n" + + " \n" + + " \n" + + " <author id=\"1\"/>\n" + + " <isbn>1234</isbn>\n" + + " </book>\n" + + " <book id=\"2\" lang=\"en\">\n" + + " <title/>\n" + + " <author id=\"2\"/>\n" + + " <isbn>5678</isbn>\n" + + " </book>\n" + + "</store>\n" + ; + private static final Document doc; + + static { + try { + var builder = + DocumentBuilderFactory.newInstance().newDocumentBuilder(); + InputStream s = new ByteArrayInputStream(XML.getBytes()); + doc = builder.parse(s); + } catch (Exception e) { + System.out.println("Exception while initializing XML document"); + throw new RuntimeException(e.getMessage()); + } + } + + /* + * DataProvider:provides XPath expression using ancestor/ancestor-or-self + * and the expected node(s) from the expression + */ + @DataProvider(name = "ancestors_axes") + public Object[][] getXPathAncestors() { + return new Object[][]{ + //test ancestor + + // abbreviated text + {"//author/ancestor::book/ancestor::store", "/store"}, + {"//isbn/ancestor::store", "/store"}, + {"//ancestor::book[1]", "//book[1]"}, + + // any node + {"//book/ancestor::*", "/store"}, + {"//author/ancestor::*[ancestor::store]/ancestor::store", "/store"}, + {"//author/ancestor::node()[ancestor::store]", "//book"}, + + // dot reference + {"//author/ancestor::book/..", "/store"}, + {"//author/ancestor::*[ancestor::store]/..", "/store"}, + {"//ancestor::book/..", "/store"}, + + // attributes + {"//author/ancestor::*[@id]/parent::*", "/store"}, + {"//author/parent::*[@id]/ancestor::*", "/store"}, + {"//author[@id='1']/ancestor::book[1]", "//book[1]"}, + {"//author[@*]/ancestor::book[1]", "//book[1]"}, + + //test ancestor-or-self + + // any node, indexing, id + {"/store/ancestor-or-self::*", "/store"}, + {"//book[*]/ancestor-or-self::book[1]", "//book[1]"}, + {"/store/book[@*]/ancestor-or-self::book[1]", "//book[1]"}, + {"//book[@id='1']/ancestor-or-self::book[1]", "//book[1]"}, + {"//author[@id='2']/ancestor-or-self::book", "//book[2]"}, + {"//book[1]/ancestor-or-self::store", "/store"}, + + }; + } + + /* + * DataProvider: provides XPath expressions that return empty NodeSet + */ + @DataProvider(name = "emptyNodeSet") + public Object[][] getEmptyNodeSet() { + return new Object[][]{ + // test ancestor + + // abbreviated text + {"/store/book/ancestor::book"}, + {"//author/ancestor::store[2]"}, + {"//author[3]/ancestor::store"}, + + // any nodes + {"/store/ancestor::*"}, + {"/store/book[3]/ancestor::*"}, + {"//book[*]/../ancestor::*"}, + {"/store/book[@id='3']/ancestor::*"}, + {"//book/ssn/ancestor::*"}, + {"//author/ancestor::*[ancestor::isbn]"}, + {"/store/../ancestor::*"}, + {"//ancestor::author"}, + + // id + {"/store/book[@id='3']/ancestor::*"}, + {"/store[@*]/ancestor::*"}, + {"/book[@*]/ancestor::*/ancestor::*"}, + {"//book[@category]/ancestor::*"}, + + //test ancestor-or-self + + // any nodes, id + {"/store/../ancestor-or-self::*"}, + {"//book[3]/ancestor-or-self::*"}, + {"//author/ancestor-or-self::title"}, + {"//author[@id='2']/ancestor-or-self::*[@id='1']"}, + }; + } + + /** + * Verifies XPath ancestor and ancestor-or-self axis specifiers + * by comparing expression and expected result. + * @param exp XPath expression + * @param expected expected result + * @throws Exception if test failed + */ + @Test(dataProvider = "ancestors_axes") + void testXPathAncestors(String exp, String parent) throws Exception { + XPath xPath = XPathFactory.newInstance().newXPath(); + Node result = xPath.evaluateExpression(exp, doc, Node.class); + Node expected = xPath.evaluateExpression(parent, doc, Node.class); + Assert.assertEquals(result, expected); + } + + /** + * Verifies no nodes returned from the XPath expression. + * + * @param exp XPath expression + * @throws Exception + */ + @Test(dataProvider = "emptyNodeSet") + void testEmptyNodeSet(String exp) throws Exception { + XPath xPath = XPathFactory.newInstance().newXPath(); + Node result = xPath.evaluateExpression(exp, doc, Node.class); + Assert.assertEquals(result, null); + } +} diff --git a/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathPrecedingTest.java b/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathPrecedingTest.java new file mode 100644 index 00000000000..03f6f3578ee --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathPrecedingTest.java @@ -0,0 +1,185 @@ +/* + * 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 xpath; + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/* + * @test + * @bug 8289508 + * @library /javax/xml/jaxp/unittest + * @run testng/othervm xpath.XPathPrecedingTest + * @summary Tests for XPath preceding and preceding-sibling axis specifiers. + */ +public class XPathPrecedingTest { + + private static final String XML = + "<store>\n" + + " <book id=\"1\" lang=\"en\">\n" + + " <title>Book1\n" + + " \n" + + " 1234\n" + + " \n" + + " \n" + + " Book2\n" + + " \n" + + " 5678\n" + + " \n" + + "\n" + ; + private static final Document doc; + + static { + try { + var builder = + DocumentBuilderFactory.newInstance().newDocumentBuilder(); + InputStream s = new ByteArrayInputStream(XML.getBytes()); + doc = builder.parse(s); + } catch (Exception e) { + System.out.println("Exception while initializing XML document"); + throw new RuntimeException(e.getMessage()); + } + } + + /* + * DataProvider: provides XPath expression using preceding/preceding-sibling + * and the expected node(s) from the expression + */ + @DataProvider(name = "preceding_axes") + public Object[][] getXPathPreceding() { + return new Object[][]{ + // test preceding + + // any nodes + {"/store/book[1]/author/preceding::*", "/store/book[1]/title"}, + + // abbreviated text + {"/store/book[1]/isbn/preceding::*[1]", "/store/book[1]/author"}, + {"(/store/book[1]/isbn/preceding::*)[1]", "/store/book[1]/title"}, + {"//isbn/preceding::book", "//book[1]"}, + {"//book[2]/preceding::book", "//book[1]"}, + {"/store/book[preceding::book]", "//book[2]"}, + {"/store/book[preceding::book]/preceding::book", "//book[1]"}, + + // id + {"//author[@id='2']/../preceding::book", "//book[1]"}, + {"//author[@id='2']/preceding::node()/preceding::book", "//book[1]"}, + {"//author[@id='1']/preceding::title", "//book[1]/title"}, + + //test preceding-sibling + + // any node + {"/store/book[1]/author/preceding-sibling::*", "/store/book[1]/title"}, + {"/store/book[2]/preceding-sibling::*", "//book[1]"}, + {"//author/preceding-sibling::*", "//title"}, + + // abbreviated text + {"/store/book[preceding::book]/preceding-sibling::book", "//book[1]"}, + + // id + {"/store/book[1]/isbn[preceding-sibling::author[@id='1']]", "/store/book[1]/isbn"}, + + }; + } + + /* + * DataProvider: provides XPath expressions that return empty NodeSet + */ + @DataProvider(name = "emptyNodeSet") + public Object[][] getEmptyNodeSet() { + return new Object[][]{ + //test preceding + + // abbreviated text + {"/store/preceding::book"}, + {"/store/book[1]/author/preceding::author"}, + + // any nodes/id + {"/store/book[1]/preceding::*"}, + {"/store/book[1]/title/preceding::*"}, + {"/store/book[@id='1']/preceding::*"}, + + //test preceding-sibling + + // any nodes + {"/store/book[1]/preceding-sibling::*"}, + {"/store/book[2]/title/preceding-sibling::*"}, + + // abbreviated text / id + {"/store/book[1]/author/preceding-sibling::isbn"}, + {"//author[@id='2']/preceding-sibling::book"}, + {"//author[@id='2']/preceding-sibling::node()/preceding-sibling::author"}, + + // attribute / namespace + {"/store/book[2]/@id/preceding-sibling::*"}, + {"/store/book/@lang/preceding-sibling::*"}, + {"/store/book[2]/namespace::*/preceding-sibling::*"}, + + // text node + {"/store/book[2]/isbn/text()/preceding-sibling::*"}, + + }; + } + + /** + * Verifies XPath preceding and preceding-sibling axis specifiers by + * comparing expression and expected result. + * @param exp XPath expression + * @param expected expected result + * @throws Exception if test failed + */ + @Test(dataProvider = "preceding_axes") + void testXPathPreceding(String exp, String parent) throws Exception { + XPath xPath = XPathFactory.newInstance().newXPath(); + Node result = xPath.evaluateExpression(exp, doc, Node.class); + Node expected = xPath.evaluateExpression(parent, doc, Node.class); + Assert.assertEquals(result, expected); + } + + /** + * Verifies no nodes returned from the XPath expression. + * + * @param exp XPath expression + * @throws Exception + */ + @Test(dataProvider = "emptyNodeSet") + void testEmptyNodeSet(String exp) throws Exception { + XPath xPath = XPathFactory.newInstance().newXPath(); + Node result = xPath.evaluateExpression(exp, doc, Node.class); + Assert.assertEquals(result, null); + } +} + diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index ec96aca13ea..a393323e912 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -472,7 +472,7 @@ java/awt/MenuBar/8007006/bug8007006.java 8213122 windows-all # below test fails only on Win 7 java/awt/font/FontNames/LocaleFamilyNames.java 8213129 windows-all -java/awt/GraphicsDevice/DisplayModes/CycleDMImage.java 7099223 linux-all,solaris-all,windows-all +java/awt/GraphicsDevice/DisplayModes/CycleDMImage.java 7099223,8274106 macosx-aarch64,linux-all,solaris-all,windows-all java/awt/keyboard/AllKeyCode/AllKeyCode.java 8242930 macosx-all java/awt/FullScreen/8013581/bug8013581.java 8169471 macosx-all java/awt/event/MouseEvent/RobotLWTest/RobotLWTest.java 8233568 macosx-all @@ -613,19 +613,14 @@ sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8161536 generic- sun/security/tools/keytool/ListKeychainStore.sh 8156889 macosx-all -sun/security/tools/jarsigner/compatibility/SignTwice.java 8217375 windows-all sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java 8026393 generic-all javax/net/ssl/DTLS/PacketLossRetransmission.java 8169086 macosx-x64 -javax/net/ssl/DTLS/RespondToRetransmit.java 8169086 macosx-x64 +javax/net/ssl/DTLS/RespondToRetransmit.java 8169086 macosx-all javax/net/ssl/DTLS/CipherSuite.java 8202059 macosx-x64 sun/security/provider/KeyStore/DKSTest.sh 8180266 windows-all -sun/security/pkcs11/KeyStore/SecretKeysBasic.java 8209398 generic-all - -security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java 8224768 generic-all - sun/security/smartcardio/TestChannel.java 8039280 generic-all sun/security/smartcardio/TestConnect.java 8039280 generic-all sun/security/smartcardio/TestConnectAgain.java 8039280 generic-all @@ -644,6 +639,7 @@ com/sun/security/sasl/gsskerb/ConfSecurityLayer.java 8039280 generic- com/sun/security/sasl/gsskerb/NoSecurityLayer.java 8039280 generic-all javax/security/auth/kerberos/KerberosHashEqualsTest.java 8039280 generic-all javax/security/auth/kerberos/KerberosTixDateTest.java 8039280 generic-all +javax/security/auth/callback/PasswordCallback/CheckCleanerBound.java 8285785,8286045,8287596 generic-all 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 @@ -741,12 +737,11 @@ java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java 8282270 linux-all java/awt/Robot/HiDPIScreenCapture/HiDPIRobotScreenCaptureTest.java 8282270 windows-all # Several tests which fail on some hidpi systems -java/awt/GraphicsDevice/DisplayModes/CycleDMImage.java 8274106 macosx-aarch64 java/awt/Window/8159168/SetShapeTest.java 8274106 macosx-aarch64 java/awt/image/multiresolution/MultiResolutionJOptionPaneIconTest.java 8274106 macosx-aarch64 javax/swing/JFrame/8175301/ScaledFrameBackgroundTest.java 8274106 macosx-aarch64 -sanity/client/SwingSet/src/ToolTipDemoTest.java 8225012 windows-all,macosx-all +sanity/client/SwingSet/src/ToolTipDemoTest.java 8293001 linux-all javax/swing/SwingWorker/6432565/bug6432565.java 8199077 generic-all javax/swing/SwingWorker/6880336/NestedWorkers.java 8199049 windows-all @@ -865,10 +860,11 @@ javax/rmi/ssl/SSLSocketParametersTest.sh 8162906 generic- # jdk_jfr jdk/jfr/event/sampling/TestNative.java 8202142 generic-all +jdk/jfr/event/sampling/TestStackFrameLineNumbers.java 8313802 linux-all,windows-all jdk/jfr/event/runtime/TestNetworkUtilizationEvent.java 8228990,8229370 generic-all jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 generic-all jdk/jfr/event/oldobject/TestLargeRootSet.java 8205651 generic-all - + ############################################################################ # dragonwell diff --git a/test/jdk/com/sun/jdi/JITDebug.java b/test/jdk/com/sun/jdi/JITDebug.java index 7356a54b886..e7a5647fdd4 100644 --- a/test/jdk/com/sun/jdi/JITDebug.java +++ b/test/jdk/com/sun/jdi/JITDebug.java @@ -104,7 +104,7 @@ boolean parseArgs(String[] args) { } void testLaunch() { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true); + ProcessBuilder pb = ProcessTools.createTestJvm(); List largs = pb.command(); largs.add("-classpath"); largs.add(Utils.TEST_CLASSES); diff --git a/test/jdk/com/sun/jdi/JdbOptions.java b/test/jdk/com/sun/jdi/JdbOptions.java new file mode 100644 index 00000000000..b6fb965e319 --- /dev/null +++ b/test/jdk/com/sun/jdi/JdbOptions.java @@ -0,0 +1,165 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8234808 + * + * @library /test/lib + * @run main/othervm JdbOptions + */ + +import jdk.test.lib.Platform; +import lib.jdb.Jdb; +import lib.jdb.JdbCommand; +import jdk.test.lib.process.OutputAnalyzer; + +import java.lang.management.ManagementFactory; +import java.util.Arrays; +import java.util.List; + +class JbdOptionsTarg { + static final String OK_MSG = "JbdOptionsTarg: OK"; + + static String argString(String s) { + return "arg >" + s + "<"; + } + + static String propString(String name, String value) { + return "prop[" + name + "] = >" + value + "<"; + } + + public static void main(String[] args) { + System.out.println(OK_MSG); + // print all args + List vmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments(); + for (String s: vmArgs) { + System.out.println(argString(s)); + } + // print requested sys.props + for (String p: args) { + System.out.println(propString(p, System.getProperty(p))); + } + } +} + +public class JdbOptions { + private static final String targ = JbdOptionsTarg.class.getName(); + + public static void main(String[] args) throws Exception { + // the simplest case + test("-connect", + "com.sun.jdi.CommandLineLaunch:vmexec=java,options=-client -XX:+PrintVMOptions,main=" + targ) + .expectedArg("-XX:+PrintVMOptions"); + + // pass property through 'options' + test("-connect", + "com.sun.jdi.CommandLineLaunch:vmexec=java,options='-Dboo=foo',main=" + targ + " boo") + .expectedProp("boo", "foo"); + + // property with spaces + test("-connect", + "com.sun.jdi.CommandLineLaunch:vmexec=java,options=\"-Dboo=foo 2\",main=" + targ + " boo") + .expectedProp("boo", "foo 2"); + + // property with spaces (with single quotes) + test("-connect", + "com.sun.jdi.CommandLineLaunch:vmexec=java,options='-Dboo=foo 2',main=" + targ + " boo") + .expectedProp("boo", "foo 2"); + + // properties with spaces (with single quotes) + test("-connect", + "com.sun.jdi.CommandLineLaunch:vmexec=java,options=-Dboo=foo '-Dboo2=foo 2',main=" + targ + " boo boo2") + .expectedProp("boo", "foo") + .expectedProp("boo2", "foo 2"); + + // 'options' contains commas - values are quoted (double quotes) + test("-connect", + "com.sun.jdi.CommandLineLaunch:vmexec=java,options=\"-client\" \"-XX:+PrintVMOptions\"" + + " -XX:+IgnoreUnrecognizedVMOptions" + + " \"-XX:StartFlightRecording=dumponexit=true,maxsize=500M\" \"-XX:FlightRecorderOptions=repository=jfrrep\"" + + ",main=" + targ) + .expectedArg("-XX:StartFlightRecording=dumponexit=true,maxsize=500M") + .expectedArg("-XX:FlightRecorderOptions=repository=jfrrep"); + + // 'options' contains commas - values are quoted (single quotes) + test("-connect", + "com.sun.jdi.CommandLineLaunch:vmexec=java,options='-client' '-XX:+PrintVMOptions'" + + " -XX:+IgnoreUnrecognizedVMOptions" + + " '-XX:StartFlightRecording=dumponexit=true,maxsize=500M' '-XX:FlightRecorderOptions=repository=jfrrep'" + + ",main=" + targ) + .expectedArg("-XX:StartFlightRecording=dumponexit=true,maxsize=500M") + .expectedArg("-XX:FlightRecorderOptions=repository=jfrrep"); + + // java options are specified in 2 ways, with and without spaces + // options are quoted by using single and double quotes. + test("-Dprop1=val1", + "-Dprop2=val 2", + "-connect", + "com.sun.jdi.CommandLineLaunch:vmexec=java,options=-Dprop3=val3 '-Dprop4=val 4'" + + " -XX:+IgnoreUnrecognizedVMOptions" + + " \"-XX:StartFlightRecording=dumponexit=true,maxsize=500M\"" + + " '-XX:FlightRecorderOptions=repository=jfrrep'" + + ",main=" + targ + " prop1 prop2 prop3 prop4") + .expectedProp("prop1", "val1") + .expectedProp("prop2", "val 2") + .expectedProp("prop3", "val3") + .expectedProp("prop4", "val 4") + .expectedArg("-XX:StartFlightRecording=dumponexit=true,maxsize=500M") + .expectedArg("-XX:FlightRecorderOptions=repository=jfrrep"); + + } + + private static class TestResult { + OutputAnalyzer out; + TestResult(OutputAnalyzer output) { + out = output; + } + TestResult expectedArg(String s) { + out.shouldContain(JbdOptionsTarg.argString(s)); + return this; + } + TestResult expectedProp(String name, String value) { + out.shouldContain(JbdOptionsTarg.propString(name, value)); + return this; + } + } + + private static TestResult test(String... args) throws Exception { + System.out.println(); + System.out.println("...testcase..."); + if (Platform.isWindows()) { + // on Windows we need to escape quotes + args = Arrays.stream(args) + .map(s -> s.replace("\"", "\\\"")) + .toArray(String[]::new); + } + try (Jdb jdb = new Jdb(args)) { + jdb.waitForSimplePrompt(1024, true); // 1024 lines should be enough + jdb.command(JdbCommand.run().allowExit()); + OutputAnalyzer out = new OutputAnalyzer(jdb.getJdbOutput()); + out.shouldContain(JbdOptionsTarg.OK_MSG); + return new TestResult(out); + } + } +} diff --git a/test/jdk/com/sun/jdi/OptionTest.java b/test/jdk/com/sun/jdi/OptionTest.java index 9d7dbb2abe1..b8869ddda5b 100644 --- a/test/jdk/com/sun/jdi/OptionTest.java +++ b/test/jdk/com/sun/jdi/OptionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -33,8 +33,6 @@ * @run driver OptionTest */ -import java.net.ServerSocket; -import java.util.regex.Matcher; import java.util.regex.Pattern; public class OptionTest extends Object { @@ -127,18 +125,12 @@ public String[] run (String[] cmdStrings) { } public static void main(String[] args) throws Exception { - // find a free port - ServerSocket ss = new ServerSocket(0); - int port = ss.getLocalPort(); - ss.close(); - String address = String.valueOf(port); - String javaExe = System.getProperty("java.home") + java.io.File.separator + "bin" + java.io.File.separator + "java"; String targetClass = "HelloWorld"; String baseOptions = "transport=dt_socket" + - ",address=" + address + + ",address=0" + ",server=y" + ",suspend=n"; diff --git a/test/jdk/com/sun/jdi/PrivateTransportTest.java b/test/jdk/com/sun/jdi/PrivateTransportTest.java index 24d71cbbc3c..c12db8b90be 100644 --- a/test/jdk/com/sun/jdi/PrivateTransportTest.java +++ b/test/jdk/com/sun/jdi/PrivateTransportTest.java @@ -82,7 +82,7 @@ private void test() throws Throwable { String libName = transportLib.getFileName().toString().replace("dt_socket", "private_dt_socket"); Files.copy(transportLib, Paths.get(Utils.TEST_CLASSES).resolve(libName)); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-agentlib:jdwp=transport=private_dt_socket,server=y,suspend=n", "-classpath", Utils.TEST_CLASSES, "HelloWorld"); diff --git a/test/jdk/com/sun/jdi/RunToExit.java b/test/jdk/com/sun/jdi/RunToExit.java index ff3a9ed83ba..b7051b77dbc 100644 --- a/test/jdk/com/sun/jdi/RunToExit.java +++ b/test/jdk/com/sun/jdi/RunToExit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -30,7 +30,6 @@ * @build VMConnection RunToExit Exit0 * @run driver RunToExit */ -import java.net.ServerSocket; import com.sun.jdi.Bootstrap; import com.sun.jdi.VirtualMachine; import com.sun.jdi.event.*; @@ -41,6 +40,8 @@ import java.util.List; import java.util.Iterator; import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import jdk.test.lib.process.ProcessTools; @@ -50,6 +51,9 @@ public class RunToExit { static volatile int error_seen = 0; static volatile boolean ready = false; + /* port the debuggee is listening on */ + private static String address; + /* * Find a connector by name */ @@ -66,12 +70,11 @@ private static Connector findConnector(String name) { } /* - * Launch a server debuggee with the given address + * Launch a server debuggee, detect debuggee listening port */ - private static Process launch(String address, String class_name) throws Exception { + private static Process launch(String class_name) throws Exception { String args[] = new String[]{ - "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=" - + address, + "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=0", class_name }; args = VMConnection.insertDebuggeeVMOptions(args); @@ -92,8 +95,17 @@ private static Process launch(String address, String class_name) throws Exceptio return p; } + /* warm-up predicate for debuggee */ + private static Pattern listenRegexp = Pattern.compile("Listening for transport \\b(.+)\\b at address: \\b(.+)\\b"); + private static boolean isTransportListening(String line) { - return line.startsWith("Listening for transport dt_socket"); + Matcher m = listenRegexp.matcher(line); + if (!m.matches()) { + return false; + } + // address is 2nd group + address = m.group(2); + return true; } private static void checkForError(String line) { @@ -103,28 +115,21 @@ private static void checkForError(String line) { } /* - * - pick a TCP port - * - Launch a server debuggee: server=y,suspend=y,address=${port} + * - Launch a server debuggee: server=y,suspend=y,address=0 + * - detect the port debuggee is listening on * - run it to VM death * - verify we saw no error */ public static void main(String args[]) throws Exception { - // find a free port - ServerSocket ss = new ServerSocket(0); - int port = ss.getLocalPort(); - ss.close(); - - String address = String.valueOf(port); - // launch the server debuggee - Process process = launch(address, "Exit0"); + Process process = launch("Exit0"); // attach to server debuggee and resume it so it can exit AttachingConnector conn = (AttachingConnector)findConnector("com.sun.jdi.SocketAttach"); Map conn_args = conn.defaultArguments(); Connector.IntegerArgument port_arg = (Connector.IntegerArgument)conn_args.get("port"); - port_arg.setValue(port); + port_arg.setValue(address); System.out.println("Connection arguments: " + conn_args); diff --git a/test/jdk/com/sun/jdi/cds/CDSJDITest.java b/test/jdk/com/sun/jdi/cds/CDSJDITest.java index bc09c41202e..bd5001d8beb 100644 --- a/test/jdk/com/sun/jdi/cds/CDSJDITest.java +++ b/test/jdk/com/sun/jdi/cds/CDSJDITest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,7 +73,7 @@ public static void runTest(String testname, String[] jarClasses) throws Exceptio "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./SharedArchiveFile.jsa", "-XX:ExtraSharedClassListFile=" + jarClasslistFile.getPath(), "-Xshare:dump"); - OutputAnalyzer outputDump = executeAndLog(pb, "exec"); + OutputAnalyzer outputDump = executeAndLog(pb, "dump"); for (String jarClass : jarClasses) { outputDump.shouldNotContain("Cannot find " + jarClass); } @@ -81,7 +81,7 @@ public static void runTest(String testname, String[] jarClasses) throws Exceptio outputDump.shouldHaveExitValue(0); // Run the test specified JDI test - pb = ProcessTools.createJavaProcessBuilder(true, testArgs); + pb = ProcessTools.createTestJvm(testArgs); OutputAnalyzer outputRun = executeAndLog(pb, "exec"); try { outputRun.shouldContain("sharing"); diff --git a/test/jdk/com/sun/jdi/lib/jdb/Debuggee.java b/test/jdk/com/sun/jdi/lib/jdb/Debuggee.java index c37fedb4f7f..76243ce5027 100644 --- a/test/jdk/com/sun/jdi/lib/jdb/Debuggee.java +++ b/test/jdk/com/sun/jdi/lib/jdb/Debuggee.java @@ -68,7 +68,6 @@ public static class Launcher { private String transport = "dt_socket"; private String address = null; private boolean suspended = true; - private boolean addTestVmAndJavaOptions = true; private Launcher(String mainClass) { this.mainClass = mainClass; @@ -96,11 +95,6 @@ public Launcher setSuspended(boolean value) { suspended = value; return this; } - // default is "true" - public Launcher addTestVmAndJavaOptions(boolean value) { - addTestVmAndJavaOptions = value; - return this; - } public ProcessBuilder prepare() { List debuggeeArgs = new LinkedList<>(); @@ -109,8 +103,7 @@ public ProcessBuilder prepare() { + ",server=y,suspend=" + (suspended ? "y" : "n")); debuggeeArgs.addAll(options); debuggeeArgs.add(mainClass); - return ProcessTools.createJavaProcessBuilder(addTestVmAndJavaOptions, - debuggeeArgs.toArray(new String[0])); + return ProcessTools.createTestJvm(debuggeeArgs); } public Debuggee launch(String name) { diff --git a/test/jdk/com/sun/net/httpserver/SimpleHttpServerTest.java b/test/jdk/com/sun/net/httpserver/SimpleHttpServerTest.java index e9d420ac8d3..92764d693a0 100644 --- a/test/jdk/com/sun/net/httpserver/SimpleHttpServerTest.java +++ b/test/jdk/com/sun/net/httpserver/SimpleHttpServerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -24,8 +24,12 @@ /** * @test * @bug 8015692 + * @key intermittent * @summary Test HttpServer instantiation, start, and stop repeated in a loop - * Testing for Bind exception on Windows + * Testing for Bind exception on Windows. This test may fail + * intermittently if other tests / process manage to bind to + * the same port that the test is using in the short window + * time where the port might appear available again. */ import java.net.InetSocketAddress; @@ -41,24 +45,40 @@ public static void main(String[] args) throws Exception { System.out.println(System.getProperty("java.version")); InetSocketAddress serverAddr = new InetSocketAddress(0); HttpServer server = HttpServer.create(serverAddr, 0); - final int serverPort = server.getAddress().getPort(); + int serverPort = server.getAddress().getPort(); server.start(); server.stop(0); serverAddr = new InetSocketAddress(serverPort); int exceptionCount = 0; + boolean failedOnce = false; System.out.println("Using serverPort == " + serverPort); - for (int i = 0; i < 100; i++) { - try { - server = HttpServer.create(serverAddr, 0); - server.start(); - server.stop(0); - } catch (Exception ex) { - ex.printStackTrace(); - exceptionCount++; + RETRY: while (exceptionCount == 0) { + for (int i = 0; i < 100; i++) { + try { + server = HttpServer.create(serverAddr, 0); + server.start(); + server.stop(0); + } catch (Exception ex) { + if (!failedOnce) { + failedOnce = true; + server = HttpServer.create(new InetSocketAddress(0), 0); + serverPort = server.getAddress().getPort(); + server.start(); + server.stop(0); + serverAddr = new InetSocketAddress(serverPort); + System.out.println("Retrying with serverPort == " + serverPort); + continue RETRY; + } + System.err.println("Got exception at iteration: " + i ); + ex.printStackTrace(); + exceptionCount++; + } } + break; } if (exceptionCount > 0) { - throw new RuntimeException("Test Failed"); + throw new RuntimeException("Test Failed: got " + + exceptionCount + " exceptions."); } } } diff --git a/test/jdk/com/sun/net/httpserver/bugs/B6393710.java b/test/jdk/com/sun/net/httpserver/bugs/B6393710.java index 6eb5a04e296..2dc8eb64a27 100644 --- a/test/jdk/com/sun/net/httpserver/bugs/B6393710.java +++ b/test/jdk/com/sun/net/httpserver/bugs/B6393710.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -24,6 +24,7 @@ /** * @test * @bug 6393710 + * @library /test/lib * @summary Non authenticated call followed by authenticated call never returns */ @@ -34,6 +35,8 @@ import java.io.*; import java.net.*; +import jdk.test.lib.Utils; + /* * Test checks for following bug(s) when a POST containing a request body * needs to be authenticated @@ -77,7 +80,7 @@ public boolean checkCredentials (String user, String pass) { server.start (); Socket s = new Socket ("localhost", server.getAddress().getPort()); - s.setSoTimeout (5000); + s.setSoTimeout ((int) Utils.adjustTimeout(5000)); OutputStream os = s.getOutputStream(); os.write (cmd.getBytes()); @@ -124,8 +127,8 @@ static boolean readAndCheck (InputStream is, String expected) throws IOException return false; } - public static boolean ok = false; - static int requests = 0; + public static volatile boolean ok = false; + static volatile int requests = 0; static class Handler implements HttpHandler { int invocation = 1; diff --git a/test/jdk/java/awt/Choice/ChoiceConsumeMouseEvents.java b/test/jdk/java/awt/Choice/ChoiceConsumeMouseEvents.java new file mode 100644 index 00000000000..c257cf9ff08 --- /dev/null +++ b/test/jdk/java/awt/Choice/ChoiceConsumeMouseEvents.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6251988 + @summary PIT: Choice consumes MouseReleased, MouseClicked events when clicking it with left button, + @key headful +*/ + +import java.awt.Choice; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +public class ChoiceConsumeMouseEvents { + + static volatile Frame frame; + static volatile Robot robot; + static volatile Choice choice1 = new Choice(); + static volatile boolean mousePressed = false; + static volatile boolean mouseReleased = false; + static volatile boolean mouseClicked = false; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(() -> createUI()); + runTest(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + } + + static void createUI() { + for (int i = 1; i<10; i++){ + choice1.add("item-0"+i); + } + choice1.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent me) { + mousePressed = true; + System.out.println(me); + } + public void mouseReleased(MouseEvent me) { + mouseReleased = true; + System.out.println(me); + } + public void mouseClicked(MouseEvent me) { + mouseClicked = true; + System.out.println(me); + } + }); + + frame = new Frame("ChoiceConsumeMouseEvents"); + frame.add(choice1); + frame.setSize(400, 400); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.validate(); + } + + static void runTest() { + try { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(50); + robot.delay(100); + testMouseClick(InputEvent.BUTTON1_DOWN_MASK, 0); + robot.delay(100); + testMouseClick(InputEvent.BUTTON1_DOWN_MASK, 100); + } catch (Throwable e) { + throw new RuntimeException("Test failed. Exception thrown: "+e); + } + } + + static void testMouseClick(int button, int delay) { + Point pt = choice1.getLocationOnScreen(); + robot.mouseMove(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2); + robot.delay(100); + robot.mousePress(button); + robot.delay(delay); + robot.mouseRelease(button); + robot.delay(200); + if (!(mousePressed && + mouseReleased && + mouseClicked)) + { + throw new RuntimeException("Test failed. Choice should generate PRESSED, RELEASED, CLICKED events"); + } else { + System.out.println("Test passed. Choice generated MouseDragged PRESSED, RELEASED, CLICKED events"); + } + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.delay(200); + mousePressed = false; + mouseReleased = false; + mouseClicked = false; + } +} diff --git a/test/jdk/java/awt/Choice/ChoiceFocusLostTest.java b/test/jdk/java/awt/Choice/ChoiceFocusLostTest.java new file mode 100644 index 00000000000..75ff15ea8fc --- /dev/null +++ b/test/jdk/java/awt/Choice/ChoiceFocusLostTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4338368 + @summary Tests that choice doesn't throw spurious mouse events when losing focus + @key headful +*/ + +import java.awt.Button; +import java.awt.Choice; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public class ChoiceFocusLostTest { + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(() -> createUI()); + Robot robot = new Robot(); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_TAB); + robot.delay(50); + robot.keyRelease(KeyEvent.VK_TAB); + robot.waitForIdle(); + robot.delay(1000); + if (!client.isPassed()) { + throw new RuntimeException("Test failed: choice fires spurious events"); + } else { + System.out.println("Test passed."); + } + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + } + + static volatile Frame frame; + static volatile ChoiceBug client; + + static void createUI() { + frame = new Frame("ChoiceFocusLostTest"); + client = new ChoiceBug(); + frame.add(client); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} + +class ChoiceBug extends Panel { + + volatile boolean passed = true; + + public ChoiceBug() { + Choice choice = new Choice(); + choice.add("item-1"); + choice.add("item-2"); + Button button = new Button("Button"); + add(choice); + add(button); + choice.addMouseListener(new MouseAdapter() { + public void mouseReleased(MouseEvent me) { + passed = false; + } + public void mouseClicked(MouseEvent me) { + passed = false; + } + }); + choice.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent fe) { + System.out.println("Focus Gained"); + System.out.println(fe); + } + public void focusLost(FocusEvent fe) { + System.out.println("Got expected FocusLost event."); + System.out.println(fe); + } + }); + setSize(400, 400); + choice.requestFocus(); + } + + public boolean isPassed() { + return passed; + } +} diff --git a/test/jdk/java/awt/Choice/ChoiceFreezeTest.java b/test/jdk/java/awt/Choice/ChoiceFreezeTest.java new file mode 100644 index 00000000000..af7082a54f5 --- /dev/null +++ b/test/jdk/java/awt/Choice/ChoiceFreezeTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4303064 + @summary Tests that choice doesn't freeze display when its container is + disabled and enabled after. + @key headful +*/ + +import java.awt.Button; +import java.awt.Choice; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public class ChoiceFreezeTest { + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(() -> createUI()); + runTest(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + } + + static volatile Frame frame; + static volatile ChoiceFreezeBug client; + + static void createUI() { + frame = new Frame("ChoiceFreezeTest"); + client = new ChoiceFreezeBug(); + frame.add(client); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + client.init(); + } + + static void runTest() throws Exception { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(2000); + robot.mouseMove(client.choice.getLocationOnScreen().x + 1, client.choice.getLocationOnScreen().y + 1); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(1000); + robot.mouseMove(client.button.getLocationOnScreen().x + 3, client.button.getLocationOnScreen().y + 3); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(1000); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(6000); + + if (!client.isPassed()) { + throw new RuntimeException("Test failed: display is frozen."); + } + } +} + +class ChoiceFreezeBug extends Panel { + + volatile Button button; + volatile Choice choice; + volatile ChoiceMouseListener listener = new ChoiceMouseListener(); + + public ChoiceFreezeBug() { + choice = new Choice(); + choice.addItem("Item 1"); + choice.addItem("Item 2"); + button = new Button("Button"); + add(choice); + add(button); + button.addMouseListener(listener); + setEnabled(false); + } + + void init() { + setEnabled(true); + choice.requestFocus(); + } + + public boolean isPassed() { + return listener.isPassed(); + } +} + +class ChoiceMouseListener extends MouseAdapter { + + volatile boolean passed = false; + + public void mouseReleased(MouseEvent e) { + passed = true; + } + + public void mousePressed(MouseEvent e) { + passed = true; + } + + public boolean isPassed() { + return passed; + } +} diff --git a/test/jdk/java/awt/Choice/ChoiceGeneratesItemEvents.java b/test/jdk/java/awt/Choice/ChoiceGeneratesItemEvents.java new file mode 100644 index 00000000000..1d4a3702d50 --- /dev/null +++ b/test/jdk/java/awt/Choice/ChoiceGeneratesItemEvents.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6239941 + @summary Choice triggers ItemEvent when selecting an item with right mouse button, Xtoolkit + @key headful + @requires (os.family == "linux") +*/ + +import java.awt.Choice; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; + +public class ChoiceGeneratesItemEvents implements ItemListener { + + public static void main(String[] args) throws Exception { + if (!System.getProperty("os.name").toLowerCase().startsWith("linux")) { + System.out.println("This test is for Linux only"); + return; + } + try { + EventQueue.invokeAndWait(() -> createUI()); + runTest(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + + } + } + } + + static volatile Frame frame; + static volatile Robot robot; + static volatile Choice choice1; + static volatile boolean passed = true; + + static void createUI() { + choice1 = new Choice(); + for (int i = 1; i<10; i++){ + choice1.add("item-0"+i); + } + choice1.setForeground(Color.red); + choice1.setBackground(Color.red); + choice1.addItemListener(new ChoiceGeneratesItemEvents()); + frame = new Frame("ChoiceGeneratesItemEvents"); + frame.add(choice1); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.validate(); + frame.setVisible(true); + } + + static void runTest() throws Exception { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(50); + robot.delay(100); + testMousePressOnChoice(InputEvent.BUTTON2_DOWN_MASK); + testMousePressOnChoice(InputEvent.BUTTON3_DOWN_MASK); + if (!passed) { + throw new RuntimeException("Test failed."); + } else { + System.out.println("Test passed. "); + } + } + + static void testMousePressOnChoice(int button) { + Point pt = choice1.getLocationOnScreen(); + robot.mouseMove(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2); + robot.delay(100); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(2000); + + int px = pt.x + choice1.getWidth()/2; + int py = pt.y + 2 * choice1.getHeight(); + Color color = robot.getPixelColor(px, py); + //we should take a color on the point on the choice's menu + System.out.println("Got color " + color + " at (" + px + "," + py + ")"); + if (!color.equals(Color.red)) { + throw new RuntimeException("Test failed. Choice wasn't open with LEFTMOUSE button." +button); + } + robot.mouseMove(pt.x + choice1.getWidth()/2, + pt.y + 5*choice1.getHeight()); + robot.delay(200); + robot.mousePress(button); + robot.mouseRelease(button); + robot.delay(200); + + //close opened choice + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.delay(200); + } + + public void itemStateChanged(ItemEvent ie) { + System.err.println("Opened Choice generated ItemEvent on RIGHT/MIDDLE mouse press." +ie); + passed = false; + } +} diff --git a/test/jdk/java/awt/Choice/ChoiceHandleMouseEvent.java b/test/jdk/java/awt/Choice/ChoiceHandleMouseEvent.java new file mode 100644 index 00000000000..1fd80a2b849 --- /dev/null +++ b/test/jdk/java/awt/Choice/ChoiceHandleMouseEvent.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 5003166 + @summary REG:Mouse button not validated before bringing up the drop-down menu for choice + @key headful + @requires (os.family == "linux" | os.family == "windows") +*/ + +import java.awt.Choice; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +public class ChoiceHandleMouseEvent { + static Robot robot; + static volatile Choice choice1; + static volatile Frame frame; + + public static void main(String[] args) throws Exception { + String os = System.getProperty("os.name").toLowerCase(); + if (!os.startsWith("windows") && !os.startsWith("linux")) { + System.out.println("This test is only for Windows and Linux"); + return; + } + try { + EventQueue.invokeAndWait(() -> createUI()); + runTest(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + } + + static void createUI() { + choice1 = new Choice(); + choice1.add("item-01"); + choice1.add("item-02"); + choice1.add("item-03"); + choice1.add("item-04"); + choice1.setForeground(Color.red); + choice1.setBackground(Color.red); + frame = new Frame("ChoiceHandleMouseEvent"); + frame.add(choice1); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.validate(); + frame.setVisible(true); + } + + static void runTest() throws Exception { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(50); + + /* + * Stage 1: Choice should only opens with LEFTMOUSE click. + * Should only pass on Windows or XAWT. + * Choice on motif might be opened only by click on small box + * in the right side. + */ + testPressMouseButton(InputEvent.BUTTON2_DOWN_MASK); + testPressMouseButton(InputEvent.BUTTON3_DOWN_MASK); + System.out.println("Passed Stage 1: Choice should only opens with LEFT BUTTON."); + + /* + * Stage 2: Choice should only change its value if pressed + * mouse button is LEFTMOUSE. + */ + // first parameter is for opening choice. The second is for + // selecting item inside the menu + testPressMouseButton_2(InputEvent.BUTTON1_DOWN_MASK, InputEvent.BUTTON2_DOWN_MASK); + testPressMouseButton_2(InputEvent.BUTTON1_DOWN_MASK, InputEvent.BUTTON3_DOWN_MASK); + System.out.println("Passed Stage 2: Choice should not change its value if pressed mouse buttonis not left."); + + /* + * Stage 3: Choice should only react on drags with LEFTMOUSE button. + */ + // first parameter is for opening choice. The second is for + // selecting item inside the menu + testDragMouseButton(InputEvent.BUTTON1_DOWN_MASK, InputEvent.BUTTON2_DOWN_MASK); + testDragMouseButton(InputEvent.BUTTON1_DOWN_MASK, InputEvent.BUTTON3_DOWN_MASK); + System.out.println("Passed Stage 3: Choice should only react on drags with LEFTMOUSE button."); + } + + static void testPressMouseButton(int button) { + Point pt = choice1.getLocationOnScreen(); + robot.mouseMove(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2); + robot.delay(100); + robot.mousePress(button); + robot.mouseRelease(button); + robot.delay(200); + + int px = pt.x + choice1.getWidth()/2; + int py = pt.y + 3 * choice1.getHeight(); + Color color = robot.getPixelColor(px, py); + //we should take a color on the point on the choice's menu + System.out.println("Got color " + color + " at (" + px + "," + py + ")"); + System.out.println("RED="+Color.red); + if (color.equals(Color.red)) { + throw new RuntimeException("Test failed. Choice opens with "+button); + } else { + System.out.println("Stage 1 passed."+ button); + } + + //close opened choice + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + } + + static void testPressMouseButton_2(int openButton, int button) { + Point pt = choice1.getLocationOnScreen(); + robot.mouseMove(pt.x + choice1.getWidth()/2, + pt.y + choice1.getHeight()/2); + robot.delay(100); + robot.mousePress(openButton); + robot.mouseRelease(openButton); + robot.delay(200); + robot.mouseMove(pt.x + choice1.getWidth()/2, + pt.y + 2 * choice1.getHeight()); + robot.mousePress(button); + robot.mouseRelease(button); + + System.out.println(); + + if (choice1.getSelectedIndex() == 0) { + System.out.println("Stage 2 passed." + openButton +":"+button); + } else { + throw new RuntimeException("Stage 2 failed." + openButton +":"+button); + } + + //close opened choice + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + } + + static void testDragMouseButton(int openButton, int button) { + Point pt = choice1.getLocationOnScreen(); + robot.mouseMove(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2); + robot.delay(100); + robot.mousePress(openButton); + robot.mouseRelease(openButton); + robot.delay(200); + + robot.mousePress(button); + dragMouse(pt.x + choice1.getWidth()/2, pt.y + + choice1.getHeight()/2, + pt.x + choice1.getWidth()/2, + pt.y + 2 * choice1.getHeight()); + robot.mouseRelease(button); + + if (choice1.getSelectedIndex() == 0 ){ + System.out.println("Stage 3 passed." + openButton +":"+button); + // System.out.println("choice1.getSelectedIndex()" + choice1.getSelectedIndex()); + } else { + throw new RuntimeException("Stage 3 failed." + openButton +":"+button); + } + + //close opened choice + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + } + + static void dragMouse(int x0, int y0, int x1, int y1) { + int curX = x0; + int curY = y0; + int dx = x0 < x1 ? 1 : -1; + int dy = y0 < y1 ? 1 : -1; + + while (curX != x1){ + curX += dx; + robot.mouseMove(curX, curY); + } + while (curY != y1 ){ + curY += dy; + robot.mouseMove(curX, curY); + } + } +} diff --git a/test/jdk/java/awt/Choice/ChoiceHandleMouseEvent_2.java b/test/jdk/java/awt/Choice/ChoiceHandleMouseEvent_2.java new file mode 100644 index 00000000000..ba726b682d2 --- /dev/null +++ b/test/jdk/java/awt/Choice/ChoiceHandleMouseEvent_2.java @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6239944 + @summary PIT: Right clicking on the scrollbar of the choice's dropdown disposes the drop-down, on XToolkit + @key headful + @requires (os.family == "linux" | os.family == "windows") +*/ + +import java.awt.Choice; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +public class ChoiceHandleMouseEvent_2 { + + static Robot robot; + static volatile Choice choice1; + static volatile Frame frame; + static boolean isWindows; + + public static void main(String[] args) throws Exception { + String os = System.getProperty("os.name").toLowerCase(); + if (!os.startsWith("windows") && !os.startsWith("linux")) { + System.out.println("This test is only for Windows and Linux"); + return; + } + isWindows = os.startsWith("windows"); + try { + EventQueue.invokeAndWait(() -> createUI()); + runTest(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + } + + static void createUI() { + choice1 = new Choice(); + for (int i = 1; i<50; i++) { + choice1.add("item-0"+i); + } + choice1.setForeground(Color.red); + choice1.setBackground(Color.red); + frame = new Frame("ChoiceHandleMouseEvent_2"); + frame.setBackground(Color.green); + Panel panel = new Panel(); + panel.setBackground(Color.green); + panel.add(choice1); + frame.add(panel); + frame.setSize(300,300); + frame.setLocationRelativeTo(null); + frame.validate(); + frame.setVisible(true); + } + + static void runTest() throws Exception { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(50); + robot.delay(100); + + /* + * Stage 1. Choice should be closed if user dragged mouse + * outside of Choice after opening it. + * Should only pass on Windows or XAWT. + * Choice on motif might be opened only by click on small box + * in the right side. + */ + testDragMouseButtonOut(InputEvent.BUTTON1_DOWN_MASK); + System.out.println("Passed Stage 1: Choice should be closed if mouse dragged out."); + + /* + * Stage 2: Choice should be closed if LeftMouse drag finished + * on Scrollbar. This involeves only one + * MousePress and one MouseRelease event + */ + // first parameter is for opening choice. The second is for + // selecting item inside the menu + testDragMouseButtonOnSB(InputEvent.BUTTON1_DOWN_MASK); + System.out.println("Passed Stage 2: Choice should be closed if " + + "LeftMouse drag finished on Scrollbar."); + + /* + * Stage 3: Pressing RIGHT/MIDDLE MouseButton on Scrollbar + * shouldn't close Choice's pop-down menu. + * Pressing LEFT MouseButton shouldn't close it too. It should + * scroll it. + * This is an unstable test because we doesn't have an API to + * get Scrollbar from Choice. There is a possibility not to + * hit the scrollbar that couldn't been predicted. + */ + // first parameter is for opening choice. The second is for + // selecting item inside the menu + testPressOnScrollbar(InputEvent.BUTTON1_DOWN_MASK, InputEvent.BUTTON2_DOWN_MASK); + testPressOnScrollbar(InputEvent.BUTTON1_DOWN_MASK, InputEvent.BUTTON3_DOWN_MASK); + System.out.println("Passed Stage 3: Choice correctly reacts on mouse click on its Scrollbar."); + + /* + * Stage 4: Choice should close its popdown menu if user opened a Choice then + * releases Mouse and then presses Mouse again and dragged it on Choice's Scrollbar + * This involves only one MousePress and one MouseRelease + * event, so it differs from Stage 2. + */ + // first parameter is for opening choice. The second is for + // selecting item inside the menu or scrollbar + testDragMouseOnScrollbar(InputEvent.BUTTON1_DOWN_MASK, InputEvent.BUTTON1_DOWN_MASK); + System.out.println("Passed Stage 4: Choice should close if user opened a " + + "Choice then releases Mouse and then presses Mouse again " + + "and drag it on Choice's Scrollbar ."); + } + + + //Stage 4 + static void testDragMouseOnScrollbar(int openButton, int button) { + Point pt = choice1.getLocationOnScreen(); + robot.mouseMove(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2); + robot.delay(100); + robot.mousePress(openButton); + robot.mouseRelease(openButton); + robot.delay(200); + + robot.mouseMove(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2); + robot.mousePress(button); + /*X-coordinate should be closer to right edge of Choice, so + divider 4 is used. */ + dragMouse(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2, + pt.x + choice1.getWidth() - choice1.getHeight()/4, pt.y + 5*choice1.getHeight()); + robot.mouseRelease(button); + robot.delay(200); + + int px = pt.x + choice1.getWidth()/2; + int py = pt.y + 3 * choice1.getHeight(); + Color color = robot.getPixelColor(px, py); + //should take a color on the point on the choice's menu + System.out.println("Got color " + color + " at (" + px + "," + py + ")"); + if (color.equals(Color.red)) { + throw new RuntimeException( + "Test failed. Choice didn't close after drag without firstPress on ScrollBar " + button); + } else { + System.out.println("Stage 4 passed."+ button); + } + + //close opened choice + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.delay(200); + } + + //stage 3 + static void testPressOnScrollbar(int openButton, int button) { + if (!isWindows) { + return; // Windows-only tests. + } + Point pt = choice1.getLocationOnScreen(); + robot.mouseMove(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2); + robot.delay(100); + robot.mousePress(openButton); + robot.mouseRelease(openButton); + robot.delay(200); + /*X-coordinate should be closer to right edge of Choice, so + divide by 4 is used. */ + int px = pt.x + choice1.getWidth() - choice1.getHeight()/4; + int py = pt.y + 5*choice1.getHeight(); + robot.mouseMove(px, py); + robot.delay(200); + robot.mousePress(button); + robot.mouseRelease(button); + robot.delay(200); + + System.out.println("x= "+px); + System.out.println("y= "+py); + + /* + This is for Windows only. + On XP theme choice become closed on RightMouseClick over a scrollbar. + A system menu is opened after that. On Classic theme Choice doesn't react on it at all. + */ + boolean isXPTheme = false; + Object themeObject = Toolkit.getDefaultToolkit().getDesktopProperty("win.xpstyle.themeActive"); + // it returns null when Classic theme is active but we should + // check it's boolean value anyway if event it's not null. + if (themeObject != null) { + isXPTheme = ((Boolean)themeObject).booleanValue(); + } + System.out.println("isXPTheme="+isXPTheme); + px = pt.x + choice1.getWidth()/2; + py = pt.y + 3 * choice1.getHeight(); + Color color = robot.getPixelColor(px, py); + //we should take a color on the point on the choice's menu + System.out.println("Got color " + color + " at (" + px + "," + py + ")"); + System.out.println("RED="+Color.red); + System.out.println("GREEN="+Color.green); + if (isXPTheme && button == InputEvent.BUTTON3_DOWN_MASK) { + if (!color.equals(Color.green)) { + throw new RuntimeException("Stage 3 failed(XP theme). " + + "Choice wasn't closed with pressing button on its Scrollbar" + openButton +":"+button); + } else { + System.out.println("Stage 3 passed(XP theme)." + openButton +":"+button); + } + } else { + if (!color.equals(Color.red)) { + throw new RuntimeException("Stage 3 failed(classic theme). " + + "Choice is being closed with pressing button on its Scrollbar" + openButton +":"+button); + } else { + System.out.println("Stage 3 passed(classic theme)." + openButton +":"+button); + } + } + + //close opened choice + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.delay(200); + } + + // Stage 1 + static void testDragMouseButtonOut(int button) { + Point pt = choice1.getLocationOnScreen(); + + robot.mouseMove(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2); + robot.mousePress(button); + dragMouse(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2, + pt.x + choice1.getWidth()*2, pt.y + choice1.getHeight()/2); + robot.mouseRelease(button); + robot.delay(200); + int px = pt.x + choice1.getWidth()/2; + int py = pt.y + 3 * choice1.getHeight(); + Color color = robot.getPixelColor(px, py); + //should take a color on the point on the choice's menu + System.out.println("Got color " + color + " at (" + px + "," + py + ")"); + System.out.println("RED="+Color.red); + // fix 6268989: On Windows Choice shouldn't been closed if + // Mouse dragged outside of Choice after one mouse press. + if (isWindows) { + if (color.equals(Color.red)) { + System.out.println("Stage 1 passed. On Windows Choice shouldn't be " + + "closed if Mouse dragged outside of Choice after one mouse press "+button); + } else { + throw new RuntimeException("Test failed. Choice on Windows shouldn't be " + + "closed after drag outside of Choice after one mouse press "+button); + } + } else { + if (color.equals(Color.red)) { + throw new RuntimeException("Test failed. Choice didn't close " + + "after drag outside of Choice "+button); + } else { + System.out.println("Stage 1 passed."+ button); + } + } + + //close opened choice + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.delay(200); + } + + //stage 2 + static void testDragMouseButtonOnSB(int button) { + Point pt = choice1.getLocationOnScreen(); + + robot.mouseMove(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2); + robot.mousePress(button); + /*X-coordinate should be closer to right edge of Choice, so + divider 4 is used. */ + dragMouse(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2, + pt.x + choice1.getWidth() - choice1.getHeight()/4, pt.y + 5*choice1.getHeight()); + robot.mouseRelease(button); + robot.delay(200); + int px = pt.x + choice1.getWidth()/2; + int py = pt.y + 3 * choice1.getHeight(); + Color color = robot.getPixelColor(px, py); + //should take a color on the point on the choice's menu + System.out.println("Got color " + color + " at (" + px + "," + py + ")"); + if (isWindows) { + if (color.equals(Color.red)) { + System.out.println("Stage 2 passed. On Windows Choice shouldn't be " + + " closed if Mouse dragged on its scrollbar "+button); + } else { + throw new RuntimeException("Test failed. On Windows Choice shouldn't be " + + " closed if Mouse dragged on its scrollbar "+button); + } + } else { + if (color.equals(Color.red)) { + throw new RuntimeException("Test failed. Choice didn't close after drag on ScrollBar "+button); + } else { + System.out.println("Stage 2 passed."+ button); + } + } + + //close opened choice + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.delay(200); + } + + static void dragMouse(int x0, int y0, int x1, int y1) { + int curX = x0; + int curY = y0; + int dx = x0 < x1 ? 1 : -1; + int dy = y0 < y1 ? 1 : -1; + + while (curX != x1) { + curX += dx; + robot.mouseMove(curX, curY); + } + while (curY != y1) { + curY += dy; + robot.mouseMove(curX, curY); + } + } +} diff --git a/test/jdk/java/awt/Choice/ChoiceMouseEventOutbounds.java b/test/jdk/java/awt/Choice/ChoiceMouseEventOutbounds.java new file mode 100644 index 00000000000..31b8eb97ef0 --- /dev/null +++ b/test/jdk/java/awt/Choice/ChoiceMouseEventOutbounds.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6272965 + @summary PIT: Choice triggers MousePressed when pressing mouse outside comp while drop-down is active, XTkt + @key headful +*/ + +import java.awt.Choice; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public class ChoiceMouseEventOutbounds { + + static final int DELAY = 100; + static volatile Choice choice1; + static volatile Frame frame; + static volatile Robot robot; + static volatile boolean mousePressed = false; + static volatile boolean mouseReleased = false; + static volatile boolean mouseClicked = false; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(() -> createUI()); + runTest(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + } + + static void createUI() { + choice1 = new Choice(); + for (int i = 1; i<10; i++) { + choice1.add("item "+i); + } + + choice1.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent me) { + mousePressed = true; + System.out.println(me); + } + public void mouseReleased(MouseEvent me) { + mouseReleased = true; + System.out.println(me); + } + public void mouseClicked(MouseEvent me) { + mouseClicked = true; + System.out.println(me); + } + }); + + frame = new Frame("ChoiceMouseEventOutbounds"); + frame.add(choice1); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.validate(); + } + + static void runTest() throws Exception { + // On Windows, Choice will not close its pop-down menu on a RIGHT + // MousePress outside of the Choice. So this scenario isn't + // tested here for that reason. + + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(50); + robot.delay(DELAY*10); + testMouseClick(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(DELAY); + testMouseClick(InputEvent.BUTTON2_DOWN_MASK); + robot.delay(DELAY); + testMouseClick(InputEvent.BUTTON3_DOWN_MASK); + + System.out.println("Test passed: Choice doesn't generate MOUSEPRESS/CLICK/RELEASE outside Choice."); + } + + static void testMouseClick(int button) { + Point pt = choice1.getLocationOnScreen(); + robot.mouseMove(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2); + robot.delay(DELAY); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(DELAY); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(DELAY*3); + + //they are true because we just pressed mouse + mousePressed = false; + mouseReleased = false; + mouseClicked = false; + + //move mouse outside Choice + robot.mouseMove(pt.x + choice1.getWidth()/2, pt.y - choice1.getHeight()); + robot.delay(DELAY*3); + robot.mousePress(button); + robot.delay(DELAY); + robot.mouseRelease(button); + + if (mousePressed || mouseReleased || mouseClicked) { + System.out.println("ERROR: "+ mousePressed+","+mouseReleased +","+mouseClicked); + throw new RuntimeException( + "Test failed. Choice shouldn't generate PRESSED, RELEASED, CLICKED events outside "+ button); + } else { + System.out.println( + "Test passed. Choice didn't generated MouseDragged PRESSED, RELEASED, CLICKED events outside "+ button); + } + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.delay(DELAY); + mousePressed = false; + mouseReleased = false; + mouseClicked = false; + } +} diff --git a/test/jdk/java/awt/Choice/ChoiceMoveTest.java b/test/jdk/java/awt/Choice/ChoiceMoveTest.java new file mode 100644 index 00000000000..878781bb523 --- /dev/null +++ b/test/jdk/java/awt/Choice/ChoiceMoveTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4323906 + @summary Test that Choice location is not updated erroneously + @key headful +*/ + +/** + * summary: The test adds a Choice to a Container with BorderLayout, and + * adds the Container to a Frame with null Layout. When + * the Container is moved in the x direction, the Choice should + * not move in the y direction. + */ + +import java.awt.BorderLayout; +import java.awt.Choice; +import java.awt.Color; +import java.awt.Container; +import java.awt.EventQueue; +import java.awt.Frame; + +public class ChoiceMoveTest { + + static volatile Frame frame; + static volatile Container c; + static volatile Choice ch; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(() -> createUI()); + runTest(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + } + + static void createUI() { + frame = new Frame("Choice Move Test"); + frame.setSize(500, 500); + frame.setLayout(null); + + c = new Container(); + c.setBackground(Color.green); + frame.add(c); + c.setSize(200, 200); + c.setLocation(100, 100); + c.setLayout(new BorderLayout()); + + ch = new Choice(); + ch.setSize(100, 27); + c.add(ch, BorderLayout.SOUTH); + frame.setVisible(true); + frame.validate(); + } + + static void runTest () throws Exception { + Thread.sleep(1000); + // If this test ever gives us problems, try putting getLocation() in a + // ComponentListener. + int xbefore = ch.getLocation().x; + int ybefore = ch.getLocation().y; + System.out.println("Choice location before: " + xbefore + ", " + ybefore); + + c.setLocation(200, 100); + Thread.sleep(1000); + + java.awt.Toolkit.getDefaultToolkit().sync(); + Thread.sleep(1000); + int xafter = ch.getLocation().x; + int yafter = ch.getLocation().y; + System.out.println("Choice location after: " + xafter + ", " + yafter); + + if (ybefore != yafter) { + System.out.println("Test FAILED"); + throw new RuntimeException("Test failed - Choice should not move in the y direction."); + } + else { + System.out.println("Test passed."); + } + } +} diff --git a/test/jdk/java/awt/Choice/ChoiceStaysOpenedOnTAB.java b/test/jdk/java/awt/Choice/ChoiceStaysOpenedOnTAB.java new file mode 100644 index 00000000000..9703a4b52a9 --- /dev/null +++ b/test/jdk/java/awt/Choice/ChoiceStaysOpenedOnTAB.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6239938 + @summary Choice drop-down does not disappear when it loses focus, on XToolkit + @key headful + @requires (os.family == "linux") +*/ + +import java.awt.Button; +import java.awt.Choice; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +public class ChoiceStaysOpenedOnTAB { + + static volatile Robot robot; + static volatile Choice choice1; + static volatile Frame frame; + + public static void main(String[] args) throws Exception { + + if (!System.getProperty("os.name").toLowerCase().startsWith("linux")) { + System.out.println("This test is for Linux only"); + return; + } + + try { + EventQueue.invokeAndWait(() -> createUI()); + runTest(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + } + + static void createUI() { + choice1 = new Choice(); + for (int i = 1; i<10; i++) { + choice1.add("item-0"+i); + } + choice1.setForeground(Color.red); + choice1.setBackground(Color.red); + Button b1 = new Button("FirstButton"); + Button b2 = new Button("SecondButton"); + frame = new Frame("ChoiceStaysOpenedOnTAB"); + Panel panel = new Panel(); + panel.add(b1); + panel.add(choice1); + panel.add(b2); + frame.add(panel); + frame.setSize(400,400); + frame.setLocationRelativeTo(null); + frame.validate(); + frame.setVisible(true); + } + + static void runTest() throws Exception { + + /* + * Choice should not lose focus while it is opened with + * TAB/Shitf-TAB KeyPress on XAWT. + * Should only pass on XAWT. + */ + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(50); + robot.delay(1000); + + testTABKeyPress(InputEvent.BUTTON1_DOWN_MASK, KeyEvent.VK_TAB, false); + testTABKeyPress(InputEvent.BUTTON1_DOWN_MASK, KeyEvent.VK_TAB, true); + System.out.println("Passed : Choice should not lose focus on TAB key press while it is opened."); + } + + static void testTABKeyPress(int openButton, int keyButton, boolean isShiftUsed) { + Point pt = choice1.getLocationOnScreen(); + robot.mouseMove(pt.x + choice1.getWidth()/2, pt.y + choice1.getHeight()/2); + robot.delay(100); + robot.mousePress(openButton); + robot.mouseRelease(openButton); + robot.delay(200); + + Color color = robot.getPixelColor(pt.x + choice1.getWidth()/2, + pt.y + 3 * choice1.getHeight()); + if (!color.equals(Color.red)) { + throw new RuntimeException( + "Choice wasn't opened with LEFTMOUSE button" + openButton +":"+keyButton+":"+isShiftUsed); + } + robot.delay(200); + if (isShiftUsed) { + robot.keyPress(KeyEvent.VK_SHIFT); + } + robot.keyPress(keyButton); + robot.keyRelease(keyButton); + + if (isShiftUsed) { + robot.keyRelease(KeyEvent.VK_SHIFT); + } + + robot.delay(200); + if (!choice1.isFocusOwner()) { + System.out.println("Choice has focus=="+choice1.isFocusOwner()); + throw new RuntimeException( + "Choice has no focus after pressing TAB/Shitf+TAB" + openButton +":"+keyButton+":"+isShiftUsed); + } + int px = pt.x + choice1.getWidth()/2; + int py = pt.y + 3 * choice1.getHeight(); + color = robot.getPixelColor(px, py); + //we should take a color on the point on the choice's menu + System.out.println("color got "+color); + if (!color.equals(Color.red)) { + throw new RuntimeException( + "Choice closed after TAB/Shift+TAB key press" + openButton +":"+keyButton+":"+isShiftUsed); + } + + //close opened choice + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.delay(200); + } +} diff --git a/test/jdk/java/awt/Choice/DragOffNoSelectTest.java b/test/jdk/java/awt/Choice/DragOffNoSelectTest.java new file mode 100644 index 00000000000..587fc701e93 --- /dev/null +++ b/test/jdk/java/awt/Choice/DragOffNoSelectTest.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4902933 + @summary Test that dragging off an unfurled Choice prevents selecting a new item + @key headful +*/ + +import java.awt.Choice; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +public class DragOffNoSelectTest implements WindowListener, Runnable { + + static volatile DragOffNoSelectTest testInstance; + static volatile Frame frame; + static volatile Choice theChoice; + static volatile Robot robot; + static final String firstItem = new String("First Choice Item"); + + static volatile Object lock = new Object(); + + public static void main(String[] args) throws Exception { + testInstance = new DragOffNoSelectTest(); + robot = new Robot(); + robot.setAutoDelay(500); + try { + EventQueue.invokeAndWait(() -> createUI()); + runTest(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + } + + static void createUI() { + frame = new Frame("DragOffNoSelectTest"); + theChoice = new Choice(); + theChoice.add(firstItem); + for (int i = 0; i < 10; i++) { + theChoice.add(new String("Choice Item " + i)); + } + frame.add(theChoice); + frame.addWindowListener(testInstance); + frame.setSize(400, 400); + frame.setLocationRelativeTo(null); + + frame.setVisible(true); + frame.validate(); + } + + static void runTest() throws Exception { + robot.mouseMove(10, 30); + synchronized (lock) { + try { + lock.wait(120000); + } + catch (InterruptedException e) {} + } + robot.waitForIdle(); + + if (!firstItem.equals(theChoice.getSelectedItem())) { + throw new RuntimeException("TEST FAILED - new item was selected"); + } + } + + public void run() { + robot.delay(1000); + // get loc of Choice on screen + Point loc = theChoice.getLocationOnScreen(); + // get bounds of Choice + Dimension size = theChoice.getSize(); + robot.mouseMove(loc.x + size.width - 10, loc.y + size.height / 2); + + robot.setAutoDelay(500); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + + robot.mouseMove(loc.x + size.width / 2, loc.y + size.height + size.height / 2); + robot.mouseMove(loc.x + size.width / 2, loc.y + 2*size.height + size.height / 2); + robot.mouseMove(loc.x + size.width / 2, loc.y + 3*size.height + size.height / 2); + robot.mouseMove(loc.x + size.width / 2, loc.y + 4*size.height + size.height / 2); + robot.mouseMove(loc.x + size.width, loc.y + 4*size.height + size.height / 2); + robot.mouseMove(loc.x + 2*size.width, loc.y + 4*size.height + size.height / 2); + robot.mouseMove(loc.x + 3*size.width, loc.y + 4*size.height + size.height / 2); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + synchronized(lock) { + lock.notify(); + } + } + + public void windowOpened(WindowEvent e) { + System.out.println("windowActivated()"); + Thread testThread = new Thread(testInstance); + testThread.start(); + } + public void windowActivated(WindowEvent e) { } + public void windowDeactivated(WindowEvent e) {} + public void windowClosed(WindowEvent e) {} + public void windowClosing(WindowEvent e) {} + public void windowIconified(WindowEvent e) {} + public void windowDeiconified(WindowEvent e) {} + +} + diff --git a/test/jdk/java/awt/Clipboard/CopyAnimatedGIFTest.java b/test/jdk/java/awt/Clipboard/CopyAnimatedGIFTest.java new file mode 100644 index 00000000000..1023654db35 --- /dev/null +++ b/test/jdk/java/awt/Clipboard/CopyAnimatedGIFTest.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Canvas; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.util.concurrent.CountDownLatch; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +/* + * @test + * @key headful + * @bug 6176679 + * @summary Tests that an application doesn't freeze when copying an animated + * gif image to the system clipboard. We run the test two times. First with + * image displayed on screen and second with it not displayed. + * @run main CopyAnimatedGIFTest + */ +public class CopyAnimatedGIFTest { + private static final long TIMEOUT = 10000; + + private final CountDownLatch latch = new CountDownLatch(1); + private final Image img = Toolkit.getDefaultToolkit().createImage(imageData); + + private static final byte[] imageData = { + (byte) 0x47, (byte) 0x49, (byte) 0x46, (byte) 0x38, (byte) 0x39, + (byte) 0x61, (byte) 0x04, (byte) 0x00, (byte) 0x04, (byte) 0x00, + (byte) 0xa1, (byte) 0x03, (byte) 0x00, (byte) 0xff, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0x00, (byte) 0xff, + (byte) 0xff, (byte) 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x21, (byte) 0xff, (byte) 0x0b, (byte) 0x4e, (byte) 0x45, + (byte) 0x54, (byte) 0x53, (byte) 0x43, (byte) 0x41, (byte) 0x50, + (byte) 0x45, (byte) 0x32, (byte) 0x2e, (byte) 0x30, (byte) 0x03, + (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x21, + (byte) 0xf9, (byte) 0x04, (byte) 0x00, (byte) 0x0a, (byte) 0x00, + (byte) 0xff, (byte) 0x00, (byte) 0x2c, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x04, + (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x04, (byte) 0x84, + (byte) 0x8f, (byte) 0x09, (byte) 0x05, (byte) 0x00, (byte) 0x21, + (byte) 0xf9, (byte) 0x04, (byte) 0x01, (byte) 0x0a, (byte) 0x00, + (byte) 0x03, (byte) 0x00, (byte) 0x2c, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x04, + (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x04, (byte) 0x94, + (byte) 0x8f, (byte) 0x29, (byte) 0x05, (byte) 0x00, (byte) 0x21, + (byte) 0xf9, (byte) 0x04, (byte) 0x01, (byte) 0x0a, (byte) 0x00, + (byte) 0x03, (byte) 0x00, (byte) 0x2c, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x04, + (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x04, (byte) 0x8c, + (byte) 0x8f, (byte) 0x19, (byte) 0x05, (byte) 0x00, (byte) 0x3b + }; + + private void createGUI() { + ImageCanvas canvas = new ImageCanvas(img); + canvas.setBackground(Color.BLUE); + + Frame frame = new Frame("CopyAnimatedGIFTest"); + frame.setSize(400, 200); + frame.add(canvas); + frame.setVisible(true); + } + + private void copyImage() { + Clipboard sys = Toolkit.getDefaultToolkit().getSystemClipboard(); + sys.setContents(new MyTransferable(img), null); + } + + private void runTest(boolean isImageDisplayed) throws Exception { + + if (isImageDisplayed) { + Robot robot = new Robot(); + EventQueue.invokeAndWait(this::createGUI); + robot.waitForIdle(); + robot.delay(1000); + } + + EventQueue.invokeLater(() -> { + copyImage(); + latch.countDown(); + }); + + if (!latch.await(TIMEOUT, MILLISECONDS)) { + String str = isImageDisplayed ? " displayed":" not displayed"; + throw new RuntimeException("Image copying taking too long for image" + + str + " case"); + } + } + + public static void main(String[] args) throws Exception { + // run test with Image showing up on screen + new CopyAnimatedGIFTest().runTest(true); + + // run test without Image showing up + new CopyAnimatedGIFTest().runTest(false); + } + + private static class ImageCanvas extends Canvas { + private final Image img; + public ImageCanvas(Image img) { + this.img = img; + } + + @Override + public void paint(Graphics g) { + g.drawImage(img, 0, 0, getWidth(), getHeight(), this); + } + } + + private static class MyTransferable implements Transferable { + private final Image img; + private final DataFlavor[] flavors = {DataFlavor.imageFlavor}; + + public MyTransferable(Image img) { + this.img = img; + } + + @Override + public DataFlavor[] getTransferDataFlavors() { + return flavors; + } + + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { + return flavors[0].equals(flavor); + } + + @Override + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException { + if (!isDataFlavorSupported(flavor)) { + throw new UnsupportedFlavorException(flavor); + } + return img; + } + } + +} diff --git a/test/jdk/java/awt/Component/ComponentRedrawnTest.java b/test/jdk/java/awt/Component/ComponentRedrawnTest.java new file mode 100644 index 00000000000..6007d23b741 --- /dev/null +++ b/test/jdk/java/awt/Component/ComponentRedrawnTest.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key headful + * @bug 8139581 + * @summary Verify that components are redrawn after + * removal and addition to a container + * @run main ComponentRedrawnTest + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Panel; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.swing.JButton; + +public class ComponentRedrawnTest { + + private static Frame frame; + private static Panel componentPanel; + private static Button buttonRemove; + private static Button buttonAdd; + private static Button awtButton; + + private static volatile Robot robot; + private static volatile int x; + private static volatile int y; + private static AtomicInteger awtPainted = new AtomicInteger(); + private static AtomicInteger swingPainted = new AtomicInteger(); + + public static void main(String args[]) throws Exception { + try { + EventQueue.invokeAndWait(() -> createGUI()); + runTest(); + System.out.println("Test Passed"); + } finally { + EventQueue.invokeAndWait(() -> dispose()); + } + } + + private static void createGUI() { + frame = new Frame("ComponentRedrawnTest"); + frame.setSize(350, 300); + frame.setBackground(Color.red); + + componentPanel = new Panel(); + componentPanel.setLayout(null); + componentPanel.setBackground(Color.green); + + awtButton = new Button("AWT Button") { + @Override + public void paint(Graphics g) { + super.paint(g); + awtPainted.incrementAndGet(); + } + }; + + awtButton.setBounds(0, 0, 330, 100); + componentPanel.add(awtButton); + + JButton swingButton = new JButton("Swing JButton") { + @Override + public void paint(Graphics g) { + super.paint(g); + swingPainted.incrementAndGet(); + } + }; + + swingButton.setBounds(0, 100, 330, 100); + componentPanel.add(swingButton); + frame.add(componentPanel, BorderLayout.CENTER); + buttonRemove = new Button("remove"); + buttonRemove.addActionListener(ae -> buttonClicked(ae)); + + buttonAdd = new Button("add"); + buttonAdd.addActionListener(ae -> buttonClicked(ae)); + + Panel controlPanel = new Panel(); + controlPanel.setLayout(new BorderLayout()); + controlPanel.add(buttonRemove, BorderLayout.NORTH); + controlPanel.add(buttonAdd, BorderLayout.SOUTH); + + frame.add(controlPanel, BorderLayout.SOUTH); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void buttonClicked(ActionEvent ae) { + if (ae.getSource() == buttonRemove) { + frame.remove(componentPanel); + } else if (ae.getSource() == buttonAdd) { + frame.add(componentPanel); + } + frame.invalidate(); + frame.validate(); + } + + private static void runTest() throws Exception { + EventQueue.invokeAndWait(() -> createGUI()); + robot = new Robot(); + robot.setAutoDelay(500); + awtPainted.set(0); + swingPainted.set(0); + + try { + EventQueue.invokeAndWait(() -> { + x = awtButton.getLocationOnScreen().x + + awtButton.getSize().width / 2; + y = awtButton.getLocationOnScreen().y + + awtButton.getSize().height / 2; + }); + } catch (Exception e) { + throw new RuntimeException("Unexpected Exception encountered: " + e); + } + + robot.mouseMove(x, y); + robot.waitForIdle(); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + + try { + EventQueue.invokeAndWait(() -> { + x = buttonRemove.getLocationOnScreen().x + + buttonRemove.getSize().width / 2; + y = buttonRemove.getLocationOnScreen().y + + buttonRemove.getSize().height / 2; + }); + } catch (Exception e) { + throw new RuntimeException("Unexpected Exception encountered: " + e); + } + + robot.mouseMove(x, y); + robot.waitForIdle(); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + + try { + EventQueue.invokeAndWait(() -> { + x = buttonAdd.getLocationOnScreen().x + + buttonAdd.getSize().width / 2; + y = buttonAdd.getLocationOnScreen().y + + buttonAdd.getSize().height / 2; + }); + + } catch (Exception e) { + throw new RuntimeException("Unexpected Exception encountered: " + e); + } + robot.mouseMove(x, y); + robot.waitForIdle(); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + + if (awtPainted.get() == 0) { + throw new RuntimeException("AWT button is not painted"); + } + if (swingPainted.get() == 0) { + throw new RuntimeException("Swing button is not painted"); + } + } + + private static void dispose() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + +} diff --git a/test/jdk/java/awt/EventDispatchThread/StoppingEdtOnPushPopTest.java b/test/jdk/java/awt/EventDispatchThread/StoppingEdtOnPushPopTest.java new file mode 100644 index 00000000000..4186e690f0d --- /dev/null +++ b/test/jdk/java/awt/EventDispatchThread/StoppingEdtOnPushPopTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4848555 + @summary Popping an event queue could cause its thread to restart inadvertently + @run main StoppingEdtOnPushPopTest +*/ + +import java.awt.AWTEvent; +import java.awt.ActiveEvent; +import java.awt.EventQueue; +import java.awt.Toolkit; + +public class StoppingEdtOnPushPopTest implements Runnable { + public void start() { + int before = countEventQueues(); + try { + for (int i = 0; i < 10; i++) { + EventQueue.invokeAndWait(this); + } + } catch (InterruptedException e) { + e.printStackTrace(); + throw new RuntimeException("Test was interrupted"); + } catch (java.lang.reflect.InvocationTargetException e) { + e.printStackTrace(); + throw new RuntimeException("InvocationTargetException occurred"); + } + pause(1000); + int after = countEventQueues(); + if (before < after && after > 1) { + throw new RuntimeException("Test failed (before=" + before + + "; after=" + after + ")"); + } + System.out.println("Test passed"); + } + + public void run() { + System.out.println("push/pop"); + MyEventQueue queue = new MyEventQueue(); + Toolkit.getDefaultToolkit().getSystemEventQueue().push(queue); + Toolkit.getDefaultToolkit().getSystemEventQueue() + .postEvent(new EmptyEvent()); + queue.pop(); + } + + public int countEventQueues() { + int count = 0; + System.out.println("All threads currently running in the system"); + Thread threads[] = new Thread[Thread.activeCount()]; + Thread.enumerate(threads); + for (int i = 0; i < threads.length; ++i) { + Thread thread = threads[i]; + if (thread != null) { + System.out.println(thread.getName()); + if (thread.getName().startsWith("AWT-EventQueue")) { + count++; + } + } + } + return count; + } + + public void pause(long aMillis) { + try { + Thread.sleep(aMillis); + } catch (InterruptedException e) { + e.printStackTrace(); + throw new RuntimeException("Test was interrupted"); + } + } + + public static void main(String[] args) { + StoppingEdtOnPushPopTest test = new StoppingEdtOnPushPopTest(); + test.start(); + } +} + +class MyEventQueue extends EventQueue { + public MyEventQueue() { + super(); + } + + public void pop() { + super.pop(); + } +} + +class EmptyEvent extends AWTEvent implements ActiveEvent { + public EmptyEvent() { + super(new Object(), 0); + } + + public void dispatch() { + System.out.println("one more EmptyEvent"); + } +} diff --git a/test/jdk/java/awt/FileDialog/ExceptionAfterSetDirectory.java b/test/jdk/java/awt/FileDialog/ExceptionAfterSetDirectory.java new file mode 100644 index 00000000000..28d63ae6216 --- /dev/null +++ b/test/jdk/java/awt/FileDialog/ExceptionAfterSetDirectory.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6308332 + @summary FileDialog.setDirectory() throws exception on Linux & Solaris + @key headful + @run main ExceptionAfterSetDirectory +*/ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.FileDialog; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import java.lang.reflect.InvocationTargetException; + +public class ExceptionAfterSetDirectory { + FileDialog fd = null; + Frame frame; + + public void start() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + frame = new Frame("ExceptionAfterSetDirectory"); + frame.setLayout(new FlowLayout()); + frame.setBounds(100, 100, 100, 100); + frame.setVisible(true); + fd = new FileDialog(frame, "file dialog", FileDialog.LOAD); + }); + + try { + test(); + } catch (Exception e) { + throw new RuntimeException("Test failed.", e); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + if (fd != null) { + EventQueue.invokeAndWait(fd::dispose);; + } + } + } + + private void test() throws InterruptedException, InvocationTargetException { + final Robot r; + + try { + r = new Robot(); + } catch (AWTException e) { + throw new RuntimeException("Can not initialize Robot.", e); + } + + r.setAutoDelay(200); + r.delay(500); + + EventQueue.invokeLater(() -> { + fd.setVisible(true); + }); + r.delay(2000); + r.waitForIdle(); + + if (System.getProperty("os.name").contains("OS X")) { + // Workaround for JDK-7186009 - try to close file dialog pressing escape + r.keyPress(KeyEvent.VK_ESCAPE); + r.keyRelease(KeyEvent.VK_ESCAPE); + r.delay(2000); + r.waitForIdle(); + } + + if (fd.isVisible()) { + EventQueue.invokeAndWait(() -> { + fd.setVisible(false); + }); + r.delay(2000); + r.waitForIdle(); + } + + // Changing directory on hidden file dialog should not cause an exception + EventQueue.invokeAndWait(() -> { + fd.setDirectory("/"); + }); + r.delay(2000); + r.waitForIdle(); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + ExceptionAfterSetDirectory test = new ExceptionAfterSetDirectory(); + test.start(); + } +} diff --git a/test/jdk/java/awt/FlowLayout/MinimumLayoutSize.java b/test/jdk/java/awt/FlowLayout/MinimumLayoutSize.java new file mode 100644 index 00000000000..7b79cc3317c --- /dev/null +++ b/test/jdk/java/awt/FlowLayout/MinimumLayoutSize.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6257219 + @summary FlowLayout gives a wrong minimum size if the first component is hidden. + @key headful + @run main MinimumLayoutSize +*/ + + +import java.awt.AWTException; +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.LayoutManager; +import java.awt.Panel; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +public class MinimumLayoutSize { + Frame frame; + Button b1; + Button b2; + Panel panel; + + public void start() throws AWTException, + InterruptedException, InvocationTargetException { + try { + Robot robot = new Robot(); + LayoutManager layout = new FlowLayout(FlowLayout.LEFT, 100, 0); + final int[] widths = new int[2]; + EventQueue.invokeAndWait(() -> { + frame = new Frame("MinimumLayoutSize"); + b1 = new Button("B1"); + b2 = new Button("B2"); + panel = new Panel(); + panel.add(b2); + frame.add(panel); + frame.pack(); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + //add hidden component b1 + EventQueue.invokeAndWait(() -> { + widths[0] = layout.minimumLayoutSize(panel).width; + b1.setVisible(false); + panel.add(b1, 0); + }); + robot.waitForIdle(); + robot.delay(1000); + EventQueue.invokeAndWait(() -> { + widths[1] = layout.minimumLayoutSize(panel).width; + frame.setVisible(false); + }); + System.out.println("TRACE: w1 = " + widths[0] + " w2 = " + widths[1]); + + if (widths[0] != widths[1]) { + throw new RuntimeException("Test FAILED. Minimum sizes are not equal." + + " w1 = " + widths[0] + " w2 = " + widths[1]); + } + } finally { + if (frame != null) { + frame.dispose(); + } + } + System.out.println("Test passed"); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + MinimumLayoutSize test = new MinimumLayoutSize(); + test.start(); + } +} diff --git a/test/jdk/java/awt/FlowLayout/PreferredLayoutSize.java b/test/jdk/java/awt/FlowLayout/PreferredLayoutSize.java new file mode 100644 index 00000000000..def1c044d24 --- /dev/null +++ b/test/jdk/java/awt/FlowLayout/PreferredLayoutSize.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4284124 + @summary FlowLayout gives a wrong size if the first component is hidden. + @key headful + @run main PreferredLayoutSize +*/ + +import java.awt.Button; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.lang.reflect.InvocationTargetException; + +public class PreferredLayoutSize { + public void start() { + Frame f = new Frame("PreferredLayoutSize"); + int[] widths = new int[2]; + + try { + f.setLocationRelativeTo(null); + Button b1 = new Button("button 1"); + Button b2 = new Button("button 2"); + f.setLayout(new FlowLayout(FlowLayout.LEFT, 50, 5)); + f.add(b1); + f.add(b2); + f.pack(); + f.setVisible(true); + b1.setVisible(false); + b2.setVisible(true); + Dimension d1 = f.getPreferredSize(); + Dimension d2 = b2.getPreferredSize(); + widths[0] = d1.width - d2.width; + b1.setVisible(true); + b2.setVisible(false); + d1 = f.getPreferredSize(); + d2 = b1.getPreferredSize(); + widths[1] = d1.width - d2.width; + f.setVisible(false); + } finally { + f.dispose(); + } + + if (widths[0] != widths[1]) { + throw new RuntimeException("Test FAILED"); + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PreferredLayoutSize test = new PreferredLayoutSize(); + EventQueue.invokeAndWait(test::start); + } +} diff --git a/test/jdk/java/awt/Focus/AsyncUpFocusCycleTest.java b/test/jdk/java/awt/Focus/AsyncUpFocusCycleTest.java new file mode 100644 index 00000000000..d15476d3f82 --- /dev/null +++ b/test/jdk/java/awt/Focus/AsyncUpFocusCycleTest.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4394789 + @summary KeyboardFocusManager.upFocusCycle is not working for Swing properly + @key headful + @run main AsyncUpFocusCycleTest +*/ + + +import javax.swing.DefaultFocusManager; +import javax.swing.JButton; +import javax.swing.JFrame; +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.DefaultKeyboardFocusManager; +import java.awt.EventQueue; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.InputEvent; +import java.lang.reflect.InvocationTargetException; + +public class AsyncUpFocusCycleTest { + volatile boolean isFailed = true; + Object sema = new Object(); + JFrame frame; + Point location; + JButton button; + Insets insets; + int width; + + public void start() throws InterruptedException, + InvocationTargetException { + try { + Robot robot = new Robot(); + robot.mouseMove(100, 100); + + EventQueue.invokeAndWait(() -> { + frame = new JFrame("AsyncUpFocusCycleTest") { + public void requestFocus() { + boolean ret = super.requestFocus(false); + System.err.println("requestFocus() on Frame " + ret); + } + + protected boolean requestFocus(boolean temporary) { + boolean ret = super.requestFocus(temporary); + System.err.println("requestFocus(" + temporary + ") on Frame " + ret); + return ret; + } + + public boolean requestFocusInWindow() { + boolean ret = super.requestFocusInWindow(); + System.err.println("requestFocusInWindow() on Frame " + ret); + return ret; + } + + protected boolean requestFocusInWindow(boolean temporary) { + boolean ret = super.requestFocusInWindow(temporary); + System.err.println("requestFocusInWindow(" + temporary + ") on Frame " + ret); + return ret; + } + }; + + Container container1 = frame.getContentPane(); + container1.setBackground(Color.yellow); + + button = new JButton("Button") { + public void requestFocus() { + boolean ret = super.requestFocus(false); + System.err.println("requestFocus() on Button " + ret); + } + + public boolean requestFocus(boolean temporary) { + boolean ret = super.requestFocus(temporary); + System.err.println("requestFocus(" + temporary + ") on Button " + ret); + return ret; + } + + public boolean requestFocusInWindow() { + boolean ret = super.requestFocusInWindow(); + System.err.println("requestFocusInWindow() on Button " + ret); + return ret; + } + + protected boolean requestFocusInWindow(boolean temporary) { + boolean ret = super.requestFocusInWindow(temporary); + System.err.println("requestFocusInWindow(" + temporary + ") on Button " + ret); + return ret; + } + }; + button.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent fe) { + System.out.println("Button receive focus"); + frame.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent fe) { + System.out.println("Frame receive focus"); + synchronized (sema) { + isFailed = false; + sema.notifyAll(); + } + } + }); + } + }); + container1.add(new JButton("empty button"), BorderLayout.WEST); + container1.add(button, BorderLayout.EAST); + frame.setBounds(0, 0, 300, 300); + frame.setVisible(true); + }); + + robot.delay(2000); + robot.waitForIdle(); + + EventQueue.invokeAndWait(() -> { + location = frame.getLocationOnScreen(); + insets = frame.getInsets(); + width = frame.getWidth(); + }); + + robot.mouseMove(location.x + width / 2, location.y + insets.top / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + DefaultKeyboardFocusManager manager = new DefaultFocusManager(); + robot.delay(1000); + EventQueue.invokeAndWait(button::requestFocus); + robot.delay(1000); + EventQueue.invokeAndWait(() -> { + manager.upFocusCycle(button); + }); + + try { + synchronized (sema) { + sema.wait(5000); + } + + if (isFailed) { + System.out.println("Test FAILED"); + throw new RuntimeException("Test FAILED"); + } else { + System.out.println("Test PASSED"); + } + } catch (InterruptedException ie) { + throw new RuntimeException("Test was interrupted"); + } + } catch (AWTException e) { + System.out.println("Problem creating Robot."); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + AsyncUpFocusCycleTest test = new AsyncUpFocusCycleTest(); + test.start(); + } +} diff --git a/test/jdk/java/awt/Focus/ClearMostRecentFocusOwnerTest.java b/test/jdk/java/awt/Focus/ClearMostRecentFocusOwnerTest.java new file mode 100644 index 00000000000..1c6ae11bf92 --- /dev/null +++ b/test/jdk/java/awt/Focus/ClearMostRecentFocusOwnerTest.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4525962 + @summary Opposite component calculated inaccurately + @key headful + @run main ClearMostRecentFocusOwnerTest +*/ + +import java.awt.AWTEvent; +import java.awt.AWTException; +import java.awt.Button; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Insets; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; + +import java.awt.event.AWTEventListener; +import java.awt.event.FocusEvent; +import java.awt.event.InputEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicBoolean; + +public class ClearMostRecentFocusOwnerTest implements AWTEventListener { + final static int ROBOT_DELAY = 50; + volatile Frame firstFrame; + volatile Frame secondFrame; + volatile Button actionButton; + volatile Button btnToRemove; + volatile Button btnToHide; + volatile Button btnToDisable; + volatile Button btnToNonFocusable; + volatile Panel pnlToHide; + volatile Button btnInPanel; + + Robot robot; + + volatile Component opposite = null; + volatile Component focusOwner = null; + volatile Object monitor = null; + + public void init() throws InterruptedException, + InvocationTargetException { + try { + robot = new Robot(); + } catch (AWTException e) { + throw new RuntimeException("Can not create awt-robot."); + } + EventQueue.invokeAndWait(() -> { + firstFrame = new Frame("The First Frame"); + firstFrame.setName("\"1st Frame\""); + secondFrame = new Frame("The Second Frame"); + secondFrame.setName("\"2nd Frame\""); + pnlToHide = new Panel(); + pnlToHide.setName("Panel"); + actionButton = new Button("Action Button"); + actionButton.setName("\"" + actionButton.getLabel() + "\""); + btnToRemove = new Button("To Remove"); + btnToRemove.setName("\"" + btnToRemove.getLabel() + "\""); + btnToHide = new Button("ToHide"); + btnToHide.setName("\"" + btnToHide.getLabel() + "\""); + btnToDisable = new Button("To Disable"); + btnToDisable.setName("\"" + btnToDisable.getLabel() + "\""); + btnToNonFocusable = new Button("To setFocusable(false)"); + btnToNonFocusable.setName("\"" + btnToNonFocusable.getLabel() + "\""); + btnInPanel = new Button("Int Panel"); + btnInPanel.setName("\"" + btnInPanel.getLabel() + "\""); + + firstFrame.add(actionButton); + + secondFrame.setLayout(new FlowLayout()); + secondFrame.add(btnToRemove); + secondFrame.add(btnToHide); + secondFrame.add(btnToDisable); + secondFrame.add(btnToNonFocusable); + secondFrame.add(pnlToHide); + pnlToHide.add(btnInPanel); + + firstFrame.pack(); + firstFrame.setVisible(true); + secondFrame.pack(); + secondFrame.setLocation(0, firstFrame.getHeight() + 50); + secondFrame.setVisible(true); + }); + } + + public void start() throws InterruptedException, InvocationTargetException { + try { + Toolkit.getDefaultToolkit(). + addAWTEventListener(this, + AWTEvent.FOCUS_EVENT_MASK); + + makeFocusOwner(btnToRemove); + EventQueue.invokeAndWait(() -> { + secondFrame.setVisible(false); + secondFrame.remove(btnToRemove); + }); + makeFocusOwner(actionButton); + opposite = null; + EventQueue.invokeAndWait(() -> { + secondFrame.setVisible(true); + }); + makeActiveFrame(secondFrame); + if (opposite != btnToHide) { + System.out.println("opposite = " + opposite); + throw new RuntimeException("Test FAILED: wrong opposite after Component.remove()."); + } + + makeFocusOwner(btnToHide); + EventQueue.invokeAndWait(() -> { + secondFrame.setVisible(false); + btnToHide.setVisible(false); + }); + makeFocusOwner(actionButton); + opposite = null; + EventQueue.invokeAndWait(() -> { + secondFrame.setVisible(true); + }); + makeActiveFrame(secondFrame); + if (opposite != btnToDisable) { + System.out.println("opposite = " + opposite); + throw new RuntimeException("Test FAILED: wrong opposite after Component.setVisible(false)."); + } + + makeFocusOwner(btnToDisable); + EventQueue.invokeAndWait(() -> { + secondFrame.setVisible(false); + btnToDisable.setEnabled(false); + }); + makeFocusOwner(actionButton); + opposite = null; + EventQueue.invokeAndWait(() -> { + secondFrame.setVisible(true); + }); + makeActiveFrame(secondFrame); + if (opposite != btnToNonFocusable) { + System.out.println("opposite = " + opposite); + throw new RuntimeException("Test FAILED: wrong opposite after Component.rsetEnabled(false)."); + } + + makeFocusOwner(btnToNonFocusable); + EventQueue.invokeAndWait(() -> { + secondFrame.setVisible(false); + btnToNonFocusable.setFocusable(false); + }); + makeFocusOwner(actionButton); + opposite = null; + EventQueue.invokeAndWait(() -> { + secondFrame.setVisible(true); + }); + makeActiveFrame(secondFrame); + if (opposite != btnInPanel) { + System.out.println("opposite = " + opposite); + throw new RuntimeException("Test FAILED: wrong opposite after Component.setFocusable(false)."); + } + + makeFocusOwner(btnInPanel); + EventQueue.invokeAndWait(() -> { + secondFrame.setVisible(false); + pnlToHide.setVisible(false); + }); + makeFocusOwner(actionButton); + opposite = null; + EventQueue.invokeAndWait(() -> { + secondFrame.setVisible(true); + }); + makeActiveFrame(secondFrame); + if (opposite == btnInPanel) { + System.out.println("opposite = " + opposite); + throw new RuntimeException("Test FAILED: wrong opposite after Container.setVisible(false)."); + } + } finally { + if (firstFrame != null) { + EventQueue.invokeAndWait(firstFrame::dispose); + } + if (secondFrame != null) { + EventQueue.invokeAndWait(secondFrame::dispose); + } + + } + } + + public void eventDispatched(AWTEvent event) { + switch (event.getID()) { + case FocusEvent.FOCUS_GAINED: + if (focusOwner == ((FocusEvent) event).getComponent() + && monitor != null) { + synchronized (monitor) { + monitor.notify(); + } + } + break; + case FocusEvent.FOCUS_LOST: + opposite = ((FocusEvent) event).getOppositeComponent(); + break; + } + System.out.println(event); + } + + void clickOnComponent(Component comp) throws InterruptedException, + InvocationTargetException { + System.err.println("clickOnComopnent " + comp.getName()); + robot.delay(3000); + int[] point = new int[2]; + EventQueue.invokeAndWait(() -> { + Point origin = comp.getLocationOnScreen(); + Dimension dim = comp.getSize(); + point[0] = origin.x + (int) dim.getWidth() / 2; + point[1] = origin.y + (int) dim.getHeight() / 2; + }); + robot.mouseMove(point[0], point[1]); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(ROBOT_DELAY); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } + + void makeFocusOwner(Component comp) throws InterruptedException, + InvocationTargetException { + AtomicBoolean isOwner = new AtomicBoolean(false); + EventQueue.invokeAndWait(() -> { + isOwner.set(comp.isFocusOwner()); + }); + if (!isOwner.get()) { + clickOnComponent(comp); + try { + EventQueue.invokeAndWait(() -> { + isOwner.set(comp.isFocusOwner()); + }); + if (!isOwner.get()) { + monitor = new Object(); + focusOwner = comp; + synchronized (monitor) { + monitor.wait(3000); + } + } + } catch (InterruptedException ie) { + throw new RuntimeException("Test was interrupted."); + } + } + EventQueue.invokeAndWait(() -> { + isOwner.set(comp.isFocusOwner()); + }); + if (!isOwner.get()) { + throw new RuntimeException("Test can not make " + + comp.getName() + " a focus owner."); + } + } + + void makeActiveFrame(Frame frame) throws InvocationTargetException, + InterruptedException { + robot.delay(3000); + if (!frame.isActive()) { + System.err.println("frame is not active"); + int[] point = new int[2]; + EventQueue.invokeAndWait(() -> { + Point origin = frame.getLocationOnScreen(); + Insets ins = frame.getInsets(); + point[0] = origin.x + frame.getWidth() / 2; + point[1] = origin.y + ins.top / 2; + }); + robot.mouseMove(point[0], point[1]); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(ROBOT_DELAY); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } + robot.delay(3000); + EventQueue.invokeAndWait(() -> { + if (!frame.isActive()) { + throw new RuntimeException("Test can not activate " + frame.getName() + "."); + } + }); + } + + public static void main(String[] args) throws InterruptedException, InvocationTargetException { + ClearMostRecentFocusOwnerTest test = new ClearMostRecentFocusOwnerTest(); + test.init(); + test.start(); + } +} diff --git a/test/jdk/java/awt/Focus/ConsumedTabKeyTest.java b/test/jdk/java/awt/Focus/ConsumedTabKeyTest.java new file mode 100644 index 00000000000..cbff8eadd97 --- /dev/null +++ b/test/jdk/java/awt/Focus/ConsumedTabKeyTest.java @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* +@test +@bug 4715649 +@summary Tests that KEY_TYPED event for Tab key arrives if Tab key is not focus traversal key +@key headful +@run main ConsumedTabKeyTest +*/ + +import java.awt.AWTEvent; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.Robot; +import java.awt.TextField; +import java.awt.Toolkit; +import java.awt.event.AWTEventListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.lang.reflect.InvocationTargetException; + +public class ConsumedTabKeyTest extends Panel { + TextField text; + Button button = new Button("none"); + Semaphore focusSema = new Semaphore(); + Semaphore releaseSema = new Semaphore(); + Semaphore buttonFocusSema = new Semaphore(); + Robot robot; + volatile boolean keyTyped; + volatile boolean hasFocus; + static Frame frame; + + public void init() { + this.setLayout(new FlowLayout()); + text = new TextField(); + + text.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + focusSema.raise(); + } + }); + button.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + buttonFocusSema.raise(); + } + }); + add(text); + add(button); + setSize(200, 200); + setVisible(true); + validate(); + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + public void eventDispatched(AWTEvent e) { + if (e.getID() == KeyEvent.KEY_RELEASED) { + releaseSema.raise(); + } + if (e.getID() == KeyEvent.KEY_TYPED) { + keyTyped = true; + } + } + }, InputEvent.KEY_EVENT_MASK); + try { + robot = new Robot(); + } catch (Exception re) { + throw new RuntimeException("Couldn't create Robot"); + } + } + + public void start() throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + if (!text.isFocusOwner()) { + text.requestFocus(); + } + + text.setFocusTraversalKeysEnabled(false); + }); + + try { + focusSema.doWait(1000); + } catch (InterruptedException ie1) { + throw new RuntimeException("Interrupted"); + } + + EventQueue.invokeAndWait(() -> { + hasFocus = text.isFocusOwner(); + }); + + if (!focusSema.getState() && !hasFocus) { + throw new RuntimeException("Text didn't receive focus"); + } + + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + try { + releaseSema.doWait(1000); + } catch (InterruptedException ie2) { + throw new RuntimeException("Interrupted"); + } + + if (!releaseSema.getState()) { + throw new RuntimeException("KEY_RELEASED hasn't arrived"); + } + + if (!keyTyped) { + throw new RuntimeException("KEY_TYPED for Tab key hasn't arrived"); + } + + EventQueue.invokeAndWait(() -> { + text.setFocusTraversalKeysEnabled(true); + }); + + releaseSema.setState(false); + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + try { + buttonFocusSema.doWait(1000); + releaseSema.doWait(1000); + } catch (InterruptedException ie2) { + throw new RuntimeException("Interrupted"); + } + + EventQueue.invokeAndWait(() -> { + hasFocus = button.isFocusOwner(); + }); + + if (!buttonFocusSema.getState() && !hasFocus) { + throw new RuntimeException("Button hasn't received focus"); + } + keyTyped = false; + releaseSema.setState(false); + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + try { + releaseSema.doWait(1000); + } catch (InterruptedException ie2) { + throw new RuntimeException("Interrupted"); + } + + if (!releaseSema.getState()) { + throw new RuntimeException("KEY_RELEASED hasn't arrived"); + } + if (!keyTyped) { + throw new RuntimeException("KEY_TYPED for A key hasn't arrived"); + } + System.err.println("PASSED"); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + ConsumedTabKeyTest test = new ConsumedTabKeyTest(); + + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame("InvocationTargetException"); + frame.setLayout(new BorderLayout()); + frame.add(test, BorderLayout.CENTER); + test.init(); + frame.setLocationRelativeTo(null); + frame.pack(); + frame.setVisible(true); + }); + test.start(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + } +} + +class Semaphore { + boolean state = false; + int waiting = 0; + + public void doWait(int timeout) throws InterruptedException { + synchronized (this) { + if (state) return; + waiting++; + wait(timeout); + waiting--; + } + } + + public void raise() { + synchronized (this) { + state = true; + if (waiting > 0) { + notifyAll(); + } + } + } + + public boolean getState() { + synchronized (this) { + return state; + } + } + + public void setState(boolean newState) { + synchronized (this) { + state = newState; + } + } +} diff --git a/test/jdk/java/awt/Focus/EventRetargetTest.java b/test/jdk/java/awt/Focus/EventRetargetTest.java new file mode 100644 index 00000000000..25862a2ef2f --- /dev/null +++ b/test/jdk/java/awt/Focus/EventRetargetTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4846162 4626092 + @summary (Key|Window|Focus)Events should not be retargeted when dispatchEvent() is called directly. + @run main EventRetargetTest +*/ + +import java.awt.AWTEvent; +import java.awt.Component; +import java.awt.Toolkit; +import java.awt.event.AWTEventListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +public class EventRetargetTest { + boolean isKEProcessed1; + boolean isKEProcessed2; + boolean isKEProcessed3; + boolean isFEProcessed1; + boolean isFEProcessed2; + boolean isFEProcessed3; + + public void start () { + final Component comp = new Component() { + public boolean isShowing() { + return true; + } + + public boolean isVisible() { + return true; + } + + public boolean isDisplayable() { + return true; + } + + protected void processKeyEvent(KeyEvent e) { + System.err.println("processKeyEvent >> " + e); + isKEProcessed1 = true; + super.processKeyEvent(e); + } + + protected void processFocusEvent(FocusEvent e) { + System.err.println("processFocusEvent >> " + e); + isFEProcessed1 = true; + super.processFocusEvent(e); + } + }; + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + public void eventDispatched(AWTEvent e) { + if (e instanceof KeyEvent) { + isKEProcessed2 = (e.getSource() == comp); + } + else if (e instanceof FocusEvent) { + isFEProcessed2 = (e.getSource() == comp); + } + System.err.println("Toolkit >> " + e); + } + }, AWTEvent.KEY_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK); + + comp.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent e) { + isKEProcessed3 = true; + System.err.println("Listener >> " + e); + } + }); + comp.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + isFEProcessed3 = true; + System.err.println("Listener >> " + e); + } + }); + + KeyEvent ke = new KeyEvent(comp, KeyEvent.KEY_TYPED, System.currentTimeMillis(), 0, + KeyEvent.VK_UNDEFINED, 'a'); + comp.dispatchEvent(ke); + + if (!(isKEProcessed1 && isKEProcessed2 && isKEProcessed3)) { + System.err.println("(" + isKEProcessed1 + "," + isKEProcessed2 + + "," + isKEProcessed3 + ")"); + throw new RuntimeException("KeyEvent is not correctly retargeted."); + } + + FocusEvent fe = new FocusEvent(comp, FocusEvent.FOCUS_GAINED, + false, null); + comp.dispatchEvent(fe); + + if (!(isFEProcessed1 && isFEProcessed2 && isFEProcessed3)) { + System.err.println("(" + isFEProcessed1 + "," + + isFEProcessed2 + "," + isFEProcessed3 + ")"); + throw new RuntimeException("FocusEvent is not correctly retargeted."); + } + } + + public static void main(String[] args) { + EventRetargetTest test = new EventRetargetTest(); + test.start(); + } +} diff --git a/test/jdk/java/awt/Focus/ExtraPropChangeNotifVetoingTest.java b/test/jdk/java/awt/Focus/ExtraPropChangeNotifVetoingTest.java new file mode 100644 index 00000000000..ef2ddbc5374 --- /dev/null +++ b/test/jdk/java/awt/Focus/ExtraPropChangeNotifVetoingTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 5072554 + @summary Tests that vetoing focus doesn't generate extra PropertyChange notification. + @key headful + @run main ExtraPropChangeNotifVetoingTest +*/ + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.KeyboardFocusManager; +import java.awt.Panel; +import java.awt.Robot; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyVetoException; +import java.beans.VetoableChangeListener; +import java.lang.reflect.InvocationTargetException; + +public class ExtraPropChangeNotifVetoingTest extends Panel { + Button one = new Button("One"); + Button two = new Button("Two"); + Robot robot; + static Frame frame; + + int i = 0; + + public void init() { + try { + robot = new Robot(); + } catch (AWTException e) { + throw new RuntimeException("Error: unable to create robot", e); + } + + setLayout(new FlowLayout()); + add(one); + add(two); + + KeyboardFocusManager.getCurrentKeyboardFocusManager(). + addVetoableChangeListener("permanentFocusOwner", + new VetoableChangeListener() { + public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException { + System.out.println((i++) + ". Old=" + e.getOldValue() + ", New=" + e.getNewValue()); + + if (e.getOldValue() == e.getNewValue()) { + throw new RuntimeException("Test failed!"); + } + + if (e.getNewValue() == two) { + System.out.println("VETOING"); + throw new PropertyVetoException("vetoed", e); + } + } + }); + setVisible(true); + } + + public void start() throws InterruptedException, InvocationTargetException { + EventQueue.invokeAndWait(one::requestFocusInWindow); + robot.waitForIdle(); + robot.delay(200); + EventQueue.invokeAndWait(two::requestFocusInWindow); + robot.waitForIdle(); + robot.delay(200); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + ExtraPropChangeNotifVetoingTest test = new ExtraPropChangeNotifVetoingTest(); + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame("ExtraPropChangeNotifVetoingTest"); + frame.setLayout(new BorderLayout()); + frame.add(test, BorderLayout.CENTER); + test.init(); + frame.setLocationRelativeTo(null); + frame.pack(); + frame.setVisible(true); + }); + test.start(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + } +} diff --git a/test/jdk/java/awt/Focus/FocusForRemovedComponentTest.java b/test/jdk/java/awt/Focus/FocusForRemovedComponentTest.java new file mode 100644 index 00000000000..c53db9c20d6 --- /dev/null +++ b/test/jdk/java/awt/Focus/FocusForRemovedComponentTest.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4722671 + @summary Accessibility problem in JRE Finder + @key headful + @run main FocusForRemovedComponentTest +*/ + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.InputEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicBoolean; + +public class FocusForRemovedComponentTest + implements ActionListener { + static int ACTIVATION_TIMEOUT = 2000; + static long WAIT_TIMEOUT = 3000; + volatile Frame frame; + volatile Button btnFirst; + volatile Button btnSecond; + volatile Button btnThird; + + public void start() throws InterruptedException, InvocationTargetException { + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame("FocusForRemovedComponentTest"); + btnFirst = new Button("First Button"); + btnSecond = new Button("Second Button"); + btnThird = new Button("Third Button"); + frame.add(btnFirst, BorderLayout.NORTH); + frame.add(btnSecond, BorderLayout.CENTER); + btnFirst.addActionListener(this); + btnFirst.requestFocusInWindow(); + frame.pack(); + frame.setVisible(true); + }); + + try { + Robot robot = new Robot(); + robot.delay(ACTIVATION_TIMEOUT); + int[] location = new int[2]; + EventQueue.invokeAndWait(() -> { + Point button_location = btnFirst.getLocationOnScreen(); + Dimension button_size = btnFirst.getSize(); + location[0] = button_location.x + button_size.width / 2; + location[1] = button_location.y + button_size.height / 2; + }); + robot.mouseMove(location[0], location[1]); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + Object monitor = new Object(); + final MonitoredFocusListener monitorer = new MonitoredFocusListener(monitor); + AtomicBoolean isFocused = new AtomicBoolean(false); + synchronized (monitor) { + EventQueue.invokeAndWait(() -> { + btnThird.addFocusListener(monitorer); + isFocused.set(btnThird.isFocusOwner()); + }); + + if (!isFocused.get()) { + monitor.wait(WAIT_TIMEOUT); + EventQueue.invokeAndWait(() -> { + isFocused.set(btnThird.isFocusOwner()); + }); + } + } + + if (!isFocused.get()) { + throw new RuntimeException("TEST FAILED. The third button is not focus owner."); + } else { + System.out.println("TEST PASSED."); + } + } catch (AWTException e) { + e.printStackTrace(); + throw new RuntimeException("Some AWTException occurred."); + } catch (InterruptedException e) { + e.printStackTrace(); + throw new RuntimeException("Test was interrupted."); + } + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + } + + public void actionPerformed(ActionEvent e) { + if (btnSecond.isVisible()) { + btnFirst.setEnabled(false); + frame.remove(btnSecond); + frame.add(btnThird, BorderLayout.CENTER); + btnThird.requestFocusInWindow(); + btnFirst.setEnabled(true); + frame.validate(); + frame.repaint(); + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + FocusForRemovedComponentTest test = new FocusForRemovedComponentTest(); + test.start(); + } +} + +class MonitoredFocusListener extends FocusAdapter { + Object monitor; + + public MonitoredFocusListener(Object monitor) { + this.monitor = monitor; + } + + public void focusGained(FocusEvent fe) { + synchronized (monitor) { + monitor.notify(); + } + } +} diff --git a/test/jdk/java/awt/Focus/FocusTraversalPolicyIAE.java b/test/jdk/java/awt/Focus/FocusTraversalPolicyIAE.java new file mode 100644 index 00000000000..c48fe83d817 --- /dev/null +++ b/test/jdk/java/awt/Focus/FocusTraversalPolicyIAE.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6225100 + @summary FocusTraversalPolicy.getInitialComponent does not work as expected + @run main FocusTraversalPolicyIAE +*/ + +import java.awt.Component; +import java.awt.Container; +import java.awt.FocusTraversalPolicy; + +public class FocusTraversalPolicyIAE { + public static void main(String[] args) { + CustomFocusTraversalPolicy cftp = new CustomFocusTraversalPolicy(); + try { + cftp.getInitialComponent(null); + throw new RuntimeException("Test failed. No exceptions thrown."); + } catch (IllegalArgumentException iae) { + System.out.println("Test passed."); + } catch (NullPointerException npe) { + throw new RuntimeException("Test failed. Unexpected NPE thrown: " + npe); + } catch (Exception e) { + throw new RuntimeException("Test failed. Unexpected exception thrown: " + e); + } + } +} + +class CustomFocusTraversalPolicy extends FocusTraversalPolicy { + public Component getComponentAfter(Container focusCycleRoot, + Component aComponent) { + return null; + } + + public Component getComponentBefore(Container focusCycleRoot, + Component aComponent) { + return null; + } + + public Component getDefaultComponent(Container focusCycleRoot) { + return null; + } + + public Component getFirstComponent(Container focusCycleRoot) { + return null; + } + + public Component getLastComponent(Container focusCycleRoot) { + return null; + } +} diff --git a/test/jdk/java/awt/Focus/InitialFocusTest.java b/test/jdk/java/awt/Focus/InitialFocusTest.java new file mode 100644 index 00000000000..489cdd7c7f1 --- /dev/null +++ b/test/jdk/java/awt/Focus/InitialFocusTest.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4150021 + @summary if user requests focus on some component, it must become a focus owner after activation + @key headful + @run main InitialFocusTest +*/ + +import java.awt.AWTException; +import java.awt.Button; +import java.awt.DefaultKeyboardFocusManager; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicBoolean; + +public class InitialFocusTest implements PropertyChangeListener { + //Declare things used in the test, like buttons and labels here + final static String FOCUSED_WINDOW_PROP = "focusedWindow"; + final static int ACTION_TIMEOUT = 2000; + + volatile Frame frame; + volatile Button btn1; + volatile Button btn2; + + public void start() throws InterruptedException, InvocationTargetException { + DefaultKeyboardFocusManager.getCurrentKeyboardFocusManager(). + addPropertyChangeListener(FOCUSED_WINDOW_PROP, this); + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame("InitialFocusTest"); + frame.setLayout(new FlowLayout()); + btn1 = new Button("First Button"); + frame.add(btn1); + btn2 = new Button("Second Button"); + frame.add(btn2); + frame.setLocationRelativeTo(null); + frame.pack(); + frame.setVisible(true); + }); + try { + Robot robot = new Robot(); + robot.delay(ACTION_TIMEOUT); + if (!activateFrame(frame, robot, ACTION_TIMEOUT)) { + throw new RuntimeException("Frame was not activated."); + } + robot.delay(ACTION_TIMEOUT); + AtomicBoolean isFocused = new AtomicBoolean(false); + EventQueue.invokeAndWait(() -> { + isFocused.set(frame.isFocused()); + }); + if (!isFocused.get()) { + throw new RuntimeException("Frame didn't become focused."); + } + EventQueue.invokeAndWait(() -> { + isFocused.set(btn2.isFocusOwner()); + }); + if (!isFocused.get()) { + throw new RuntimeException("Btn2 didn't receive focus."); + } + } catch (AWTException e) { + e.printStackTrace(); + } + System.out.printf("Test passed."); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + } + + public void propertyChange(PropertyChangeEvent pce) { + if (FOCUSED_WINDOW_PROP.equals(pce.getPropertyName())) { + if (pce.getNewValue() == frame) { + System.out.println("requesting focus on btn2"); + btn2.requestFocusInWindow(); + } + } + } + + boolean activateFrame(Frame frame, Robot robot, int timeout) + throws InterruptedException, InvocationTargetException { + AtomicBoolean isActive = new AtomicBoolean(false); + EventQueue.invokeAndWait(() -> { + isActive.set(frame.isActive()); + }); + if (!isActive.get()) { + int[] point = new int[2]; + EventQueue.invokeAndWait(() -> { + Point origin = frame.getLocationOnScreen(); + Dimension dim = frame.getSize(); + Insets insets = frame.getInsets(); + point[0] = origin.x + dim.width / 2; + point[1] = origin.y + insets.top / 2; + }); + robot.mouseMove(point[0], point[1]); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(timeout); + EventQueue.invokeAndWait(() -> { + isActive.set(frame.isActive()); + }); + } + return frame.isActive(); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + InitialFocusTest test = new InitialFocusTest(); + test.start(); + } +} diff --git a/test/jdk/java/awt/Focus/LabelScrollBarFocus.java b/test/jdk/java/awt/Focus/LabelScrollBarFocus.java new file mode 100644 index 00000000000..c69d9406ea9 --- /dev/null +++ b/test/jdk/java/awt/Focus/LabelScrollBarFocus.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4027897 + @summary Test that Label can't be made focused by the mouse, while ScrollBar should become focused. + @key headful + @run main LabelScrollBarFocus +*/ + +import java.awt.BorderLayout; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Scrollbar; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.InputEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicBoolean; + +public class LabelScrollBarFocus extends Panel { + static final Semaphore sema = new Semaphore(); + Label lab; + Scrollbar scr; + static Frame frame; + + public void init() { + this.setLayout(new FlowLayout()); + FocusAdapter fa = new FocusAdapter() { + public void focusGained(FocusEvent e) { + sema.raise(); + } + }; + + lab = new Label("Label"); + scr = new Scrollbar(Scrollbar.HORIZONTAL); + lab.addFocusListener(fa); + scr.addFocusListener(fa); + add(lab); + add(scr); + setSize(200, 200); + validate(); + setVisible(true); + } + + public void start() throws InterruptedException, + InvocationTargetException { + Robot robot = null; + try { + robot = new Robot(); + } catch (Exception e) { + throw new RuntimeException("Can't create robot instance"); + } + int[] point = new int[2]; + EventQueue.invokeAndWait(() -> { + Point labLoc = lab.getLocationOnScreen(); + point[0] = labLoc.x + 5; + point[1] = labLoc.y + 5; + }); + robot.mouseMove(point[0], point[1]); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(1000); + robot.waitForIdle(); + try { + sema.doWait(2000); + } catch (InterruptedException ie) { + throw new RuntimeException("Interrupted"); + } + + AtomicBoolean isFocusOwner = new AtomicBoolean(false); + EventQueue.invokeAndWait(() -> { + isFocusOwner.set(lab.isFocusOwner()); + }); + if (isFocusOwner.get()) { + throw new RuntimeException("Label is focused"); + } + + EventQueue.invokeAndWait(() -> { + Point scrLoc = scr.getLocationOnScreen(); + point[0] = scrLoc.x + 20; + point[1] = scrLoc.y + 5; + }); + robot.mouseMove(point[0], point[1]); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(1000); + robot.waitForIdle(); + try { + sema.doWait(2000); + } catch (InterruptedException ie) { + throw new RuntimeException("Interrupted"); + } + + EventQueue.invokeAndWait(() -> { + isFocusOwner.set(scr.isFocusOwner()); + }); + if (!isFocusOwner.get()) { + throw new RuntimeException("Scroll bar is not focused"); + } + System.out.println("Test passed"); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + try { + LabelScrollBarFocus test = new LabelScrollBarFocus(); + EventQueue.invokeAndWait(() -> { + frame = new Frame("LabelScrollBarFocus"); + test.init(); + frame.setLayout(new BorderLayout()); + frame.add(test, BorderLayout.CENTER); + frame.setLocationRelativeTo(null); + frame.pack(); + frame.setVisible(true); + }); + test.start(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + } +} + +class Semaphore { + boolean state = false; + Object lock = new Object(); + int waiting = 0; + + public Semaphore() { + } + + public void doWait(int timeout) throws InterruptedException { + synchronized (lock) { + waiting++; + synchronized (this) { + wait(timeout); + } + waiting--; + } + } + + public void raise() { + synchronized (lock) { + state = true; + if (waiting > 0) { + synchronized (this) { + notifyAll(); + } + } + } + } +} diff --git a/test/jdk/java/awt/Focus/ModalDialogInFocusEventTest.java b/test/jdk/java/awt/Focus/ModalDialogInFocusEventTest.java new file mode 100644 index 00000000000..d4f0d65f071 --- /dev/null +++ b/test/jdk/java/awt/Focus/ModalDialogInFocusEventTest.java @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + test + @bug 4531693 4636269 4681908 4688142 4691646 4721470 + @summary Showing modal dialog during dispatching SequencedEvent + @key headful + @run main AutomaticAppletTest +*/ + +import java.awt.AWTEvent; +import java.awt.AWTException; +import java.awt.Button; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.InputEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.awt.event.WindowListener; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicBoolean; + +public class ModalDialogInFocusEventTest + implements ActionListener, Runnable, WindowListener, + WindowFocusListener, FocusListener { + static final int CLICK_DELAY = 50; + static final int ACTIVATION_TIMEOUT = 2000; + static final long STAGE_TIMEOUT = 3 * ACTIVATION_TIMEOUT; + static final StageInfo[] stages = { + new StageInfo(WindowEvent.WINDOW_ACTIVATED, "Window Activated", false), + new StageInfo(WindowEvent.WINDOW_GAINED_FOCUS, "Window Gained Focus", false), + new StageInfo(FocusEvent.FOCUS_GAINED, "Focus Gained", false), + new StageInfo(FocusEvent.FOCUS_LOST, "Focus Lost", true), + new StageInfo(WindowEvent.WINDOW_LOST_FOCUS, "Window Lost Focus", true), + new StageInfo(WindowEvent.WINDOW_DEACTIVATED, "Window Deactivated", true) + }; + static final int MAX_STAGE_NUM = stages.length; + static final Object stageMonitor = new Object(); + + Robot robot = null; + Frame frame; + Frame oppositeFrame; + Dialog dialog; + Button closeButton; + int nStage = MAX_STAGE_NUM; + + public void start() throws InterruptedException, InvocationTargetException { + try { + FocusListener focusEventTracker = new FocusListener() { + public void focusGained(FocusEvent e) { + System.out.println(e); + } + + public void focusLost(FocusEvent e) { + System.out.println(e); + } + }; + + WindowAdapter windowEventTracker = new WindowAdapter() { + public void windowActivated(WindowEvent e) { + System.out.println(e); + } + + public void windowDeactivated(WindowEvent e) { + System.out.println(e); + } + + public void windowGainedFocus(WindowEvent e) { + System.out.println(e); + } + + public void windowLostFocus(WindowEvent e) { + System.out.println(e); + } + }; + EventQueue.invokeAndWait(() -> { + frame = new Frame("ModalDialogInFocusEventTest Main Frame"); + oppositeFrame = new Frame("ModalDialogInFocusEventTest Opposite Frame"); + dialog = new Dialog(frame, "ModalDialogInFocusEventTest Modal Dialog", true); + closeButton = new Button("Close Button"); + closeButton.addActionListener(this); + dialog.add(closeButton); + dialog.setBounds(10, 200, 300, 100); + + dialog.addFocusListener(focusEventTracker); + dialog.addWindowListener(windowEventTracker); + dialog.addWindowFocusListener(windowEventTracker); + oppositeFrame.addFocusListener(focusEventTracker); + oppositeFrame.addWindowListener(windowEventTracker); + oppositeFrame.addWindowFocusListener(windowEventTracker); + + frame.setName("ModalDialogInFocusEventTest MainFrame"); + frame.addFocusListener(this); + frame.addWindowListener(this); + frame.addWindowFocusListener(this); + frame.setSize(300, 100); + + oppositeFrame.setName("ModalDialogInFocusEventTest OppositeName"); + oppositeFrame.setBounds(350, 200, 300, 100); + }); + + + try { + robot = new Robot(); + robot.setAutoDelay(CLICK_DELAY); + + for (int i = 0; i < MAX_STAGE_NUM; i++) { + StageInfo stage = stages[i]; + if (stage.shouldActivateOpposite()) { + EventQueue.invokeAndWait(() -> { + oppositeFrame.setVisible(true); + frame.setVisible(true); + }); + robot.delay(ACTIVATION_TIMEOUT); + AtomicBoolean isActive = new AtomicBoolean(false); + EventQueue.invokeAndWait(() -> { + isActive.set(frame.isActive()); + }); + if (!isActive.get()) { + clickOnFrameTitle(frame); + robot.delay(ACTIVATION_TIMEOUT); + } + } else { + EventQueue.invokeAndWait(() -> { + frame.setVisible(true); + oppositeFrame.setVisible(true); + }); + robot.delay(ACTIVATION_TIMEOUT); + AtomicBoolean isActive = new AtomicBoolean(false); + EventQueue.invokeAndWait(() -> { + isActive.set(oppositeFrame.isActive()); + }); + if (!isActive.get()) { + clickOnFrameTitle(oppositeFrame); + robot.delay(ACTIVATION_TIMEOUT); + } + } + + nStage = i; + System.out.println("Stage " + i + " started."); + + synchronized (stageMonitor) { + if (stage.shouldActivateOpposite()) { + clickOnFrameTitle(oppositeFrame); + } else { + clickOnFrameTitle(frame); + } + stageMonitor.wait(STAGE_TIMEOUT); + if (!stage.isFinished()) { + throw new RuntimeException(stages[nStage].toString()); + } + } + EventQueue.invokeAndWait(() -> { + oppositeFrame.setVisible(false); + frame.setVisible(false); + }); + robot.delay(ACTIVATION_TIMEOUT); + } + } catch (AWTException e) { + throw new RuntimeException("Some AWT-Robot problem occurred", e); + } catch (InterruptedException ie) { + ie.printStackTrace(); + throw new RuntimeException("Test was interrupted"); + } + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + if (oppositeFrame != null) { + EventQueue.invokeAndWait(oppositeFrame::dispose); + } + if (dialog != null) { + EventQueue.invokeAndWait(dialog::dispose); + } + } + System.out.println("Test passed."); + } + + void clickOnFrameTitle(Frame frame) throws InterruptedException, + InvocationTargetException { + System.out.println("click on title of " + frame.getName()); + int[] point = new int[2]; + EventQueue.invokeAndWait(() -> { + Point location = frame.getLocationOnScreen(); + Insets insets = frame.getInsets(); + int width = frame.getWidth(); + point[0] = location.x + width / 2; + point[1] = location.y + insets.top / 2; + }); + robot.mouseMove(point[0], point[1]); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + EventQueue.invokeAndWait(frame::requestFocusInWindow); + } + + void openAndCloseModalDialog() throws InterruptedException, + InvocationTargetException { + (new Thread(this)).start(); + dialog.setVisible(true); + } + + void performStage(AWTEvent e) throws InterruptedException, + InvocationTargetException { + if (nStage < MAX_STAGE_NUM && + e.getID() == stages[nStage].getEventID() && + !stages[nStage].isStarted()) { + stages[nStage].start(); + openAndCloseModalDialog(); + stages[nStage].finish(); + synchronized (stageMonitor) { + stageMonitor.notifyAll(); + } + } + } + + public void actionPerformed(ActionEvent ae) { + System.out.println(ae); + dialog.setVisible(false); + } + + public void run() { + try { + Thread.sleep(ACTIVATION_TIMEOUT); + int[] point = new int[2]; + EventQueue.invokeAndWait(() -> { + Point location = closeButton.getLocationOnScreen(); + Dimension dim = closeButton.getSize(); + point[0] = location.x + dim.width / 2; + point[1] = location.y + dim.height / 2; + }); + robot.mouseMove(point[0], point[1]); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + System.out.println("click"); + } catch (InterruptedException | InvocationTargetException ie) { + throw new RuntimeException("Test was interrupted", ie); + } + } + + public void windowOpened(WindowEvent e) { + /* Empty. Unneeded for this test */ + } + + public void windowClosing(WindowEvent e) { + /* Empty. Unneeded for this test */ + } + + public void windowClosed(WindowEvent e) { + /* Empty. Unneeded for this test */ + } + + public void windowIconified(WindowEvent e) { + /* Empty. Unneeded for this test */ + } + + public void windowDeiconified(WindowEvent e) { + /* Empty. Unneeded for this test */ + } + + public void windowActivated(WindowEvent e) { + System.out.println(e); + try { + performStage(e); + } catch (InterruptedException | InvocationTargetException ex) { + throw new RuntimeException(ex); + } + } + + public void windowDeactivated(WindowEvent e) { + System.out.println(e); + try { + performStage(e); + } catch (InterruptedException | InvocationTargetException ex) { + throw new RuntimeException(ex); + } + } + + public void windowGainedFocus(WindowEvent e) { + System.out.println(e); + try { + performStage(e); + } catch (InterruptedException | InvocationTargetException ex) { + throw new RuntimeException(ex); + } + } + + public void windowLostFocus(WindowEvent e) { + System.out.println(e); + try { + performStage(e); + } catch (InterruptedException | InvocationTargetException ex) { + throw new RuntimeException(ex); + } + } + + public void focusGained(FocusEvent e) { + System.out.println(e); + try { + performStage(e); + } catch (InterruptedException | InvocationTargetException ex) { + throw new RuntimeException(ex); + } + } + + public void focusLost(FocusEvent e) { + System.out.println(e); + try { + performStage(e); + } catch (InterruptedException | InvocationTargetException ex) { + throw new RuntimeException(ex); + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + ModalDialogInFocusEventTest test = new ModalDialogInFocusEventTest(); + test.start(); + } +} + +class StageInfo { + private String name; + private int eventID; + private boolean started = false; + private boolean finished = false; + + /* + * whether we should activate opposite frame during this stage. + * Note: we need to activate "another" frame BEFORE stage + * i.e. if we should activate frame during stage then we + * need to activate oppositeFrame before it and vice versa. + */ + private boolean activateOpposite; + + StageInfo(int eventID, String name, boolean activateOpposite) { + this.eventID = eventID; + this.name = name; + this.activateOpposite = activateOpposite; + } + + public String toString() { + String str = "Stage [\"" + name + "\""; + if (!started) { + str += " not"; + } + str += " started, "; + if (!finished) { + str += " not"; + } + str += " finished"; + if (activateOpposite) { + str += ", activate opposite"; + } + str += "]"; + return str; + } + + int getEventID() { + return eventID; + } + + boolean isStarted() { + return started; + } + + void start() { + started = true; + System.out.println(this.toString()); + } + + boolean isFinished() { + return finished; + } + + void finish() { + finished = true; + System.out.println(this.toString()); + } + + boolean shouldActivateOpposite() { + return activateOpposite; + } +} diff --git a/test/jdk/java/awt/ScrollPane/ComponentScrollTest.java b/test/jdk/java/awt/ScrollPane/ComponentScrollTest.java new file mode 100644 index 00000000000..3a3a514fe4e --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ComponentScrollTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + @test + @bug 4342129 + @summary Unable to scroll in scrollpane for canvas + @key headful +*/ + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.ScrollPane; + +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; + +public class ComponentScrollTest { + public ScrollPane scrollpane; + public Frame frame; + public volatile int count = 0; + + public static void main(String[] args) throws Exception { + ComponentScrollTest cst = new ComponentScrollTest(); + cst.init(); + cst.start(); + } + + public void init() throws Exception { + EventQueue.invokeAndWait(() -> { + scrollpane = new ScrollPane(); + frame = new Frame("Component Scroll Test"); + scrollpane.add(new Component() { + public Dimension getPreferredSize() { + return new Dimension(500, 500); + } + + public void paint(Graphics g) { + g.drawLine(0, 0, 500, 500); + } + }); + frame.add(scrollpane); + scrollpane.getVAdjustable().addAdjustmentListener(new AdjustmentListener() { + @Override + public void adjustmentValueChanged(AdjustmentEvent adjustmentEvent) { + count++; + scrollpane.getVAdjustable().setValue(20); + } + }); + frame.pack(); + frame.setVisible(true); + }); + } + + public void start() throws Exception { + try { + EventQueue.invokeAndWait(() -> { + scrollpane.getVAdjustable().setValue(20); + }); + + Thread.sleep(1000); + + System.out.println("Count = " + count); + if (count > 50) { + throw new RuntimeException(); + } + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneExtraScrollBar.java b/test/jdk/java/awt/ScrollPane/ScrollPaneExtraScrollBar.java new file mode 100644 index 00000000000..3a4f2fb5c91 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneExtraScrollBar.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4152524 8310054 + @requires os.family=="windows" + @summary Test that scroll pane doesn't have scroll bars visible when it is + shown for the first time with SCROLLBARS_AS_NEEDED style + @key headful +*/ + +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.ScrollPane; + +import java.awt.event.InputEvent; + +public class ScrollPaneExtraScrollBar { + ScrollPane sp; + Frame f; + volatile Rectangle r; + + public static void main(String[] args) throws Exception { + ScrollPaneExtraScrollBar scrollTest = new ScrollPaneExtraScrollBar(); + scrollTest.init(); + scrollTest.start(); + } + + public void init() throws Exception { + EventQueue.invokeAndWait(() -> { + f = new Frame("ScrollPaneExtraScrollBar"); + sp = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); + sp.add(new Button("TEST")); + f.add("Center", sp); + // Frame must not be packed, otherwise the bug isn't reproduced + f.setLocationRelativeTo(null); + f.setVisible(true); + }); + } + + public void start() throws Exception { + try { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(100); + EventQueue.invokeAndWait(() -> { + r = f.getBounds(); + }); + robot.mouseMove(r.x + r.width - 1, r.y + r.height - 1); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseMove(r.x + r.width + 50, r.y + r.height + 50); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.waitForIdle(); + robot.delay(1000); + + EventQueue.invokeAndWait(() -> { + Insets insets = sp.getInsets(); + if (insets.left != insets.right || insets.top != insets.bottom) { + throw new RuntimeException("ScrollPane has scroll bars visible" + + " when it shouldn't"); + } + }); + } finally { + EventQueue.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneLeakTest.java b/test/jdk/java/awt/ScrollPane/ScrollPaneLeakTest.java new file mode 100644 index 00000000000..19b817d595a --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneLeakTest.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.AWTException; +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.ScrollPane; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicReference; + +import static java.awt.EventQueue.invokeAndWait; + +/* + * @test + * @bug 8297923 + * @key headful + * @requires os.family=="windows" + * @summary Verifies no GDI objects are leaked after scrolling continuously + * @run main/othervm -Dsun.java2d.d3d=false ScrollPaneLeakTest + */ +public class ScrollPaneLeakTest { + + /** + * The number of times the test repeats scrolling cycles. + */ + private static final int REPEATS = 1; + + /** + * The number of times the robot moves the scroll bar thumb down and up + * per one cycle. + */ + private static final int UP_DOWN_CYCLES = 20; + + private static final Color CANVAS_FOREGROUND = new Color(200, 240, 200); + private static final Color CANVAS_BACKGROUND = new Color(240, 200, 240); + private static final Color SCROLL_PANE_BACKGROUND = new Color(240, 240, 200); + + private static final Dimension CANVAS_SIZE = new Dimension(400, 600); + private static final Dimension FRAME_SIZE = new Dimension(CANVAS_SIZE.width * 2, + 3 * CANVAS_SIZE.height / 4); + private static final Dimension SCROLL_PANE_SIZE = new Dimension(CANVAS_SIZE.width, + CANVAS_SIZE.height / 2); + + private static Frame frame; + private static ScrollPane scroll; + + private static final AtomicReference frameBounds = new AtomicReference<>(); + + private static final AtomicReference scrollBounds = new AtomicReference<>(); + + private static final AtomicReference vertBarWidth = new AtomicReference<>(); + private static final AtomicReference horzBarHeight = new AtomicReference<>(); + + public static void main(String[] args) + throws InterruptedException, InvocationTargetException, AWTException { + try { + invokeAndWait(ScrollPaneLeakTest::createUI); + + final Robot robot = new Robot(); + robot.waitForIdle(); + + invokeAndWait(() -> frame.setExtendedState(frame.getExtendedState() + | Frame.MAXIMIZED_BOTH)); + robot.waitForIdle(); + + invokeAndWait(() -> { + scrollBounds.set(new Rectangle(scroll.getLocationOnScreen(), + scroll.getSize())); + + vertBarWidth.set(scroll.getVScrollbarWidth()); + horzBarHeight.set(scroll.getHScrollbarHeight()); + }); + robot.waitForIdle(); + + invokeAndWait(() -> scroll.setScrollPosition(0, 0)); + robot.waitForIdle(); + robot.delay(1000); + + final Rectangle sb = scrollBounds.get(); + final int vbar = vertBarWidth.get(); + final int hbar = horzBarHeight.get() * 2; + + final Point pos = new Point(); + for (int no = 0; no < REPEATS; no++) { + pos.x = sb.x + sb.width - vbar / 3; + pos.y = sb.y + hbar; + + robot.mouseMove(pos.x, pos.y); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + for (int i = 0; i < UP_DOWN_CYCLES; i++) { + while (++pos.y < sb.y + sb.height - hbar) { + robot.mouseMove(pos.x, pos.y); + robot.delay(5); + } + while (--pos.y > sb.y + hbar) { + robot.mouseMove(pos.x, pos.y); + robot.delay(5); + } + } + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + + invokeAndWait(() -> frame.setExtendedState(frame.getExtendedState() + | Frame.ICONIFIED)); + robot.delay(500); + invokeAndWait(() -> frame.setExtendedState(frame.getExtendedState() + & ~Frame.ICONIFIED)); + robot.delay(500); + } + + invokeAndWait(() -> scroll.setScrollPosition(0, sb.height / 2)); + + invokeAndWait(() -> { + Rectangle bounds = frame.getBounds(); + frameBounds.set(bounds); + }); + + // Throws OutOfMemoryError when the test fails + robot.createScreenCapture(frameBounds.get()); + + System.out.println("Robot created a screenshot: test passed"); + } finally { + invokeAndWait(frame::dispose); + } + } + + private static void createUI() { + frame = new Frame("Scroll Pane Leak Test"); + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + frame.setLayout(new FlowLayout(FlowLayout.CENTER)); + frame.setLocation(0, 0); + + Canvas canvas = new Canvas() { + @Override + public void paint(Graphics g) { + g.setColor(CANVAS_FOREGROUND); + g.fillRect(0, 0, getWidth(), getHeight()); + } + }; + canvas.setBackground(CANVAS_BACKGROUND); + canvas.setSize(CANVAS_SIZE); + + scroll = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); + scroll.add(canvas); + scroll.setSize(SCROLL_PANE_SIZE); + scroll.setBackground(SCROLL_PANE_BACKGROUND); + + frame.add(scroll); + frame.setSize(FRAME_SIZE); + + frame.setVisible(true); + } + +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneLimitation.java b/test/jdk/java/awt/ScrollPane/ScrollPaneLimitation.java new file mode 100644 index 00000000000..52842ed617f --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneLimitation.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4046446 + @requires os.family=="windows" + @summary Tests 16-bit limitations of scroll pane, child's position and size + and mouse coordinates + @key headful +*/ + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.ScrollPane; + +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseAdapter; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class ScrollPaneLimitation { + static final int SCROLL_POS = 50000; + public static Component child = null; + static final CountDownLatch go = new CountDownLatch(1); + public Frame frame; + volatile Point point; + ScrollPane pane; + + public static void main(String[] args) throws Exception { + ScrollPaneLimitation scrollTest = new ScrollPaneLimitation(); + scrollTest.init(); + scrollTest.start(); + } + + public void init() throws Exception { + EventQueue.invokeAndWait(() -> { + frame = new Frame("Scroll Pane Limitation"); + frame.setLayout(new BorderLayout()); + pane = new ScrollPane(); + frame.add(pane); + child = new MyPanel(); + child.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + if (e.getID() == MouseEvent.MOUSE_PRESSED + && e.getSource() == ScrollPaneLimitation.child + && e.getY() > SCROLL_POS) { + go.countDown(); + } + } + }); + pane.add(child); + frame.setSize(200, 200); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setAlwaysOnTop(true); + frame.setVisible(true); + pane.doLayout(); + }); + } + + public void start() throws Exception { + try { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + + EventQueue.invokeAndWait(() -> { + Point p = child.getLocation(); + System.out.println("Child's initial location " + p); + System.out.println("Pane's insets " + pane.getInsets()); + pane.setScrollPosition(0, SCROLL_POS); + p = pane.getScrollPosition(); + System.out.println("Scroll pos = " + p); + if (p.y != SCROLL_POS) { + throw new RuntimeException("wrong scroll position"); + } + p = child.getLocation(); + System.out.println("Child pos = " + p); + if (p.y != -SCROLL_POS) { + if (child.isLightweight()) { + // If it is lightweight it will always have (0, 0) location. + // Check location of its parent - it is Panel and it should + // be at (inset left, inset top + position) + Container cp = child.getParent(); + p = cp.getLocation(); + System.out.println("Child's parent pos = " + p); + if (p.y != -SCROLL_POS) { + throw new RuntimeException("wrong child location"); + } + } else { + throw new RuntimeException("wrong child location"); + } + } + + p = pane.getLocationOnScreen(); + Dimension d = pane.getSize(); + point = new Point(p.x + d.width / 2, p.y + d.height / 2); + }); + robot.mouseMove(point.x, point.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + if (!go.await(3, TimeUnit.SECONDS)) { + throw new RuntimeException("mouse was not pressed"); + } + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static class MyPanel extends Component { + public Dimension getPreferredSize() { + return new Dimension(100, 100000); + } + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneRemoveAdd.java b/test/jdk/java/awt/ScrollPane/ScrollPaneRemoveAdd.java new file mode 100644 index 00000000000..0a7a0164b15 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneRemoveAdd.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4100671 + @summary Tests that after removing/adding a component can be still access. + @key headful +*/ + +import java.awt.Button; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.ScrollPane; + +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class ScrollPaneRemoveAdd { + Button button; + ScrollPane pane; + Frame frame; + volatile Point buttonLoc; + volatile Dimension buttonSize; + volatile CountDownLatch latch; + + public static void main(String[] args) throws Exception { + ScrollPaneRemoveAdd scrollTest = new ScrollPaneRemoveAdd(); + scrollTest.init(); + scrollTest.start(); + } + + public void init() throws Exception { + EventQueue.invokeAndWait(() -> { + frame = new Frame("Scroll pane Add/Remove"); + pane = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); + button = new Button("press"); + latch = new CountDownLatch(1); + + pane.add(button); + frame.add(pane); + + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + latch.countDown(); + } + }); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setAlwaysOnTop(true); + frame.setVisible(true); + }); + } + + public void start() throws Exception { + try { + EventQueue.invokeAndWait(() -> { + pane.remove(0); + pane.add(button); + buttonLoc = button.getLocationOnScreen(); + buttonSize = button.getSize(); + }); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + + robot.mouseMove(buttonLoc.x + buttonSize.width / 2, + buttonLoc.y + buttonSize.height / 2); + robot.delay(50); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + if (!latch.await(1, TimeUnit.SECONDS)) { + throw new RuntimeException("ScrollPane doesn't handle " + + "correctly add after remove"); + } + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneScrollEnd.java b/test/jdk/java/awt/ScrollPane/ScrollPaneScrollEnd.java new file mode 100644 index 00000000000..00ca273d76b --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneScrollEnd.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Robot; +import java.awt.ScrollPane; + +/* + * @test + * @bug 8311689 + * @key headful + * @requires os.family=="windows" + * @summary Verifies ScrollPane allows viewing the whole contents of its child + * @run main ScrollPaneScrollEnd + */ +public final class ScrollPaneScrollEnd { + private static final Color CANVAS_BACKGROUND = new Color(255, 200, 200); + private static final Color CANVAS_FOREGROUND = new Color(255, 255, 200); + private static final int OFFSET = 12; + + private static final Dimension CANVAS_SIZE = new Dimension(900, 600); + private static final Dimension SCROLL_PANE_SIZE = + new Dimension(CANVAS_SIZE.width / 3, CANVAS_SIZE.height / 3); + private static final int SCROLL_OFFSET = 100; + + private static final int DELAY = 200; + + public static void main(String[] args) throws Exception { + Canvas canvas = new Canvas() { + @Override + public void paint(Graphics g) { + g.setColor(CANVAS_BACKGROUND); + g.fillRect(0, 0, getWidth(), getHeight()); + + g.setColor(CANVAS_FOREGROUND); + g.fillRect(OFFSET, OFFSET, + getWidth() - OFFSET * 2, getHeight() - OFFSET * 2); + } + }; + canvas.setSize(CANVAS_SIZE); + + ScrollPane scrollPane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); + scrollPane.add(canvas); + scrollPane.setSize(SCROLL_PANE_SIZE); + + Frame frame = new Frame("ScrollPaneScrollEnd"); + frame.add(scrollPane, "Center"); + frame.setLocation(100, 100); + frame.pack(); + frame.setVisible(true); + + final Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(DELAY); + + final Dimension vp = scrollPane.getViewportSize(); + final Point expected = new Point(CANVAS_SIZE.width - vp.width, + CANVAS_SIZE.height - vp.height); + + scrollPane.setScrollPosition(CANVAS_SIZE.width + SCROLL_OFFSET, + CANVAS_SIZE.height + SCROLL_OFFSET); + try { + if (!expected.equals(scrollPane.getScrollPosition())) { + throw new Error("Can't scroll to the end of the child component"); + } + } finally { + frame.dispose(); + } + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneWindowsTest.java b/test/jdk/java/awt/ScrollPane/ScrollPaneWindowsTest.java new file mode 100644 index 00000000000..b1d50f5c6e4 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneWindowsTest.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4452612 + @requires os.family=="windows" + @summary The popup menu of the scroll bar doesn't work properly in Window2000. + @key headful +*/ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Insets; +import java.awt.Panel; +import java.awt.Robot; +import java.awt.ScrollPane; +import java.awt.ScrollPaneAdjustable; + +import java.awt.event.AdjustmentListener; +import java.awt.event.AdjustmentEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +public class ScrollPaneWindowsTest implements AdjustmentListener { + ScrollPane sp; + Panel p; + Robot robot; + Frame frame; + Insets paneInsets; + public static final Object LOCK = new Object(); + ScrollPaneAdjustable vScroll; + ScrollPaneAdjustable hScroll; + boolean notifyReceived = false; + volatile int xPos = 0; + volatile int yPos = 0; + + public static void main(String[] args) throws Exception { + ScrollPaneWindowsTest scrollTest = new ScrollPaneWindowsTest(); + scrollTest.init(); + scrollTest.start(); + } + + public void init() throws Exception { + EventQueue.invokeAndWait(() -> { + frame = new Frame("ScrollPaneWindowsTest"); + frame.setLayout(new BorderLayout(1, 1)); + p = new Panel(); + p.setLayout(null); + p.setSize(new Dimension(800, 800)); + sp = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); + vScroll = (ScrollPaneAdjustable) sp.getVAdjustable(); + hScroll = (ScrollPaneAdjustable) sp.getHAdjustable(); + vScroll.addAdjustmentListener(ScrollPaneWindowsTest.this); + hScroll.addAdjustmentListener(ScrollPaneWindowsTest.this); + sp.add(p); + frame.add(sp); + frame.pack(); + frame.setSize(400, 400); + frame.setLocationRelativeTo(null); + frame.setAlwaysOnTop(true); + frame.setVisible(true); + }); + } + + public void start() throws Exception { + try { + EventQueue.invokeAndWait(() -> { + paneInsets = sp.getInsets(); + System.out.println("Insets: right = " + paneInsets.right + " bottom = " + paneInsets.bottom); + }); + + robot = new Robot(); + robot.waitForIdle(); + robot.delay(100); + + EventQueue.invokeAndWait(() -> { + xPos = sp.getLocationOnScreen().x + sp.getWidth() - paneInsets.right / 2; + yPos = sp.getLocationOnScreen().y + sp.getHeight() / 2; + }); + + robot.mouseMove(xPos, yPos); + testOneScrollbar(vScroll); + + robot.waitForIdle(); + robot.delay(100); + + EventQueue.invokeAndWait(() -> { + xPos = sp.getLocationOnScreen().x + sp.getWidth() / 2; + yPos = sp.getLocationOnScreen().y + sp.getHeight() - paneInsets.bottom / 2; + }); + + robot.mouseMove(xPos, yPos); + testOneScrollbar(hScroll); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + System.out.println("Test passed. "); + } + + public void testOneScrollbar(ScrollPaneAdjustable scroll) throws Exception { + //to Bottom - right + robot.mousePress(InputEvent.BUTTON3_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK); + robot.waitForIdle(); + robot.delay(2000); + + synchronized (LOCK) { + notifyReceived = false; + for (int i = 0; i < 3; i++) { + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + } + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + if (!notifyReceived) { + System.out.println("we are waiting 1"); + LOCK.wait(2000); + } + if (scroll.getValue() + scroll.getVisibleAmount() != scroll.getMaximum()) { + System.out.println("scroll.getValue() = " + scroll.getValue()); + System.out.println("scroll.getVisibleAmount() = " + scroll.getVisibleAmount()); + System.out.println("scroll.getMaximum() = " + scroll.getMaximum()); + throw new RuntimeException("Test Failed. Position of scrollbar is incorrect."); + } else { + System.out.println("Test stage 1 passed."); + } + notifyReceived = false; + } + + //to top-left + robot.mousePress(InputEvent.BUTTON3_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK); + robot.waitForIdle(); + robot.delay(2000); + + synchronized (LOCK) { + for (int i = 0; i < 2; i++) { + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + } + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + if (!notifyReceived) { + System.out.println("we are waiting 2"); + LOCK.wait(2000); + } + if (scroll.getValue() != 0) { + System.out.println("scroll.getValue() = " + scroll.getValue()); + throw new RuntimeException("Test Failed. Position of scrollbar is incorrect."); + } else { + System.out.println("Test stage 2 passed."); + } + } + } + + @Override + public void adjustmentValueChanged(AdjustmentEvent adjustmentEvent) { + synchronized (ScrollPaneWindowsTest.LOCK) { + notifyReceived = true; + ScrollPaneWindowsTest.LOCK.notify(); + } + System.out.println("Adjustment Event called "); + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPositionIntact.java b/test/jdk/java/awt/ScrollPane/ScrollPositionIntact.java new file mode 100644 index 00000000000..793548ca168 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPositionIntact.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + @test + @bug 6404832 + @summary Tests that scroll position is not changed by validate() for mode SCROLLBARS_NEVER + @key headful + @run main ScrollPositionIntact +*/ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Robot; +import java.awt.ScrollPane; + +public class ScrollPositionIntact { + Frame frame; + ScrollPane sp; + Panel pa; + public static final int X_POS = 100; + + public static void main(String[] args) throws Exception { + ScrollPositionIntact test = new ScrollPositionIntact(); + test.init(); + test.start(); + } + + public void init() throws Exception { + EventQueue.invokeAndWait(() -> { + pa = new Panel(); + pa.setSize(600, 50); + pa.setPreferredSize(new Dimension(600, 50)); + pa.setBackground(Color.red); + sp = new ScrollPane(ScrollPane.SCROLLBARS_NEVER); + sp.setSize(200, 50); + pa.setLayout(new GridLayout(1, 3)); + pa.add("West", new Label("west", Label.LEFT)); + pa.add("West", new Label()); + pa.add("East", new Label("East", Label.RIGHT)); + sp.add(pa); + frame = new Frame("ScrollPositionIntact"); + frame.setSize(200, 100); + frame.add(sp); + frame.setVisible(true); + }); + } + + public void start() throws Exception { + try { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + + EventQueue.invokeAndWait(() -> { + frame.toFront(); + frame.requestFocus(); + + sp.setScrollPosition(X_POS, sp.getScrollPosition().y); + pa.validate(); + // Now, before the fix, in Windows XP, Windows XP theme and on Vista, + // scrollposition would be reset to zero.. + sp.validate(); + + int i = (int) (sp.getScrollPosition().getX()); + if (i <= 0) { + // actual position MAY be not equal to X_POS; still, it must be > 0. + throw new RuntimeException("Test failure: zero scroll position.\n\n"); + } + }); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/java/awt/Toolkit/ToolkitListenerTest/ToolkitListenerTest.java b/test/jdk/java/awt/Toolkit/ToolkitListenerTest/ToolkitListenerTest.java new file mode 100644 index 00000000000..3d7b6df2cba --- /dev/null +++ b/test/jdk/java/awt/Toolkit/ToolkitListenerTest/ToolkitListenerTest.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4460376 + @summary we should create Component-, Container- and HierarchyEvents if + appropriate AWTEventListener added on Toolkit + @key headful +*/ + +import java.awt.AWTEvent; +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Toolkit; +import java.awt.event.AWTEventListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ContainerEvent; +import java.awt.event.HierarchyEvent; +import java.lang.reflect.InvocationTargetException; + +public class ToolkitListenerTest implements AWTEventListener +{ + public static Frame frame; + static boolean containerEventReceived = false; + static boolean componentEventReceived = false; + static boolean hierarchyEventReceived = false; + static boolean hierarchyBoundsEventReceived = false; + + public static void main(String[] args) throws Exception { + ToolkitListenerTest test = new ToolkitListenerTest(); + test.start(); + } + public void start() throws Exception { + Toolkit.getDefaultToolkit(). + addAWTEventListener(this, + AWTEvent.COMPONENT_EVENT_MASK | + AWTEvent.CONTAINER_EVENT_MASK | + AWTEvent.HIERARCHY_EVENT_MASK | + AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK); + EventQueue.invokeAndWait(() -> { + frame = new Frame("ToolkitListenerTest"); + frame.setSize(200, 200); + frame.add(new Button()); + frame.setBounds(100, 100, 100, 100); + }); + try { + Toolkit.getDefaultToolkit().getSystemEventQueue(). + invokeAndWait(new Runnable() { + public void run() {} + }); + + EventQueue.invokeAndWait(() -> { + if (!componentEventReceived) { + throw new RuntimeException("Test Failed: ComponentEvent " + + "was not dispatched"); + } + if (!containerEventReceived) { + throw new RuntimeException("Test Failed: ContainerEvent " + + "was not dispatched"); + } + if (!hierarchyEventReceived) { + throw new RuntimeException("Test Failed: " + + "HierarchyEvent(HIERARCHY_CHANGED) was not dispatched"); + } + if (!hierarchyBoundsEventReceived) { + throw new RuntimeException("Test Failed: " + + "HierarchyEvent(ANCESTOR_MOVED or ANCESTOR_RESIZED) " + + "was not dispatched"); + } + }); + } catch (InterruptedException ie) { + throw new RuntimeException("Test Failed: InterruptedException " + + "accured."); + } catch (InvocationTargetException ite) { + throw new RuntimeException("Test Failed: " + + "InvocationTargetException accured."); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public void eventDispatched(AWTEvent e) { + System.err.println(e); + if (e instanceof ContainerEvent) { + containerEventReceived = true; + } else if (e instanceof ComponentEvent) { + componentEventReceived = true; + } else if (e instanceof HierarchyEvent) { + switch (e.getID()) { + case HierarchyEvent.HIERARCHY_CHANGED: + hierarchyEventReceived = true; + break; + case HierarchyEvent.ANCESTOR_MOVED: + case HierarchyEvent.ANCESTOR_RESIZED: + hierarchyBoundsEventReceived = true; + break; + } + } + } +} diff --git a/test/jdk/java/awt/Window/MultiWindowApp/ChildAlwaysOnTopTest.java b/test/jdk/java/awt/Window/MultiWindowApp/ChildAlwaysOnTopTest.java index 74fc6f9b4e3..d4ae37aff03 100644 --- a/test/jdk/java/awt/Window/MultiWindowApp/ChildAlwaysOnTopTest.java +++ b/test/jdk/java/awt/Window/MultiWindowApp/ChildAlwaysOnTopTest.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 @@ -21,142 +21,236 @@ * questions. */ -/** +/* * @test * @key headful - * @summary setAlwaysOnTop doesn't behave correctly in Linux/Solaris under - * certain scenarios * @bug 8021961 - * @author Semyon Sadetsky + * @summary To test setAlwaysOnTop functionality. * @run main/othervm -Dsun.java2d.uiScale=1 ChildAlwaysOnTopTest */ -import javax.swing.*; -import java.awt.*; +import java.awt.Color; +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.Window; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; + +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; + +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.SwingUtilities; public class ChildAlwaysOnTopTest { private static Window win1; private static Window win2; private static Point point; + private static Robot robot; + private static int caseNo = 0; + private static StringBuffer errorLog = new StringBuffer(); + private static String[] errorMsg= new String[] { + " Scenario 1 Failed: alwaysOnTop window is sent back by another" + + " child window with setVisible().", + " Scenario 2 Failed: alwaysOnTop window is" + + " sent back by another child window with toFront().", + " Scenario 3 Failed: Failed to unset alwaysOnTop ", + }; public static void main(String[] args) throws Exception { - if( Toolkit.getDefaultToolkit().isAlwaysOnTopSupported() ) { + if (!Toolkit.getDefaultToolkit().isAlwaysOnTopSupported()) { + System.out.println("alwaysOnTop not supported by: "+ + Toolkit.getDefaultToolkit().getClass().getName()); + return; + } - test(null); + // CASE 1 - JDialog without parent/owner + System.out.println("Testing CASE 1: JDialog without parent/owner"); + caseNo = 1; + test(null); + System.out.println("CASE 1 Completed"); + System.out.println(); - Window f = new Frame(); - f.setBackground(Color.darkGray); - f.setSize(500, 500); - try { - test(f); - } finally { - f.dispose(); - } + // CASE 2 - JDialog with JFrame as owner + System.out.println("Testing CASE 2: JDialog with JFrame as owner"); + caseNo = 2; + Window f = new Frame(); + f.setBackground(Color.darkGray); + f.setSize(500, 500); + try { + test(f); + } finally { + f.dispose(); + } + System.out.println("CASE 2 Completed"); + System.out.println(); - f = new Frame(); - f.setBackground(Color.darkGray); - f.setSize(500, 500); - f.setVisible(true); - f = new Dialog((Frame)f); - try { - test(f); - } finally { - ((Frame)f.getParent()).dispose(); - } + // CASE 3 - JDialog within another JDialog as owner + System.out.println("Testing CASE 3:Dialog within another"+ + " JDialog as owner"); + caseNo = 3; + f = new Frame(); + f.setBackground(Color.darkGray); + f.setSize(500, 500); + f.setVisible(true); + f = new Dialog((Frame)f); + try { + test(f); + } finally { + ((Frame)f.getParent()).dispose(); + } + System.out.println("CASE 3 Completed"); + System.out.println(); + + if (errorLog.length() == 0) { + System.out.println("All three cases passed !!"); + } + else { + throw new RuntimeException("Following cases and scenarios failed."+ + " Please check the saved screenshots.\n"+ errorLog); } - System.out.println("ok"); } public static void test(Window parent) throws Exception { - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - win1 = parent == null ? new JDialog() : new JDialog(parent); - win1.setName("top"); - win2 = parent == null ? new JDialog() : new JDialog(parent); - win2.setName("behind"); - win1.setSize(200, 200); - Panel panel = new Panel(); - panel.setBackground(Color.GREEN); - win1.add(panel); - panel = new Panel(); - panel.setBackground(Color.RED); - win2.add(panel); - win1.setAlwaysOnTop(true); - win2.setAlwaysOnTop(false); - win1.setVisible(true); - } - }); + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + win1 = parent == null ? new JDialog() : new JDialog(parent); + win1.setName("Top"); - Robot robot = new Robot(); - robot.delay(500); - robot.waitForIdle(); + win2 = parent == null ? new JDialog() : new JDialog(parent); + win2.setName("Behind"); + + JLabel label = new JLabel("TOP WINDOW"); + // top window - green and smaller + win1.setSize(200, 200); + Panel panel = new Panel(); + panel.setBackground(Color.GREEN); + panel.add(label); + win1.add(panel); + win1.setAlwaysOnTop(true); + + // behind window - red and bigger + label = new JLabel("BEHIND WINDOW"); + win2.setSize(300, 300); + panel = new Panel(); + panel.setBackground(Color.RED); + panel.add(label); + win2.add(panel); - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { + win1.setVisible(true); + win2.setVisible(true); + } + }); + + robot = new Robot(); + robot.setAutoDelay(300); + robot.waitForIdle(); + + // Scenario 1: Trying to unset the alwaysOnTop (green window) + // by setting the setVisible to true for behind (red) window + System.out.println(" >> Testing Scenario 1 ..."); + SwingUtilities.invokeAndWait(()-> { point = win1.getLocationOnScreen(); - win2.setBounds(win1.getBounds()); win2.setVisible(true); - } - }); + }); - robot.delay(500); - robot.waitForIdle(); + checkTopWindow(caseNo, 1, Color.GREEN); - Color color = robot.getPixelColor(point.x + 100, point.y + 100); - if(!color.equals(Color.GREEN)) { - win1.dispose(); - win2.dispose(); - throw new RuntimeException("alawaysOnTop window is sent back by " + - "another child window setVisible(). " + color); - } + /*---------------------------------------------------------------*/ - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { + // Scenario 2: Trying to unset the alwaysOnTop (green window) + // by setting toFront() to true for behind (red) window + System.out.println(" >> Testing Scenario 2 ..."); + SwingUtilities.invokeAndWait(()-> { win2.toFront(); if (parent != null) { parent.setLocation(win1.getLocation()); parent.toFront(); } - } - }); + }); - robot.delay(500); - robot.waitForIdle(); + checkTopWindow(caseNo, 2, Color.GREEN); - color = robot.getPixelColor(point.x + 100, point.y + 100); - if(!color.equals(Color.GREEN)) { - win1.dispose(); - win2.dispose(); - throw new RuntimeException("alawaysOnTop window is sent back by " + - "another child window toFront(). " + color); - } + /*----------------------------------------------------------------*/ - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - win1.setAlwaysOnTop(false); - if (parent != null) { - parent.setVisible(false); - parent.setVisible(true); + // Scenario 3: Trying to unset the alwaysOnTop (green window) + // by setting alwaysOnTop to false. The unsetting should work + // in this case and bring the red window to the top. + System.out.println(" >> Testing Scenario 3 ..."); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + win1.setAlwaysOnTop(false); + if (parent != null) { + parent.setVisible(false); + parent.setVisible(true); + } } - win2.toFront(); + }); + + robot.delay(300); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + win2.toFront(); + } + }); + + checkTopWindow(caseNo, 3, Color.RED); + + } finally { + if (win1 != null) { + SwingUtilities.invokeAndWait(()-> win1.dispose()); } - }); + if (win2 != null) { + SwingUtilities.invokeAndWait(()-> win2.dispose()); + } + } + } + // to check if the current top window background color + // matches the expected color + private static void checkTopWindow(int caseNo, int scenarioNo, + Color expectedColor) { robot.delay(500); robot.waitForIdle(); + Color actualColor = robot.getPixelColor(point.x + 100, point.y + 100); + + saveScreenCapture(caseNo , scenarioNo); - color = robot.getPixelColor(point.x + 100, point.y + 100); - if(!color.equals(Color.RED)) { - throw new RuntimeException("Failed to unset alawaysOnTop " + color); + if (!actualColor.equals(expectedColor)) { + System.out.println(" >> Scenario "+ scenarioNo +" FAILED !!"); + errorLog.append("Case "+ caseNo + errorMsg[scenarioNo - 1] + +" Expected Color: "+ expectedColor +" vs Actual Color: " + + actualColor +"\n"); + } + else { + System.out.println(" >> Scenario "+ scenarioNo +" Passed"); } + } - win1.dispose(); - win2.dispose(); + // For Debugging purpose - method used to save the screen capture as + // BufferedImage in the event the test fails + private static void saveScreenCapture(int caseNo, int scenarioNo) { + String filename = "img_"+ caseNo +"_"+ scenarioNo; + BufferedImage image = robot.createScreenCapture( + new Rectangle(0, 0, 500, 500)); + try { + ImageIO.write(image, "png", new File(filename)); + } catch (IOException e) { + e.printStackTrace(); + } } -} +} \ No newline at end of file diff --git a/test/jdk/java/awt/datatransfer/CRLFTest/CRLFTest.java b/test/jdk/java/awt/datatransfer/CRLFTest/CRLFTest.java new file mode 100644 index 00000000000..c61791d13fa --- /dev/null +++ b/test/jdk/java/awt/datatransfer/CRLFTest/CRLFTest.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4914613 + @summary tests that "\r\n" is not converted to "\r\r\n" + @key headful +*/ + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.SystemFlavorMap; +import java.awt.datatransfer.Transferable; +import java.io.File; +import java.io.InputStream; + +public class CRLFTest { + private int returnCode = 0; + + public static void main(String[] args) { + CRLFTest parent = new CRLFTest(); + parent.start(); + } + public void start() { + + try { + String javaPath = System.getProperty("java.home", ""); + String command = javaPath + File.separator + "bin" + + File.separator + "java -cp " + + System.getProperty("test.classes", ".") + + " CRLFTestClipboard"; + + Process process = Runtime.getRuntime().exec(command); + ProcessResults pres = ProcessResults.doWaitFor(process); + returnCode = pres.exitValue; + + if (pres.stderr != null && pres.stderr.length() > 0) { + System.err.println("========= Child VM System.err ========"); + System.err.print(pres.stderr); + System.err.println("======================================"); + } + + if (pres.stdout != null && pres.stdout.length() > 0) { + System.err.println("========= Child VM System.out ========"); + System.err.print(pres.stdout); + System.err.println("======================================"); + } + + System.err.println("Child return code=" + returnCode); + } catch (Throwable e) { + e.printStackTrace(); + } + } +} + +class CRLFTestClipboard implements ClipboardOwner { + private static final Clipboard clipboard = + Toolkit.getDefaultToolkit().getSystemClipboard(); + + public static void main(String[] args) { + CRLFTestClipboard child = new CRLFTestClipboard(); + child.run(); + } + + public void run() { + ClipboardOwner owner = new ClipboardOwner() { + public void lostOwnership(Clipboard clipboard, + Transferable contents) { + System.exit(0); + } + }; + clipboard.setContents(new StringSelection("\r\n"), owner); + + // Wait to let the parent retrieve the contents. + try { + Thread.sleep(30000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public void lostOwnership(Clipboard clip, Transferable contents) { + final DataFlavor df = + new DataFlavor("text/test-subtype; class=java.io.InputStream", + null); + SystemFlavorMap sfm = + (SystemFlavorMap)SystemFlavorMap.getDefaultFlavorMap(); + sfm.addUnencodedNativeForFlavor(df, "TEXT"); + sfm.addFlavorForUnencodedNative("TEXT", df); + Runnable r = new Runnable() { + public void run() { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Transferable t = clipboard.getContents(null); + boolean passed = true; + try { + InputStream is = + (InputStream)t.getTransferData(df); + int prev = 0; + int b = 0; + System.err.print("Bytes: "); + while ((b = is.read()) != -1) { + System.err.print(" " + Integer. + toHexString((int)b & 0xFF)); + if (b == 0xD && prev == 0xD) { + passed = false; + } + prev = b; + } + System.err.println(); + } catch (Exception e) { + e.printStackTrace(); + } + clipboard.setContents(new StringSelection(""), null); + + if (!passed) { + throw new RuntimeException("Test failed"); + } + } + }; + new Thread(r).start(); + } +} + +class ProcessResults { + public int exitValue; + public String stdout; + public String stderr; + + public ProcessResults() { + exitValue = -1; + stdout = ""; + stderr = ""; + } + + /** + * Method to perform a "wait" for a process and return its exit value. + * This is a workaround for Process.waitFor() never returning. + */ + public static ProcessResults doWaitFor(Process p) { + ProcessResults pres = new ProcessResults(); + + InputStream in = null; + InputStream err = null; + + try { + in = p.getInputStream(); + err = p.getErrorStream(); + + boolean finished = false; + + while (!finished) { + try { + while (in.available() > 0) { + pres.stdout += (char)in.read(); + } + while (err.available() > 0) { + pres.stderr += (char)err.read(); + } + // Ask the process for its exitValue. If the process + // is not finished, an IllegalThreadStateException + // is thrown. If it is finished, we fall through and + // the variable finished is set to true. + pres.exitValue = p.exitValue(); + finished = true; + } + catch (IllegalThreadStateException e) { + // Process is not finished yet; + // Sleep a little to save on CPU cycles + Thread.currentThread().sleep(500); + } + } + if (in != null) in.close(); + if (err != null) err.close(); + } + catch (Throwable e) { + System.err.println("doWaitFor(): unexpected exception"); + e.printStackTrace(); + } + return pres; + } +} diff --git a/test/jdk/java/awt/datatransfer/DataConversionDeadlockTest/DataConversionDeadlockTest.java b/test/jdk/java/awt/datatransfer/DataConversionDeadlockTest/DataConversionDeadlockTest.java new file mode 100644 index 00000000000..e1257a4e99f --- /dev/null +++ b/test/jdk/java/awt/datatransfer/DataConversionDeadlockTest/DataConversionDeadlockTest.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4760364 + @summary Tests that the deadlock doesn't happen when two apps request + selection data from each other. + @key headful +*/ + +import java.awt.EventQueue; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +public class DataConversionDeadlockTest { + + public static void main(String[] args) { + DataConversionDeadlockTest parent = new DataConversionDeadlockTest(); + parent.start(); + } + + public void start() { + try { + String javaPath = System.getProperty("java.home", ""); + String cmd = javaPath + File.separator + "bin" + + File.separator + "java -cp " + + System.getProperty("test.classes", ".") + + " DataConversionDeadlockTestChild"; + + Process process = Runtime.getRuntime().exec(cmd); + ProcessResults pres = ProcessResults.doWaitFor(process); + + if (pres.stderr != null && pres.stderr.length() > 0) { + System.err.println("========= Child VM System.err ========"); + System.err.print(pres.stderr); + System.err.println("======================================"); + } + + if (pres.stdout != null && pres.stdout.length() > 0) { + System.err.println("========= Child VM System.out ========"); + System.err.print(pres.stdout); + System.err.println("======================================"); + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} + +class DataConversionDeadlockTestChild implements ClipboardOwner, Runnable { + private static final Toolkit toolkit = Toolkit.getDefaultToolkit(); + private static final Clipboard clipboard = toolkit.getSystemClipboard(); + private static final Clipboard selection = toolkit.getSystemSelection(); + private static final Transferable t = new StringSelection("TEXT"); + + public void lostOwnership(Clipboard cb, Transferable contents) { + ClipboardUtil.setClipboardContents(selection, t, this); + new Thread(this).start(); + } + + public void run() { + for (int i = 0; i < 100; i++) { + EventQueue.invokeLater(new Runnable() { + public void run() { + ClipboardUtil.getClipboardContents(clipboard, null); + } + }); + } + } + + public static void main(String[] args) { + if (clipboard == null || selection == null) { + return; + } + ClipboardUtil.setClipboardContents(clipboard, t, null); + for (int i = 0; i < 100; i++) { + EventQueue.invokeLater(new Runnable() { + public void run() { + ClipboardUtil.getClipboardContents(selection, null); + } + }); + } + } +} + +class ClipboardUtil { + public static void setClipboardContents(Clipboard cb, + Transferable contents, + ClipboardOwner owner) { + synchronized (cb) { + boolean set = false; + while (!set) { + try { + cb.setContents(contents, owner); + set = true; + } catch (IllegalStateException ise) { + try { Thread.sleep(100); } + catch (InterruptedException e) { e.printStackTrace(); } + } + } + } + } + + public static Transferable getClipboardContents(Clipboard cb, + Object requestor) { + synchronized (cb) { + while (true) { + try { + Transferable t = cb.getContents(requestor); + return t; + } catch (IllegalStateException ise) { + try { Thread.sleep(100); } + catch (InterruptedException e) { e.printStackTrace(); } + } + } + } + } +} + +class ProcessResults { + public int exitValue; + public String stdout; + public String stderr; + + public ProcessResults() { + exitValue = -1; + stdout = ""; + stderr = ""; + } + + /** + * Method to perform a "wait" for a process and return its exit value. + * This is a workaround for Process.waitFor() never returning. + */ + public static ProcessResults doWaitFor(Process p) { + ProcessResults pres = new ProcessResults(); + + InputStream in = null; + InputStream err = null; + + try { + in = p.getInputStream(); + err = p.getErrorStream(); + + boolean finished = false; + + while (!finished) { + try { + while (in.available() > 0) { + pres.stdout += (char)in.read(); + } + while (err.available() > 0) { + pres.stderr += (char)err.read(); + } + // Ask the process for its exitValue. If the process + // is not finished, an IllegalThreadStateException + // is thrown. If it is finished, we fall through and + // the variable finished is set to true. + pres.exitValue = p.exitValue(); + finished = true; + } + catch (IllegalThreadStateException e) { + // Process is not finished yet; + // Sleep a little to save on CPU cycles + Thread.currentThread().sleep(500); + } + } + if (in != null) in.close(); + if (err != null) err.close(); + } + catch (Throwable e) { + System.err.println("doWaitFor(): unexpected exception"); + e.printStackTrace(); + } + return pres; + } +} diff --git a/test/jdk/java/awt/datatransfer/DataFlavor/BestTextFlavorTest/BestTextFlavorTest.java b/test/jdk/java/awt/datatransfer/DataFlavor/BestTextFlavorTest/BestTextFlavorTest.java new file mode 100644 index 00000000000..81558d23ad8 --- /dev/null +++ b/test/jdk/java/awt/datatransfer/DataFlavor/BestTextFlavorTest/BestTextFlavorTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @summary To test if the DataFlavor.selectBestTextFlavor() method + is selecting the correct best flavor from an array of flavors. +*/ + + +import java.awt.datatransfer.DataFlavor; +import java.util.Vector; + +public class BestTextFlavorTest { + public static DataFlavor plainISOFlavor, + plainAsciiFlavor, + plainTextFlavor, + enrichFlavor; + public static DataFlavor[] bestFlavorArray1; + public static DataFlavor[] bestFlavorArray2; + public static DataFlavor bestFlavor1,bestFlavor2; + private static Vector tmpFlavors; + + //Creating new flavors + static { + + tmpFlavors = new Vector(); + try { + tmpFlavors.addElement(DataFlavor.stringFlavor); + tmpFlavors.addElement(new DataFlavor + ("text/plain; charset=unicode")); + tmpFlavors.addElement( + new DataFlavor("text/plain; charset=us-ascii")); + enrichFlavor=new DataFlavor("text/enriched; charset=ascii"); + tmpFlavors.addElement(enrichFlavor); + plainTextFlavor=DataFlavor.getTextPlainUnicodeFlavor(); + tmpFlavors.addElement(plainTextFlavor); + plainAsciiFlavor=new DataFlavor("text/plain; charset=ascii"); + tmpFlavors.addElement(plainAsciiFlavor); + plainISOFlavor=new DataFlavor("text/plain; charset=iso8859-1"); + tmpFlavors.addElement(plainISOFlavor); + } + catch (ClassNotFoundException e) { + // should never happen... + System.out.println("ClassNotFound Exception is thrown when"+ + "flavors are created"); + } + } + + public static void main(String[] args) { + bestFlavorArray1 = new DataFlavor[tmpFlavors.size()]; + tmpFlavors.copyInto(bestFlavorArray1); + + //Selecting the best text flavor from a set of Data Flavors. + bestFlavor1 = DataFlavor.selectBestTextFlavor(bestFlavorArray1); + System.out.println("The Best Text Flavor is " + bestFlavor1); + + bestFlavorArray2 = reverseDataFlavor(bestFlavorArray1); + bestFlavor2 = DataFlavor.selectBestTextFlavor(bestFlavorArray2); + System.out.println("The Best Text Flavor is " + bestFlavor2); + + //Checking whether the selected flavors in both the arrays are same. + if (bestFlavor2.match(bestFlavor1)) { + System.out.println("The test is Passed"); + } + else { + System.out.println("The test is Failed"); + throw new RuntimeException("SelectBestTextFlavor doesn't return "+ + "the same best Text flavor from a set of DataFlavors, "+ + "it always returns the first Text Flavor encountered."); + } + } + + //Returns the array of DataFlavor passed in reverse order. + public static DataFlavor[] reverseDataFlavor(DataFlavor[] dataflavor) { + + DataFlavor[] tempFlavor = new DataFlavor[dataflavor.length]; + int j = 0; + for (int i = dataflavor.length - 1 ; i >= 0; i--) { + tempFlavor[j] = dataflavor[i]; + j++; + } + return tempFlavor; + } +} diff --git a/test/jdk/java/awt/datatransfer/FileTransferAWTLockTest/FileTransferAWTLockTest.java b/test/jdk/java/awt/datatransfer/FileTransferAWTLockTest/FileTransferAWTLockTest.java new file mode 100644 index 00000000000..ac4ff5c9b11 --- /dev/null +++ b/test/jdk/java/awt/datatransfer/FileTransferAWTLockTest/FileTransferAWTLockTest.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + @test + @bug 4916420 + @requires os.family == "linux" + @summary verifies that AWT_LOCK is properly taken during file transfer + @key headful +*/ + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; + +public class FileTransferAWTLockTest { + + public static void main(String[] args) { + if (!(System.getProperty("os.name").startsWith("Linux"))) { + return; + } + FileTransferAWTLockTest parent = new FileTransferAWTLockTest(); + parent.start(); + } + + public void start() { + String stderr = null; + try { + String javaPath = System.getProperty("java.home", ""); + String command = javaPath + File.separator + "bin" + + File.separator + "java -cp " + + System.getProperty("test.classes", ".") + + " -Dawt.toolkit=sun.awt.X11.XToolkit" + + " FileTransferAWTLockTestChild"; + + Process process = Runtime.getRuntime().exec(command); + ProcessResults pres = ProcessResults.doWaitFor(process); + + stderr = pres.stderr; + + if (pres.stderr != null && pres.stderr.length() > 0) { + System.err.println("========= Child VM System.err ========"); + System.err.print(pres.stderr); + System.err.println("======================================"); + } + + if (pres.stdout != null && pres.stdout.length() > 0) { + System.err.println("========= Child VM System.out ========"); + System.err.print(pres.stdout); + System.err.println("======================================"); + } + + System.err.println("Child VM return code: " + pres.exitValue); + } catch (Throwable e) { + e.printStackTrace(); + } + + if (stderr != null && stderr.indexOf("InternalError") >= 0) { + throw new RuntimeException("Test failed"); + } + } +} + +class FileTransferAWTLockTestChild { + static final Clipboard clipboard = + Toolkit.getDefaultToolkit().getSystemClipboard(); + static final Transferable transferable = new Transferable() { + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[] { DataFlavor.javaFileListFlavor }; + } + public boolean isDataFlavorSupported(DataFlavor df) { + return DataFlavor.javaFileListFlavor.equals(df); + } + public Object getTransferData(DataFlavor df) + throws IOException, UnsupportedFlavorException { + if (!isDataFlavorSupported(df)) { + throw new UnsupportedFlavorException(df); + } + + File file = new File("file.txt"); + ArrayList list = new ArrayList(); + list.add(file); + return list; + } + }; + + public static void main(String[] args) { + Util.setClipboardContents(clipboard, transferable, null); + FileTransferAWTLockTestChild test = new FileTransferAWTLockTestChild(); + test.run(); + } + + public void run() { + Transferable t = Util.getClipboardContents(clipboard, null); + try { + t.getTransferData(DataFlavor.javaFileListFlavor); + } catch (Exception e) { + e.printStackTrace(); + } + } +} + +class Util { + public static void setClipboardContents(Clipboard cb, + Transferable contents, + ClipboardOwner owner) { + synchronized (cb) { + while (true) { + try { + cb.setContents(contents, owner); + return; + } catch (IllegalStateException ise) { + try { Thread.sleep(100); } + catch (InterruptedException e) { e.printStackTrace(); } + } + } + } + } + + public static Transferable getClipboardContents(Clipboard cb, + Object requestor) { + synchronized (cb) { + while (true) { + try { + return cb.getContents(requestor); + } catch (IllegalStateException ise) { + try { Thread.sleep(100); } + catch (InterruptedException e) { e.printStackTrace(); } + } + } + } + } +} + +class ProcessResults { + public int exitValue; + public String stdout; + public String stderr; + + public ProcessResults() { + exitValue = -1; + stdout = ""; + stderr = ""; + } + + /** + * Method to perform a "wait" for a process and return its exit value. + * This is a workaround for Process.waitFor() never returning. + */ + public static ProcessResults doWaitFor(Process p) { + ProcessResults pres = new ProcessResults(); + + InputStream in = null; + InputStream err = null; + + try { + in = p.getInputStream(); + err = p.getErrorStream(); + + boolean finished = false; + + while (!finished) { + try { + while (in.available() > 0) { + pres.stdout += (char)in.read(); + } + while (err.available() > 0) { + pres.stderr += (char)err.read(); + } + // Ask the process for its exitValue. If the process + // is not finished, an IllegalThreadStateException + // is thrown. If it is finished, we fall through and + // the variable finished is set to true. + pres.exitValue = p.exitValue(); + finished = true; + } + catch (IllegalThreadStateException e) { + // Process is not finished yet; + // Sleep a little to save on CPU cycles + Thread.currentThread().sleep(500); + } + } + if (in != null) in.close(); + if (err != null) err.close(); + } + catch (Throwable e) { + System.err.println("doWaitFor(): unexpected exception"); + e.printStackTrace(); + } + return pres; + } +} diff --git a/test/jdk/java/awt/dnd/MouseExitGestureTriggerTest.java b/test/jdk/java/awt/dnd/MouseExitGestureTriggerTest.java new file mode 100644 index 00000000000..4626a628099 --- /dev/null +++ b/test/jdk/java/awt/dnd/MouseExitGestureTriggerTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTree; +import java.awt.EventQueue; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.event.InputEvent; + +/* + @test + @bug 4273712 4396746 + @summary tests that mouse exit event doesn't trigger drag + @key headful + @run main MouseExitGestureTriggerTest +*/ + +public class MouseExitGestureTriggerTest { + + boolean recognized = false; + volatile JFrame frame; + volatile JPanel panel; + volatile JTree tree; + volatile DragSource dragSource; + volatile Point srcPoint; + volatile Rectangle r; + volatile DragGestureListener dgl; + static final int FRAME_ACTIVATION_TIMEOUT = 2000; + static final int RECOGNITION_TIMEOUT = 1000; + + public static void main(String[] args) throws Exception { + MouseExitGestureTriggerTest test = new MouseExitGestureTriggerTest(); + EventQueue.invokeAndWait(test::init); + try { + test.start(); + } finally { + EventQueue.invokeAndWait(() -> { + if (test.frame != null) { + test.frame.dispose(); + } + }); + } + } + + public void init() { + frame = new JFrame("MouseExitGestureTriggerTest"); + panel = new JPanel(); + tree = new JTree(); + + dragSource = DragSource.getDefaultDragSource(); + dgl = new DragGestureListener() { + public void dragGestureRecognized(DragGestureEvent dge) { + Thread.dumpStack(); + recognized = true; + } + }; + + tree.setEditable(true); + dragSource.createDefaultDragGestureRecognizer(tree, + DnDConstants.ACTION_MOVE, + dgl); + panel.add(tree); + frame.getContentPane().add(panel); + frame.setLocation(200, 200); + + frame.pack(); + frame.setVisible(true); + } + + public void start() throws Exception { + final Robot robot = new Robot(); + Thread.sleep(FRAME_ACTIVATION_TIMEOUT); + + clickRootNode(robot); + clickRootNode(robot); + clickRootNode(robot); + + Thread.sleep(RECOGNITION_TIMEOUT); + + EventQueue.invokeAndWait(() -> { + if (recognized) { + throw new RuntimeException("Mouse exit event triggered drag"); + } + }); + } + + void clickRootNode(final Robot robot) throws Exception { + EventQueue.invokeAndWait(() -> { + srcPoint = tree.getLocationOnScreen(); + r = tree.getRowBounds(0); + }); + srcPoint.translate(r.x + 2 * r.width /3 , r.y + r.height / 2); + robot.mouseMove(srcPoint.x ,srcPoint.y); + + robot.mousePress(InputEvent.BUTTON1_MASK); + Thread.sleep(10); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + Thread.sleep(10); + } +} diff --git a/test/jdk/java/awt/dnd/MozillaDnDTest.java b/test/jdk/java/awt/dnd/MozillaDnDTest.java new file mode 100644 index 00000000000..f442d0825ae --- /dev/null +++ b/test/jdk/java/awt/dnd/MozillaDnDTest.java @@ -0,0 +1,494 @@ +/* + * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.AWTEvent; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.SystemFlavorMap; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragGestureRecognizer; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceListener; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetContext; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.event.AWTEventListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; + +/* + @test + @bug 4746177 + @summary tests that data types exported by Netscape 6.2 are supported + @requires (os.family != "windows") + @key headful + @run main MozillaDnDTest +*/ + +public class MozillaDnDTest { + + public static final int CODE_NOT_RETURNED = -1; + public static final int CODE_OK = 0; + public static final int CODE_FAILURE = 1; + public static final String DATA = "www.sun.com"; + + private int returnCode = CODE_NOT_RETURNED; + + volatile Frame frame; + volatile Robot robot; + volatile Panel panel; + volatile Point p; + volatile Dimension d; + + public static void main(String[] args) throws Exception { + MozillaDnDTest test = new MozillaDnDTest(); + if (args.length > 0) { + test.run(args); + } else { + EventQueue.invokeAndWait(test::init); + try { + test.start(); + } finally { + EventQueue.invokeAndWait(() -> { + if (test.frame != null) { + test.frame.dispose(); + } + }); + } + } + } + + public void run(String[] args) { + try { + if (args.length != 4) { + throw new RuntimeException("Incorrect command line arguments."); + } + + int x = Integer.parseInt(args[0]); + int y = Integer.parseInt(args[1]); + int w = Integer.parseInt(args[2]); + int h = Integer.parseInt(args[3]); + + panel = new DragSourcePanel(); + frame = new Frame(); + + frame.setTitle("DragSource frame"); + frame.setLocation(300, 200); + frame.add(panel); + frame.pack(); + frame.setVisible(true); + + Util.waitForInit(); + + Point sourcePoint = panel.getLocationOnScreen(); + Dimension d = panel.getSize(); + sourcePoint.translate(d.width / 2, d.height / 2); + + Point targetPoint = new Point(x + w / 2, y + h / 2); + + robot = new Robot(); + + if (!Util.pointInComponent(robot, sourcePoint, panel)) { + System.err.println("WARNING: Couldn't locate " + panel + + " at point " + sourcePoint); + System.exit(MozillaDnDTest.CODE_OK); + } + + robot.mouseMove(sourcePoint.x, sourcePoint.y); + robot.keyPress(KeyEvent.VK_CONTROL); + robot.mousePress(InputEvent.BUTTON1_MASK); + for (; !sourcePoint.equals(targetPoint); + sourcePoint.translate(sign(targetPoint.x - sourcePoint.x), + sign(targetPoint.y - sourcePoint.y))) { + robot.mouseMove(sourcePoint.x, sourcePoint.y); + Thread.sleep(50); + } + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.keyRelease(KeyEvent.VK_CONTROL); + + } catch (Throwable e) { + e.printStackTrace(); + System.exit(MozillaDnDTest.CODE_FAILURE); + } + } + + public static int sign(int n) { + return n < 0 ? -1 : n == 0 ? 0 : 1; + } + + public void init() { + frame = new Frame(); + panel = new DropTargetPanel(); + + frame.setTitle("DropTarget frame"); + frame.setLocation(10, 200); + frame.add(panel); + + frame.pack(); + frame.setVisible(true); + } + + public void start() { + // Solaris/Linux-only test + if (System.getProperty("os.name").startsWith("Windows")) { + return; + } + try { + Util.waitForInit(); + EventQueue.invokeAndWait(() -> { + p = panel.getLocationOnScreen(); + d = panel.getSize(); + }); + + Robot robot = new Robot(); + Point pp = new Point(p); + pp.translate(d.width / 2, d.height / 2); + if (!Util.pointInComponent(robot, pp, panel)) { + System.err.println("WARNING: Couldn't locate " + panel + + " at point " + pp); + return; + } + + String javaPath = System.getProperty("java.home", ""); + String command = javaPath + File.separator + "bin" + + File.separator + "java -cp " + System.getProperty("test.classes", ".") + + " MozillaDnDTest " + + p.x + " " + p.y + " " + d.width + " " + d.height; + + Process process = Runtime.getRuntime().exec(command); + ProcessResults pres = ProcessResults.doWaitFor(process); + returnCode = pres.exitValue; + + if (pres.stderr != null && pres.stderr.length() > 0) { + System.err.println("========= Child VM System.err ========"); + System.err.print(pres.stderr); + System.err.println("======================================"); + } + + if (pres.stdout != null && pres.stdout.length() > 0) { + System.err.println("========= Child VM System.out ========"); + System.err.print(pres.stdout); + System.err.println("======================================"); + } + + } catch (Throwable e) { + e.printStackTrace(); + } + switch (returnCode) { + case CODE_NOT_RETURNED: + System.err.println("Child VM: failed to start"); + break; + case CODE_OK: + System.err.println("Child VM: normal termination"); + break; + case CODE_FAILURE: + System.err.println("Child VM: abnormal termination"); + break; + } + if (returnCode != CODE_OK) { + throw new RuntimeException("The test failed."); + } + } +} + +class Util implements AWTEventListener { + private static final Toolkit tk = Toolkit.getDefaultToolkit(); + public static final Object SYNC_LOCK = new Object(); + private Component clickedComponent = null; + private static final int PAINT_TIMEOUT = 10000; + private static final int MOUSE_RELEASE_TIMEOUT = 10000; + private static final Util util = new Util(); + + static { + tk.addAWTEventListener(util, 0xFFFFFFFF); + } + + private void reset() { + clickedComponent = null; + } + + public void eventDispatched(AWTEvent e) { + if (e.getID() == MouseEvent.MOUSE_RELEASED) { + clickedComponent = (Component)e.getSource(); + synchronized (SYNC_LOCK) { + SYNC_LOCK.notifyAll(); + } + } + } + + public static boolean pointInComponent(Robot robot, Point p, Component comp) + throws InterruptedException { + return util.isPointInComponent(robot, p, comp); + } + + private boolean isPointInComponent(Robot robot, Point p, Component comp) + throws InterruptedException { + tk.sync(); + robot.waitForIdle(); + reset(); + robot.mouseMove(p.x, p.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + synchronized (SYNC_LOCK) { + robot.mouseRelease(InputEvent.BUTTON1_MASK); + SYNC_LOCK.wait(MOUSE_RELEASE_TIMEOUT); + } + + Component c = clickedComponent; + + while (c != null && c != comp) { + c = c.getParent(); + } + + return c == comp; + } + + public static void waitForInit() throws InterruptedException { + final Frame f = new Frame() { + public void paint(Graphics g) { + dispose(); + synchronized (SYNC_LOCK) { + SYNC_LOCK.notifyAll(); + } + } + }; + f.setBounds(600, 400, 200, 200); + synchronized (SYNC_LOCK) { + f.setVisible(true); + SYNC_LOCK.wait(PAINT_TIMEOUT); + } + tk.sync(); + } +} + +class ProcessResults { + public int exitValue; + public String stdout; + public String stderr; + + public ProcessResults() { + exitValue = -1; + stdout = ""; + stderr = ""; + } + + /** + * Method to perform a "wait" for a process and return its exit value. + * This is a workaround for Process.waitFor() never returning. + */ + public static ProcessResults doWaitFor(Process p) { + ProcessResults pres = new ProcessResults(); + + InputStream in = null; + InputStream err = null; + + try { + in = p.getInputStream(); + err = p.getErrorStream(); + + boolean finished = false; + + while (!finished) { + try { + while (in.available() > 0) { + pres.stdout += (char)in.read(); + } + while (err.available() > 0) { + pres.stderr += (char)err.read(); + } + // Ask the process for its exitValue. If the process + // is not finished, an IllegalThreadStateException + // is thrown. If it is finished, we fall through and + // the variable finished is set to true. + pres.exitValue = p.exitValue(); + finished = true; + } + catch (IllegalThreadStateException e) { + // Process is not finished yet; + // Sleep a little to save on CPU cycles + Thread.currentThread().sleep(500); + } + } + if (in != null) in.close(); + if (err != null) err.close(); + } + catch (Throwable e) { + System.err.println("doWaitFor(): unexpected exception"); + e.printStackTrace(); + } + return pres; + } +} + +class DragSourcePanel extends Panel { + static final Dimension preferredDimension = new Dimension(200, 200); + static final DataFlavor df = new DataFlavor("application/mozilla-test-flavor", + null); + final DragSource ds = DragSource.getDefaultDragSource(); + final Transferable t = new Transferable() { + final DataFlavor[] flavors = new DataFlavor[] { df }; + public DataFlavor[] getTransferDataFlavors() { + return flavors; + } + public boolean isDataFlavorSupported(DataFlavor flav) { + return df.equals(flav); + } + public Object getTransferData(DataFlavor flav) + throws IOException, UnsupportedFlavorException { + if (!isDataFlavorSupported(flav)) { + throw new UnsupportedFlavorException(flav); + } + byte[] bytes = MozillaDnDTest.DATA.getBytes("ASCII"); + return new ByteArrayInputStream(bytes); + } + }; + final DragSourceListener dsl = new DragSourceAdapter() { + public void dragDropEnd(DragSourceDropEvent dsde) { + System.exit(MozillaDnDTest.CODE_OK); + } + }; + final DragGestureListener dgl = new DragGestureListener() { + public void dragGestureRecognized(DragGestureEvent dge) { + dge.startDrag(null, t, dsl); + } + }; + final DragGestureRecognizer dgr = + ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, + dgl); + static { + SystemFlavorMap sfm = + (SystemFlavorMap)SystemFlavorMap.getDefaultFlavorMap(); + String[] natives = new String[] { + "_NETSCAPE_URL", + "text/plain", + "text/unicode", + "text/x-moz-url", + "text/html" + }; + sfm.setNativesForFlavor(df, natives); + } + + public Dimension getPreferredSize() { + return preferredDimension; + } +} + +class DropTargetPanel extends Panel implements DropTargetListener { + + final Dimension preferredDimension = new Dimension(200, 200); + final DropTarget dt = new DropTarget(this, this); + + public Dimension getPreferredSize() { + return preferredDimension; + } + + public void dragEnter(DropTargetDragEvent dtde) { + dtde.acceptDrag(DnDConstants.ACTION_COPY); + } + + public void dragExit(DropTargetEvent dte) {} + + public void dragOver(DropTargetDragEvent dtde) { + dtde.acceptDrag(DnDConstants.ACTION_COPY); + } + + public String getTransferString(Transferable t) { + String string = null; + DataFlavor[] dfs = t.getTransferDataFlavors(); + for (int i = 0; i < dfs.length; i++) { + if ("text".equals(dfs[i].getPrimaryType()) || + DataFlavor.stringFlavor.equals(dfs[i])) { + try { + Object o = t.getTransferData(dfs[i]); + if (o instanceof InputStream || + o instanceof Reader) { + Reader reader = null; + if (o instanceof InputStream) { + InputStream is = (InputStream)o; + reader = new InputStreamReader(is); + } else { + reader = (Reader)o; + } + StringBuffer buf = new StringBuffer(); + for (int c = reader.read(); c != -1; c = reader.read()) { + buf.append((char)c); + } + reader.close(); + string = buf.toString(); + break; + } else if (o instanceof String) { + string = (String)o; + break; + } + } catch (Exception e) { + // ignore. + } + } + } + return string; + } + + public void drop(DropTargetDropEvent dtde) { + DropTargetContext dtc = dtde.getDropTargetContext(); + + if ((dtde.getSourceActions() & DnDConstants.ACTION_COPY) != 0) { + dtde.acceptDrop(DnDConstants.ACTION_COPY); + } else { + dtde.rejectDrop(); + return; + } + + Transferable t = dtde.getTransferable(); + String str = getTransferString(t); + dtde.dropComplete(true); + + if (!MozillaDnDTest.DATA.equals(str)) { + throw new RuntimeException("Drop data:" + str); + } + } + + public void dropActionChanged(DropTargetDragEvent dtde) {} +} diff --git a/test/jdk/java/awt/dnd/MultiDataFlavorDropTest.java b/test/jdk/java/awt/dnd/MultiDataFlavorDropTest.java new file mode 100644 index 00000000000..41ae7f609c8 --- /dev/null +++ b/test/jdk/java/awt/dnd/MultiDataFlavorDropTest.java @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Button; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.List; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceDragEvent; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceEvent; +import java.awt.dnd.DragSourceListener; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetContext; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.io.File; +import java.io.InputStream; +import java.io.Serializable; + +/* + @test + @bug 4399700 + @summary tests that drop transfer data can be requested in several data flavors. + @key headful + @run main MultiDataFlavorDropTest +*/ + +public class MultiDataFlavorDropTest { + + public static final int CODE_NOT_RETURNED = -1; + public static final int CODE_OK = 0; + public static final int CODE_FAILURE = 1; + public static final int FRAME_ACTIVATION_TIMEOUT = 2000; + public static final int DROP_TIMEOUT = 10000; + public static final int DROP_COMPLETION_TIMEOUT = 1000; + + private int returnCode = CODE_NOT_RETURNED; + + volatile Frame frame; + volatile Robot robot; + volatile Panel panel; + volatile Point p; + volatile Dimension d; + + public static void main(String[] args) throws Exception { + MultiDataFlavorDropTest test = new MultiDataFlavorDropTest(); + if (args.length > 0) { + test.run(args); + } else { + EventQueue.invokeAndWait(test::init); + try { + test.start(); + } finally { + EventQueue.invokeAndWait(() -> { + if (test.frame != null) { + test.frame.dispose(); + } + }); + } + } + } + + public void run(String[] args) { + try { + if (args.length != 4) { + throw new RuntimeException("Incorrect command line arguments."); + } + + int x = Integer.parseInt(args[0]); + int y = Integer.parseInt(args[1]); + int w = Integer.parseInt(args[2]); + int h = Integer.parseInt(args[3]); + + Transferable t = new TransferableNumber(); + panel = new DragSourcePanel(t); + + frame = new Frame(); + frame.setTitle("DragSource frame"); + frame.setLocation(300, 200); + frame.add(panel); + frame.pack(); + frame.setVisible(true); + + Thread.sleep(FRAME_ACTIVATION_TIMEOUT); + + Point sourcePoint = panel.getLocationOnScreen(); + Dimension d = panel.getSize(); + sourcePoint.translate(d.width / 2, d.height / 2); + + Point targetPoint = new Point(x + w / 2, y + h / 2); + + robot = new Robot(); + robot.mouseMove(sourcePoint.x, sourcePoint.y); + robot.keyPress(KeyEvent.VK_CONTROL); + robot.mousePress(InputEvent.BUTTON1_MASK); + for (; !sourcePoint.equals(targetPoint); + sourcePoint.translate(sign(targetPoint.x - sourcePoint.x), + sign(targetPoint.y - sourcePoint.y))) { + robot.mouseMove(sourcePoint.x, sourcePoint.y); + Thread.sleep(10); + } + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.keyRelease(KeyEvent.VK_CONTROL); + + synchronized (t) { + t.wait(DROP_TIMEOUT); + } + + Thread.sleep(DROP_COMPLETION_TIMEOUT); + + } catch (Throwable e) { + e.printStackTrace(); + System.exit(MultiDataFlavorDropTest.CODE_FAILURE); + } + System.exit(MultiDataFlavorDropTest.CODE_OK); + } + + public static int sign(int n) { + return n < 0 ? -1 : n == 0 ? 0 : 1; + } + + public void init() { + frame = new Frame(); + panel = new DropTargetPanel(); + + frame.setTitle("MultiDataFlavorDropTest"); + frame.setLocation(10, 200); + frame.add(panel); + + frame.pack(); + frame.setVisible(true); + } + + public void start() throws Exception { + Thread.sleep(FRAME_ACTIVATION_TIMEOUT); + + EventQueue.invokeAndWait(() -> { + p = panel.getLocationOnScreen(); + d = panel.getSize(); + }); + + String javaPath = System.getProperty("java.home", ""); + String command = javaPath + File.separator + "bin" + + File.separator + "java -cp " + System.getProperty("test.classes", ".") + + " MultiDataFlavorDropTest " + + p.x + " " + p.y + " " + d.width + " " + d.height; + + Process process = Runtime.getRuntime().exec(command); + returnCode = process.waitFor(); + + InputStream errorStream = process.getErrorStream(); + int count = errorStream.available(); + if (count > 0) { + byte[] b = new byte[count]; + errorStream.read(b); + System.err.println("========= Child VM System.err ========"); + System.err.print(new String(b)); + System.err.println("======================================"); + } + + switch (returnCode) { + case CODE_NOT_RETURNED: + System.err.println("Child VM: failed to start"); + break; + case CODE_OK: + System.err.println("Child VM: normal termination"); + break; + case CODE_FAILURE: + System.err.println("Child VM: abnormal termination"); + break; + } + if (returnCode != CODE_OK) { + throw new RuntimeException("The test failed."); + } + } +} + +class DragSourceButton extends Button implements Serializable, + DragGestureListener, + DragSourceListener { + + final Transferable transferable; + + public DragSourceButton(Transferable t) { + super("DragSourceButton"); + + this.transferable = t; + DragSource ds = DragSource.getDefaultDragSource(); + ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, + this); + } + + public void dragGestureRecognized(DragGestureEvent dge) { + dge.startDrag(null, transferable, this); + } + + public void dragEnter(DragSourceDragEvent dsde) {} + + public void dragExit(DragSourceEvent dse) {} + + public void dragOver(DragSourceDragEvent dsde) {} + + public void dragDropEnd(DragSourceDropEvent dsde) {} + + public void dropActionChanged(DragSourceDragEvent dsde) {} +} + +class IntegerDataFlavor extends DataFlavor { + + private final int number; + + public IntegerDataFlavor(int n) throws ClassNotFoundException { + super("application/integer-" + n + + "; class=java.lang.Integer"); + this.number = n; + } + + public int getNumber() { + return number; + } +} + +class TransferableNumber implements Transferable { + + private int transferDataRequestCount = 0; + public static final int NUM_DATA_FLAVORS = 5; + static final DataFlavor[] supportedFlavors = + new DataFlavor[NUM_DATA_FLAVORS]; + + static { + try { + for (int i = 0; i < NUM_DATA_FLAVORS; i++) { + supportedFlavors[i] = + new IntegerDataFlavor(i); + } + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + + public DataFlavor[] getTransferDataFlavors() { + return supportedFlavors; + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + if (flavor instanceof IntegerDataFlavor) { + IntegerDataFlavor integerFlavor = (IntegerDataFlavor)flavor; + int flavorNumber = integerFlavor.getNumber(); + if (flavorNumber >= 0 && flavorNumber < NUM_DATA_FLAVORS) { + return true; + } + } + return false; + } + + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException { + + if (!isDataFlavorSupported(flavor)) { + throw new UnsupportedFlavorException(flavor); + } + + transferDataRequestCount++; + + if (transferDataRequestCount >= NUM_DATA_FLAVORS) { + synchronized (this) { + this.notifyAll(); + } + } + + IntegerDataFlavor integerFlavor = (IntegerDataFlavor)flavor; + return new Integer(integerFlavor.getNumber()); + } +} + +class DragSourcePanel extends Panel { + + final Dimension preferredDimension = new Dimension(200, 200); + + public DragSourcePanel(Transferable t) { + setLayout(new GridLayout(1, 1)); + add(new DragSourceButton(t)); + } + + public Dimension getPreferredSize() { + return preferredDimension; + } +} + +class DropTargetPanel extends Panel implements DropTargetListener { + + final Dimension preferredDimension = new Dimension(200, 200); + + public DropTargetPanel() { + setBackground(Color.green); + setDropTarget(new DropTarget(this, this)); + setLayout(new GridLayout(1, 1)); + } + + public Dimension getPreferredSize() { + return preferredDimension; + } + + public void dragEnter(DropTargetDragEvent dtde) { + dtde.acceptDrag(DnDConstants.ACTION_COPY); + } + + public void dragExit(DropTargetEvent dte) {} + + public void dragOver(DropTargetDragEvent dtde) { + dtde.acceptDrag(DnDConstants.ACTION_COPY); + } + + public void drop(DropTargetDropEvent dtde) { + DropTargetContext dtc = dtde.getDropTargetContext(); + + if ((dtde.getSourceActions() & DnDConstants.ACTION_COPY) != 0) { + dtde.acceptDrop(DnDConstants.ACTION_COPY); + } else { + dtde.rejectDrop(); + return; + } + + removeAll(); + final List list = new List(); + add(list); + + Transferable t = dtde.getTransferable(); + DataFlavor[] dfs = t.getTransferDataFlavors(); + + if (dfs.length != TransferableNumber.NUM_DATA_FLAVORS) { + throw new RuntimeException("FAILED: Incorrect number of data flavors."); + } + + for (int i = 0; i < dfs.length; i++) { + + DataFlavor flavor = dfs[i]; + Integer transferNumber = null; + + if (flavor.getRepresentationClass().equals(Integer.class)) { + try { + transferNumber = (Integer)t.getTransferData(flavor); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("FAILED: Cannot get data: " + + flavor.getMimeType()); + } + } + + boolean supportedFlavor = false; + for (int j = 0; j < TransferableNumber.NUM_DATA_FLAVORS; j++) { + int number = (i + j) % TransferableNumber.NUM_DATA_FLAVORS; + try { + if (flavor.equals(new IntegerDataFlavor(number))) { + if (!(new Integer(number).equals(transferNumber))) { + throw new RuntimeException("FAILED: Invalid data \n" + + "\tflavor : " + flavor + + "\tdata : " + transferNumber); + } + supportedFlavor = true; + break; + } + } catch (ClassNotFoundException cannotHappen) { + } + } + if (!supportedFlavor) { + throw new RuntimeException("FAILED: Invalid flavor: " + flavor); + } + + list.add(transferNumber + ":" + flavor.getMimeType()); + } + + dtc.dropComplete(true); + validate(); + } + + public void dropActionChanged(DropTargetDragEvent dtde) {} +} diff --git a/test/jdk/java/awt/dnd/NativeDragJavaDropTest.java b/test/jdk/java/awt/dnd/NativeDragJavaDropTest.java new file mode 100644 index 00000000000..9bc0dff3b44 --- /dev/null +++ b/test/jdk/java/awt/dnd/NativeDragJavaDropTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Point; +import java.awt.Robot; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetContext; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.event.InputEvent; + +/* + @test + @bug 4399700 + @summary tests that Motif drag support for label widget doesn't cause + crash when used for drag and drop from label to Java drop target + @key headful + @run main NativeDragJavaDropTest +*/ + +public class NativeDragJavaDropTest { + + volatile Frame frame; + volatile DropTargetLabel label; + volatile Point p; + volatile Dimension d; + public static final int FRAME_ACTIVATION_TIMEOUT = 1000; + public static final int DRAG_START_TIMEOUT = 500; + public static final int DROP_COMPLETION_TIMEOUT = 2000; + + public static void main(String[] args) throws Exception { + NativeDragJavaDropTest test = new NativeDragJavaDropTest(); + EventQueue.invokeAndWait(test::init); + try { + test.start(); + } finally { + EventQueue.invokeAndWait(() -> { + if (test.frame != null) { + test.frame.dispose(); + } + }); + } + } + + public void init() { + frame = new Frame(); + label = new DropTargetLabel(); + frame.setTitle("NativeDragJavaDropTest"); + frame.setLocation(200, 200); + frame.add(label); + + frame.pack(); + frame.setVisible(true); + } + + public void start() throws Exception { + Robot robot = new Robot(); + robot.waitForIdle(); + Thread.sleep(FRAME_ACTIVATION_TIMEOUT); + + EventQueue.invokeAndWait(() -> { + p = label.getLocationOnScreen(); + d = label.getSize(); + }); + + p.translate(d.width / 2, d.height / 2); + + robot.mouseMove(p.x, p.y); + robot.mousePress(InputEvent.BUTTON2_MASK); + + Thread.sleep(DRAG_START_TIMEOUT); + + robot.mouseRelease(InputEvent.BUTTON2_MASK); + + Thread.sleep(DROP_COMPLETION_TIMEOUT); + } +} + +class DropTargetLabel extends Label implements DropTargetListener { + + final Dimension preferredDimension = new Dimension(200, 100); + + public DropTargetLabel() { + super("Label"); + setDropTarget(new DropTarget(this, this)); + } + + public Dimension getPreferredSize() { + return preferredDimension; + } + + public void dragEnter(DropTargetDragEvent dtde) {} + + public void dragExit(DropTargetEvent dte) {} + + public void dragOver(DropTargetDragEvent dtde) {} + + public void dropActionChanged(DropTargetDragEvent dtde) {} + + public void drop(DropTargetDropEvent dtde) { + DropTargetContext dtc = dtde.getDropTargetContext(); + + if ((dtde.getSourceActions() & DnDConstants.ACTION_COPY) != 0) { + dtde.acceptDrop(DnDConstants.ACTION_COPY); + } else { + dtde.rejectDrop(); + } + + DataFlavor[] dfs = dtde.getCurrentDataFlavors(); + + if (dfs != null && dfs.length >= 1) { + Transferable transfer = dtde.getTransferable(); + + try { + Object obj = (Object)transfer.getTransferData(dfs[0]); + } catch (Throwable e) { + e.printStackTrace(); + dtc.dropComplete(false); + } + } + dtc.dropComplete(true); + } +} diff --git a/test/jdk/java/awt/dnd/NestedHeavyweightDropTargetTest.java b/test/jdk/java/awt/dnd/NestedHeavyweightDropTargetTest.java new file mode 100644 index 00000000000..9f36e687833 --- /dev/null +++ b/test/jdk/java/awt/dnd/NestedHeavyweightDropTargetTest.java @@ -0,0 +1,492 @@ +/* + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.AWTEvent; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.GridLayout; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceDragEvent; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceEvent; +import java.awt.dnd.DragSourceListener; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetContext; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.event.AWTEventListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +/* + @test + @bug 4389284 + @summary tests that drop targets registered on nested heavyweight + components work properly + @key headful + @run main NestedHeavyweightDropTargetTest +*/ + +public class NestedHeavyweightDropTargetTest { + + volatile Frame frame; + volatile DragSourceButton dragSourceButton; + volatile DropTargetPanel dropTargetPanel; + volatile InnerDropTargetPanel innerDropTargetPanel; + volatile Button button; + volatile Dimension d; + volatile Point srcPoint; + volatile Point dstPoint; + + static final int DROP_COMPLETION_TIMEOUT = 1000; + + public static void main(String[] args) throws Exception { + NestedHeavyweightDropTargetTest test = new NestedHeavyweightDropTargetTest(); + EventQueue.invokeAndWait(test::init); + try { + test.start(); + } finally { + EventQueue.invokeAndWait(() -> { + if (test.frame != null) { + test.frame.dispose(); + } + }); + } + } + + public void init() { + frame = new Frame(); + dragSourceButton = new DragSourceButton(); + dropTargetPanel = new DropTargetPanel(); + innerDropTargetPanel = new InnerDropTargetPanel(); + button = new Button("button"); + button.setBackground(Color.red); + + innerDropTargetPanel.setLayout(new GridLayout(3, 1)); + innerDropTargetPanel.add(button); + innerDropTargetPanel.setBackground(Color.yellow); + + dropTargetPanel.setLayout(new GridLayout(2, 1)); + dropTargetPanel.add(innerDropTargetPanel); + dropTargetPanel.setBackground(Color.green); + + frame.setTitle("NestedHeavyweightDropTargetTest"); + frame.setLocation(200, 200); + frame.setLayout(new BorderLayout()); + frame.add(dropTargetPanel, BorderLayout.CENTER); + frame.add(dragSourceButton, BorderLayout.SOUTH); + + frame.pack(); + + innerDropTargetPanel.setDropTarget(new DropTarget(innerDropTargetPanel, innerDropTargetPanel)); + dropTargetPanel.setDropTarget(new DropTarget(dropTargetPanel, dropTargetPanel)); + + frame.setVisible(true); + } + + public void start() throws Exception { + Robot robot = new Robot(); + Util.waitForInit(); + + test1(robot); + test2(robot); + } + + public static int sign(int n) { + return n < 0 ? -1 : n == 0 ? 0 : 1; + } + + public void test1(Robot robot) throws Exception { + innerDropTargetPanel.setDragEnterTriggered(false); + innerDropTargetPanel.setDragOverTriggered(false); + innerDropTargetPanel.setDragExitTriggered(false); + innerDropTargetPanel.setDropTriggered(false); + + EventQueue.invokeAndWait(() -> { + srcPoint = dragSourceButton.getLocationOnScreen(); + d = dragSourceButton.getSize(); + }); + + srcPoint.translate(d.width / 2, d.height / 2); + + if (!Util.pointInComponent(robot, srcPoint, dragSourceButton)) { + System.err.println("WARNING: Couldn't locate " + dragSourceButton + + " at point " + srcPoint); + return; + } + + EventQueue.invokeAndWait(() -> { + dstPoint = innerDropTargetPanel.getLocationOnScreen(); + d = innerDropTargetPanel.getSize(); + }); + + dstPoint.translate(d.width / 2, d.height / 2); + + if (!Util.pointInComponent(robot, dstPoint, innerDropTargetPanel)) { + System.err.println("WARNING: Couldn't locate " + innerDropTargetPanel + + " at point " + dstPoint); + return; + } + + robot.mouseMove(srcPoint.x, srcPoint.y); + robot.keyPress(KeyEvent.VK_CONTROL); + robot.mousePress(InputEvent.BUTTON1_MASK); + for (;!srcPoint.equals(dstPoint); + srcPoint.translate(sign(dstPoint.x - srcPoint.x), + sign(dstPoint.y - srcPoint.y))) { + robot.mouseMove(srcPoint.x, srcPoint.y); + Thread.sleep(10); + } + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.keyRelease(KeyEvent.VK_CONTROL); + + Thread.sleep(DROP_COMPLETION_TIMEOUT); + + if (!innerDropTargetPanel.isDragEnterTriggered()) { + throw new RuntimeException("child dragEnter() not triggered"); + } + + if (!innerDropTargetPanel.isDragOverTriggered()) { + throw new RuntimeException("child dragOver() not triggered"); + } + + if (!innerDropTargetPanel.isDropTriggered()) { + throw new RuntimeException("child drop() not triggered"); + } + } + + public void test2(Robot robot) throws Exception { + innerDropTargetPanel.setDragEnterTriggered(false); + innerDropTargetPanel.setDragOverTriggered(false); + innerDropTargetPanel.setDragExitTriggered(false); + innerDropTargetPanel.setDropTriggered(false); + + EventQueue.invokeAndWait(() -> { + srcPoint = dragSourceButton.getLocationOnScreen(); + d = dragSourceButton.getSize(); + }); + srcPoint.translate(d.width / 2, d.height / 2); + + if (!Util.pointInComponent(robot, srcPoint, dragSourceButton)) { + System.err.println("WARNING: Couldn't locate " + dragSourceButton + + " at point " + srcPoint); + return; + } + + EventQueue.invokeAndWait(() -> { + dstPoint = button.getLocationOnScreen(); + d = button.getSize(); + }); + + dstPoint.translate(d.width / 2, d.height / 2); + + if (!Util.pointInComponent(robot, dstPoint, button)) { + System.err.println("WARNING: Couldn't locate " + button + + " at point " + dstPoint); + return; + } + + robot.mouseMove(srcPoint.x, srcPoint.y); + robot.keyPress(KeyEvent.VK_CONTROL); + robot.mousePress(InputEvent.BUTTON1_MASK); + for (;!srcPoint.equals(dstPoint); + srcPoint.translate(sign(dstPoint.x - srcPoint.x), + sign(dstPoint.y - srcPoint.y))) { + robot.mouseMove(srcPoint.x, srcPoint.y); + Thread.sleep(10); + } + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.keyRelease(KeyEvent.VK_CONTROL); + + Thread.sleep(DROP_COMPLETION_TIMEOUT); + + if (!innerDropTargetPanel.isDragEnterTriggered()) { + throw new RuntimeException("child dragEnter() not triggered"); + } + + if (!innerDropTargetPanel.isDragOverTriggered()) { + throw new RuntimeException("child dragOver() not triggered"); + } + + if (!innerDropTargetPanel.isDropTriggered()) { + throw new RuntimeException("child drop() not triggered"); + } + } +} + +class Util implements AWTEventListener { + private static final Toolkit tk = Toolkit.getDefaultToolkit(); + public static final Object SYNC_LOCK = new Object(); + private Component clickedComponent = null; + private static final int PAINT_TIMEOUT = 10000; + private static final int MOUSE_RELEASE_TIMEOUT = 10000; + private static final Util util = new Util(); + + static { + tk.addAWTEventListener(util, 0xFFFFFFFF); + } + + private void reset() { + clickedComponent = null; + } + + public void eventDispatched(AWTEvent e) { + if (e.getID() == MouseEvent.MOUSE_RELEASED) { + clickedComponent = (Component)e.getSource(); + synchronized (SYNC_LOCK) { + SYNC_LOCK.notifyAll(); + } + } + } + + public static boolean pointInComponent(Robot robot, Point p, Component comp) + throws InterruptedException { + return util.isPointInComponent(robot, p, comp); + } + + private boolean isPointInComponent(Robot robot, Point p, Component comp) + throws InterruptedException { + tk.sync(); + robot.waitForIdle(); + reset(); + robot.mouseMove(p.x, p.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + synchronized (SYNC_LOCK) { + robot.mouseRelease(InputEvent.BUTTON1_MASK); + SYNC_LOCK.wait(MOUSE_RELEASE_TIMEOUT); + } + + Component c = clickedComponent; + + while (c != null && c != comp) { + c = c.getParent(); + } + + return c == comp; + } + + public static void waitForInit() throws InterruptedException { + final Frame f = new Frame() { + public void paint(Graphics g) { + dispose(); + synchronized (SYNC_LOCK) { + SYNC_LOCK.notifyAll(); + } + } + }; + f.setBounds(600, 400, 200, 200); + synchronized (SYNC_LOCK) { + f.setVisible(true); + SYNC_LOCK.wait(PAINT_TIMEOUT); + } + tk.sync(); + } +} + +class DragSourceButton extends Button implements Serializable, + Transferable, + DragGestureListener, + DragSourceListener { + private final DataFlavor dataflavor = + new DataFlavor(Button.class, "DragSourceButton"); + + public DragSourceButton() { + this("DragSourceButton"); + } + + public DragSourceButton(String str) { + super(str); + + DragSource ds = DragSource.getDefaultDragSource(); + ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, + this); + } + + public void dragGestureRecognized(DragGestureEvent dge) { + dge.startDrag(null, this, this); + } + + public void dragEnter(DragSourceDragEvent dsde) {} + + public void dragExit(DragSourceEvent dse) {} + + public void dragOver(DragSourceDragEvent dsde) {} + + public void dragDropEnd(DragSourceDropEvent dsde) {} + + public void dropActionChanged(DragSourceDragEvent dsde) {} + + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException, IOException { + + if (!isDataFlavorSupported(flavor)) { + throw new UnsupportedFlavorException(flavor); + } + + Object retObj = null; + + ByteArrayOutputStream baoStream = new ByteArrayOutputStream(); + ObjectOutputStream ooStream = new ObjectOutputStream(baoStream); + ooStream.writeObject(this); + + ByteArrayInputStream baiStream = new ByteArrayInputStream(baoStream.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(baiStream); + try { + retObj = ois.readObject(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + throw new RuntimeException(e.toString()); + } + + return retObj; + } + + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[] { dataflavor }; + } + + public boolean isDataFlavorSupported(DataFlavor dflavor) { + return dataflavor.equals(dflavor); + } +} + +class InnerDropTargetPanel extends DropTargetPanel { + private boolean dragEnterTriggered = false; + private boolean dragOverTriggered = false; + private boolean dragExitTriggered = false; + private boolean dropTriggered = false; + + public void dragEnter(DropTargetDragEvent dtde) { + setDragEnterTriggered(true); + } + + public void dragExit(DropTargetEvent dte) { + setDragExitTriggered(true); + } + + public void dragOver(DropTargetDragEvent dtde) { + setDragOverTriggered(true); + } + + public void dropActionChanged(DropTargetDragEvent dtde) {} + + public void drop(DropTargetDropEvent dtde) { + setDropTriggered(true); + dtde.rejectDrop(); + } + + public boolean isDragEnterTriggered() { + return dragEnterTriggered; + } + + public boolean isDragOverTriggered() { + return dragOverTriggered; + } + + public boolean isDragExitTriggered() { + return dragExitTriggered; + } + + public boolean isDropTriggered() { + return dropTriggered; + } + + public void setDragEnterTriggered(boolean b) { + dragEnterTriggered = b; + } + + public void setDragOverTriggered(boolean b) { + dragOverTriggered = b; + } + + public void setDragExitTriggered(boolean b) { + dragExitTriggered = b; + } + + public void setDropTriggered(boolean b) { + dropTriggered = b; + } +} + +class DropTargetPanel extends Panel implements DropTargetListener { + + public void dragEnter(DropTargetDragEvent dtde) {} + + public void dragExit(DropTargetEvent dte) {} + + public void dragOver(DropTargetDragEvent dtde) {} + + public void dropActionChanged(DropTargetDragEvent dtde) {} + + public void drop(DropTargetDropEvent dtde) { + DropTargetContext dtc = dtde.getDropTargetContext(); + + if ((dtde.getSourceActions() & DnDConstants.ACTION_COPY) != 0) { + dtde.acceptDrop(DnDConstants.ACTION_COPY); + } else { + dtde.rejectDrop(); + } + + DataFlavor[] dfs = dtde.getCurrentDataFlavors(); + Component comp = null; + + if (dfs != null && dfs.length >= 1) { + Transferable transfer = dtde.getTransferable(); + + try { + comp = (Component)transfer.getTransferData(dfs[0]); + } catch (Throwable e) { + e.printStackTrace(); + dtc.dropComplete(false); + } + } + dtc.dropComplete(true); + + add(comp); + } +} diff --git a/test/jdk/java/awt/dnd/NextDropActionTest/NextDropActionTest.java b/test/jdk/java/awt/dnd/NextDropActionTest/NextDropActionTest.java new file mode 100644 index 00000000000..e4d61a5d166 --- /dev/null +++ b/test/jdk/java/awt/dnd/NextDropActionTest/NextDropActionTest.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4887150 + @summary tests that after performing COPY drop, MOVE drop can be performed too + @key headful + @run main NextDropActionTest +*/ + +import java.awt.AWTException; +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.datatransfer.StringSelection; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceListener; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetAdapter; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.lang.reflect.InvocationTargetException; + + +public class NextDropActionTest { + private final long WAIT_TIMEOUT = 30000; + private volatile boolean failed; + private volatile boolean firstEnd; + private volatile boolean secondEnd; + private final Object LOCK = new Object(); + private Frame frame; + private Panel panel; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + NextDropActionTest nextDropActionTest = new NextDropActionTest(); + nextDropActionTest.start(); + } + + public void start() throws InterruptedException, + InvocationTargetException, AWTException { + + EventQueue.invokeAndWait(() -> { + panel = new Panel(); + frame = new Frame("NextDropActionTest"); + frame.add(panel); + frame.setBounds(300, 300, 300, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.validate(); + }); + + try { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + + final DragSourceListener dsl = new DragSourceAdapter() { + boolean firstCall = true; + public void dragDropEnd(DragSourceDropEvent e) { + System.err.println("DragSourseListener.dragDropEnd(): " + + " firstCall=" + firstCall + + " drop action=" + e.getDropAction()); + if (firstCall) { + firstCall = false; + synchronized (LOCK) { + firstEnd = true; + LOCK.notifyAll(); + } + return; + } + if (e.getDropAction() != DnDConstants.ACTION_MOVE) { + System.err.println("FAILURE: wrong drop action:" + + e.getDropAction()); + failed = true; + } + synchronized (LOCK) { + secondEnd = true; + LOCK.notifyAll(); + } + } + }; + + DragGestureListener dgl = dge -> + dge.startDrag(null, new StringSelection("test"), dsl); + + new DragSource().createDefaultDragGestureRecognizer(panel, + DnDConstants.ACTION_COPY_OR_MOVE, dgl); + + DropTargetListener dtl = new DropTargetAdapter() { + public void drop(DropTargetDropEvent e) { + System.err.println("DropTargetListener.drop(): " + + "accepting the user drop action=" + e.getDropAction()); + e.acceptDrop(e.getDropAction()); + e.dropComplete(true); + } + }; + + new DropTarget(frame, DnDConstants.ACTION_COPY_OR_MOVE, dtl); + + Point startPoint = new Point(Util.blockTillDisplayed(panel)); + startPoint.translate(50, 50); + Point endPoint = new Point(startPoint.x + + DragSource.getDragThreshold() + 10, + startPoint.y + DragSource.getDragThreshold() + 10); + + synchronized (LOCK) { + robot.keyPress(KeyEvent.VK_CONTROL); + Util.doDragDrop(robot, startPoint, endPoint); + robot.keyRelease(KeyEvent.VK_CONTROL); + LOCK.wait(WAIT_TIMEOUT); + } + if (!firstEnd) { + System.err.println("DragSourseListener.dragDropEnd() " + + "was not called, returning"); + return; + } + + synchronized (LOCK) { + Util.doDragDrop(robot, startPoint, endPoint); + LOCK.wait(WAIT_TIMEOUT); + } + if (!secondEnd) { + System.err.println("DragSourseListener.dragDropEnd() " + + "was not called, returning"); + return; + } + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + + if (failed) { + throw new RuntimeException("wrong next drop action!"); + } + + System.err.println("test passed!"); + } +} + +class Util { + public static int sign(int n) { + return n < 0 ? -1 : n == 0 ? 0 : 1; + } + + public static void doDragDrop(Robot robot, Point startPoint, Point endPoint) { + robot.mouseMove(startPoint.x, startPoint.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + for (Point p = new Point(startPoint); !p.equals(endPoint); + p.translate(Util.sign(endPoint.x - p.x), + Util.sign(endPoint.y - p.y))) { + robot.mouseMove(p.x, p.y); + robot.delay(100); + } + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } + + public static Point blockTillDisplayed(Component comp) { + Point p = null; + while (p == null) { + try { + p = comp.getLocationOnScreen(); + } catch (IllegalStateException e) { + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + } + } + } + return p; + } +} \ No newline at end of file diff --git a/test/jdk/java/awt/dnd/NoFormatsDragEnterTest/NoFormatsDragEnterTest.java b/test/jdk/java/awt/dnd/NoFormatsDragEnterTest/NoFormatsDragEnterTest.java new file mode 100644 index 00000000000..9fea9fa55d8 --- /dev/null +++ b/test/jdk/java/awt/dnd/NoFormatsDragEnterTest/NoFormatsDragEnterTest.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4702735 + @summary tests that a dragEnter is called even if the source doesn't + export data in native formats. + @key headful + @run main NoFormatsDragEnterTest +*/ + +import java.awt.AWTException; +import java.awt.Canvas; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceListener; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + + +public class NoFormatsDragEnterTest { + + Frame frame; + DragSourcePanel dragSourcePanel; + DropTargetPanel dropTargetPanel; + + static final int FRAME_ACTIVATION_TIMEOUT = 1000; + static final int DROP_COMPLETION_TIMEOUT = 1000; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + NoFormatsDragEnterTest noFormatsDragEnterTest = new NoFormatsDragEnterTest(); + EventQueue.invokeAndWait(noFormatsDragEnterTest::init); + noFormatsDragEnterTest.start(); + } + + public void init() { + frame = new Frame(); + dragSourcePanel = new DragSourcePanel(); + dropTargetPanel = new DropTargetPanel(); + + frame.setTitle("NoFormatsDragEnterTest"); + frame.setLayout(new GridLayout(2, 1)); + frame.add(dragSourcePanel); + frame.add(dropTargetPanel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.validate(); + } + + public void start() throws AWTException, InterruptedException, + InvocationTargetException { + try { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(FRAME_ACTIVATION_TIMEOUT); + + final Point srcPoint = dragSourcePanel.getLocationOnScreen(); + Dimension d = dragSourcePanel.getSize(); + srcPoint.translate(d.width / 2, d.height / 2); + + final Point dstPoint = dropTargetPanel.getLocationOnScreen(); + d = dropTargetPanel.getSize(); + dstPoint.translate(d.width / 2, d.height / 2); + + robot.mouseMove(srcPoint.x, srcPoint.y); + robot.keyPress(KeyEvent.VK_CONTROL); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + for (Point curPoint = new Point(srcPoint); + !curPoint.equals(dstPoint); + curPoint.translate(sign(dstPoint.x - curPoint.x), + sign(dstPoint.y - curPoint.y))) { + robot.mouseMove(curPoint.x, curPoint.y); + robot.delay(100); + } + robot.keyRelease(KeyEvent.VK_CONTROL); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.delay(DROP_COMPLETION_TIMEOUT); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + + if (!dropTargetPanel.passed()) { + throw new RuntimeException("Drop doesn't happen."); + } + } + + public static int sign(int n) { + return n < 0 ? -1 : n > 0 ? 1 : 0; + } +} + +class DragSourcePanel extends Canvas implements DragGestureListener { + + private final Dimension preferredDimension = new Dimension(200, 100); + private final DragSourceListener listener = new DragSourceAdapter() {}; + + public DragSourcePanel() { + DragSource ds = DragSource.getDefaultDragSource(); + ds.createDefaultDragGestureRecognizer(this, + DnDConstants.ACTION_COPY_OR_MOVE, + this); + } + + public Dimension getPreferredSize() { + return preferredDimension; + } + + public void dragGestureRecognized(DragGestureEvent dge) { + dge.startDrag(null, new TestTransferable(), listener); + } +} + +class TestTransferable implements Transferable { + + public static DataFlavor dataFlavor = null; + static final Object data = new Object(); + + static { + DataFlavor df = null; + try { + df = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + + "; class=java.lang.Object"); + } catch (ClassNotFoundException e) { + throw new ExceptionInInitializerError(e); + } + dataFlavor = df; + } + + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[] { dataFlavor }; + } + + public boolean isDataFlavorSupported(DataFlavor df) { + return dataFlavor.equals(df); + } + + public Object getTransferData(DataFlavor df) + throws UnsupportedFlavorException, IOException { + if (!isDataFlavorSupported(df)) { + throw new UnsupportedFlavorException(df); + } + return data; + } +} + +class DropTargetPanel extends Canvas implements DropTargetListener { + + private final Dimension preferredDimension = new Dimension(200, 100); + private boolean dragEnterTriggered = false; + private boolean dragOverTriggered = false; + + public DropTargetPanel() { + setDropTarget(new DropTarget(this, this)); + } + + public Dimension getPreferredSize() { + return preferredDimension; + } + + public void dragEnter(DropTargetDragEvent dtde) { + dragEnterTriggered = true; + } + + public void dragExit(DropTargetEvent dte) {} + + public void dragOver(DropTargetDragEvent dtde) { + dragOverTriggered = true; + } + + public void dropActionChanged(DropTargetDragEvent dtde) {} + + public void drop(DropTargetDropEvent dtde) { + dtde.rejectDrop(); + } + + public boolean passed() { + // asserts that dragEnter has been called if dragOver has been called. + return !dragOverTriggered || dragEnterTriggered; + } +} \ No newline at end of file diff --git a/test/jdk/java/awt/dnd/NoFormatsDropTest/NoFormatsDropTest.java b/test/jdk/java/awt/dnd/NoFormatsDropTest/NoFormatsDropTest.java new file mode 100644 index 00000000000..fe0346d95ec --- /dev/null +++ b/test/jdk/java/awt/dnd/NoFormatsDropTest/NoFormatsDropTest.java @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4473062 + @summary tests that a drop happens even if the source doesn't export + data in native formats. + @key headful + @run main NoFormatsDropTest +*/ + +import java.awt.AWTEvent; +import java.awt.AWTException; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceListener; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetContext; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.event.AWTEventListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +public class NoFormatsDropTest implements AWTEventListener { + + Frame frame; + DragSourcePanel dragSourcePanel; + DropTargetPanel dropTargetPanel; + + static final int FRAME_ACTIVATION_TIMEOUT = 1000; + static final int DROP_COMPLETION_TIMEOUT = 1000; + static final int MOUSE_RELEASE_TIMEOUT = 1000; + static final Object SYNC_LOCK = new Object(); + + Component clickedComponent = null; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + NoFormatsDropTest noFormatsDropTest = new NoFormatsDropTest(); + EventQueue.invokeAndWait(noFormatsDropTest::init); + noFormatsDropTest.start(); + } + + public void init() { + frame = new Frame(); + dragSourcePanel = new DragSourcePanel(); + dropTargetPanel = new DropTargetPanel(); + + frame.setTitle("NoFormatsDropTest"); + frame.setLayout(new GridLayout(2, 1)); + frame.add(dragSourcePanel); + frame.add(dropTargetPanel); + + frame.getToolkit().addAWTEventListener(this, AWTEvent.MOUSE_EVENT_MASK); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.validate(); + } + + public void start() throws InterruptedException, AWTException, + InvocationTargetException { + try { + Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.delay(FRAME_ACTIVATION_TIMEOUT); + + final Point srcPoint = dragSourcePanel.getLocationOnScreen(); + Dimension d = dragSourcePanel.getSize(); + srcPoint.translate(d.width / 2, d.height / 2); + + if (!pointInComponent(robot, srcPoint, dragSourcePanel)) { + System.err.println("WARNING: Couldn't locate source panel."); + return; + } + + final Point dstPoint = dropTargetPanel.getLocationOnScreen(); + d = dropTargetPanel.getSize(); + dstPoint.translate(d.width / 2, d.height / 2); + + if (!pointInComponent(robot, dstPoint, dropTargetPanel)) { + System.err.println("WARNING: Couldn't locate target panel."); + return; + } + + robot.mouseMove(srcPoint.x, srcPoint.y); + robot.keyPress(KeyEvent.VK_CONTROL); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + for (Point curPoint = new Point(srcPoint); + !curPoint.equals(dstPoint); + curPoint.translate(sign(dstPoint.x - curPoint.x), + sign(dstPoint.y - curPoint.y))) { + robot.mouseMove(curPoint.x, curPoint.y); + robot.delay(100); + } + robot.keyRelease(KeyEvent.VK_CONTROL); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.delay(DROP_COMPLETION_TIMEOUT); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + + if (!dropTargetPanel.passed()) { + throw new RuntimeException("Drop doesn't happen."); + } + } + + public static int sign(int n) { + return n < 0 ? -1 : n > 0 ? 1 : 0; + } + + public void reset() { + clickedComponent = null; + } + + public void eventDispatched(AWTEvent e) { + if (e.getID() == MouseEvent.MOUSE_RELEASED) { + clickedComponent = (Component)e.getSource(); + synchronized (SYNC_LOCK) { + SYNC_LOCK.notifyAll(); + } + } + } + + boolean pointInComponent(Robot robot, Point p, Component comp) + throws InterruptedException { + robot.waitForIdle(); + reset(); + robot.mouseMove(p.x, p.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + synchronized (SYNC_LOCK) { + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + SYNC_LOCK.wait(MOUSE_RELEASE_TIMEOUT); + } + + Component c = clickedComponent; + + while (c != null && c != comp) { + c = c.getParent(); + } + + return c == comp; + } +} + +class DragSourcePanel extends Panel implements DragGestureListener { + + private final Dimension preferredDimension = new Dimension(200, 100); + private final DragSourceListener listener = new DragSourceAdapter() {}; + + public DragSourcePanel() { + DragSource ds = DragSource.getDefaultDragSource(); + ds.createDefaultDragGestureRecognizer(this, + DnDConstants.ACTION_COPY_OR_MOVE, + this); + } + + public Dimension getPreferredSize() { + return preferredDimension; + } + + public void dragGestureRecognized(DragGestureEvent dge) { + dge.startDrag(null, new TestTransferable(), listener); + } +} + +class TestTransferable implements Transferable { + + public static DataFlavor dataFlavor = null; + static final Object data = new Object(); + + static { + DataFlavor df = null; + try { + df = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + + "; class=java.lang.Object"); + } catch (ClassNotFoundException e) { + throw new ExceptionInInitializerError(e); + } + dataFlavor = df; + } + + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[] { dataFlavor }; + } + + public boolean isDataFlavorSupported(DataFlavor df) { + return dataFlavor.equals(df); + } + + public Object getTransferData(DataFlavor df) + throws UnsupportedFlavorException, IOException { + if (!isDataFlavorSupported(df)) { + throw new UnsupportedFlavorException(df); + } + return data; + } +} + +class DropTargetPanel extends Panel implements DropTargetListener { + + final Dimension preferredDimension = new Dimension(200, 100); + boolean passed = false; + + public DropTargetPanel() { + setDropTarget(new DropTarget(this, this)); + } + + public Dimension getPreferredSize() { + return preferredDimension; + } + + public void dragEnter(DropTargetDragEvent dtde) {} + + public void dragExit(DropTargetEvent dte) {} + + public void dragOver(DropTargetDragEvent dtde) {} + + public void dropActionChanged(DropTargetDragEvent dtde) {} + + public void drop(DropTargetDropEvent dtde) { + DropTargetContext dtc = dtde.getDropTargetContext(); + + if ((dtde.getSourceActions() & DnDConstants.ACTION_COPY) != 0) { + dtde.acceptDrop(DnDConstants.ACTION_COPY); + } else { + dtde.rejectDrop(); + } + + Transferable transfer = dtde.getTransferable(); + + if (transfer.isDataFlavorSupported(TestTransferable.dataFlavor)) { + try { + Object data = + transfer.getTransferData(TestTransferable.dataFlavor); + passed = true; + dtc.dropComplete(true); + } catch (IOException e) { + e.printStackTrace(); + dtc.dropComplete(false); + } catch (UnsupportedFlavorException e) { + e.printStackTrace(); + dtc.dropComplete(false); + } + } else { + dtc.dropComplete(false); + } + } + + boolean passed() { + return passed; + } +} \ No newline at end of file diff --git a/test/jdk/java/awt/dnd/NoTargetNoDragExitTest/NoTargetNoDragExitTest.java b/test/jdk/java/awt/dnd/NoTargetNoDragExitTest/NoTargetNoDragExitTest.java new file mode 100644 index 00000000000..0b1db2dcb5f --- /dev/null +++ b/test/jdk/java/awt/dnd/NoTargetNoDragExitTest/NoTargetNoDragExitTest.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4874092 + @summary tests that DragSourceListener.dragExit() is not called if the mouse + is not dragged over any drop site + @key headful + @run main NoTargetNoDragExitTest +*/ + +import java.awt.AWTEvent; +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceEvent; +import java.awt.dnd.DragSourceListener; +import java.awt.event.AWTEventListener; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; + + +public class NoTargetNoDragExitTest { + private volatile boolean failed; + private volatile boolean end; + private final Object LOCK = new Object(); + private Frame frame; + private Panel panel; + + public static void main(String[] args) throws Exception { + NoTargetNoDragExitTest noTargetNoDragExitTest = new NoTargetNoDragExitTest(); + EventQueue.invokeAndWait(noTargetNoDragExitTest::init); + noTargetNoDragExitTest.start(); + } + + public void init() { + frame = new Frame("NoTargetNoDragExitTest"); + panel = new Panel(); + frame.add(panel); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.validate(); + } + + public void start() throws Exception { + try { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + + final DragSourceListener dsl = new DragSourceAdapter() { + public void dragExit(DragSourceEvent e) { + failed = true; + System.err.println("FAILURE: DragSourceListener.dragExit() called!"); + } + public void dragDropEnd(DragSourceDropEvent e) { + System.err.println("DragSourceListener.dragDropEnd()"); + synchronized (LOCK) { + end = true; + LOCK.notifyAll(); + } + } + }; + + DragGestureListener dgl = dge -> + dge.startDrag(null, new StringSelection("NoTargetNoDragExitTest"), dsl); + + new DragSource().createDefaultDragGestureRecognizer(panel, + DnDConstants.ACTION_COPY_OR_MOVE, dgl); + + Point startPoint = frame.getLocationOnScreen(); + startPoint.translate(50, 50); + Point endPoint = new Point(startPoint.x + 100, startPoint.y + 100); + + Util.waitForInit(); + + if (!Util.pointInComponent(robot, startPoint, frame)) { + System.err.println("WARNING: Could not locate " + frame + + " at point " + startPoint); + return; + } + + robot.mouseMove(startPoint.x, startPoint.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + for (Point p = new Point(startPoint); !p.equals(endPoint); + p.translate(Util.sign(endPoint.x - p.x), + Util.sign(endPoint.y - p.y))) { + robot.mouseMove(p.x, p.y); + robot.delay(100); + } + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + synchronized (LOCK) { + while (!end) { + LOCK.wait(); + } + } + } finally { + if (frame != null) { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + + if (failed) { + throw new RuntimeException("DragSourceListener.dragExit() called!"); + } + + System.err.println("test passed!"); + } +} + + +class Util implements AWTEventListener { + private static final Toolkit tk = Toolkit.getDefaultToolkit(); + private static final Object SYNC_LOCK = new Object(); + private Component clickedComponent = null; + private static final int PAINT_TIMEOUT = 10000; + private static final int MOUSE_RELEASE_TIMEOUT = 10000; + private static final Util util = new Util(); + + static { + tk.addAWTEventListener(util, 0xFFFFFFFF); + } + + private void reset() { + clickedComponent = null; + } + + public void eventDispatched(AWTEvent e) { + if (e.getID() == MouseEvent.MOUSE_RELEASED) { + clickedComponent = (Component)e.getSource(); + synchronized (SYNC_LOCK) { + SYNC_LOCK.notifyAll(); + } + } + } + + public static boolean pointInComponent(Robot robot, Point p, Component comp) + throws InterruptedException { + return util.isPointInComponent(robot, p, comp); + } + + private boolean isPointInComponent(Robot robot, Point p, Component comp) + throws InterruptedException { + tk.sync(); + robot.waitForIdle(); + reset(); + robot.mouseMove(p.x, p.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + synchronized (SYNC_LOCK) { + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + SYNC_LOCK.wait(MOUSE_RELEASE_TIMEOUT); + } + + Component c = clickedComponent; + + while (c != null && c != comp) { + c = c.getParent(); + } + + return c == comp; + } + + public static void waitForInit() throws InterruptedException { + final Frame f = new Frame() { + public void paint(Graphics g) { + dispose(); + synchronized (SYNC_LOCK) { + SYNC_LOCK.notifyAll(); + } + } + }; + f.setBounds(600, 400, 200, 200); + synchronized (SYNC_LOCK) { + f.setVisible(true); + SYNC_LOCK.wait(PAINT_TIMEOUT); + } + tk.sync(); + } + + public static int sign(int n) { + return n < 0 ? -1 : n == 0 ? 0 : 1; + } +} \ No newline at end of file diff --git a/test/jdk/java/awt/dnd/NotReallySerializableTest/NotReallySerializableTest.java b/test/jdk/java/awt/dnd/NotReallySerializableTest/NotReallySerializableTest.java new file mode 100644 index 00000000000..1c80f479eef --- /dev/null +++ b/test/jdk/java/awt/dnd/NotReallySerializableTest/NotReallySerializableTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @key headful + @bug 4187912 + @summary Test that some incorrectly written DnD code cannot hang the app + @run main NotReallySerializableTest +*/ + +import java.awt.Button; +import java.awt.Cursor; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragGestureRecognizer; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceContext; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetAdapter; +import java.awt.dnd.DropTargetDropEvent; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.Serializable; +import java.util.ArrayList; + + +public class NotReallySerializableTest { + public static void main(String[] args) throws IOException { + Toolkit tk = Toolkit.getDefaultToolkit(); + + DragGestureRecognizer dgr = tk.createDragGestureRecognizer + (java.awt.dnd.MouseDragGestureRecognizer.class, + DragSource.getDefaultDragSource(), new Button(), + DnDConstants.ACTION_LINK, new TrickDragGestureListener()); + DragGestureEvent dge = new DragGestureEvent + (dgr, DnDConstants.ACTION_LINK, new Point(0, 0), + new TrickList()); + DragSourceContext dsc = new DragSourceContext(dge, + Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), + null, null, new TrickTransferable(), + new TrickDragSourceListener()); + DropTarget dt = new DropTarget(new Button(), + new TrickDropTargetListener()); + + ObjectOutputStream stream = new ObjectOutputStream + (new OutputStream() { + public void write(int b) {} + }); + + stream.writeObject(dgr); + stream.writeObject(dge); + stream.writeObject(dsc); + stream.writeObject(dt); + + System.out.println("test passed"); + } +} + +class TrickList extends ArrayList implements Serializable { + Object trick = new Object(); + + TrickList() { + add(trick); + } +} + +class TrickDragGestureListener implements DragGestureListener, Serializable { + Object trick = new Object(); + + public void dragGestureRecognized(DragGestureEvent dge) {} +} + +class TrickTransferable extends StringSelection implements Serializable { + Object trick = new Object(); + + TrickTransferable() { + super(""); + } +} + +class TrickDragSourceListener extends DragSourceAdapter + implements Serializable +{ + Object trick = new Object(); +} + +class TrickDropTargetListener extends DropTargetAdapter + implements Serializable +{ + Object trick = new Object(); + + public void drop(DropTargetDropEvent dtde) {} +} diff --git a/test/jdk/java/awt/font/FontScaling/StretchedFontTest.java b/test/jdk/java/awt/font/FontScaling/StretchedFontTest.java new file mode 100644 index 00000000000..52ea3571a03 --- /dev/null +++ b/test/jdk/java/awt/font/FontScaling/StretchedFontTest.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.imageio.ImageIO; + +import static java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment; +import static java.awt.RenderingHints.KEY_TEXT_ANTIALIASING; +import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB; +import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF; +import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON; +import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR; + +/* + * @test + * @bug 8312555 + * @summary Verifies that hieroglyphs are stretched by AffineTransform.scale(2, 1) + * @run main StretchedFontTest + */ +public final class StretchedFontTest { + private static final String TEXT = "\u6F22"; + private static final int FONT_SIZE = 20; + + private static final Color BACKGROUND = Color.WHITE; + private static final Color[] FOREGROUNDS = { + new Color(0xFF000000, true), + new Color(0x7F000000, true) + }; + + private static final AffineTransform STRETCH_TRANSFORM = + AffineTransform.getScaleInstance(2.0, 1.0); + + public static void main(String[] args) { + List errors = + Arrays.stream(getLocalGraphicsEnvironment() + .getAvailableFontFamilyNames(Locale.ENGLISH)) + .map(family -> new Font(family, Font.PLAIN, FONT_SIZE)) + .filter(font -> font.canDisplay(TEXT.codePointAt(0))) + .map(font -> font.deriveFont(STRETCH_TRANSFORM)) + .flatMap(StretchedFontTest::testFont) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + if (!errors.isEmpty()) { + errors.forEach(System.err::println); + throw new Error(errors.size() + " failure(s) found;" + + " the first one: " + errors.get(0)); + } + } + + /** + * Tests the font with a set of text antialiasing hints. + * + * @param font the font to test + * @return a stream of test results + * @see #testFont(Font, Object) + */ + private static Stream testFont(final Font font) { + return Stream.of(VALUE_TEXT_ANTIALIAS_OFF, + VALUE_TEXT_ANTIALIAS_ON, + VALUE_TEXT_ANTIALIAS_LCD_HRGB) + .flatMap(hint -> testFont(font, hint)); + } + + /** + * Tests the font with the specified text antialiasing hint and a set of + * foreground colors. + * + * @param font the font to test + * @param hint the text antialiasing hint to test + * @return a stream of test results + * @see #testFont(Font, Object, Color) + */ + private static Stream testFont(final Font font, final Object hint) { + return Stream.of(FOREGROUNDS) + .map(foreground -> testFont(font, hint, foreground)); + } + + /** + * Tests the font with the specified text antialiasing hint and + * foreground color. In case of failure, it saves the rendered + * image to a file. + * + * @param font the font to test + * @param hint the text antialiasing hint to test + * @param foreground the foreground color to use + * @return {@code null} if the text rendered correctly; otherwise, + * a {@code String} with the font family name, the value of + * the rendering hint and the color in hex + */ + private static String testFont(final Font font, + final Object hint, + final Color foreground) { + final Dimension size = getTextSize(font); + final BufferedImage image = + new BufferedImage(size.width, size.height, TYPE_3BYTE_BGR); + + final Graphics2D g2d = image.createGraphics(); + try { + g2d.setColor(BACKGROUND); + g2d.fillRect(0, 0, size.width, size.height); + + g2d.setRenderingHint(KEY_TEXT_ANTIALIASING, hint); + g2d.setColor(foreground); + g2d.setFont(font); + g2d.drawString(TEXT, 0, g2d.getFontMetrics(font).getAscent()); + } finally { + g2d.dispose(); + } + + if (verifyImage(image)) { + return null; + } + String fontName = font.getFontName(Locale.ENGLISH); + String hintValue = getHintString(hint); + String hexColor = String.format("0x%08x", foreground.getRGB()); + saveImage(image, fontName + "-" + hintValue + "-" + hexColor); + return "Font: " + fontName + ", Hint: " + hintValue + ", Color: " + hexColor; + } + + /** + * Verifies the rendered image of the hieroglyph. The hieroglyph + * should be stretched across the entire width of the image. + * If the right half of the image contains only pixels of the background + * color, the hieroglyph isn't stretched correctly + * — it's a failure. + * + * @param image the image to verify + * @return {@code true} if the hieroglyph is stretched correctly; or + * {@code false} if right half of the image contains only + * background-colored pixels, which means the hieroglyph isn't + * stretched. + */ + private static boolean verifyImage(final BufferedImage image) { + final int width = image.getWidth(); + final int height = image.getHeight(); + for (int x = width / 2; x < width; x++) { + for (int y = 0; y < height; y++) { + if (image.getRGB(x, y) != BACKGROUND.getRGB()) { + // Any other color but background means the glyph is stretched + return true; + } + } + } + + // The right side of the image is filled with the background color only, + // the glyph isn't stretched. + return false; + } + + private static String getHintString(final Object hint) { + if (hint == VALUE_TEXT_ANTIALIAS_OFF) { + return "off"; + } else if (hint == VALUE_TEXT_ANTIALIAS_ON) { + return "on"; + } else if (hint == VALUE_TEXT_ANTIALIAS_LCD_HRGB) { + return "lcd"; + } else { + throw new IllegalArgumentException("Unexpected hint: " + hint); + } + } + + private static final BufferedImage dummyImage = + new BufferedImage(5, 5, TYPE_3BYTE_BGR); + + private static Dimension getTextSize(final Font font) { + final Graphics g = dummyImage.getGraphics(); + try { + return g.getFontMetrics(font) + .getStringBounds(TEXT, g) + .getBounds() + .getSize(); + } finally { + g.dispose(); + } + } + + private static void saveImage(final BufferedImage image, + final String fileName) { + try { + ImageIO.write(image, + "png", + new File(fileName + ".png")); + } catch (IOException ignored) { + } + } +} diff --git a/test/jdk/java/awt/print/PageFormat/PrintContentCutOffTest.java b/test/jdk/java/awt/print/PageFormat/PrintContentCutOffTest.java new file mode 100644 index 00000000000..d2362cdc815 --- /dev/null +++ b/test/jdk/java/awt/print/PageFormat/PrintContentCutOffTest.java @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, BELLSOFT. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8295737 + * @summary macOS: Print content cut off when width > height with portrait orientation + * @run main/othervm/manual PrintContentCutOffTest + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.font.FontRenderContext; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import java.awt.print.Book; +import java.awt.image.BufferedImage; +import java.awt.print.Paper; + +import javax.print.PrintServiceLookup; +import javax.print.attribute.Size2DSyntax; +import javax.print.attribute.standard.MediaSize; +import javax.print.attribute.standard.MediaSizeName; + + +public class PrintContentCutOffTest { + + private static final String DESCRIPTION = + + " 1. To run the test it is required to have a virtual PDF printer" + + " or any other printer supporting A4 paper size.\n" + + " 2. Press Print button to print 4 rectangles.\n" + + " - rectangle with paper width is less than height, orientation portrait\n" + + " - rectangle with paper width is less than height, orientation landscape\n" + + " - rectangle with paper width is greater than height, orientation portrait\n" + + " - rectangle with paper width is greater than height, orientation landscape\n" + + " [Note: PageFormat size returns transformed Paper size according to the set orientation value.\n" + + " 3. Check that 4 printed rectangles (one per page) have fully drawn 8 vertical areas\n" + + " labeled from 1 to 8, and that the blue diagonal lines end at the corners of the yellow rectangle.\n" + + " [Note: those are the pass/fail criteria. The messages printed in red are only informative\n" + + " and should not be used as a reason to file a bug].\n" + + " 4. If so, press PASS button, otherwise press FAIL button.\n"; + + + private static final CountDownLatch testEndedSignal = new CountDownLatch(1); + private static final int testTimeout = 300000; + private static volatile String testFailureMsg; + private static volatile boolean testPassed; + private static volatile boolean testFinished; + + private static final double DOC_WIDTH; + private static final double DOC_HEIGHT; + + static { + MediaSize isoA4Size = MediaSize.getMediaSizeForName(MediaSizeName.ISO_A4); + float[] size = isoA4Size.getSize(Size2DSyntax.INCH); + + DOC_WIDTH = size[0] * 72.0; + DOC_HEIGHT = size[1] * 72.0; + } + + private static void paintImage(Graphics2D g, PageFormat page, int pageIndex) { + BufferedImage img = createImage(page, pageIndex); + g.drawImage(img, 0, 0, null); + } + + private static void appendToBook(PrinterJob job, Book book, double width, double height, int orientation) { + + PageFormat page = job.getPageFormat(null); + page.setOrientation(orientation); + Paper paper = page.getPaper(); + + paper.setSize(width, height); + paper.setImageableArea(0, 0, width, height); + + page.setPaper(paper); + page.setOrientation(orientation); + book.append(new TestPrintable(), page); + } + + private static void print(double width, double height) throws PrinterException { + PrinterJob job = PrinterJob.getPrinterJob(); + job.setPrintService(PrintServiceLookup.lookupDefaultPrintService()); + + Book book = new Book(); + appendToBook(job, book, width, height, PageFormat.PORTRAIT); + appendToBook(job, book, width, height, PageFormat.LANDSCAPE); + appendToBook(job, book, height, width, PageFormat.PORTRAIT); + appendToBook(job, book, height, width, PageFormat.LANDSCAPE); + + job.setPageable(book); + + if (job.printDialog()) { + job.print(); + } else { + throw new RuntimeException("Printing was canceled!"); + } + } + + private static String getOrientation(int orientation) { + switch (orientation) { + case PageFormat.LANDSCAPE: + return "LANDSCAPE"; + case PageFormat.PORTRAIT: + return "PORTRAIT"; + case PageFormat.REVERSE_LANDSCAPE: + return "REVERSE_LANDSCAPE"; + default: + return "UNKNOWN"; + } + } + + private static BufferedImage createImage(PageFormat page, int pageIndex) { + + int w = (int) page.getWidth(); + int h = (int) page.getHeight(); + + int x = 0; + int y = 0; + + BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = img.createGraphics(); + + g.setClip(null); + + g.setColor(Color.ORANGE); + g.fillRect(x, y, w, h); + + g.setColor(Color.BLUE); + g.drawRect(x, y, w, h); + g.drawRect(x + 1, y + 1, w - 2, h - 2); + g.drawLine(x, y, x + w, y + h); + g.drawLine(x, y + h, x + w, y); + + g.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); + + int N = 8; + int dx = w / N; + + for (int i = 0; i < N; i++) { + int xx = i * dx + x; + g.setColor(Color.BLUE); + g.drawLine(xx, y, xx, y + h); + g.setColor(Color.BLUE); + g.drawString("" + (i + 1), xx + 3, y + h / 2); + } + + int NN = 5; + int arrX = x + w / 2 - 4; + g.setColor(Color.RED); + for (int i = 0; i < NN; i++) { + g.drawLine(arrX + i, y + h / 3, arrX + i, y + 2 * h / 3); + } + + int r = 7; + g.fillOval(arrX + NN / 2 - r, y + h / 3 - r - 5, 2 * r, 2 * r); + + g.setColor(Color.RED); + g.setFont(g.getFont().deriveFont(Font.BOLD, 16.0f)); + + int textX = x + w / 18; + int textY = y + h / 3; + int textDelta = h / 16; + + Paper paper = page.getPaper(); + String paperSize = String.format("Paper size: %dx%d", + (int) paper.getWidth(), (int) paper.getHeight()); + g.drawString(paperSize, textX, textY); + + String pageFormatSize = String.format("PageFormat size: %dx%d", w, h); + g.drawString(pageFormatSize, textX, textY + textDelta); + + String orientation = String.format("Orientation: %s", + getOrientation(page.getOrientation())); + g.drawString(orientation, textX, textY + 2 * textDelta); + + g.setColor(Color.BLACK); + g.setFont(g.getFont().deriveFont(28.0f)); + g.drawString(String.format("P:%d", pageIndex + 1), x + w / 2, y + 2 * h / 3); + + g.dispose(); + return img; + } + + private static class TestPrintable implements Printable { + + @Override + public int print(Graphics graphics, PageFormat pageFormat, int index) { + paintImage((Graphics2D) graphics, pageFormat, index); + return PAGE_EXISTS; + } + } + + public static void main(String[] args) throws Exception { + + SwingUtilities.invokeLater(() -> createAndShowTestDialog()); + + try { + if (!testEndedSignal.await(testTimeout, TimeUnit.MILLISECONDS)) { + throw new RuntimeException(String.format( + "Test timeout '%d ms' elapsed.", testTimeout)); + } + if (!testPassed) { + String failureMsg = testFailureMsg; + if ((failureMsg != null) && (!failureMsg.trim().isEmpty())) { + throw new RuntimeException(failureMsg); + } else { + throw new RuntimeException("Test failed."); + } + } + } catch (InterruptedException ie) { + throw new RuntimeException(ie); + } finally { + testFinished = true; + } + } + + private static void pass() { + testPassed = true; + testEndedSignal.countDown(); + } + + private static void fail(String failureMsg) { + testFailureMsg = failureMsg; + testPassed = false; + testEndedSignal.countDown(); + } + + private static String convertMillisToTimeStr(int millis) { + if (millis < 0) { + return "00:00:00"; + } + int hours = millis / 3600000; + int minutes = (millis - hours * 3600000) / 60000; + int seconds = (millis - hours * 3600000 - minutes * 60000) / 1000; + return String.format("%02d:%02d:%02d", hours, minutes, seconds); + } + + private static void createAndShowTestDialog() { + + final JDialog dialog = new JDialog(); + dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + dialog.dispose(); + fail("Main dialog was closed."); + } + }); + + final JLabel testTimeoutLabel = new JLabel(String.format( + "Test timeout: %s", convertMillisToTimeStr(testTimeout))); + final long startTime = System.currentTimeMillis(); + final Timer timer = new Timer(0, null); + timer.setDelay(1000); + timer.addActionListener((e) -> { + int leftTime = testTimeout - (int) (System.currentTimeMillis() - startTime); + if ((leftTime < 0) || testFinished) { + timer.stop(); + dialog.dispose(); + } + testTimeoutLabel.setText(String.format( + "Test timeout: %s", convertMillisToTimeStr(leftTime))); + }); + timer.start(); + + JTextArea textArea = new JTextArea(DESCRIPTION); + textArea.setEditable(false); + + final JButton testButton = new JButton("Print"); + final JButton passButton = new JButton("PASS"); + final JButton failButton = new JButton("FAIL"); + + testButton.addActionListener((e) -> { + testButton.setEnabled(false); + new Thread(() -> { + try { + doTest(); + + SwingUtilities.invokeLater(() -> { + passButton.setEnabled(true); + failButton.setEnabled(true); + }); + } catch (Throwable t) { + t.printStackTrace(); + dialog.dispose(); + fail("Exception occurred in a thread executing the test."); + } + }).start(); + }); + passButton.setEnabled(false); + passButton.addActionListener((e) -> { + dialog.dispose(); + pass(); + }); + failButton.setEnabled(false); + failButton.addActionListener((e) -> { + dialog.dispose(); + fail("TitledBorder label is cut off"); + }); + + JPanel mainPanel = new JPanel(new BorderLayout()); + + JPanel labelPanel = new JPanel(new FlowLayout()); + labelPanel.add(testTimeoutLabel); + mainPanel.add(labelPanel, BorderLayout.NORTH); + mainPanel.add(textArea, BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(new FlowLayout()); + buttonPanel.add(testButton); + buttonPanel.add(passButton); + buttonPanel.add(failButton); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + dialog.add(mainPanel); + + dialog.pack(); + dialog.setVisible(true); + } + + private static void doTest() throws Exception { + SwingUtilities.invokeAndWait(() -> { + try { + print(DOC_WIDTH, DOC_HEIGHT); + } catch (PrinterException e) { + throw new RuntimeException(e); + } + }); + } +} diff --git a/test/jdk/java/awt/print/PrinterJob/InitToBlack.java b/test/jdk/java/awt/print/PrinterJob/InitToBlack.java index 783320829b6..bab35cc7a98 100644 --- a/test/jdk/java/awt/print/PrinterJob/InitToBlack.java +++ b/test/jdk/java/awt/print/PrinterJob/InitToBlack.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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,21 +22,57 @@ */ /** + * @test * @bug 4184565 * @summary Confirm that the default foreground color on a printer * graphics object is black so that rendering will appear * without having to execute setColor first. - * @run applet/manual=yesno InitToBlack.html + * @run main/manual InitToBlack */ -import java.awt.*; -import java.awt.print.*; -import java.applet.Applet; +import java.awt.BorderLayout; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.print.Book; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; -public class InitToBlack extends Applet implements Printable { +public class InitToBlack implements Printable { - public void init() { + private static volatile JFrame frame; + private static volatile boolean testResult = false; + private static volatile CountDownLatch printButtonCountDownLatch = + new CountDownLatch(1); + private static volatile CountDownLatch CountDownLatch = + new CountDownLatch(1); + private static volatile String failureReason; + + @Override + public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { + Graphics2D g2d = (Graphics2D) graphics; + g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY()); + graphics.drawString("Test Passes", 200, 200); + return PAGE_EXISTS; + } + + private void test() { PrinterJob pjob = PrinterJob.getPrinterJob(); + if (pjob.getPrintService() == null) { + System.out.println("There is no printer configured on this system"); + return; + } Book book = new Book(); book.append(this, pjob.defaultPage()); @@ -49,17 +85,95 @@ public void init() { } } - public int print(Graphics g, PageFormat pf, int pageIndex) { - Graphics2D g2d = (Graphics2D) g; - g2d.translate(pf.getImageableX(), pf.getImageableY()); + private static void createTestUI() { + frame = new JFrame("Test InitToBlack"); + String INSTRUCTION = "Aim: This test checks whether the default foreground color on a printer\n" + + "graphics object is black so that rendering will appear without having\n" + + "to execute setColor.\n" + + "Step:\n" + + "1) Click on the \"Print\" button. Check whether page is printed on the printer.\n" + + "2) Check whether \"Test Passes\" is printed on the page and it should be in\n" + + "black color. If yes then press \"Pass\" button else press \"Fail\" button.\n"; + JTextArea instructionTextArea = new JTextArea(INSTRUCTION, 4, 40); + instructionTextArea.setEditable(false); - g.drawString("Test Passes", 200, 200); + JPanel buttonPanel = new JPanel(); + JButton printButton = new JButton("Print"); + printButton.addActionListener((ae) -> { + InitToBlack initToBlack = new InitToBlack(); + initToBlack.test(); + printButtonCountDownLatch.countDown(); + }); - return PAGE_EXISTS; + JButton passButton = new JButton("Pass"); + passButton.addActionListener((ae) -> { + testResult = true; + CountDownLatch.countDown(); + frame.dispose(); + }); + JButton failButton = new JButton("Fail"); + failButton.addActionListener((ae) -> { + getFailureReason(); + frame.dispose(); + }); + buttonPanel.add(printButton); + buttonPanel.add(passButton); + buttonPanel.add(failButton); + + JPanel panel = new JPanel(new BorderLayout()); + panel.add(instructionTextArea, BorderLayout.CENTER); + panel.add(buttonPanel, BorderLayout.SOUTH); + + frame.add(panel); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.pack(); + frame.setVisible(true); + } + + public static void getFailureReason() { + final JDialog dialog = new JDialog(); + dialog.setTitle("Read testcase failure reason"); + JPanel jPanel = new JPanel(new BorderLayout()); + JTextArea jTextArea = new JTextArea(5, 20); + + JButton okButton = new JButton("Ok"); + okButton.addActionListener((ae) -> { + failureReason = jTextArea.getText(); + testResult = false; + CountDownLatch.countDown(); + dialog.dispose(); + }); + + jPanel.add(new JLabel("Enter the testcase failed reason below and " + + "click OK button", JLabel.CENTER), BorderLayout.NORTH); + jPanel.add(jTextArea, BorderLayout.CENTER); + + JPanel okayBtnPanel = new JPanel(); + okayBtnPanel.add(okButton); + + jPanel.add(okayBtnPanel, BorderLayout.SOUTH); + dialog.add(jPanel); + dialog.setLocationRelativeTo(null); + dialog.pack(); + dialog.setVisible(true); } - public static void main(String[] args) { - new InitToBlack().init(); - System.exit(0); + public static void main(String[] args) throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(InitToBlack::createTestUI); + if (!printButtonCountDownLatch.await(2, TimeUnit.MINUTES)) { + throw new RuntimeException("Timeout: User did not perform action " + + "on Print button."); + } + if (!CountDownLatch.await(2, TimeUnit.MINUTES)) { + throw new RuntimeException("Timeout : User did not decide " + + "whether test passed or failed"); + } + + if (!testResult) { + throw new RuntimeException("Test failed : " + failureReason); + } else { + System.out.println("Test Passed"); + } } } diff --git a/test/jdk/java/io/ByteArrayOutputStream/MaxCapacity.java b/test/jdk/java/io/ByteArrayOutputStream/MaxCapacity.java index e46786cca27..f159087e464 100644 --- a/test/jdk/java/io/ByteArrayOutputStream/MaxCapacity.java +++ b/test/jdk/java/io/ByteArrayOutputStream/MaxCapacity.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2014 Google Inc. All rights reserved. + * Copyright (c) 2014, Google Inc. All rights reserved. + * 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 @@ -23,11 +24,11 @@ /* * @test - * @ignore This test has huge memory requirements - * @run main/timeout=1800/othervm -Xmx8g MaxCapacity * @bug 8055949 * @summary Check that we can write (almost) Integer.MAX_VALUE bytes * to a ByteArrayOutputStream. + * @requires (sun.arch.data.model == "64" & os.maxMemory >= 10g) + * @run main/timeout=1800/othervm -Xmx8g MaxCapacity * @author Martin Buchholz */ import java.io.ByteArrayOutputStream; diff --git a/test/jdk/java/io/File/MacPath.java b/test/jdk/java/io/File/MacPath.java index 08ffc83534b..a9d91018783 100644 --- a/test/jdk/java/io/File/MacPath.java +++ b/test/jdk/java/io/File/MacPath.java @@ -38,7 +38,7 @@ public class MacPath { public static void main(String args[]) throws Exception { final ProcessBuilder pb = - ProcessTools.createJavaProcessBuilder(true, MacPathTest.class.getName()); + ProcessTools.createTestJvm(MacPathTest.class.getName()); final Map env = pb.environment(); env.put("LC_ALL", "en_US.UTF-8"); Process p = ProcessTools.startProcess("Mac Path Test", pb); diff --git a/test/jdk/java/io/File/SetLastModified.java b/test/jdk/java/io/File/SetLastModified.java index 1f45dd912ef..a0ad52638ec 100644 --- a/test/jdk/java/io/File/SetLastModified.java +++ b/test/jdk/java/io/File/SetLastModified.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -23,6 +23,7 @@ /* @test @bug 4091757 6652379 8177809 + @requires os.maxMemory >= 16G @summary Basic test for setLastModified method */ diff --git a/test/jdk/java/io/Serializable/evolution/RenamePackage/RenamePackageTest.java b/test/jdk/java/io/Serializable/evolution/RenamePackage/RenamePackageTest.java index 7a3da8e04d5..faccc09bb4b 100644 --- a/test/jdk/java/io/Serializable/evolution/RenamePackage/RenamePackageTest.java +++ b/test/jdk/java/io/Serializable/evolution/RenamePackage/RenamePackageTest.java @@ -81,7 +81,7 @@ private static void setup() throws Exception { } private static void runTestSerialDriver() throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-classpath", SHARE.toString() + File.pathSeparator @@ -93,7 +93,7 @@ private static void runTestSerialDriver() throws Exception { } private static void runInstallSerialDriver() throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, + ProcessBuilder pb = ProcessTools.createTestJvm( "-classpath", SHARE.toString() + File.pathSeparator diff --git a/test/jdk/java/lang/Runtime/shutdown/ShutdownInterruptedMain.java b/test/jdk/java/lang/Runtime/shutdown/ShutdownInterruptedMain.java index 4a4751ee61d..e141fc35212 100644 --- a/test/jdk/java/lang/Runtime/shutdown/ShutdownInterruptedMain.java +++ b/test/jdk/java/lang/Runtime/shutdown/ShutdownInterruptedMain.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -31,14 +31,14 @@ */ import jdk.test.lib.process.OutputAnalyzer; -import static jdk.test.lib.process.ProcessTools.createJavaProcessBuilder; +import static jdk.test.lib.process.ProcessTools.createTestJvm; import static jdk.test.lib.process.ProcessTools.executeProcess; public class ShutdownInterruptedMain { public static void main(String[] args) throws Exception { if (args.length > 0) { - ProcessBuilder pb = createJavaProcessBuilder(true, "ShutdownInterruptedMain"); + ProcessBuilder pb = createTestJvm("ShutdownInterruptedMain"); OutputAnalyzer output = executeProcess(pb); output.shouldContain("Shutdown Hook"); output.shouldHaveExitValue(0); diff --git a/test/jdk/java/lang/StackWalker/CallerFromMain.java b/test/jdk/java/lang/StackWalker/CallerFromMain.java index f1b352f7cb1..3cb599c6859 100644 --- a/test/jdk/java/lang/StackWalker/CallerFromMain.java +++ b/test/jdk/java/lang/StackWalker/CallerFromMain.java @@ -37,7 +37,7 @@ public class CallerFromMain { private static final StackWalker sw = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); public static void main(String[] args) throws Exception { if (args.length > 0) { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "CallerFromMain"); + ProcessBuilder pb = ProcessTools.createTestJvm("CallerFromMain"); OutputAnalyzer output = ProcessTools.executeProcess(pb); System.out.println(output.getOutput()); output.shouldHaveExitValue(0); diff --git a/test/jdk/java/lang/StringBuilder/HugeCapacity.java b/test/jdk/java/lang/StringBuilder/HugeCapacity.java index c9229b244aa..f9b4cd2bcff 100644 --- a/test/jdk/java/lang/StringBuilder/HugeCapacity.java +++ b/test/jdk/java/lang/StringBuilder/HugeCapacity.java @@ -27,25 +27,32 @@ * @summary Capacity should not get close to Integer.MAX_VALUE unless * necessary * @requires (sun.arch.data.model == "64" & os.maxMemory >= 6G) - * @run main/othervm -Xmx5G HugeCapacity + * @run main/othervm -Xms5G -Xmx5G -XX:+CompactStrings HugeCapacity true + * @run main/othervm -Xms5G -Xmx5G -XX:-CompactStrings HugeCapacity false */ public class HugeCapacity { private static int failures = 0; public static void main(String[] args) { - testLatin1(); + if (args.length == 0) { + throw new IllegalArgumentException("Need the argument"); + } + boolean isCompact = Boolean.parseBoolean(args[0]); + + testLatin1(isCompact); testUtf16(); if (failures > 0) { throw new RuntimeException(failures + " tests failed"); } } - private static void testLatin1() { + private static void testLatin1(boolean isCompact) { try { + int divisor = isCompact ? 2 : 4; StringBuilder sb = new StringBuilder(); - sb.ensureCapacity(Integer.MAX_VALUE / 2); - sb.ensureCapacity(Integer.MAX_VALUE / 2 + 1); + sb.ensureCapacity(Integer.MAX_VALUE / divisor); + sb.ensureCapacity(Integer.MAX_VALUE / divisor + 1); } catch (OutOfMemoryError oom) { oom.printStackTrace(); failures++; diff --git a/test/jdk/java/lang/System/MacEncoding/MacJNUEncoding.java b/test/jdk/java/lang/System/MacEncoding/MacJNUEncoding.java index d1464ba4fd0..24cc9adab16 100644 --- a/test/jdk/java/lang/System/MacEncoding/MacJNUEncoding.java +++ b/test/jdk/java/lang/System/MacEncoding/MacJNUEncoding.java @@ -49,7 +49,7 @@ public static void main(String[] args) throws Exception { final String locale = args[2]; System.out.println("Running test for locale: " + locale); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, + ProcessBuilder pb = ProcessTools.createTestJvm( ExpectedEncoding.class.getName(), args[0], args[1]); Map env = pb.environment(); env.put("LANG", locale); diff --git a/test/jdk/java/lang/instrument/DaemonThread/TestDaemonThreadLauncher.java b/test/jdk/java/lang/instrument/DaemonThread/TestDaemonThreadLauncher.java index 7dca12ebe45..728fc5d17ab 100644 --- a/test/jdk/java/lang/instrument/DaemonThread/TestDaemonThreadLauncher.java +++ b/test/jdk/java/lang/instrument/DaemonThread/TestDaemonThreadLauncher.java @@ -29,7 +29,7 @@ public class TestDaemonThreadLauncher { public static void main(String args[]) throws Exception { for(int i=0; i<50; i++) { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-javaagent:DummyAgent.jar", "TestDaemonThread", "."); + ProcessBuilder pb = ProcessTools.createTestJvm("-javaagent:DummyAgent.jar", "TestDaemonThread", "."); OutputAnalyzer analyzer = ProcessTools.executeProcess(pb); analyzer.shouldNotContain("ASSERTION FAILED"); analyzer.shouldHaveExitValue(0); diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java index ea85761a9a9..47977761d47 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.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 @@ -443,9 +443,16 @@ static void testInstanceField(VarHandleTestAccessBoolean recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(recv, true, false); } - assertEquals(success, true, "weakCompareAndSetPlain boolean"); + assertEquals(success, true, "success weakCompareAndSetPlain boolean"); boolean x = (boolean) vh.get(recv); - assertEquals(x, false, "weakCompareAndSetPlain boolean value"); + assertEquals(x, false, "success weakCompareAndSetPlain boolean value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(recv, true, false); + assertEquals(success, false, "failing weakCompareAndSetPlain boolean"); + boolean x = (boolean) vh.get(recv); + assertEquals(x, false, "failing weakCompareAndSetPlain boolean value"); } { @@ -453,9 +460,16 @@ static void testInstanceField(VarHandleTestAccessBoolean recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(recv, false, true); } - assertEquals(success, true, "weakCompareAndSetAcquire boolean"); + assertEquals(success, true, "success weakCompareAndSetAcquire boolean"); + boolean x = (boolean) vh.get(recv); + assertEquals(x, true, "success weakCompareAndSetAcquire boolean"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(recv, false, false); + assertEquals(success, false, "failing weakCompareAndSetAcquire boolean"); boolean x = (boolean) vh.get(recv); - assertEquals(x, true, "weakCompareAndSetAcquire boolean"); + assertEquals(x, true, "failing weakCompareAndSetAcquire boolean value"); } { @@ -463,9 +477,16 @@ static void testInstanceField(VarHandleTestAccessBoolean recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(recv, true, false); } - assertEquals(success, true, "weakCompareAndSetRelease boolean"); + assertEquals(success, true, "success weakCompareAndSetRelease boolean"); + boolean x = (boolean) vh.get(recv); + assertEquals(x, false, "success weakCompareAndSetRelease boolean"); + } + + { + boolean success = vh.weakCompareAndSetRelease(recv, true, false); + assertEquals(success, false, "failing weakCompareAndSetRelease boolean"); boolean x = (boolean) vh.get(recv); - assertEquals(x, false, "weakCompareAndSetRelease boolean"); + assertEquals(x, false, "failing weakCompareAndSetRelease boolean value"); } { @@ -473,9 +494,16 @@ static void testInstanceField(VarHandleTestAccessBoolean recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(recv, false, true); } - assertEquals(success, true, "weakCompareAndSet boolean"); + assertEquals(success, true, "success weakCompareAndSet boolean"); boolean x = (boolean) vh.get(recv); - assertEquals(x, true, "weakCompareAndSet boolean value"); + assertEquals(x, true, "success weakCompareAndSet boolean value"); + } + + { + boolean success = vh.weakCompareAndSet(recv, false, false); + assertEquals(success, false, "failing weakCompareAndSet boolean"); + boolean x = (boolean) vh.get(recv); + assertEquals(x, true, "failing weakCompareAndSet boolean value"); } // Compare set and get @@ -703,9 +731,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(true, false); } - assertEquals(success, true, "weakCompareAndSetPlain boolean"); + assertEquals(success, true, "success weakCompareAndSetPlain boolean"); + boolean x = (boolean) vh.get(); + assertEquals(x, false, "success weakCompareAndSetPlain boolean value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(true, false); + assertEquals(success, false, "failing weakCompareAndSetPlain boolean"); boolean x = (boolean) vh.get(); - assertEquals(x, false, "weakCompareAndSetPlain boolean value"); + assertEquals(x, false, "failing weakCompareAndSetPlain boolean value"); } { @@ -713,9 +748,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(false, true); } - assertEquals(success, true, "weakCompareAndSetAcquire boolean"); + assertEquals(success, true, "success weakCompareAndSetAcquire boolean"); + boolean x = (boolean) vh.get(); + assertEquals(x, true, "success weakCompareAndSetAcquire boolean"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(false, false); + assertEquals(success, false, "failing weakCompareAndSetAcquire boolean"); boolean x = (boolean) vh.get(); - assertEquals(x, true, "weakCompareAndSetAcquire boolean"); + assertEquals(x, true, "failing weakCompareAndSetAcquire boolean value"); } { @@ -723,9 +765,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(true, false); } - assertEquals(success, true, "weakCompareAndSetRelease boolean"); + assertEquals(success, true, "success weakCompareAndSetRelease boolean"); boolean x = (boolean) vh.get(); - assertEquals(x, false, "weakCompareAndSetRelease boolean"); + assertEquals(x, false, "success weakCompareAndSetRelease boolean"); + } + + { + boolean success = vh.weakCompareAndSetRelease(true, false); + assertEquals(success, false, "failing weakCompareAndSetRelease boolean"); + boolean x = (boolean) vh.get(); + assertEquals(x, false, "failing weakCompareAndSetRelease boolean value"); } { @@ -733,9 +782,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(false, true); } - assertEquals(success, true, "weakCompareAndSet boolean"); + assertEquals(success, true, "success weakCompareAndSet boolean"); + boolean x = (boolean) vh.get(); + assertEquals(x, true, "success weakCompareAndSet boolean"); + } + + { + boolean success = vh.weakCompareAndSet(false, false); + assertEquals(success, false, "failing weakCompareAndSet boolean"); boolean x = (boolean) vh.get(); - assertEquals(x, true, "weakCompareAndSet boolean"); + assertEquals(x, true, "failing weakCompareAndSet boolean value"); } // Compare set and get @@ -966,9 +1022,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, true, false); } - assertEquals(success, true, "weakCompareAndSetPlain boolean"); + assertEquals(success, true, "success weakCompareAndSetPlain boolean"); + boolean x = (boolean) vh.get(array, i); + assertEquals(x, false, "success weakCompareAndSetPlain boolean value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, true, false); + assertEquals(success, false, "failing weakCompareAndSetPlain boolean"); boolean x = (boolean) vh.get(array, i); - assertEquals(x, false, "weakCompareAndSetPlain boolean value"); + assertEquals(x, false, "failing weakCompareAndSetPlain boolean value"); } { @@ -976,9 +1039,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, false, true); } - assertEquals(success, true, "weakCompareAndSetAcquire boolean"); + assertEquals(success, true, "success weakCompareAndSetAcquire boolean"); boolean x = (boolean) vh.get(array, i); - assertEquals(x, true, "weakCompareAndSetAcquire boolean"); + assertEquals(x, true, "success weakCompareAndSetAcquire boolean"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, false, false); + assertEquals(success, false, "failing weakCompareAndSetAcquire boolean"); + boolean x = (boolean) vh.get(array, i); + assertEquals(x, true, "failing weakCompareAndSetAcquire boolean value"); } { @@ -986,9 +1056,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, true, false); } - assertEquals(success, true, "weakCompareAndSetRelease boolean"); + assertEquals(success, true, "success weakCompareAndSetRelease boolean"); + boolean x = (boolean) vh.get(array, i); + assertEquals(x, false, "success weakCompareAndSetRelease boolean"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, true, false); + assertEquals(success, false, "failing weakCompareAndSetRelease boolean"); boolean x = (boolean) vh.get(array, i); - assertEquals(x, false, "weakCompareAndSetRelease boolean"); + assertEquals(x, false, "failing weakCompareAndSetRelease boolean value"); } { @@ -996,9 +1073,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, false, true); } - assertEquals(success, true, "weakCompareAndSet boolean"); + assertEquals(success, true, "success weakCompareAndSet boolean"); + boolean x = (boolean) vh.get(array, i); + assertEquals(x, true, "success weakCompareAndSet boolean"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, false, false); + assertEquals(success, false, "failing weakCompareAndSet boolean"); boolean x = (boolean) vh.get(array, i); - assertEquals(x, true, "weakCompareAndSet boolean"); + assertEquals(x, true, "failing weakCompareAndSet boolean value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java index 033451a7753..302b72997e7 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.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 @@ -421,9 +421,16 @@ static void testInstanceField(VarHandleTestAccessByte recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(recv, (byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetPlain byte"); + assertEquals(success, true, "success weakCompareAndSetPlain byte"); byte x = (byte) vh.get(recv); - assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value"); + assertEquals(x, (byte)0x23, "success weakCompareAndSetPlain byte value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(recv, (byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetPlain byte"); + byte x = (byte) vh.get(recv); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetPlain byte value"); } { @@ -431,9 +438,16 @@ static void testInstanceField(VarHandleTestAccessByte recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(recv, (byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSetAcquire byte"); + assertEquals(success, true, "success weakCompareAndSetAcquire byte"); + byte x = (byte) vh.get(recv); + assertEquals(x, (byte)0x01, "success weakCompareAndSetAcquire byte"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(recv, (byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetAcquire byte"); byte x = (byte) vh.get(recv); - assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte"); + assertEquals(x, (byte)0x01, "failing weakCompareAndSetAcquire byte value"); } { @@ -441,9 +455,16 @@ static void testInstanceField(VarHandleTestAccessByte recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(recv, (byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetRelease byte"); + assertEquals(success, true, "success weakCompareAndSetRelease byte"); + byte x = (byte) vh.get(recv); + assertEquals(x, (byte)0x23, "success weakCompareAndSetRelease byte"); + } + + { + boolean success = vh.weakCompareAndSetRelease(recv, (byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetRelease byte"); byte x = (byte) vh.get(recv); - assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte"); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetRelease byte value"); } { @@ -451,9 +472,16 @@ static void testInstanceField(VarHandleTestAccessByte recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(recv, (byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSet byte"); + assertEquals(success, true, "success weakCompareAndSet byte"); byte x = (byte) vh.get(recv); - assertEquals(x, (byte)0x01, "weakCompareAndSet byte value"); + assertEquals(x, (byte)0x01, "success weakCompareAndSet byte value"); + } + + { + boolean success = vh.weakCompareAndSet(recv, (byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSet byte"); + byte x = (byte) vh.get(recv); + assertEquals(x, (byte)0x01, "failing weakCompareAndSet byte value"); } // Compare set and get @@ -697,9 +725,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain((byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetPlain byte"); + assertEquals(success, true, "success weakCompareAndSetPlain byte"); + byte x = (byte) vh.get(); + assertEquals(x, (byte)0x23, "success weakCompareAndSetPlain byte value"); + } + + { + boolean success = vh.weakCompareAndSetPlain((byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetPlain byte"); byte x = (byte) vh.get(); - assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value"); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetPlain byte value"); } { @@ -707,9 +742,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire((byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSetAcquire byte"); + assertEquals(success, true, "success weakCompareAndSetAcquire byte"); + byte x = (byte) vh.get(); + assertEquals(x, (byte)0x01, "success weakCompareAndSetAcquire byte"); + } + + { + boolean success = vh.weakCompareAndSetAcquire((byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetAcquire byte"); byte x = (byte) vh.get(); - assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte"); + assertEquals(x, (byte)0x01, "failing weakCompareAndSetAcquire byte value"); } { @@ -717,9 +759,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease((byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetRelease byte"); + assertEquals(success, true, "success weakCompareAndSetRelease byte"); byte x = (byte) vh.get(); - assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte"); + assertEquals(x, (byte)0x23, "success weakCompareAndSetRelease byte"); + } + + { + boolean success = vh.weakCompareAndSetRelease((byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetRelease byte"); + byte x = (byte) vh.get(); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetRelease byte value"); } { @@ -727,9 +776,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet((byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSet byte"); + assertEquals(success, true, "success weakCompareAndSet byte"); + byte x = (byte) vh.get(); + assertEquals(x, (byte)0x01, "success weakCompareAndSet byte"); + } + + { + boolean success = vh.weakCompareAndSet((byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSet byte"); byte x = (byte) vh.get(); - assertEquals(x, (byte)0x01, "weakCompareAndSet byte"); + assertEquals(x, (byte)0x01, "failing weakCompareAndSet byte value"); } // Compare set and get @@ -976,9 +1032,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, (byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetPlain byte"); + assertEquals(success, true, "success weakCompareAndSetPlain byte"); + byte x = (byte) vh.get(array, i); + assertEquals(x, (byte)0x23, "success weakCompareAndSetPlain byte value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, (byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetPlain byte"); byte x = (byte) vh.get(array, i); - assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value"); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetPlain byte value"); } { @@ -986,9 +1049,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, (byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSetAcquire byte"); + assertEquals(success, true, "success weakCompareAndSetAcquire byte"); byte x = (byte) vh.get(array, i); - assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte"); + assertEquals(x, (byte)0x01, "success weakCompareAndSetAcquire byte"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, (byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetAcquire byte"); + byte x = (byte) vh.get(array, i); + assertEquals(x, (byte)0x01, "failing weakCompareAndSetAcquire byte value"); } { @@ -996,9 +1066,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, (byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetRelease byte"); + assertEquals(success, true, "success weakCompareAndSetRelease byte"); + byte x = (byte) vh.get(array, i); + assertEquals(x, (byte)0x23, "success weakCompareAndSetRelease byte"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, (byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetRelease byte"); byte x = (byte) vh.get(array, i); - assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte"); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetRelease byte value"); } { @@ -1006,9 +1083,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, (byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSet byte"); + assertEquals(success, true, "success weakCompareAndSet byte"); + byte x = (byte) vh.get(array, i); + assertEquals(x, (byte)0x01, "success weakCompareAndSet byte"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, (byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSet byte"); byte x = (byte) vh.get(array, i); - assertEquals(x, (byte)0x01, "weakCompareAndSet byte"); + assertEquals(x, (byte)0x01, "failing weakCompareAndSet byte value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java index ecd685f073e..534ebf83b8a 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.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 @@ -421,9 +421,16 @@ static void testInstanceField(VarHandleTestAccessChar recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(recv, '\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetPlain char"); + assertEquals(success, true, "success weakCompareAndSetPlain char"); char x = (char) vh.get(recv); - assertEquals(x, '\u4567', "weakCompareAndSetPlain char value"); + assertEquals(x, '\u4567', "success weakCompareAndSetPlain char value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(recv, '\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetPlain char"); + char x = (char) vh.get(recv); + assertEquals(x, '\u4567', "failing weakCompareAndSetPlain char value"); } { @@ -431,9 +438,16 @@ static void testInstanceField(VarHandleTestAccessChar recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(recv, '\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSetAcquire char"); + assertEquals(success, true, "success weakCompareAndSetAcquire char"); + char x = (char) vh.get(recv); + assertEquals(x, '\u0123', "success weakCompareAndSetAcquire char"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(recv, '\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetAcquire char"); char x = (char) vh.get(recv); - assertEquals(x, '\u0123', "weakCompareAndSetAcquire char"); + assertEquals(x, '\u0123', "failing weakCompareAndSetAcquire char value"); } { @@ -441,9 +455,16 @@ static void testInstanceField(VarHandleTestAccessChar recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(recv, '\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetRelease char"); + assertEquals(success, true, "success weakCompareAndSetRelease char"); + char x = (char) vh.get(recv); + assertEquals(x, '\u4567', "success weakCompareAndSetRelease char"); + } + + { + boolean success = vh.weakCompareAndSetRelease(recv, '\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetRelease char"); char x = (char) vh.get(recv); - assertEquals(x, '\u4567', "weakCompareAndSetRelease char"); + assertEquals(x, '\u4567', "failing weakCompareAndSetRelease char value"); } { @@ -451,9 +472,16 @@ static void testInstanceField(VarHandleTestAccessChar recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(recv, '\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSet char"); + assertEquals(success, true, "success weakCompareAndSet char"); char x = (char) vh.get(recv); - assertEquals(x, '\u0123', "weakCompareAndSet char value"); + assertEquals(x, '\u0123', "success weakCompareAndSet char value"); + } + + { + boolean success = vh.weakCompareAndSet(recv, '\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSet char"); + char x = (char) vh.get(recv); + assertEquals(x, '\u0123', "failing weakCompareAndSet char value"); } // Compare set and get @@ -697,9 +725,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain('\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetPlain char"); + assertEquals(success, true, "success weakCompareAndSetPlain char"); + char x = (char) vh.get(); + assertEquals(x, '\u4567', "success weakCompareAndSetPlain char value"); + } + + { + boolean success = vh.weakCompareAndSetPlain('\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetPlain char"); char x = (char) vh.get(); - assertEquals(x, '\u4567', "weakCompareAndSetPlain char value"); + assertEquals(x, '\u4567', "failing weakCompareAndSetPlain char value"); } { @@ -707,9 +742,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire('\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSetAcquire char"); + assertEquals(success, true, "success weakCompareAndSetAcquire char"); + char x = (char) vh.get(); + assertEquals(x, '\u0123', "success weakCompareAndSetAcquire char"); + } + + { + boolean success = vh.weakCompareAndSetAcquire('\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetAcquire char"); char x = (char) vh.get(); - assertEquals(x, '\u0123', "weakCompareAndSetAcquire char"); + assertEquals(x, '\u0123', "failing weakCompareAndSetAcquire char value"); } { @@ -717,9 +759,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease('\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetRelease char"); + assertEquals(success, true, "success weakCompareAndSetRelease char"); char x = (char) vh.get(); - assertEquals(x, '\u4567', "weakCompareAndSetRelease char"); + assertEquals(x, '\u4567', "success weakCompareAndSetRelease char"); + } + + { + boolean success = vh.weakCompareAndSetRelease('\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetRelease char"); + char x = (char) vh.get(); + assertEquals(x, '\u4567', "failing weakCompareAndSetRelease char value"); } { @@ -727,9 +776,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet('\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSet char"); + assertEquals(success, true, "success weakCompareAndSet char"); + char x = (char) vh.get(); + assertEquals(x, '\u0123', "success weakCompareAndSet char"); + } + + { + boolean success = vh.weakCompareAndSet('\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSet char"); char x = (char) vh.get(); - assertEquals(x, '\u0123', "weakCompareAndSet char"); + assertEquals(x, '\u0123', "failing weakCompareAndSet char value"); } // Compare set and get @@ -976,9 +1032,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, '\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetPlain char"); + assertEquals(success, true, "success weakCompareAndSetPlain char"); + char x = (char) vh.get(array, i); + assertEquals(x, '\u4567', "success weakCompareAndSetPlain char value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, '\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetPlain char"); char x = (char) vh.get(array, i); - assertEquals(x, '\u4567', "weakCompareAndSetPlain char value"); + assertEquals(x, '\u4567', "failing weakCompareAndSetPlain char value"); } { @@ -986,9 +1049,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, '\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSetAcquire char"); + assertEquals(success, true, "success weakCompareAndSetAcquire char"); char x = (char) vh.get(array, i); - assertEquals(x, '\u0123', "weakCompareAndSetAcquire char"); + assertEquals(x, '\u0123', "success weakCompareAndSetAcquire char"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, '\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetAcquire char"); + char x = (char) vh.get(array, i); + assertEquals(x, '\u0123', "failing weakCompareAndSetAcquire char value"); } { @@ -996,9 +1066,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, '\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetRelease char"); + assertEquals(success, true, "success weakCompareAndSetRelease char"); + char x = (char) vh.get(array, i); + assertEquals(x, '\u4567', "success weakCompareAndSetRelease char"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, '\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetRelease char"); char x = (char) vh.get(array, i); - assertEquals(x, '\u4567', "weakCompareAndSetRelease char"); + assertEquals(x, '\u4567', "failing weakCompareAndSetRelease char value"); } { @@ -1006,9 +1083,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, '\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSet char"); + assertEquals(success, true, "success weakCompareAndSet char"); + char x = (char) vh.get(array, i); + assertEquals(x, '\u0123', "success weakCompareAndSet char"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, '\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSet char"); char x = (char) vh.get(array, i); - assertEquals(x, '\u0123', "weakCompareAndSet char"); + assertEquals(x, '\u0123', "failing weakCompareAndSet char value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java index 3aa12aa4098..8f5bfca9cf7 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.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 @@ -491,9 +491,16 @@ static void testInstanceField(VarHandleTestAccessDouble recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(recv, 1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetPlain double"); + assertEquals(success, true, "success weakCompareAndSetPlain double"); double x = (double) vh.get(recv); - assertEquals(x, 2.0d, "weakCompareAndSetPlain double value"); + assertEquals(x, 2.0d, "success weakCompareAndSetPlain double value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(recv, 1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetPlain double"); + double x = (double) vh.get(recv); + assertEquals(x, 2.0d, "failing weakCompareAndSetPlain double value"); } { @@ -501,9 +508,16 @@ static void testInstanceField(VarHandleTestAccessDouble recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(recv, 2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSetAcquire double"); + assertEquals(success, true, "success weakCompareAndSetAcquire double"); + double x = (double) vh.get(recv); + assertEquals(x, 1.0d, "success weakCompareAndSetAcquire double"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(recv, 2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetAcquire double"); double x = (double) vh.get(recv); - assertEquals(x, 1.0d, "weakCompareAndSetAcquire double"); + assertEquals(x, 1.0d, "failing weakCompareAndSetAcquire double value"); } { @@ -511,9 +525,16 @@ static void testInstanceField(VarHandleTestAccessDouble recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(recv, 1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetRelease double"); + assertEquals(success, true, "success weakCompareAndSetRelease double"); + double x = (double) vh.get(recv); + assertEquals(x, 2.0d, "success weakCompareAndSetRelease double"); + } + + { + boolean success = vh.weakCompareAndSetRelease(recv, 1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetRelease double"); double x = (double) vh.get(recv); - assertEquals(x, 2.0d, "weakCompareAndSetRelease double"); + assertEquals(x, 2.0d, "failing weakCompareAndSetRelease double value"); } { @@ -521,9 +542,16 @@ static void testInstanceField(VarHandleTestAccessDouble recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(recv, 2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSet double"); + assertEquals(success, true, "success weakCompareAndSet double"); double x = (double) vh.get(recv); - assertEquals(x, 1.0d, "weakCompareAndSet double value"); + assertEquals(x, 1.0d, "success weakCompareAndSet double value"); + } + + { + boolean success = vh.weakCompareAndSet(recv, 2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSet double"); + double x = (double) vh.get(recv); + assertEquals(x, 1.0d, "failing weakCompareAndSet double value"); } // Compare set and get @@ -719,9 +747,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetPlain double"); + assertEquals(success, true, "success weakCompareAndSetPlain double"); + double x = (double) vh.get(); + assertEquals(x, 2.0d, "success weakCompareAndSetPlain double value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetPlain double"); double x = (double) vh.get(); - assertEquals(x, 2.0d, "weakCompareAndSetPlain double value"); + assertEquals(x, 2.0d, "failing weakCompareAndSetPlain double value"); } { @@ -729,9 +764,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSetAcquire double"); + assertEquals(success, true, "success weakCompareAndSetAcquire double"); + double x = (double) vh.get(); + assertEquals(x, 1.0d, "success weakCompareAndSetAcquire double"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetAcquire double"); double x = (double) vh.get(); - assertEquals(x, 1.0d, "weakCompareAndSetAcquire double"); + assertEquals(x, 1.0d, "failing weakCompareAndSetAcquire double value"); } { @@ -739,9 +781,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetRelease double"); + assertEquals(success, true, "success weakCompareAndSetRelease double"); double x = (double) vh.get(); - assertEquals(x, 2.0d, "weakCompareAndSetRelease double"); + assertEquals(x, 2.0d, "success weakCompareAndSetRelease double"); + } + + { + boolean success = vh.weakCompareAndSetRelease(1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetRelease double"); + double x = (double) vh.get(); + assertEquals(x, 2.0d, "failing weakCompareAndSetRelease double value"); } { @@ -749,9 +798,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSet double"); + assertEquals(success, true, "success weakCompareAndSet double"); + double x = (double) vh.get(); + assertEquals(x, 1.0d, "success weakCompareAndSet double"); + } + + { + boolean success = vh.weakCompareAndSet(2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSet double"); double x = (double) vh.get(); - assertEquals(x, 1.0d, "weakCompareAndSet double"); + assertEquals(x, 1.0d, "failing weakCompareAndSet double value"); } // Compare set and get @@ -950,9 +1006,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, 1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetPlain double"); + assertEquals(success, true, "success weakCompareAndSetPlain double"); + double x = (double) vh.get(array, i); + assertEquals(x, 2.0d, "success weakCompareAndSetPlain double value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, 1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetPlain double"); double x = (double) vh.get(array, i); - assertEquals(x, 2.0d, "weakCompareAndSetPlain double value"); + assertEquals(x, 2.0d, "failing weakCompareAndSetPlain double value"); } { @@ -960,9 +1023,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, 2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSetAcquire double"); + assertEquals(success, true, "success weakCompareAndSetAcquire double"); double x = (double) vh.get(array, i); - assertEquals(x, 1.0d, "weakCompareAndSetAcquire double"); + assertEquals(x, 1.0d, "success weakCompareAndSetAcquire double"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, 2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetAcquire double"); + double x = (double) vh.get(array, i); + assertEquals(x, 1.0d, "failing weakCompareAndSetAcquire double value"); } { @@ -970,9 +1040,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, 1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetRelease double"); + assertEquals(success, true, "success weakCompareAndSetRelease double"); + double x = (double) vh.get(array, i); + assertEquals(x, 2.0d, "success weakCompareAndSetRelease double"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, 1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetRelease double"); double x = (double) vh.get(array, i); - assertEquals(x, 2.0d, "weakCompareAndSetRelease double"); + assertEquals(x, 2.0d, "failing weakCompareAndSetRelease double value"); } { @@ -980,9 +1057,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, 2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSet double"); + assertEquals(success, true, "success weakCompareAndSet double"); + double x = (double) vh.get(array, i); + assertEquals(x, 1.0d, "success weakCompareAndSet double"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, 2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSet double"); double x = (double) vh.get(array, i); - assertEquals(x, 1.0d, "weakCompareAndSet double"); + assertEquals(x, 1.0d, "failing weakCompareAndSet double value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java index 81f19fb91dd..13bc8a12b02 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.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 @@ -491,9 +491,16 @@ static void testInstanceField(VarHandleTestAccessFloat recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(recv, 1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetPlain float"); + assertEquals(success, true, "success weakCompareAndSetPlain float"); float x = (float) vh.get(recv); - assertEquals(x, 2.0f, "weakCompareAndSetPlain float value"); + assertEquals(x, 2.0f, "success weakCompareAndSetPlain float value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(recv, 1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetPlain float"); + float x = (float) vh.get(recv); + assertEquals(x, 2.0f, "failing weakCompareAndSetPlain float value"); } { @@ -501,9 +508,16 @@ static void testInstanceField(VarHandleTestAccessFloat recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(recv, 2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSetAcquire float"); + assertEquals(success, true, "success weakCompareAndSetAcquire float"); + float x = (float) vh.get(recv); + assertEquals(x, 1.0f, "success weakCompareAndSetAcquire float"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(recv, 2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetAcquire float"); float x = (float) vh.get(recv); - assertEquals(x, 1.0f, "weakCompareAndSetAcquire float"); + assertEquals(x, 1.0f, "failing weakCompareAndSetAcquire float value"); } { @@ -511,9 +525,16 @@ static void testInstanceField(VarHandleTestAccessFloat recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(recv, 1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetRelease float"); + assertEquals(success, true, "success weakCompareAndSetRelease float"); + float x = (float) vh.get(recv); + assertEquals(x, 2.0f, "success weakCompareAndSetRelease float"); + } + + { + boolean success = vh.weakCompareAndSetRelease(recv, 1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetRelease float"); float x = (float) vh.get(recv); - assertEquals(x, 2.0f, "weakCompareAndSetRelease float"); + assertEquals(x, 2.0f, "failing weakCompareAndSetRelease float value"); } { @@ -521,9 +542,16 @@ static void testInstanceField(VarHandleTestAccessFloat recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(recv, 2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSet float"); + assertEquals(success, true, "success weakCompareAndSet float"); float x = (float) vh.get(recv); - assertEquals(x, 1.0f, "weakCompareAndSet float value"); + assertEquals(x, 1.0f, "success weakCompareAndSet float value"); + } + + { + boolean success = vh.weakCompareAndSet(recv, 2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSet float"); + float x = (float) vh.get(recv); + assertEquals(x, 1.0f, "failing weakCompareAndSet float value"); } // Compare set and get @@ -719,9 +747,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetPlain float"); + assertEquals(success, true, "success weakCompareAndSetPlain float"); + float x = (float) vh.get(); + assertEquals(x, 2.0f, "success weakCompareAndSetPlain float value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetPlain float"); float x = (float) vh.get(); - assertEquals(x, 2.0f, "weakCompareAndSetPlain float value"); + assertEquals(x, 2.0f, "failing weakCompareAndSetPlain float value"); } { @@ -729,9 +764,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSetAcquire float"); + assertEquals(success, true, "success weakCompareAndSetAcquire float"); + float x = (float) vh.get(); + assertEquals(x, 1.0f, "success weakCompareAndSetAcquire float"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetAcquire float"); float x = (float) vh.get(); - assertEquals(x, 1.0f, "weakCompareAndSetAcquire float"); + assertEquals(x, 1.0f, "failing weakCompareAndSetAcquire float value"); } { @@ -739,9 +781,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetRelease float"); + assertEquals(success, true, "success weakCompareAndSetRelease float"); float x = (float) vh.get(); - assertEquals(x, 2.0f, "weakCompareAndSetRelease float"); + assertEquals(x, 2.0f, "success weakCompareAndSetRelease float"); + } + + { + boolean success = vh.weakCompareAndSetRelease(1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetRelease float"); + float x = (float) vh.get(); + assertEquals(x, 2.0f, "failing weakCompareAndSetRelease float value"); } { @@ -749,9 +798,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSet float"); + assertEquals(success, true, "success weakCompareAndSet float"); + float x = (float) vh.get(); + assertEquals(x, 1.0f, "success weakCompareAndSet float"); + } + + { + boolean success = vh.weakCompareAndSet(2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSet float"); float x = (float) vh.get(); - assertEquals(x, 1.0f, "weakCompareAndSet float"); + assertEquals(x, 1.0f, "failing weakCompareAndSet float value"); } // Compare set and get @@ -950,9 +1006,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, 1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetPlain float"); + assertEquals(success, true, "success weakCompareAndSetPlain float"); + float x = (float) vh.get(array, i); + assertEquals(x, 2.0f, "success weakCompareAndSetPlain float value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, 1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetPlain float"); float x = (float) vh.get(array, i); - assertEquals(x, 2.0f, "weakCompareAndSetPlain float value"); + assertEquals(x, 2.0f, "failing weakCompareAndSetPlain float value"); } { @@ -960,9 +1023,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, 2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSetAcquire float"); + assertEquals(success, true, "success weakCompareAndSetAcquire float"); float x = (float) vh.get(array, i); - assertEquals(x, 1.0f, "weakCompareAndSetAcquire float"); + assertEquals(x, 1.0f, "success weakCompareAndSetAcquire float"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, 2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetAcquire float"); + float x = (float) vh.get(array, i); + assertEquals(x, 1.0f, "failing weakCompareAndSetAcquire float value"); } { @@ -970,9 +1040,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, 1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetRelease float"); + assertEquals(success, true, "success weakCompareAndSetRelease float"); + float x = (float) vh.get(array, i); + assertEquals(x, 2.0f, "success weakCompareAndSetRelease float"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, 1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetRelease float"); float x = (float) vh.get(array, i); - assertEquals(x, 2.0f, "weakCompareAndSetRelease float"); + assertEquals(x, 2.0f, "failing weakCompareAndSetRelease float value"); } { @@ -980,9 +1057,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, 2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSet float"); + assertEquals(success, true, "success weakCompareAndSet float"); + float x = (float) vh.get(array, i); + assertEquals(x, 1.0f, "success weakCompareAndSet float"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, 2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSet float"); float x = (float) vh.get(array, i); - assertEquals(x, 1.0f, "weakCompareAndSet float"); + assertEquals(x, 1.0f, "failing weakCompareAndSet float value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java index bfa7665a8f5..d459e8eebe5 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.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 @@ -421,9 +421,16 @@ static void testInstanceField(VarHandleTestAccessInt recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(recv, 0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetPlain int"); + assertEquals(success, true, "success weakCompareAndSetPlain int"); int x = (int) vh.get(recv); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value"); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetPlain int value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(recv, 0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetPlain int"); + int x = (int) vh.get(recv); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetPlain int value"); } { @@ -431,9 +438,16 @@ static void testInstanceField(VarHandleTestAccessInt recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(recv, 0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSetAcquire int"); + assertEquals(success, true, "success weakCompareAndSetAcquire int"); + int x = (int) vh.get(recv); + assertEquals(x, 0x01234567, "success weakCompareAndSetAcquire int"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(recv, 0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetAcquire int"); int x = (int) vh.get(recv); - assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int"); + assertEquals(x, 0x01234567, "failing weakCompareAndSetAcquire int value"); } { @@ -441,9 +455,16 @@ static void testInstanceField(VarHandleTestAccessInt recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(recv, 0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetRelease int"); + assertEquals(success, true, "success weakCompareAndSetRelease int"); + int x = (int) vh.get(recv); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetRelease int"); + } + + { + boolean success = vh.weakCompareAndSetRelease(recv, 0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetRelease int"); int x = (int) vh.get(recv); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int"); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetRelease int value"); } { @@ -451,9 +472,16 @@ static void testInstanceField(VarHandleTestAccessInt recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(recv, 0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSet int"); + assertEquals(success, true, "success weakCompareAndSet int"); int x = (int) vh.get(recv); - assertEquals(x, 0x01234567, "weakCompareAndSet int value"); + assertEquals(x, 0x01234567, "success weakCompareAndSet int value"); + } + + { + boolean success = vh.weakCompareAndSet(recv, 0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSet int"); + int x = (int) vh.get(recv); + assertEquals(x, 0x01234567, "failing weakCompareAndSet int value"); } // Compare set and get @@ -697,9 +725,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetPlain int"); + assertEquals(success, true, "success weakCompareAndSetPlain int"); + int x = (int) vh.get(); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetPlain int value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetPlain int"); int x = (int) vh.get(); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value"); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetPlain int value"); } { @@ -707,9 +742,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSetAcquire int"); + assertEquals(success, true, "success weakCompareAndSetAcquire int"); + int x = (int) vh.get(); + assertEquals(x, 0x01234567, "success weakCompareAndSetAcquire int"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetAcquire int"); int x = (int) vh.get(); - assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int"); + assertEquals(x, 0x01234567, "failing weakCompareAndSetAcquire int value"); } { @@ -717,9 +759,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetRelease int"); + assertEquals(success, true, "success weakCompareAndSetRelease int"); int x = (int) vh.get(); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int"); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetRelease int"); + } + + { + boolean success = vh.weakCompareAndSetRelease(0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetRelease int"); + int x = (int) vh.get(); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetRelease int value"); } { @@ -727,9 +776,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSet int"); + assertEquals(success, true, "success weakCompareAndSet int"); + int x = (int) vh.get(); + assertEquals(x, 0x01234567, "success weakCompareAndSet int"); + } + + { + boolean success = vh.weakCompareAndSet(0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSet int"); int x = (int) vh.get(); - assertEquals(x, 0x01234567, "weakCompareAndSet int"); + assertEquals(x, 0x01234567, "failing weakCompareAndSet int value"); } // Compare set and get @@ -976,9 +1032,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, 0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetPlain int"); + assertEquals(success, true, "success weakCompareAndSetPlain int"); + int x = (int) vh.get(array, i); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetPlain int value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, 0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetPlain int"); int x = (int) vh.get(array, i); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value"); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetPlain int value"); } { @@ -986,9 +1049,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, 0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSetAcquire int"); + assertEquals(success, true, "success weakCompareAndSetAcquire int"); int x = (int) vh.get(array, i); - assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int"); + assertEquals(x, 0x01234567, "success weakCompareAndSetAcquire int"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, 0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetAcquire int"); + int x = (int) vh.get(array, i); + assertEquals(x, 0x01234567, "failing weakCompareAndSetAcquire int value"); } { @@ -996,9 +1066,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, 0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetRelease int"); + assertEquals(success, true, "success weakCompareAndSetRelease int"); + int x = (int) vh.get(array, i); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetRelease int"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, 0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetRelease int"); int x = (int) vh.get(array, i); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int"); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetRelease int value"); } { @@ -1006,9 +1083,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, 0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSet int"); + assertEquals(success, true, "success weakCompareAndSet int"); + int x = (int) vh.get(array, i); + assertEquals(x, 0x01234567, "success weakCompareAndSet int"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, 0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSet int"); int x = (int) vh.get(array, i); - assertEquals(x, 0x01234567, "weakCompareAndSet int"); + assertEquals(x, 0x01234567, "failing weakCompareAndSet int value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java index 6d948593f86..ce6fc2b1137 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.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 @@ -421,9 +421,16 @@ static void testInstanceField(VarHandleTestAccessLong recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(recv, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetPlain long"); + assertEquals(success, true, "success weakCompareAndSetPlain long"); long x = (long) vh.get(recv); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetPlain long value"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetPlain long value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(recv, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetPlain long"); + long x = (long) vh.get(recv); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetPlain long value"); } { @@ -431,9 +438,16 @@ static void testInstanceField(VarHandleTestAccessLong recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(recv, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSetAcquire long"); + assertEquals(success, true, "success weakCompareAndSetAcquire long"); + long x = (long) vh.get(recv); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSetAcquire long"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(recv, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetAcquire long"); long x = (long) vh.get(recv); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSetAcquire long"); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSetAcquire long value"); } { @@ -441,9 +455,16 @@ static void testInstanceField(VarHandleTestAccessLong recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(recv, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetRelease long"); + assertEquals(success, true, "success weakCompareAndSetRelease long"); + long x = (long) vh.get(recv); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetRelease long"); + } + + { + boolean success = vh.weakCompareAndSetRelease(recv, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetRelease long"); long x = (long) vh.get(recv); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetRelease long"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetRelease long value"); } { @@ -451,9 +472,16 @@ static void testInstanceField(VarHandleTestAccessLong recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(recv, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSet long"); + assertEquals(success, true, "success weakCompareAndSet long"); long x = (long) vh.get(recv); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSet long value"); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSet long value"); + } + + { + boolean success = vh.weakCompareAndSet(recv, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSet long"); + long x = (long) vh.get(recv); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSet long value"); } // Compare set and get @@ -697,9 +725,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetPlain long"); + assertEquals(success, true, "success weakCompareAndSetPlain long"); + long x = (long) vh.get(); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetPlain long value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetPlain long"); long x = (long) vh.get(); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetPlain long value"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetPlain long value"); } { @@ -707,9 +742,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSetAcquire long"); + assertEquals(success, true, "success weakCompareAndSetAcquire long"); + long x = (long) vh.get(); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSetAcquire long"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetAcquire long"); long x = (long) vh.get(); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSetAcquire long"); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSetAcquire long value"); } { @@ -717,9 +759,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetRelease long"); + assertEquals(success, true, "success weakCompareAndSetRelease long"); long x = (long) vh.get(); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetRelease long"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetRelease long"); + } + + { + boolean success = vh.weakCompareAndSetRelease(0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetRelease long"); + long x = (long) vh.get(); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetRelease long value"); } { @@ -727,9 +776,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSet long"); + assertEquals(success, true, "success weakCompareAndSet long"); + long x = (long) vh.get(); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSet long"); + } + + { + boolean success = vh.weakCompareAndSet(0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSet long"); long x = (long) vh.get(); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSet long"); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSet long value"); } // Compare set and get @@ -976,9 +1032,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetPlain long"); + assertEquals(success, true, "success weakCompareAndSetPlain long"); + long x = (long) vh.get(array, i); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetPlain long value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetPlain long"); long x = (long) vh.get(array, i); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetPlain long value"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetPlain long value"); } { @@ -986,9 +1049,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSetAcquire long"); + assertEquals(success, true, "success weakCompareAndSetAcquire long"); long x = (long) vh.get(array, i); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSetAcquire long"); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSetAcquire long"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetAcquire long"); + long x = (long) vh.get(array, i); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSetAcquire long value"); } { @@ -996,9 +1066,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetRelease long"); + assertEquals(success, true, "success weakCompareAndSetRelease long"); + long x = (long) vh.get(array, i); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetRelease long"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetRelease long"); long x = (long) vh.get(array, i); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetRelease long"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetRelease long value"); } { @@ -1006,9 +1083,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSet long"); + assertEquals(success, true, "success weakCompareAndSet long"); + long x = (long) vh.get(array, i); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSet long"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSet long"); long x = (long) vh.get(array, i); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSet long"); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSet long value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java index 088de606734..5e8f61b3cdb 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.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 @@ -421,9 +421,16 @@ static void testInstanceField(VarHandleTestAccessShort recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(recv, (short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetPlain short"); + assertEquals(success, true, "success weakCompareAndSetPlain short"); short x = (short) vh.get(recv); - assertEquals(x, (short)0x4567, "weakCompareAndSetPlain short value"); + assertEquals(x, (short)0x4567, "success weakCompareAndSetPlain short value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(recv, (short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetPlain short"); + short x = (short) vh.get(recv); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetPlain short value"); } { @@ -431,9 +438,16 @@ static void testInstanceField(VarHandleTestAccessShort recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(recv, (short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSetAcquire short"); + assertEquals(success, true, "success weakCompareAndSetAcquire short"); + short x = (short) vh.get(recv); + assertEquals(x, (short)0x0123, "success weakCompareAndSetAcquire short"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(recv, (short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetAcquire short"); short x = (short) vh.get(recv); - assertEquals(x, (short)0x0123, "weakCompareAndSetAcquire short"); + assertEquals(x, (short)0x0123, "failing weakCompareAndSetAcquire short value"); } { @@ -441,9 +455,16 @@ static void testInstanceField(VarHandleTestAccessShort recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(recv, (short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetRelease short"); + assertEquals(success, true, "success weakCompareAndSetRelease short"); + short x = (short) vh.get(recv); + assertEquals(x, (short)0x4567, "success weakCompareAndSetRelease short"); + } + + { + boolean success = vh.weakCompareAndSetRelease(recv, (short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetRelease short"); short x = (short) vh.get(recv); - assertEquals(x, (short)0x4567, "weakCompareAndSetRelease short"); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetRelease short value"); } { @@ -451,9 +472,16 @@ static void testInstanceField(VarHandleTestAccessShort recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(recv, (short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSet short"); + assertEquals(success, true, "success weakCompareAndSet short"); short x = (short) vh.get(recv); - assertEquals(x, (short)0x0123, "weakCompareAndSet short value"); + assertEquals(x, (short)0x0123, "success weakCompareAndSet short value"); + } + + { + boolean success = vh.weakCompareAndSet(recv, (short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSet short"); + short x = (short) vh.get(recv); + assertEquals(x, (short)0x0123, "failing weakCompareAndSet short value"); } // Compare set and get @@ -697,9 +725,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain((short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetPlain short"); + assertEquals(success, true, "success weakCompareAndSetPlain short"); + short x = (short) vh.get(); + assertEquals(x, (short)0x4567, "success weakCompareAndSetPlain short value"); + } + + { + boolean success = vh.weakCompareAndSetPlain((short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetPlain short"); short x = (short) vh.get(); - assertEquals(x, (short)0x4567, "weakCompareAndSetPlain short value"); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetPlain short value"); } { @@ -707,9 +742,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire((short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSetAcquire short"); + assertEquals(success, true, "success weakCompareAndSetAcquire short"); + short x = (short) vh.get(); + assertEquals(x, (short)0x0123, "success weakCompareAndSetAcquire short"); + } + + { + boolean success = vh.weakCompareAndSetAcquire((short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetAcquire short"); short x = (short) vh.get(); - assertEquals(x, (short)0x0123, "weakCompareAndSetAcquire short"); + assertEquals(x, (short)0x0123, "failing weakCompareAndSetAcquire short value"); } { @@ -717,9 +759,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease((short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetRelease short"); + assertEquals(success, true, "success weakCompareAndSetRelease short"); short x = (short) vh.get(); - assertEquals(x, (short)0x4567, "weakCompareAndSetRelease short"); + assertEquals(x, (short)0x4567, "success weakCompareAndSetRelease short"); + } + + { + boolean success = vh.weakCompareAndSetRelease((short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetRelease short"); + short x = (short) vh.get(); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetRelease short value"); } { @@ -727,9 +776,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet((short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSet short"); + assertEquals(success, true, "success weakCompareAndSet short"); + short x = (short) vh.get(); + assertEquals(x, (short)0x0123, "success weakCompareAndSet short"); + } + + { + boolean success = vh.weakCompareAndSet((short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSet short"); short x = (short) vh.get(); - assertEquals(x, (short)0x0123, "weakCompareAndSet short"); + assertEquals(x, (short)0x0123, "failing weakCompareAndSet short value"); } // Compare set and get @@ -976,9 +1032,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, (short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetPlain short"); + assertEquals(success, true, "success weakCompareAndSetPlain short"); + short x = (short) vh.get(array, i); + assertEquals(x, (short)0x4567, "success weakCompareAndSetPlain short value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, (short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetPlain short"); short x = (short) vh.get(array, i); - assertEquals(x, (short)0x4567, "weakCompareAndSetPlain short value"); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetPlain short value"); } { @@ -986,9 +1049,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, (short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSetAcquire short"); + assertEquals(success, true, "success weakCompareAndSetAcquire short"); short x = (short) vh.get(array, i); - assertEquals(x, (short)0x0123, "weakCompareAndSetAcquire short"); + assertEquals(x, (short)0x0123, "success weakCompareAndSetAcquire short"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, (short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetAcquire short"); + short x = (short) vh.get(array, i); + assertEquals(x, (short)0x0123, "failing weakCompareAndSetAcquire short value"); } { @@ -996,9 +1066,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, (short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetRelease short"); + assertEquals(success, true, "success weakCompareAndSetRelease short"); + short x = (short) vh.get(array, i); + assertEquals(x, (short)0x4567, "success weakCompareAndSetRelease short"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, (short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetRelease short"); short x = (short) vh.get(array, i); - assertEquals(x, (short)0x4567, "weakCompareAndSetRelease short"); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetRelease short value"); } { @@ -1006,9 +1083,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, (short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSet short"); + assertEquals(success, true, "success weakCompareAndSet short"); + short x = (short) vh.get(array, i); + assertEquals(x, (short)0x0123, "success weakCompareAndSet short"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, (short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSet short"); short x = (short) vh.get(array, i); - assertEquals(x, (short)0x0123, "weakCompareAndSet short"); + assertEquals(x, (short)0x0123, "failing weakCompareAndSet short value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java index 04ed5de6c35..f3705210594 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.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 @@ -520,9 +520,16 @@ static void testInstanceField(VarHandleTestAccessString recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(recv, "foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetPlain String"); + assertEquals(success, true, "success weakCompareAndSetPlain String"); String x = (String) vh.get(recv); - assertEquals(x, "bar", "weakCompareAndSetPlain String value"); + assertEquals(x, "bar", "success weakCompareAndSetPlain String value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(recv, "foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetPlain String"); + String x = (String) vh.get(recv); + assertEquals(x, "bar", "failing weakCompareAndSetPlain String value"); } { @@ -530,9 +537,16 @@ static void testInstanceField(VarHandleTestAccessString recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(recv, "bar", "foo"); } - assertEquals(success, true, "weakCompareAndSetAcquire String"); + assertEquals(success, true, "success weakCompareAndSetAcquire String"); + String x = (String) vh.get(recv); + assertEquals(x, "foo", "success weakCompareAndSetAcquire String"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(recv, "bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSetAcquire String"); String x = (String) vh.get(recv); - assertEquals(x, "foo", "weakCompareAndSetAcquire String"); + assertEquals(x, "foo", "failing weakCompareAndSetAcquire String value"); } { @@ -540,9 +554,16 @@ static void testInstanceField(VarHandleTestAccessString recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(recv, "foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetRelease String"); + assertEquals(success, true, "success weakCompareAndSetRelease String"); + String x = (String) vh.get(recv); + assertEquals(x, "bar", "success weakCompareAndSetRelease String"); + } + + { + boolean success = vh.weakCompareAndSetRelease(recv, "foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetRelease String"); String x = (String) vh.get(recv); - assertEquals(x, "bar", "weakCompareAndSetRelease String"); + assertEquals(x, "bar", "failing weakCompareAndSetRelease String value"); } { @@ -550,9 +571,16 @@ static void testInstanceField(VarHandleTestAccessString recv, VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(recv, "bar", "foo"); } - assertEquals(success, true, "weakCompareAndSet String"); + assertEquals(success, true, "success weakCompareAndSet String"); String x = (String) vh.get(recv); - assertEquals(x, "foo", "weakCompareAndSet String value"); + assertEquals(x, "foo", "success weakCompareAndSet String value"); + } + + { + boolean success = vh.weakCompareAndSet(recv, "bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSet String"); + String x = (String) vh.get(recv); + assertEquals(x, "foo", "failing weakCompareAndSet String value"); } // Compare set and get @@ -732,9 +760,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain("foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetPlain String"); + assertEquals(success, true, "success weakCompareAndSetPlain String"); + String x = (String) vh.get(); + assertEquals(x, "bar", "success weakCompareAndSetPlain String value"); + } + + { + boolean success = vh.weakCompareAndSetPlain("foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetPlain String"); String x = (String) vh.get(); - assertEquals(x, "bar", "weakCompareAndSetPlain String value"); + assertEquals(x, "bar", "failing weakCompareAndSetPlain String value"); } { @@ -742,9 +777,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire("bar", "foo"); } - assertEquals(success, true, "weakCompareAndSetAcquire String"); + assertEquals(success, true, "success weakCompareAndSetAcquire String"); + String x = (String) vh.get(); + assertEquals(x, "foo", "success weakCompareAndSetAcquire String"); + } + + { + boolean success = vh.weakCompareAndSetAcquire("bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSetAcquire String"); String x = (String) vh.get(); - assertEquals(x, "foo", "weakCompareAndSetAcquire String"); + assertEquals(x, "foo", "failing weakCompareAndSetAcquire String value"); } { @@ -752,9 +794,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease("foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetRelease String"); + assertEquals(success, true, "success weakCompareAndSetRelease String"); String x = (String) vh.get(); - assertEquals(x, "bar", "weakCompareAndSetRelease String"); + assertEquals(x, "bar", "success weakCompareAndSetRelease String"); + } + + { + boolean success = vh.weakCompareAndSetRelease("foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetRelease String"); + String x = (String) vh.get(); + assertEquals(x, "bar", "failing weakCompareAndSetRelease String value"); } { @@ -762,9 +811,16 @@ static void testStaticField(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet("bar", "foo"); } - assertEquals(success, true, "weakCompareAndSet String"); + assertEquals(success, true, "success weakCompareAndSet String"); + String x = (String) vh.get(); + assertEquals(x, "foo", "success weakCompareAndSet String"); + } + + { + boolean success = vh.weakCompareAndSet("bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSet String"); String x = (String) vh.get(); - assertEquals(x, "foo", "weakCompareAndSet String"); + assertEquals(x, "foo", "failing weakCompareAndSet String value"); } // Compare set and get @@ -947,9 +1003,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, "foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetPlain String"); + assertEquals(success, true, "success weakCompareAndSetPlain String"); + String x = (String) vh.get(array, i); + assertEquals(x, "bar", "success weakCompareAndSetPlain String value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, "foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetPlain String"); String x = (String) vh.get(array, i); - assertEquals(x, "bar", "weakCompareAndSetPlain String value"); + assertEquals(x, "bar", "failing weakCompareAndSetPlain String value"); } { @@ -957,9 +1020,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, "bar", "foo"); } - assertEquals(success, true, "weakCompareAndSetAcquire String"); + assertEquals(success, true, "success weakCompareAndSetAcquire String"); String x = (String) vh.get(array, i); - assertEquals(x, "foo", "weakCompareAndSetAcquire String"); + assertEquals(x, "foo", "success weakCompareAndSetAcquire String"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, "bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSetAcquire String"); + String x = (String) vh.get(array, i); + assertEquals(x, "foo", "failing weakCompareAndSetAcquire String value"); } { @@ -967,9 +1037,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, "foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetRelease String"); + assertEquals(success, true, "success weakCompareAndSetRelease String"); + String x = (String) vh.get(array, i); + assertEquals(x, "bar", "success weakCompareAndSetRelease String"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, "foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetRelease String"); String x = (String) vh.get(array, i); - assertEquals(x, "bar", "weakCompareAndSetRelease String"); + assertEquals(x, "bar", "failing weakCompareAndSetRelease String value"); } { @@ -977,9 +1054,16 @@ static void testArray(VarHandle vh) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, "bar", "foo"); } - assertEquals(success, true, "weakCompareAndSet String"); + assertEquals(success, true, "success weakCompareAndSet String"); + String x = (String) vh.get(array, i); + assertEquals(x, "foo", "success weakCompareAndSet String"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, "bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSet String"); String x = (String) vh.get(array, i); - assertEquals(x, "foo", "weakCompareAndSet String"); + assertEquals(x, "foo", "failing weakCompareAndSet String value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java index 95f8f99c46c..4815dd2f249 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, 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 diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java index db9fa172089..4b67fa9a250 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, 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 @@ -1051,9 +1051,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetPlain double"); + assertEquals(success, true, "success weakCompareAndSetPlain double"); double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetPlain double value"); + assertEquals(x, VALUE_2, "success weakCompareAndSetPlain double value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetPlain double"); + double x = (double) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain double value"); } { @@ -1061,9 +1068,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSetAcquire double"); + assertEquals(success, true, "success weakCompareAndSetAcquire double"); + double x = (double) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire double"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetAcquire double"); double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double"); + assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire double value"); } { @@ -1071,9 +1085,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetRelease double"); + assertEquals(success, true, "success weakCompareAndSetRelease double"); double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetRelease double"); + assertEquals(x, VALUE_2, "success weakCompareAndSetRelease double"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetRelease double"); + double x = (double) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease double value"); } { @@ -1081,9 +1102,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSet double"); + assertEquals(success, true, "success weakCompareAndSet double"); + double x = (double) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSet double"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSet double"); double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSet double"); + assertEquals(x, VALUE_1, "failing weakCompareAndSet double value"); } // Compare set and get @@ -1224,9 +1252,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetPlain double"); + assertEquals(success, true, "success weakCompareAndSetPlain double"); double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetPlain double value"); + assertEquals(x, VALUE_2, "success weakCompareAndSetPlain double value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetPlain double"); + double x = (double) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain double value"); } { @@ -1234,9 +1269,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSetAcquire double"); + assertEquals(success, true, "success weakCompareAndSetAcquire double"); + double x = (double) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire double"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetAcquire double"); double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double"); + assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire double value"); } { @@ -1244,9 +1286,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetRelease double"); + assertEquals(success, true, "success weakCompareAndSetRelease double"); double x = (double) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetRelease double"); + assertEquals(x, VALUE_2, "success weakCompareAndSetRelease double"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetRelease double"); + double x = (double) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease double value"); } { @@ -1254,9 +1303,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSet double"); + assertEquals(success, true, "success weakCompareAndSet double"); + double x = (double) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSet double"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSet double"); double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSet double"); + assertEquals(x, VALUE_1, "failing weakCompareAndSet double value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java index cde308ff093..a5afcf76ca5 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, 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 @@ -1051,9 +1051,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetPlain float"); + assertEquals(success, true, "success weakCompareAndSetPlain float"); float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetPlain float value"); + assertEquals(x, VALUE_2, "success weakCompareAndSetPlain float value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetPlain float"); + float x = (float) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain float value"); } { @@ -1061,9 +1068,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSetAcquire float"); + assertEquals(success, true, "success weakCompareAndSetAcquire float"); + float x = (float) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire float"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetAcquire float"); float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float"); + assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire float value"); } { @@ -1071,9 +1085,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetRelease float"); + assertEquals(success, true, "success weakCompareAndSetRelease float"); float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetRelease float"); + assertEquals(x, VALUE_2, "success weakCompareAndSetRelease float"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetRelease float"); + float x = (float) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease float value"); } { @@ -1081,9 +1102,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSet float"); + assertEquals(success, true, "success weakCompareAndSet float"); + float x = (float) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSet float"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSet float"); float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSet float"); + assertEquals(x, VALUE_1, "failing weakCompareAndSet float value"); } // Compare set and get @@ -1224,9 +1252,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetPlain float"); + assertEquals(success, true, "success weakCompareAndSetPlain float"); float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetPlain float value"); + assertEquals(x, VALUE_2, "success weakCompareAndSetPlain float value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetPlain float"); + float x = (float) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain float value"); } { @@ -1234,9 +1269,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSetAcquire float"); + assertEquals(success, true, "success weakCompareAndSetAcquire float"); + float x = (float) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire float"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetAcquire float"); float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float"); + assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire float value"); } { @@ -1244,9 +1286,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetRelease float"); + assertEquals(success, true, "success weakCompareAndSetRelease float"); float x = (float) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetRelease float"); + assertEquals(x, VALUE_2, "success weakCompareAndSetRelease float"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetRelease float"); + float x = (float) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease float value"); } { @@ -1254,9 +1303,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSet float"); + assertEquals(success, true, "success weakCompareAndSet float"); + float x = (float) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSet float"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSet float"); float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSet float"); + assertEquals(x, VALUE_1, "failing weakCompareAndSet float value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java index 8f499591dc6..e40a84ddc19 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, 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 @@ -1235,9 +1235,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetPlain int"); + assertEquals(success, true, "success weakCompareAndSetPlain int"); int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetPlain int value"); + assertEquals(x, VALUE_2, "success weakCompareAndSetPlain int value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetPlain int"); + int x = (int) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain int value"); } { @@ -1245,9 +1252,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSetAcquire int"); + assertEquals(success, true, "success weakCompareAndSetAcquire int"); + int x = (int) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire int"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetAcquire int"); int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int"); + assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire int value"); } { @@ -1255,9 +1269,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetRelease int"); + assertEquals(success, true, "success weakCompareAndSetRelease int"); int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetRelease int"); + assertEquals(x, VALUE_2, "success weakCompareAndSetRelease int"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetRelease int"); + int x = (int) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease int value"); } { @@ -1265,9 +1286,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSet int"); + assertEquals(success, true, "success weakCompareAndSet int"); + int x = (int) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSet int"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSet int"); int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSet int"); + assertEquals(x, VALUE_1, "failing weakCompareAndSet int value"); } // Compare set and get @@ -1518,9 +1546,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetPlain int"); + assertEquals(success, true, "success weakCompareAndSetPlain int"); int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetPlain int value"); + assertEquals(x, VALUE_2, "success weakCompareAndSetPlain int value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetPlain int"); + int x = (int) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain int value"); } { @@ -1528,9 +1563,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSetAcquire int"); + assertEquals(success, true, "success weakCompareAndSetAcquire int"); + int x = (int) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire int"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetAcquire int"); int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int"); + assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire int value"); } { @@ -1538,9 +1580,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetRelease int"); + assertEquals(success, true, "success weakCompareAndSetRelease int"); int x = (int) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetRelease int"); + assertEquals(x, VALUE_2, "success weakCompareAndSetRelease int"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetRelease int"); + int x = (int) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease int value"); } { @@ -1548,9 +1597,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSet int"); + assertEquals(success, true, "success weakCompareAndSet int"); + int x = (int) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSet int"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSet int"); int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSet int"); + assertEquals(x, VALUE_1, "failing weakCompareAndSet int value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java index 355dca74887..18e6902082b 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, 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 @@ -1235,9 +1235,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetPlain long"); + assertEquals(success, true, "success weakCompareAndSetPlain long"); long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetPlain long value"); + assertEquals(x, VALUE_2, "success weakCompareAndSetPlain long value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetPlain long"); + long x = (long) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain long value"); } { @@ -1245,9 +1252,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSetAcquire long"); + assertEquals(success, true, "success weakCompareAndSetAcquire long"); + long x = (long) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire long"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetAcquire long"); long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long"); + assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire long value"); } { @@ -1255,9 +1269,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetRelease long"); + assertEquals(success, true, "success weakCompareAndSetRelease long"); long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetRelease long"); + assertEquals(x, VALUE_2, "success weakCompareAndSetRelease long"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetRelease long"); + long x = (long) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease long value"); } { @@ -1265,9 +1286,16 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSet long"); + assertEquals(success, true, "success weakCompareAndSet long"); + long x = (long) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSet long"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSet long"); long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSet long"); + assertEquals(x, VALUE_1, "failing weakCompareAndSet long value"); } // Compare set and get @@ -1518,9 +1546,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetPlain long"); + assertEquals(success, true, "success weakCompareAndSetPlain long"); long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetPlain long value"); + assertEquals(x, VALUE_2, "success weakCompareAndSetPlain long value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetPlain long"); + long x = (long) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain long value"); } { @@ -1528,9 +1563,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSetAcquire long"); + assertEquals(success, true, "success weakCompareAndSetAcquire long"); + long x = (long) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire long"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetAcquire long"); long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long"); + assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire long value"); } { @@ -1538,9 +1580,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetRelease long"); + assertEquals(success, true, "success weakCompareAndSetRelease long"); long x = (long) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetRelease long"); + assertEquals(x, VALUE_2, "success weakCompareAndSetRelease long"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetRelease long"); + long x = (long) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease long value"); } { @@ -1548,9 +1597,16 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSet long"); + assertEquals(success, true, "success weakCompareAndSet long"); + long x = (long) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSet long"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSet long"); long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSet long"); + assertEquals(x, VALUE_1, "failing weakCompareAndSet long value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java index 46a7fff99ff..336ff4addec 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, 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 diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java index 99904d32c02..3be56ac3c4a 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, 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 @@ -212,9 +212,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessBoolean recv, Handl for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, true, false); } - assertEquals(success, true, "weakCompareAndSetPlain boolean"); + assertEquals(success, true, "success weakCompareAndSetPlain boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, false, "weakCompareAndSetPlain boolean value"); + assertEquals(x, false, "success weakCompareAndSetPlain boolean value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, true, false); + assertEquals(success, false, "failing weakCompareAndSetPlain boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, false, "failing weakCompareAndSetPlain boolean value"); } { @@ -222,9 +229,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessBoolean recv, Handl for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, false, true); } - assertEquals(success, true, "weakCompareAndSetAcquire boolean"); + assertEquals(success, true, "success weakCompareAndSetAcquire boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, true, "success weakCompareAndSetAcquire boolean"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, false, false); + assertEquals(success, false, "failing weakCompareAndSetAcquire boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, true, "weakCompareAndSetAcquire boolean"); + assertEquals(x, true, "failing weakCompareAndSetAcquire boolean value"); } { @@ -232,9 +246,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessBoolean recv, Handl for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, true, false); } - assertEquals(success, true, "weakCompareAndSetRelease boolean"); + assertEquals(success, true, "success weakCompareAndSetRelease boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, false, "success weakCompareAndSetRelease boolean"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, true, false); + assertEquals(success, false, "failing weakCompareAndSetRelease boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, false, "weakCompareAndSetRelease boolean"); + assertEquals(x, false, "failing weakCompareAndSetRelease boolean value"); } { @@ -242,9 +263,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessBoolean recv, Handl for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, false, true); } - assertEquals(success, true, "weakCompareAndSet boolean"); + assertEquals(success, true, "success weakCompareAndSet boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, true, "weakCompareAndSet boolean"); + assertEquals(x, true, "success weakCompareAndSet boolean"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, false, false); + assertEquals(success, false, "failing weakCompareAndSet boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, true, "failing weakCompareAndSet boolean value"); } // Compare set and get @@ -446,9 +474,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(true, false); } - assertEquals(success, true, "weakCompareAndSetPlain boolean"); + assertEquals(success, true, "success weakCompareAndSetPlain boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, false, "success weakCompareAndSetPlain boolean value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(true, false); + assertEquals(success, false, "failing weakCompareAndSetPlain boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, false, "weakCompareAndSetPlain boolean value"); + assertEquals(x, false, "failing weakCompareAndSetPlain boolean value"); } { @@ -456,9 +491,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(false, true); } - assertEquals(success, true, "weakCompareAndSetAcquire boolean"); + assertEquals(success, true, "success weakCompareAndSetAcquire boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, true, "success weakCompareAndSetAcquire boolean"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(false, false); + assertEquals(success, false, "failing weakCompareAndSetAcquire boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, true, "weakCompareAndSetAcquire boolean"); + assertEquals(x, true, "failing weakCompareAndSetAcquire boolean value"); } { @@ -466,9 +508,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(true, false); } - assertEquals(success, true, "weakCompareAndSetRelease boolean"); + assertEquals(success, true, "success weakCompareAndSetRelease boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, false, "weakCompareAndSetRelease boolean"); + assertEquals(x, false, "success weakCompareAndSetRelease boolean"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(true, false); + assertEquals(success, false, "failing weakCompareAndSetRelease boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, false, "failing weakCompareAndSetRelease boolean value"); } { @@ -476,9 +525,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(false, true); } - assertEquals(success, true, "weakCompareAndSet boolean"); + assertEquals(success, true, "success weakCompareAndSet boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, true, "success weakCompareAndSet boolean"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(false, false); + assertEquals(success, false, "failing weakCompareAndSet boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, true, "weakCompareAndSet boolean"); + assertEquals(x, true, "failing weakCompareAndSetRe boolean value"); } // Compare set and get @@ -705,9 +761,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, true, false); } - assertEquals(success, true, "weakCompareAndSetPlain boolean"); + assertEquals(success, true, "success weakCompareAndSetPlain boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, false, "success weakCompareAndSetPlain boolean value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, true, false); + assertEquals(success, false, "failing weakCompareAndSetPlain boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, false, "weakCompareAndSetPlain boolean value"); + assertEquals(x, false, "failing weakCompareAndSetPlain boolean value"); } { @@ -715,9 +778,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, false, true); } - assertEquals(success, true, "weakCompareAndSetAcquire boolean"); + assertEquals(success, true, "success weakCompareAndSetAcquire boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, true, "weakCompareAndSetAcquire boolean"); + assertEquals(x, true, "success weakCompareAndSetAcquire boolean"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, false, false); + assertEquals(success, false, "failing weakCompareAndSetAcquire boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, true, "failing weakCompareAndSetAcquire boolean value"); } { @@ -725,9 +795,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, true, false); } - assertEquals(success, true, "weakCompareAndSetRelease boolean"); + assertEquals(success, true, "success weakCompareAndSetRelease boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, false, "success weakCompareAndSetRelease boolean"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, true, false); + assertEquals(success, false, "failing weakCompareAndSetAcquire boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, false, "weakCompareAndSetRelease boolean"); + assertEquals(x, false, "failing weakCompareAndSetAcquire boolean value"); } { @@ -735,9 +812,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, false, true); } - assertEquals(success, true, "weakCompareAndSet boolean"); + assertEquals(success, true, "success weakCompareAndSet boolean"); + boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, true, "success weakCompareAndSet boolean"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, false, false); + assertEquals(success, false, "failing weakCompareAndSet boolean"); boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, true, "weakCompareAndSet boolean"); + assertEquals(x, true, "failing weakCompareAndSet boolean value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java index 7ab3b99f949..b60ab7bd8e6 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, 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 @@ -212,9 +212,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessByte recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, (byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetPlain byte"); + assertEquals(success, true, "success weakCompareAndSetPlain byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value"); + assertEquals(x, (byte)0x23, "success weakCompareAndSetPlain byte value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, (byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetPlain byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetPlain byte value"); } { @@ -222,9 +229,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessByte recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, (byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSetAcquire byte"); + assertEquals(success, true, "success weakCompareAndSetAcquire byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, (byte)0x01, "success weakCompareAndSetAcquire byte"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, (byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetAcquire byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte"); + assertEquals(x, (byte)0x01, "failing weakCompareAndSetAcquire byte value"); } { @@ -232,9 +246,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessByte recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, (byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetRelease byte"); + assertEquals(success, true, "success weakCompareAndSetRelease byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, (byte)0x23, "success weakCompareAndSetRelease byte"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, (byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetRelease byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte"); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetRelease byte value"); } { @@ -242,9 +263,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessByte recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, (byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSet byte"); + assertEquals(success, true, "success weakCompareAndSet byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, (byte)0x01, "weakCompareAndSet byte"); + assertEquals(x, (byte)0x01, "success weakCompareAndSet byte"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, (byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSet byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, (byte)0x01, "failing weakCompareAndSet byte value"); } // Compare set and get @@ -468,9 +496,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact((byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetPlain byte"); + assertEquals(success, true, "success weakCompareAndSetPlain byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, (byte)0x23, "success weakCompareAndSetPlain byte value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact((byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetPlain byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value"); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetPlain byte value"); } { @@ -478,9 +513,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact((byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSetAcquire byte"); + assertEquals(success, true, "success weakCompareAndSetAcquire byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, (byte)0x01, "success weakCompareAndSetAcquire byte"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact((byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetAcquire byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte"); + assertEquals(x, (byte)0x01, "failing weakCompareAndSetAcquire byte value"); } { @@ -488,9 +530,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact((byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetRelease byte"); + assertEquals(success, true, "success weakCompareAndSetRelease byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte"); + assertEquals(x, (byte)0x23, "success weakCompareAndSetRelease byte"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact((byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetRelease byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetRelease byte value"); } { @@ -498,9 +547,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact((byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSet byte"); + assertEquals(success, true, "success weakCompareAndSet byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, (byte)0x01, "success weakCompareAndSet byte"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact((byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSet byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, (byte)0x01, "weakCompareAndSet byte"); + assertEquals(x, (byte)0x01, "failing weakCompareAndSetRe byte value"); } // Compare set and get @@ -749,9 +805,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, (byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetPlain byte"); + assertEquals(success, true, "success weakCompareAndSetPlain byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, (byte)0x23, "success weakCompareAndSetPlain byte value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, (byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetPlain byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value"); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetPlain byte value"); } { @@ -759,9 +822,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, (byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSetAcquire byte"); + assertEquals(success, true, "success weakCompareAndSetAcquire byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte"); + assertEquals(x, (byte)0x01, "success weakCompareAndSetAcquire byte"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, (byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetAcquire byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, (byte)0x01, "failing weakCompareAndSetAcquire byte value"); } { @@ -769,9 +839,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, (byte)0x01, (byte)0x23); } - assertEquals(success, true, "weakCompareAndSetRelease byte"); + assertEquals(success, true, "success weakCompareAndSetRelease byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, (byte)0x23, "success weakCompareAndSetRelease byte"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, (byte)0x01, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSetAcquire byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte"); + assertEquals(x, (byte)0x23, "failing weakCompareAndSetAcquire byte value"); } { @@ -779,9 +856,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, (byte)0x23, (byte)0x01); } - assertEquals(success, true, "weakCompareAndSet byte"); + assertEquals(success, true, "success weakCompareAndSet byte"); + byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, (byte)0x01, "success weakCompareAndSet byte"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, (byte)0x23, (byte)0x45); + assertEquals(success, false, "failing weakCompareAndSet byte"); byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, (byte)0x01, "weakCompareAndSet byte"); + assertEquals(x, (byte)0x01, "failing weakCompareAndSet byte value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java index 762134b625f..79bbb8622e4 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, 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 @@ -212,9 +212,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessChar recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, '\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetPlain char"); + assertEquals(success, true, "success weakCompareAndSetPlain char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, '\u4567', "weakCompareAndSetPlain char value"); + assertEquals(x, '\u4567', "success weakCompareAndSetPlain char value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, '\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetPlain char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, '\u4567', "failing weakCompareAndSetPlain char value"); } { @@ -222,9 +229,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessChar recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, '\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSetAcquire char"); + assertEquals(success, true, "success weakCompareAndSetAcquire char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, '\u0123', "success weakCompareAndSetAcquire char"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, '\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetAcquire char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, '\u0123', "weakCompareAndSetAcquire char"); + assertEquals(x, '\u0123', "failing weakCompareAndSetAcquire char value"); } { @@ -232,9 +246,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessChar recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, '\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetRelease char"); + assertEquals(success, true, "success weakCompareAndSetRelease char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, '\u4567', "success weakCompareAndSetRelease char"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, '\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetRelease char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, '\u4567', "weakCompareAndSetRelease char"); + assertEquals(x, '\u4567', "failing weakCompareAndSetRelease char value"); } { @@ -242,9 +263,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessChar recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, '\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSet char"); + assertEquals(success, true, "success weakCompareAndSet char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, '\u0123', "weakCompareAndSet char"); + assertEquals(x, '\u0123', "success weakCompareAndSet char"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, '\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSet char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, '\u0123', "failing weakCompareAndSet char value"); } // Compare set and get @@ -468,9 +496,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact('\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetPlain char"); + assertEquals(success, true, "success weakCompareAndSetPlain char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, '\u4567', "success weakCompareAndSetPlain char value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact('\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetPlain char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, '\u4567', "weakCompareAndSetPlain char value"); + assertEquals(x, '\u4567', "failing weakCompareAndSetPlain char value"); } { @@ -478,9 +513,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact('\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSetAcquire char"); + assertEquals(success, true, "success weakCompareAndSetAcquire char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, '\u0123', "success weakCompareAndSetAcquire char"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact('\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetAcquire char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, '\u0123', "weakCompareAndSetAcquire char"); + assertEquals(x, '\u0123', "failing weakCompareAndSetAcquire char value"); } { @@ -488,9 +530,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact('\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetRelease char"); + assertEquals(success, true, "success weakCompareAndSetRelease char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, '\u4567', "weakCompareAndSetRelease char"); + assertEquals(x, '\u4567', "success weakCompareAndSetRelease char"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact('\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetRelease char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, '\u4567', "failing weakCompareAndSetRelease char value"); } { @@ -498,9 +547,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact('\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSet char"); + assertEquals(success, true, "success weakCompareAndSet char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, '\u0123', "success weakCompareAndSet char"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact('\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSet char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, '\u0123', "weakCompareAndSet char"); + assertEquals(x, '\u0123', "failing weakCompareAndSetRe char value"); } // Compare set and get @@ -749,9 +805,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, '\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetPlain char"); + assertEquals(success, true, "success weakCompareAndSetPlain char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, '\u4567', "success weakCompareAndSetPlain char value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, '\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetPlain char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, '\u4567', "weakCompareAndSetPlain char value"); + assertEquals(x, '\u4567', "failing weakCompareAndSetPlain char value"); } { @@ -759,9 +822,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, '\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSetAcquire char"); + assertEquals(success, true, "success weakCompareAndSetAcquire char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, '\u0123', "weakCompareAndSetAcquire char"); + assertEquals(x, '\u0123', "success weakCompareAndSetAcquire char"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, '\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetAcquire char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, '\u0123', "failing weakCompareAndSetAcquire char value"); } { @@ -769,9 +839,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, '\u0123', '\u4567'); } - assertEquals(success, true, "weakCompareAndSetRelease char"); + assertEquals(success, true, "success weakCompareAndSetRelease char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, '\u4567', "success weakCompareAndSetRelease char"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, '\u0123', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSetAcquire char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, '\u4567', "weakCompareAndSetRelease char"); + assertEquals(x, '\u4567', "failing weakCompareAndSetAcquire char value"); } { @@ -779,9 +856,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, '\u4567', '\u0123'); } - assertEquals(success, true, "weakCompareAndSet char"); + assertEquals(success, true, "success weakCompareAndSet char"); + char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, '\u0123', "success weakCompareAndSet char"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, '\u4567', '\u89AB'); + assertEquals(success, false, "failing weakCompareAndSet char"); char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, '\u0123', "weakCompareAndSet char"); + assertEquals(x, '\u0123', "failing weakCompareAndSet char value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java index 409d700c474..ae31f8dc9b2 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, 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 @@ -212,9 +212,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessDouble recv, Handle for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetPlain double"); + assertEquals(success, true, "success weakCompareAndSetPlain double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 2.0d, "weakCompareAndSetPlain double value"); + assertEquals(x, 2.0d, "success weakCompareAndSetPlain double value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetPlain double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 2.0d, "failing weakCompareAndSetPlain double value"); } { @@ -222,9 +229,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessDouble recv, Handle for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSetAcquire double"); + assertEquals(success, true, "success weakCompareAndSetAcquire double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 1.0d, "success weakCompareAndSetAcquire double"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetAcquire double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 1.0d, "weakCompareAndSetAcquire double"); + assertEquals(x, 1.0d, "failing weakCompareAndSetAcquire double value"); } { @@ -232,9 +246,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessDouble recv, Handle for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetRelease double"); + assertEquals(success, true, "success weakCompareAndSetRelease double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 2.0d, "success weakCompareAndSetRelease double"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetRelease double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 2.0d, "weakCompareAndSetRelease double"); + assertEquals(x, 2.0d, "failing weakCompareAndSetRelease double value"); } { @@ -242,9 +263,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessDouble recv, Handle for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSet double"); + assertEquals(success, true, "success weakCompareAndSet double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 1.0d, "weakCompareAndSet double"); + assertEquals(x, 1.0d, "success weakCompareAndSet double"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSet double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 1.0d, "failing weakCompareAndSet double value"); } // Compare set and get @@ -390,9 +418,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetPlain double"); + assertEquals(success, true, "success weakCompareAndSetPlain double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 2.0d, "success weakCompareAndSetPlain double value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetPlain double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 2.0d, "weakCompareAndSetPlain double value"); + assertEquals(x, 2.0d, "failing weakCompareAndSetPlain double value"); } { @@ -400,9 +435,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSetAcquire double"); + assertEquals(success, true, "success weakCompareAndSetAcquire double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 1.0d, "success weakCompareAndSetAcquire double"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetAcquire double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 1.0d, "weakCompareAndSetAcquire double"); + assertEquals(x, 1.0d, "failing weakCompareAndSetAcquire double value"); } { @@ -410,9 +452,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetRelease double"); + assertEquals(success, true, "success weakCompareAndSetRelease double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 2.0d, "weakCompareAndSetRelease double"); + assertEquals(x, 2.0d, "success weakCompareAndSetRelease double"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetRelease double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 2.0d, "failing weakCompareAndSetRelease double value"); } { @@ -420,9 +469,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSet double"); + assertEquals(success, true, "success weakCompareAndSet double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 1.0d, "success weakCompareAndSet double"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSet double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 1.0d, "weakCompareAndSet double"); + assertEquals(x, 1.0d, "failing weakCompareAndSetRe double value"); } // Compare set and get @@ -593,9 +649,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetPlain double"); + assertEquals(success, true, "success weakCompareAndSetPlain double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 2.0d, "success weakCompareAndSetPlain double value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetPlain double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 2.0d, "weakCompareAndSetPlain double value"); + assertEquals(x, 2.0d, "failing weakCompareAndSetPlain double value"); } { @@ -603,9 +666,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSetAcquire double"); + assertEquals(success, true, "success weakCompareAndSetAcquire double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 1.0d, "weakCompareAndSetAcquire double"); + assertEquals(x, 1.0d, "success weakCompareAndSetAcquire double"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetAcquire double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 1.0d, "failing weakCompareAndSetAcquire double value"); } { @@ -613,9 +683,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1.0d, 2.0d); } - assertEquals(success, true, "weakCompareAndSetRelease double"); + assertEquals(success, true, "success weakCompareAndSetRelease double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 2.0d, "success weakCompareAndSetRelease double"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 1.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSetAcquire double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 2.0d, "weakCompareAndSetRelease double"); + assertEquals(x, 2.0d, "failing weakCompareAndSetAcquire double value"); } { @@ -623,9 +700,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 2.0d, 1.0d); } - assertEquals(success, true, "weakCompareAndSet double"); + assertEquals(success, true, "success weakCompareAndSet double"); + double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 1.0d, "success weakCompareAndSet double"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 2.0d, 3.0d); + assertEquals(success, false, "failing weakCompareAndSet double"); double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 1.0d, "weakCompareAndSet double"); + assertEquals(x, 1.0d, "failing weakCompareAndSet double value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java index b826e18d483..4fdc63dff0c 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, 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 @@ -212,9 +212,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessFloat recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetPlain float"); + assertEquals(success, true, "success weakCompareAndSetPlain float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 2.0f, "weakCompareAndSetPlain float value"); + assertEquals(x, 2.0f, "success weakCompareAndSetPlain float value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetPlain float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 2.0f, "failing weakCompareAndSetPlain float value"); } { @@ -222,9 +229,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessFloat recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSetAcquire float"); + assertEquals(success, true, "success weakCompareAndSetAcquire float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 1.0f, "success weakCompareAndSetAcquire float"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetAcquire float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 1.0f, "weakCompareAndSetAcquire float"); + assertEquals(x, 1.0f, "failing weakCompareAndSetAcquire float value"); } { @@ -232,9 +246,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessFloat recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetRelease float"); + assertEquals(success, true, "success weakCompareAndSetRelease float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 2.0f, "success weakCompareAndSetRelease float"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetRelease float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 2.0f, "weakCompareAndSetRelease float"); + assertEquals(x, 2.0f, "failing weakCompareAndSetRelease float value"); } { @@ -242,9 +263,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessFloat recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSet float"); + assertEquals(success, true, "success weakCompareAndSet float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 1.0f, "weakCompareAndSet float"); + assertEquals(x, 1.0f, "success weakCompareAndSet float"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSet float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 1.0f, "failing weakCompareAndSet float value"); } // Compare set and get @@ -390,9 +418,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetPlain float"); + assertEquals(success, true, "success weakCompareAndSetPlain float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 2.0f, "success weakCompareAndSetPlain float value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetPlain float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 2.0f, "weakCompareAndSetPlain float value"); + assertEquals(x, 2.0f, "failing weakCompareAndSetPlain float value"); } { @@ -400,9 +435,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSetAcquire float"); + assertEquals(success, true, "success weakCompareAndSetAcquire float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 1.0f, "success weakCompareAndSetAcquire float"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetAcquire float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 1.0f, "weakCompareAndSetAcquire float"); + assertEquals(x, 1.0f, "failing weakCompareAndSetAcquire float value"); } { @@ -410,9 +452,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetRelease float"); + assertEquals(success, true, "success weakCompareAndSetRelease float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 2.0f, "weakCompareAndSetRelease float"); + assertEquals(x, 2.0f, "success weakCompareAndSetRelease float"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetRelease float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 2.0f, "failing weakCompareAndSetRelease float value"); } { @@ -420,9 +469,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSet float"); + assertEquals(success, true, "success weakCompareAndSet float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 1.0f, "success weakCompareAndSet float"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSet float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 1.0f, "weakCompareAndSet float"); + assertEquals(x, 1.0f, "failing weakCompareAndSetRe float value"); } // Compare set and get @@ -593,9 +649,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetPlain float"); + assertEquals(success, true, "success weakCompareAndSetPlain float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 2.0f, "success weakCompareAndSetPlain float value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetPlain float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 2.0f, "weakCompareAndSetPlain float value"); + assertEquals(x, 2.0f, "failing weakCompareAndSetPlain float value"); } { @@ -603,9 +666,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSetAcquire float"); + assertEquals(success, true, "success weakCompareAndSetAcquire float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 1.0f, "weakCompareAndSetAcquire float"); + assertEquals(x, 1.0f, "success weakCompareAndSetAcquire float"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetAcquire float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 1.0f, "failing weakCompareAndSetAcquire float value"); } { @@ -613,9 +683,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1.0f, 2.0f); } - assertEquals(success, true, "weakCompareAndSetRelease float"); + assertEquals(success, true, "success weakCompareAndSetRelease float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 2.0f, "success weakCompareAndSetRelease float"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 1.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSetAcquire float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 2.0f, "weakCompareAndSetRelease float"); + assertEquals(x, 2.0f, "failing weakCompareAndSetAcquire float value"); } { @@ -623,9 +700,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 2.0f, 1.0f); } - assertEquals(success, true, "weakCompareAndSet float"); + assertEquals(success, true, "success weakCompareAndSet float"); + float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 1.0f, "success weakCompareAndSet float"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 2.0f, 3.0f); + assertEquals(success, false, "failing weakCompareAndSet float"); float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 1.0f, "weakCompareAndSet float"); + assertEquals(x, 1.0f, "failing weakCompareAndSet float value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java index da0c63fa155..aebeece1254 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, 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 @@ -212,9 +212,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessInt recv, Handles h for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetPlain int"); + assertEquals(success, true, "success weakCompareAndSetPlain int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value"); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetPlain int value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetPlain int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetPlain int value"); } { @@ -222,9 +229,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessInt recv, Handles h for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSetAcquire int"); + assertEquals(success, true, "success weakCompareAndSetAcquire int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 0x01234567, "success weakCompareAndSetAcquire int"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetAcquire int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int"); + assertEquals(x, 0x01234567, "failing weakCompareAndSetAcquire int value"); } { @@ -232,9 +246,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessInt recv, Handles h for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetRelease int"); + assertEquals(success, true, "success weakCompareAndSetRelease int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetRelease int"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetRelease int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int"); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetRelease int value"); } { @@ -242,9 +263,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessInt recv, Handles h for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSet int"); + assertEquals(success, true, "success weakCompareAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 0x01234567, "weakCompareAndSet int"); + assertEquals(x, 0x01234567, "success weakCompareAndSet int"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSet int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 0x01234567, "failing weakCompareAndSet int value"); } // Compare set and get @@ -468,9 +496,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetPlain int"); + assertEquals(success, true, "success weakCompareAndSetPlain int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetPlain int value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetPlain int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value"); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetPlain int value"); } { @@ -478,9 +513,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSetAcquire int"); + assertEquals(success, true, "success weakCompareAndSetAcquire int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 0x01234567, "success weakCompareAndSetAcquire int"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetAcquire int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int"); + assertEquals(x, 0x01234567, "failing weakCompareAndSetAcquire int value"); } { @@ -488,9 +530,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetRelease int"); + assertEquals(success, true, "success weakCompareAndSetRelease int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int"); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetRelease int"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetRelease int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetRelease int value"); } { @@ -498,9 +547,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSet int"); + assertEquals(success, true, "success weakCompareAndSet int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 0x01234567, "success weakCompareAndSet int"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 0x01234567, "weakCompareAndSet int"); + assertEquals(x, 0x01234567, "failing weakCompareAndSetRe int value"); } // Compare set and get @@ -749,9 +805,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetPlain int"); + assertEquals(success, true, "success weakCompareAndSetPlain int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetPlain int value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetPlain int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value"); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetPlain int value"); } { @@ -759,9 +822,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSetAcquire int"); + assertEquals(success, true, "success weakCompareAndSetAcquire int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int"); + assertEquals(x, 0x01234567, "success weakCompareAndSetAcquire int"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetAcquire int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 0x01234567, "failing weakCompareAndSetAcquire int value"); } { @@ -769,9 +839,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 0x01234567, 0x89ABCDEF); } - assertEquals(success, true, "weakCompareAndSetRelease int"); + assertEquals(success, true, "success weakCompareAndSetRelease int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 0x89ABCDEF, "success weakCompareAndSetRelease int"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 0x01234567, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSetAcquire int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int"); + assertEquals(x, 0x89ABCDEF, "failing weakCompareAndSetAcquire int value"); } { @@ -779,9 +856,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 0x89ABCDEF, 0x01234567); } - assertEquals(success, true, "weakCompareAndSet int"); + assertEquals(success, true, "success weakCompareAndSet int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 0x01234567, "success weakCompareAndSet int"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 0x89ABCDEF, 0xCAFEBABE); + assertEquals(success, false, "failing weakCompareAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 0x01234567, "weakCompareAndSet int"); + assertEquals(x, 0x01234567, "failing weakCompareAndSet int value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java index 6e16e7c82da..c30b1395ee3 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, 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 @@ -212,9 +212,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessLong recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetPlain long"); + assertEquals(success, true, "success weakCompareAndSetPlain long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetPlain long value"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetPlain long value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetPlain long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetPlain long value"); } { @@ -222,9 +229,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessLong recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSetAcquire long"); + assertEquals(success, true, "success weakCompareAndSetAcquire long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSetAcquire long"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetAcquire long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSetAcquire long"); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSetAcquire long value"); } { @@ -232,9 +246,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessLong recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetRelease long"); + assertEquals(success, true, "success weakCompareAndSetRelease long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetRelease long"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetRelease long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetRelease long"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetRelease long value"); } { @@ -242,9 +263,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessLong recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSet long"); + assertEquals(success, true, "success weakCompareAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSet long"); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSet long"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSet long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSet long value"); } // Compare set and get @@ -468,9 +496,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetPlain long"); + assertEquals(success, true, "success weakCompareAndSetPlain long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetPlain long value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetPlain long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetPlain long value"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetPlain long value"); } { @@ -478,9 +513,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSetAcquire long"); + assertEquals(success, true, "success weakCompareAndSetAcquire long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSetAcquire long"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetAcquire long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSetAcquire long"); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSetAcquire long value"); } { @@ -488,9 +530,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetRelease long"); + assertEquals(success, true, "success weakCompareAndSetRelease long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetRelease long"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetRelease long"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetRelease long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetRelease long value"); } { @@ -498,9 +547,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSet long"); + assertEquals(success, true, "success weakCompareAndSet long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSet long"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSet long"); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSetRe long value"); } // Compare set and get @@ -749,9 +805,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetPlain long"); + assertEquals(success, true, "success weakCompareAndSetPlain long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetPlain long value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetPlain long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetPlain long value"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetPlain long value"); } { @@ -759,9 +822,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSetAcquire long"); + assertEquals(success, true, "success weakCompareAndSetAcquire long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSetAcquire long"); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSetAcquire long"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetAcquire long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSetAcquire long value"); } { @@ -769,9 +839,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL); } - assertEquals(success, true, "weakCompareAndSetRelease long"); + assertEquals(success, true, "success weakCompareAndSetRelease long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 0xCAFEBABECAFEBABEL, "success weakCompareAndSetRelease long"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSetAcquire long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetRelease long"); + assertEquals(x, 0xCAFEBABECAFEBABEL, "failing weakCompareAndSetAcquire long value"); } { @@ -779,9 +856,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL); } - assertEquals(success, true, "weakCompareAndSet long"); + assertEquals(success, true, "success weakCompareAndSet long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 0x0123456789ABCDEFL, "success weakCompareAndSet long"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL); + assertEquals(success, false, "failing weakCompareAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSet long"); + assertEquals(x, 0x0123456789ABCDEFL, "failing weakCompareAndSet long value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java index 5b6b8ad39c7..49e9f744b9b 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, 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 @@ -212,9 +212,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessShort recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, (short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetPlain short"); + assertEquals(success, true, "success weakCompareAndSetPlain short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, (short)0x4567, "weakCompareAndSetPlain short value"); + assertEquals(x, (short)0x4567, "success weakCompareAndSetPlain short value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, (short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetPlain short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetPlain short value"); } { @@ -222,9 +229,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessShort recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, (short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSetAcquire short"); + assertEquals(success, true, "success weakCompareAndSetAcquire short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, (short)0x0123, "success weakCompareAndSetAcquire short"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, (short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetAcquire short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, (short)0x0123, "weakCompareAndSetAcquire short"); + assertEquals(x, (short)0x0123, "failing weakCompareAndSetAcquire short value"); } { @@ -232,9 +246,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessShort recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, (short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetRelease short"); + assertEquals(success, true, "success weakCompareAndSetRelease short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, (short)0x4567, "success weakCompareAndSetRelease short"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, (short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetRelease short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, (short)0x4567, "weakCompareAndSetRelease short"); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetRelease short value"); } { @@ -242,9 +263,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessShort recv, Handles for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, (short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSet short"); + assertEquals(success, true, "success weakCompareAndSet short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, (short)0x0123, "weakCompareAndSet short"); + assertEquals(x, (short)0x0123, "success weakCompareAndSet short"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, (short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSet short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, (short)0x0123, "failing weakCompareAndSet short value"); } // Compare set and get @@ -468,9 +496,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact((short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetPlain short"); + assertEquals(success, true, "success weakCompareAndSetPlain short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, (short)0x4567, "success weakCompareAndSetPlain short value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact((short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetPlain short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, (short)0x4567, "weakCompareAndSetPlain short value"); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetPlain short value"); } { @@ -478,9 +513,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact((short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSetAcquire short"); + assertEquals(success, true, "success weakCompareAndSetAcquire short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, (short)0x0123, "success weakCompareAndSetAcquire short"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact((short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetAcquire short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, (short)0x0123, "weakCompareAndSetAcquire short"); + assertEquals(x, (short)0x0123, "failing weakCompareAndSetAcquire short value"); } { @@ -488,9 +530,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact((short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetRelease short"); + assertEquals(success, true, "success weakCompareAndSetRelease short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, (short)0x4567, "weakCompareAndSetRelease short"); + assertEquals(x, (short)0x4567, "success weakCompareAndSetRelease short"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact((short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetRelease short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetRelease short value"); } { @@ -498,9 +547,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact((short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSet short"); + assertEquals(success, true, "success weakCompareAndSet short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, (short)0x0123, "success weakCompareAndSet short"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact((short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSet short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, (short)0x0123, "weakCompareAndSet short"); + assertEquals(x, (short)0x0123, "failing weakCompareAndSetRe short value"); } // Compare set and get @@ -749,9 +805,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, (short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetPlain short"); + assertEquals(success, true, "success weakCompareAndSetPlain short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, (short)0x4567, "success weakCompareAndSetPlain short value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, (short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetPlain short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, (short)0x4567, "weakCompareAndSetPlain short value"); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetPlain short value"); } { @@ -759,9 +822,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, (short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSetAcquire short"); + assertEquals(success, true, "success weakCompareAndSetAcquire short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, (short)0x0123, "weakCompareAndSetAcquire short"); + assertEquals(x, (short)0x0123, "success weakCompareAndSetAcquire short"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, (short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetAcquire short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, (short)0x0123, "failing weakCompareAndSetAcquire short value"); } { @@ -769,9 +839,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, (short)0x0123, (short)0x4567); } - assertEquals(success, true, "weakCompareAndSetRelease short"); + assertEquals(success, true, "success weakCompareAndSetRelease short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, (short)0x4567, "success weakCompareAndSetRelease short"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, (short)0x0123, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSetAcquire short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, (short)0x4567, "weakCompareAndSetRelease short"); + assertEquals(x, (short)0x4567, "failing weakCompareAndSetAcquire short value"); } { @@ -779,9 +856,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, (short)0x4567, (short)0x0123); } - assertEquals(success, true, "weakCompareAndSet short"); + assertEquals(success, true, "success weakCompareAndSet short"); + short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, (short)0x0123, "success weakCompareAndSet short"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, (short)0x4567, (short)0x89AB); + assertEquals(success, false, "failing weakCompareAndSet short"); short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, (short)0x0123, "weakCompareAndSet short"); + assertEquals(x, (short)0x0123, "failing weakCompareAndSet short value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java index 0eb978588b5..cd70d2d7928 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, 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 @@ -212,9 +212,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessString recv, Handle for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, "foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetPlain String"); + assertEquals(success, true, "success weakCompareAndSetPlain String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, "bar", "weakCompareAndSetPlain String value"); + assertEquals(x, "bar", "success weakCompareAndSetPlain String value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, "foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetPlain String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, "bar", "failing weakCompareAndSetPlain String value"); } { @@ -222,9 +229,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessString recv, Handle for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, "bar", "foo"); } - assertEquals(success, true, "weakCompareAndSetAcquire String"); + assertEquals(success, true, "success weakCompareAndSetAcquire String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, "foo", "success weakCompareAndSetAcquire String"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, "bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSetAcquire String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, "foo", "weakCompareAndSetAcquire String"); + assertEquals(x, "foo", "failing weakCompareAndSetAcquire String value"); } { @@ -232,9 +246,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessString recv, Handle for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, "foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetRelease String"); + assertEquals(success, true, "success weakCompareAndSetRelease String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, "bar", "success weakCompareAndSetRelease String"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, "foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetRelease String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, "bar", "weakCompareAndSetRelease String"); + assertEquals(x, "bar", "failing weakCompareAndSetRelease String value"); } { @@ -242,9 +263,16 @@ static void testInstanceField(VarHandleTestMethodHandleAccessString recv, Handle for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, "bar", "foo"); } - assertEquals(success, true, "weakCompareAndSet String"); + assertEquals(success, true, "success weakCompareAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, "foo", "weakCompareAndSet String"); + assertEquals(x, "foo", "success weakCompareAndSet String"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, "bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSet String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, "foo", "failing weakCompareAndSet String value"); } // Compare set and get @@ -368,9 +396,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact("foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetPlain String"); + assertEquals(success, true, "success weakCompareAndSetPlain String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, "bar", "success weakCompareAndSetPlain String value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact("foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetPlain String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, "bar", "weakCompareAndSetPlain String value"); + assertEquals(x, "bar", "failing weakCompareAndSetPlain String value"); } { @@ -378,9 +413,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact("bar", "foo"); } - assertEquals(success, true, "weakCompareAndSetAcquire String"); + assertEquals(success, true, "success weakCompareAndSetAcquire String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, "foo", "success weakCompareAndSetAcquire String"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact("bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSetAcquire String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, "foo", "weakCompareAndSetAcquire String"); + assertEquals(x, "foo", "failing weakCompareAndSetAcquire String value"); } { @@ -388,9 +430,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact("foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetRelease String"); + assertEquals(success, true, "success weakCompareAndSetRelease String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, "bar", "weakCompareAndSetRelease String"); + assertEquals(x, "bar", "success weakCompareAndSetRelease String"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact("foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetRelease String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, "bar", "failing weakCompareAndSetRelease String value"); } { @@ -398,9 +447,16 @@ static void testStaticField(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact("bar", "foo"); } - assertEquals(success, true, "weakCompareAndSet String"); + assertEquals(success, true, "success weakCompareAndSet String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, "foo", "success weakCompareAndSet String"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact("bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, "foo", "weakCompareAndSet String"); + assertEquals(x, "foo", "failing weakCompareAndSetRe String value"); } // Compare set and get @@ -549,9 +605,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, "foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetPlain String"); + assertEquals(success, true, "success weakCompareAndSetPlain String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, "bar", "success weakCompareAndSetPlain String value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, "foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetPlain String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, "bar", "weakCompareAndSetPlain String value"); + assertEquals(x, "bar", "failing weakCompareAndSetPlain String value"); } { @@ -559,9 +622,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "bar", "foo"); } - assertEquals(success, true, "weakCompareAndSetAcquire String"); + assertEquals(success, true, "success weakCompareAndSetAcquire String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, "foo", "weakCompareAndSetAcquire String"); + assertEquals(x, "foo", "success weakCompareAndSetAcquire String"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSetAcquire String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, "foo", "failing weakCompareAndSetAcquire String value"); } { @@ -569,9 +639,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, "foo", "bar"); } - assertEquals(success, true, "weakCompareAndSetRelease String"); + assertEquals(success, true, "success weakCompareAndSetRelease String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, "bar", "success weakCompareAndSetRelease String"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "foo", "baz"); + assertEquals(success, false, "failing weakCompareAndSetAcquire String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, "bar", "weakCompareAndSetRelease String"); + assertEquals(x, "bar", "failing weakCompareAndSetAcquire String value"); } { @@ -579,9 +656,16 @@ static void testArray(Handles hs) throws Throwable { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, "bar", "foo"); } - assertEquals(success, true, "weakCompareAndSet String"); + assertEquals(success, true, "success weakCompareAndSet String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, "foo", "success weakCompareAndSet String"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, "bar", "baz"); + assertEquals(success, false, "failing weakCompareAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, "foo", "weakCompareAndSet String"); + assertEquals(x, "foo", "failing weakCompareAndSet String value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template index 5014fc1b187..9f409dfaf0b 100644 --- a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template +++ b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template @@ -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 @@ -659,9 +659,16 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(recv, $value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetPlain $type$"); + assertEquals(success, true, "success weakCompareAndSetPlain $type$"); $type$ x = ($type$) vh.get(recv); - assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value"); + assertEquals(x, $value2$, "success weakCompareAndSetPlain $type$ value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(recv, $value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetPlain $type$"); + $type$ x = ($type$) vh.get(recv); + assertEquals(x, $value2$, "failing weakCompareAndSetPlain $type$ value"); } { @@ -669,9 +676,16 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(recv, $value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSetAcquire $type$"); + assertEquals(success, true, "success weakCompareAndSetAcquire $type$"); + $type$ x = ($type$) vh.get(recv); + assertEquals(x, $value1$, "success weakCompareAndSetAcquire $type$"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(recv, $value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(recv); - assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); + assertEquals(x, $value1$, "failing weakCompareAndSetAcquire $type$ value"); } { @@ -679,9 +693,16 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(recv, $value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetRelease $type$"); + assertEquals(success, true, "success weakCompareAndSetRelease $type$"); + $type$ x = ($type$) vh.get(recv); + assertEquals(x, $value2$, "success weakCompareAndSetRelease $type$"); + } + + { + boolean success = vh.weakCompareAndSetRelease(recv, $value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(recv); - assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); + assertEquals(x, $value2$, "failing weakCompareAndSetRelease $type$ value"); } { @@ -689,9 +710,16 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(recv, $value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSet $type$"); + assertEquals(success, true, "success weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(recv); - assertEquals(x, $value1$, "weakCompareAndSet $type$ value"); + assertEquals(x, $value1$, "success weakCompareAndSet $type$ value"); + } + + { + boolean success = vh.weakCompareAndSet(recv, $value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSet $type$"); + $type$ x = ($type$) vh.get(recv); + assertEquals(x, $value1$, "failing weakCompareAndSet $type$ value"); } // Compare set and get @@ -1036,9 +1064,16 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain($value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetPlain $type$"); + assertEquals(success, true, "success weakCompareAndSetPlain $type$"); + $type$ x = ($type$) vh.get(); + assertEquals(x, $value2$, "success weakCompareAndSetPlain $type$ value"); + } + + { + boolean success = vh.weakCompareAndSetPlain($value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetPlain $type$"); $type$ x = ($type$) vh.get(); - assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value"); + assertEquals(x, $value2$, "failing weakCompareAndSetPlain $type$ value"); } { @@ -1046,9 +1081,16 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire($value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSetAcquire $type$"); + assertEquals(success, true, "success weakCompareAndSetAcquire $type$"); + $type$ x = ($type$) vh.get(); + assertEquals(x, $value1$, "success weakCompareAndSetAcquire $type$"); + } + + { + boolean success = vh.weakCompareAndSetAcquire($value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(); - assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); + assertEquals(x, $value1$, "failing weakCompareAndSetAcquire $type$ value"); } { @@ -1056,9 +1098,16 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease($value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetRelease $type$"); + assertEquals(success, true, "success weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(); - assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); + assertEquals(x, $value2$, "success weakCompareAndSetRelease $type$"); + } + + { + boolean success = vh.weakCompareAndSetRelease($value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetRelease $type$"); + $type$ x = ($type$) vh.get(); + assertEquals(x, $value2$, "failing weakCompareAndSetRelease $type$ value"); } { @@ -1066,9 +1115,16 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet($value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSet $type$"); + assertEquals(success, true, "success weakCompareAndSet $type$"); + $type$ x = ($type$) vh.get(); + assertEquals(x, $value1$, "success weakCompareAndSet $type$"); + } + + { + boolean success = vh.weakCompareAndSet($value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(); - assertEquals(x, $value1$, "weakCompareAndSet $type$"); + assertEquals(x, $value1$, "failing weakCompareAndSet $type$ value"); } // Compare set and get @@ -1416,9 +1472,16 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, $value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetPlain $type$"); + assertEquals(success, true, "success weakCompareAndSetPlain $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, $value2$, "success weakCompareAndSetPlain $type$ value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, $value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetPlain $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value"); + assertEquals(x, $value2$, "failing weakCompareAndSetPlain $type$ value"); } { @@ -1426,9 +1489,16 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, $value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSetAcquire $type$"); + assertEquals(success, true, "success weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); + assertEquals(x, $value1$, "success weakCompareAndSetAcquire $type$"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, $value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetAcquire $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, $value1$, "failing weakCompareAndSetAcquire $type$ value"); } { @@ -1436,9 +1506,16 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, $value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetRelease $type$"); + assertEquals(success, true, "success weakCompareAndSetRelease $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, $value2$, "success weakCompareAndSetRelease $type$"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, $value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); + assertEquals(x, $value2$, "failing weakCompareAndSetRelease $type$ value"); } { @@ -1446,9 +1523,16 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, $value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSet $type$"); + assertEquals(success, true, "success weakCompareAndSet $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, $value1$, "success weakCompareAndSet $type$"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, $value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, $value1$, "weakCompareAndSet $type$"); + assertEquals(x, $value1$, "failing weakCompareAndSet $type$ value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template index cdd9815e2e2..bea9fec4e2b 100644 --- a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template +++ b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, 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 @@ -1592,9 +1592,16 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetPlain $type$"); + assertEquals(success, true, "success weakCompareAndSetPlain $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetPlain $type$ value"); + assertEquals(x, VALUE_2, "success weakCompareAndSetPlain $type$ value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetPlain $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain $type$ value"); } { @@ -1602,9 +1609,16 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSetAcquire $type$"); + assertEquals(success, true, "success weakCompareAndSetAcquire $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire $type$"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$"); + assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire $type$ value"); } { @@ -1612,9 +1626,16 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetRelease $type$"); + assertEquals(success, true, "success weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$"); + assertEquals(x, VALUE_2, "success weakCompareAndSetRelease $type$"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetRelease $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease $type$ value"); } { @@ -1622,9 +1643,16 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSet $type$"); + assertEquals(success, true, "success weakCompareAndSet $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSet $type$"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSet $type$"); + assertEquals(x, VALUE_1, "failing weakCompareAndSet $type$ value"); } // Compare set and get @@ -1881,9 +1909,16 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetPlain $type$"); + assertEquals(success, true, "success weakCompareAndSetPlain $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetPlain $type$ value"); + assertEquals(x, VALUE_2, "success weakCompareAndSetPlain $type$ value"); + } + + { + boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetPlain $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain $type$ value"); } { @@ -1891,9 +1926,16 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSetAcquire $type$"); + assertEquals(success, true, "success weakCompareAndSetAcquire $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire $type$"); + } + + { + boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$"); + assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire $type$ value"); } { @@ -1901,9 +1943,16 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); } - assertEquals(success, true, "weakCompareAndSetRelease $type$"); + assertEquals(success, true, "success weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$"); + assertEquals(x, VALUE_2, "success weakCompareAndSetRelease $type$"); + } + + { + boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSetRelease $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease $type$ value"); } { @@ -1911,9 +1960,16 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1); } - assertEquals(success, true, "weakCompareAndSet $type$"); + assertEquals(success, true, "success weakCompareAndSet $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, VALUE_1, "success weakCompareAndSet $type$"); + } + + { + boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3); + assertEquals(success, false, "failing weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "weakCompareAndSet $type$"); + assertEquals(x, VALUE_1, "failing weakCompareAndSet $type$ value"); } // Compare set and get diff --git a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template index c82d533878a..79875db904b 100644 --- a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template +++ b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, 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 @@ -213,9 +213,16 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, $value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetPlain $type$"); + assertEquals(success, true, "success weakCompareAndSetPlain $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value"); + assertEquals(x, $value2$, "success weakCompareAndSetPlain $type$ value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, $value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetPlain $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, $value2$, "failing weakCompareAndSetPlain $type$ value"); } { @@ -223,9 +230,16 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, $value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSetAcquire $type$"); + assertEquals(success, true, "success weakCompareAndSetAcquire $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, $value1$, "success weakCompareAndSetAcquire $type$"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, $value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetAcquire $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); + assertEquals(x, $value1$, "failing weakCompareAndSetAcquire $type$ value"); } { @@ -233,9 +247,16 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, $value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetRelease $type$"); + assertEquals(success, true, "success weakCompareAndSetRelease $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, $value2$, "success weakCompareAndSetRelease $type$"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, $value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetRelease $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); + assertEquals(x, $value2$, "failing weakCompareAndSetRelease $type$ value"); } { @@ -243,9 +264,16 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, $value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSet $type$"); + assertEquals(success, true, "success weakCompareAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, $value1$, "weakCompareAndSet $type$"); + assertEquals(x, $value1$, "success weakCompareAndSet $type$"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, $value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSet $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, $value1$, "failing weakCompareAndSet $type$ value"); } // Compare set and get @@ -508,9 +536,16 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact($value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetPlain $type$"); + assertEquals(success, true, "success weakCompareAndSetPlain $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, $value2$, "success weakCompareAndSetPlain $type$ value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact($value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetPlain $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value"); + assertEquals(x, $value2$, "failing weakCompareAndSetPlain $type$ value"); } { @@ -518,9 +553,16 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact($value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSetAcquire $type$"); + assertEquals(success, true, "success weakCompareAndSetAcquire $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, $value1$, "success weakCompareAndSetAcquire $type$"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact($value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetAcquire $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); + assertEquals(x, $value1$, "failing weakCompareAndSetAcquire $type$ value"); } { @@ -528,9 +570,16 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact($value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetRelease $type$"); + assertEquals(success, true, "success weakCompareAndSetRelease $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); + assertEquals(x, $value2$, "success weakCompareAndSetRelease $type$"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact($value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetRelease $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, $value2$, "failing weakCompareAndSetRelease $type$ value"); } { @@ -538,9 +587,16 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact($value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSet $type$"); + assertEquals(success, true, "success weakCompareAndSet $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, $value1$, "success weakCompareAndSet $type$"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact($value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, $value1$, "weakCompareAndSet $type$"); + assertEquals(x, $value1$, "failing weakCompareAndSetRe $type$ value"); } // Compare set and get @@ -828,9 +884,16 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, $value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetPlain $type$"); + assertEquals(success, true, "success weakCompareAndSetPlain $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, $value2$, "success weakCompareAndSetPlain $type$ value"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, $value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetPlain $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value"); + assertEquals(x, $value2$, "failing weakCompareAndSetPlain $type$ value"); } { @@ -838,9 +901,16 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, $value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSetAcquire $type$"); + assertEquals(success, true, "success weakCompareAndSetAcquire $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); + assertEquals(x, $value1$, "success weakCompareAndSetAcquire $type$"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, $value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetAcquire $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, $value1$, "failing weakCompareAndSetAcquire $type$ value"); } { @@ -848,9 +918,16 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, $value1$, $value2$); } - assertEquals(success, true, "weakCompareAndSetRelease $type$"); + assertEquals(success, true, "success weakCompareAndSetRelease $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, $value2$, "success weakCompareAndSetRelease $type$"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, $value1$, $value3$); + assertEquals(success, false, "failing weakCompareAndSetAcquire $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); + assertEquals(x, $value2$, "failing weakCompareAndSetAcquire $type$ value"); } { @@ -858,9 +935,16 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, $value2$, $value1$); } - assertEquals(success, true, "weakCompareAndSet $type$"); + assertEquals(success, true, "success weakCompareAndSet $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, $value1$, "success weakCompareAndSet $type$"); + } + + { + boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, $value2$, $value3$); + assertEquals(success, false, "failing weakCompareAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, $value1$, "weakCompareAndSet $type$"); + assertEquals(x, $value1$, "failing weakCompareAndSet $type$ value"); } // Compare set and get diff --git a/test/jdk/java/math/BigInteger/DivisionOverflow.java b/test/jdk/java/math/BigInteger/largeMemory/DivisionOverflow.java similarity index 91% rename from test/jdk/java/math/BigInteger/DivisionOverflow.java rename to test/jdk/java/math/BigInteger/largeMemory/DivisionOverflow.java index 7f35d07adca..f8a5c89e74b 100644 --- a/test/jdk/java/math/BigInteger/DivisionOverflow.java +++ b/test/jdk/java/math/BigInteger/largeMemory/DivisionOverflow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -25,7 +25,8 @@ * @test * @bug 8022780 * @summary Test division of large values - * @run main/othervm -Xshare:off DivisionOverflow + * @requires (sun.arch.data.model == "64" & os.maxMemory > 8g) + * @run main/othervm -Xshare:off -Xmx8g DivisionOverflow * @author Dmitry Nadezhin */ import java.math.BigInteger; diff --git a/test/jdk/java/math/BigInteger/StringConstructorOverflow.java b/test/jdk/java/math/BigInteger/largeMemory/StringConstructorOverflow.java similarity index 97% rename from test/jdk/java/math/BigInteger/StringConstructorOverflow.java rename to test/jdk/java/math/BigInteger/largeMemory/StringConstructorOverflow.java index 0ecab7fc4ab..4004a0bdf30 100644 --- a/test/jdk/java/math/BigInteger/StringConstructorOverflow.java +++ b/test/jdk/java/math/BigInteger/largeMemory/StringConstructorOverflow.java @@ -25,7 +25,7 @@ * @test * @bug 8021204 * @summary Test constructor BigInteger(String val, int radix) on very long string - * @ignore This test has huge memory requirements + * @requires (sun.arch.data.model == "64" & os.maxMemory > 8g) * @run main/othervm -Xshare:off -Xmx8g StringConstructorOverflow * @author Dmitry Nadezhin */ diff --git a/test/jdk/java/math/BigInteger/SymmetricRangeTests.java b/test/jdk/java/math/BigInteger/largeMemory/SymmetricRangeTests.java similarity index 99% rename from test/jdk/java/math/BigInteger/SymmetricRangeTests.java rename to test/jdk/java/math/BigInteger/largeMemory/SymmetricRangeTests.java index 31334cc49b7..e71afe6a028 100644 --- a/test/jdk/java/math/BigInteger/SymmetricRangeTests.java +++ b/test/jdk/java/math/BigInteger/largeMemory/SymmetricRangeTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -23,11 +23,11 @@ /* * @test - * @library /test/lib - * @ignore This test has huge memory requirements - * @run main/timeout=180/othervm -Xmx8g SymmetricRangeTests * @bug 6910473 8021204 8021203 9005933 8074460 8078672 * @summary Test range of BigInteger values (use -Dseed=X to set PRNG seed) + * @library /test/lib + * @requires (sun.arch.data.model == "64" & os.maxMemory >= 10g) + * @run main/timeout=180/othervm -Xmx8g -XX:+CompactStrings SymmetricRangeTests * @author Dmitry Nadezhin * @key randomness */ diff --git a/test/jdk/java/net/BindException/Test.java b/test/jdk/java/net/BindException/Test.java index ab13b083ffe..1195ae53fea 100644 --- a/test/jdk/java/net/BindException/Test.java +++ b/test/jdk/java/net/BindException/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -45,18 +45,24 @@ static Object[][] getTestCombinations() { static int count; static int failures; + static boolean retried; static void doTest(Object test[], InetAddress ia1, InetAddress ia2, boolean silent) throws Exception { - String s1_type = (String)test[0]; - String s2_type = (String)test[1]; - int port = 0; - /* * Increment test count */ count++; + doTest(test, count, ia1, ia2, silent, !retried); + } + + static void doTest(Object test[], int count, InetAddress ia1, InetAddress ia2, + boolean silent, boolean retry) throws Exception { + String s1_type = (String)test[0]; + String s2_type = (String)test[1]; + int port = 0; + /* * Do the test */ @@ -68,6 +74,8 @@ static void doTest(Object test[], InetAddress ia1, InetAddress ia2, Socket sock1 = null; ServerSocket ss = null; DatagramSocket dsock1 = null; + boolean firstBound = false; + try { /* bind the first socket */ @@ -89,6 +97,13 @@ static void doTest(Object test[], InetAddress ia1, InetAddress ia2, /* bind the second socket */ + // The fact that the port was available for ia1 does not + // guarantee that it will also be available for ia2 as something + // else might already be bound to that port. + // For the sake of test stability we will retry once in + // case of unexpected bind exception. + + firstBound = true; if (s2_type.equals("Socket")) { try (Socket sock2 = new Socket()) { sock2.bind( new InetSocketAddress(ia2, port)); @@ -141,6 +156,18 @@ static void doTest(Object test[], InetAddress ia1, InetAddress ia2, return; } + if (failed && retry && firstBound) { + // retry once at the first failure only + retried = true; + if (!silent) { + System.out.println(""); + System.out.println("**************************"); + System.out.println("Test " + count + ": Retrying..."); + } + doTest(test, count, ia1, ia2, silent, false); + return; + } + if (failed || !silent) { System.out.println(""); System.out.println("**************************"); diff --git a/test/jdk/java/net/DatagramSocket/UnreferencedDatagramSockets.java b/test/jdk/java/net/DatagramSocket/UnreferencedDatagramSockets.java index ac19aede382..04d64afa01b 100644 --- a/test/jdk/java/net/DatagramSocket/UnreferencedDatagramSockets.java +++ b/test/jdk/java/net/DatagramSocket/UnreferencedDatagramSockets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -48,6 +48,7 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; +import java.util.concurrent.CountDownLatch; import com.sun.management.UnixOperatingSystemMXBean; @@ -67,9 +68,10 @@ public class UnreferencedDatagramSockets { static class Server implements Runnable { DatagramSocket ss; + CountDownLatch latch = new CountDownLatch(1); Server() throws IOException { - ss = new DatagramSocket(0); + ss = new DatagramSocket(0, getHost()); System.out.printf(" DatagramServer addr: %s: %d%n", this.getHost(), this.getPort()); pendingSockets.add(new NamedWeak(ss, pendingQueue, "serverDatagramSocket")); @@ -77,7 +79,7 @@ static class Server implements Runnable { } InetAddress getHost() throws UnknownHostException { - InetAddress localhost = InetAddress.getByName("localhost"); //.getLocalHost(); + InetAddress localhost = lookupLocalHost(); return localhost; } @@ -93,7 +95,7 @@ public void run() { ss.receive(p); buffer[0] += 1; ss.send(p); // send back +1 - + latch.await(); // wait for the client to receive the packet // do NOT close but 'forget' the datagram socket reference ss = null; } catch (Exception ioe) { @@ -102,10 +104,14 @@ public void run() { } } + static InetAddress lookupLocalHost() throws UnknownHostException { + return InetAddress.getByName("localhost"); //.getLocalHost(); + } + public static void main(String args[]) throws Exception { // Create and close a DatagramSocket to warm up the FD count for side effects. - try (DatagramSocket s = new DatagramSocket(0)) { + try (DatagramSocket s = new DatagramSocket(0, lookupLocalHost())) { // no-op; close immediately s.getLocalPort(); // no-op } @@ -118,7 +124,7 @@ public static void main(String args[]) throws Exception { Thread thr = new Thread(svr); thr.start(); - DatagramSocket client = new DatagramSocket(0); + DatagramSocket client = new DatagramSocket(0, lookupLocalHost()); client.connect(svr.getHost(), svr.getPort()); pendingSockets.add(new NamedWeak(client, pendingQueue, "clientDatagramSocket")); extractRefs(client, "clientDatagramSocket"); @@ -130,6 +136,8 @@ public static void main(String args[]) throws Exception { p = new DatagramPacket(msg, msg.length); client.receive(p); + svr.latch.countDown(); // unblock the server + System.out.printf("echo received from: %s%n", p.getSocketAddress()); if (msg[0] != 2) { diff --git a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java index 04e90db5e11..505e0e159da 100644 --- a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java +++ b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java @@ -978,6 +978,8 @@ static class HttpsProxyTunnel extends HTTPTestServer implements Runnable { final ServerSocket ss; + private volatile boolean stop; + public HttpsProxyTunnel(HttpServer server, HTTPTestServer target, HttpHandler delegate) throws IOException { @@ -996,9 +998,10 @@ final void start() throws IOException { @Override public void stop() { - super.stop(); - try { - ss.close(); + try (var toClose = ss) { + stop = true; + System.out.println("Server " + ss + " stop requested"); + super.stop(); } catch (IOException ex) { if (DEBUG) ex.printStackTrace(System.out); } @@ -1048,6 +1051,9 @@ String readLine(InputStream r) throws IOException { if (c == '\n') break; b.appendCodePoint(c); } + if (b.length() == 0) { + return ""; + } if (b.codePointAt(b.length() -1) == '\r') { b.delete(b.length() -1, b.length()); } @@ -1057,80 +1063,121 @@ String readLine(InputStream r) throws IOException { @Override public void run() { Socket clientConnection = null; - try { - while (true) { - System.out.println("Tunnel: Waiting for client at: " + ss); - Socket previous = clientConnection; + while (!stop) { + System.out.println("Tunnel: Waiting for client at: " + ss); + final Socket previous = clientConnection; + try { + clientConnection = ss.accept(); + } catch (IOException io) { try { - clientConnection = ss.accept(); - } catch (IOException io) { - if (DEBUG) io.printStackTrace(System.out); - break; - } finally { - // close the previous connection - if (previous != null) previous.close(); + ss.close(); + } catch (IOException ex) { + if (DEBUG) { + ex.printStackTrace(System.out); + } } - System.out.println("Tunnel: Client accepted"); - Socket targetConnection = null; - InputStream ccis = clientConnection.getInputStream(); - OutputStream ccos = clientConnection.getOutputStream(); - Writer w = new OutputStreamWriter( - clientConnection.getOutputStream(), "UTF-8"); - PrintWriter pw = new PrintWriter(w); - System.out.println("Tunnel: Reading request line"); - String requestLine = readLine(ccis); - System.out.println("Tunnel: Request line: " + requestLine); - if (requestLine.startsWith("CONNECT ")) { - // We should probably check that the next word following - // CONNECT is the host:port of our HTTPS serverImpl. - // Some improvement for a followup! - - // Read all headers until we find the empty line that - // signals the end of all headers. - while(!requestLine.equals("")) { - System.out.println("Tunnel: Reading header: " - + (requestLine = readLine(ccis))); + // log the reason that caused the server to stop accepting connections + if (!stop) { + System.err.println("Server will stop accepting connections due to an exception:"); + io.printStackTrace(); + } + break; + } finally { + // close the previous connection + if (previous != null) { + try { + previous.close(); + } catch (IOException e) { + // ignore + if (DEBUG) { + System.out.println("Ignoring exception that happened while closing " + + "an older connection:"); + e.printStackTrace(System.out); + } } - - targetConnection = new Socket( - serverImpl.getAddress().getAddress(), - serverImpl.getAddress().getPort()); - - // Then send the 200 OK response to the client - System.out.println("Tunnel: Sending " - + "HTTP/1.1 200 OK\r\n\r\n"); - pw.print("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); - pw.flush(); - } else { - // This should not happen. If it does let our serverImpl - // deal with it. - throw new IOException("Tunnel: Unexpected status line: " - + requestLine); } - - // Pipe the input stream of the client connection to the - // output stream of the target connection and conversely. - // Now the client and target will just talk to each other. - System.out.println("Tunnel: Starting tunnel pipes"); - Thread t1 = pipe(ccis, targetConnection.getOutputStream(), '+'); - Thread t2 = pipe(targetConnection.getInputStream(), ccos, '-'); - t1.start(); - t2.start(); - - // We have only 1 client... wait until it has finished before - // accepting a new connection request. - t1.join(); - t2.join(); } - } catch (Throwable ex) { + System.out.println("Tunnel: Client accepted"); try { - ss.close(); - } catch (IOException ex1) { - ex.addSuppressed(ex1); + // We have only 1 client... process the current client + // request and wait until it has finished before + // accepting a new connection request. + processRequestAndWaitToComplete(clientConnection); + } catch (IOException ioe) { + // close the client connection + try { + clientConnection.close(); + } catch (IOException io) { + // ignore + if (DEBUG) { + System.out.println("Ignoring exception that happened during client" + + " connection close:"); + io.printStackTrace(System.out); + } + } finally { + clientConnection = null; + } + } catch (Throwable t) { + // don't close the client connection for non-IOExceptions, instead + // just log it and move on to accept next connection + if (!stop) { + t.printStackTrace(); + } } - ex.printStackTrace(System.err); } } + private void processRequestAndWaitToComplete(final Socket clientConnection) + throws IOException, InterruptedException { + final Socket targetConnection; + InputStream ccis = clientConnection.getInputStream(); + OutputStream ccos = clientConnection.getOutputStream(); + Writer w = new OutputStreamWriter( + clientConnection.getOutputStream(), "UTF-8"); + PrintWriter pw = new PrintWriter(w); + System.out.println("Tunnel: Reading request line"); + String requestLine = readLine(ccis); + System.out.println("Tunnel: Request line: " + requestLine); + if (requestLine.startsWith("CONNECT ")) { + // We should probably check that the next word following + // CONNECT is the host:port of our HTTPS serverImpl. + // Some improvement for a followup! + + // Read all headers until we find the empty line that + // signals the end of all headers. + while(!requestLine.equals("")) { + System.out.println("Tunnel: Reading header: " + + (requestLine = readLine(ccis))); + } + + targetConnection = new Socket( + serverImpl.getAddress().getAddress(), + serverImpl.getAddress().getPort()); + + // Then send the 200 OK response to the client + System.out.println("Tunnel: Sending " + + "HTTP/1.1 200 OK\r\n\r\n"); + pw.print("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + pw.flush(); + } else { + // This should not happen. If it does then consider it a + // client error and throw an IOException + System.out.println("Tunnel: Throwing an IOException due to unexpected" + + " request line: " + requestLine); + throw new IOException("Client request error - Unexpected request line"); + } + + // Pipe the input stream of the client connection to the + // output stream of the target connection and conversely. + // Now the client and target will just talk to each other. + System.out.println("Tunnel: Starting tunnel pipes"); + Thread t1 = pipe(ccis, targetConnection.getOutputStream(), '+'); + Thread t2 = pipe(targetConnection.getInputStream(), ccos, '-'); + t1.start(); + t2.start(); + // wait for the request to complete + t1.join(); + t2.join(); + } } } diff --git a/test/jdk/java/net/InetAddress/ptr/Lookup.java b/test/jdk/java/net/InetAddress/ptr/Lookup.java index d3051173297..2b7e5b56acc 100644 --- a/test/jdk/java/net/InetAddress/ptr/Lookup.java +++ b/test/jdk/java/net/InetAddress/ptr/Lookup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -42,6 +42,8 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.List; +import java.util.stream.Stream; +import java.util.stream.Collectors; import jdk.test.lib.JDKToolFinder; import jdk.test.lib.process.OutputAnalyzer; @@ -55,40 +57,80 @@ public class Lookup { public static void main(String args[]) throws IOException { String addr = null; String ipv4Name = null; + String ipv4Reversed = null; + if (args.length == 0) { - // First check that host resolves to IPv4 address + // called from lookupWithIPv4Prefer + // obtain an IPv4 address from the hostname. try { InetAddress ia = InetAddress.getByName(HOST); addr = ia.getHostAddress(); + ia = InetAddress.getByName(addr); + System.out.print(addr + ":" + ia.getHostName()); + return; } catch (UnknownHostException e) { System.out.print(SKIP); return; } - } else { - String tmp = lookupWithIPv4Prefer(); - System.out.println("IPv4 lookup results: [" + tmp + "]"); - if (SKIP.equals(tmp)) { - System.out.println(HOST + " can't be resolved - test skipped."); + } else if (args.length == 2 && args[0].equals("reverse")) { + // called from reverseWithIPv4Prefer + // Check that IPv4 address can be resolved to host + // with -Djava.net.preferIPv4Stack=true + try { + InetAddress ia = InetAddress.getByName(args[1]); + addr = ia.getHostAddress(); + ipv4Reversed = ia.getHostName(); + System.out.print(addr + ":" + ipv4Reversed); + return; + } catch (UnknownHostException e) { + System.out.print(SKIP); return; } + } else if (args.length != 1 || !args[0].equals("root")) { + throw new IllegalArgumentException(Stream.of(args).collect(Collectors.joining(" "))); + } + + // spawn a subprocess to obtain the IPv4 address + String tmp = lookupWithIPv4Prefer(); + System.out.println("IPv4 lookup results: [" + tmp + "]"); + if (SKIP.equals(tmp)) { + System.out.println(HOST + " can't be resolved - test skipped."); + return; + } + + String[] strs = tmp.split(":"); + addr = strs[0]; + ipv4Name = strs[1]; - String[] strs = tmp.split(":"); - addr = strs[0]; - ipv4Name = strs[1]; + // check that the a reverse lookup of the IPv4 address + // will succeed with the IPv4 only stack + tmp = reverseWithIPv4Prefer(addr); + System.out.println("IPv4 reverse lookup results: [" + tmp + "]"); + if (SKIP.equals(tmp)) { + System.out.println(addr + " can't be resolved with preferIPv4 - test skipped."); + return; } - // reverse lookup + strs = tmp.split(":"); + ipv4Reversed = strs[1]; + + // Now check that a reverse lookup will succeed with the dual stack. InetAddress ia = InetAddress.getByName(addr); String name = ia.getHostName(); - if (args.length == 0) { - System.out.print(addr + ":" + name); - return; - } else { - System.out.println("(default) " + addr + "--> " + name); - if (!ipv4Name.equals(name)) { - throw new RuntimeException("Mismatch between default" - + " and java.net.preferIPv4Stack=true results"); + + System.out.println("(default) " + addr + "--> " + name + + " (reversed IPv4: " + ipv4Reversed + ")"); + if (!ipv4Name.equals(name)) { + // adding some diagnosting + System.err.println("name=" + name + " doesn't match expected=" + ipv4Name); + System.err.println("Listing all adresses:"); + for (InetAddress any : InetAddress.getAllByName(HOST)) { + System.err.println("\t[" + any + "] address=" + any.getHostAddress() + + ", host=" + any.getHostName()); } + // make the test fail... + throw new RuntimeException("Mismatch between default" + + " and java.net.preferIPv4Stack=true results"); } } @@ -100,5 +142,13 @@ static String lookupWithIPv4Prefer() throws IOException { System.out.println("Executing: " + cmd); return new OutputAnalyzer(new ProcessBuilder(cmd).start()).getOutput(); } -} + static String reverseWithIPv4Prefer(String addr) throws IOException { + String java = JDKToolFinder.getTestJDKTool("java"); + String testClz = Lookup.class.getName(); + List cmd = List.of(java, "-Djava.net.preferIPv4Stack=true", + "-cp", CLASS_PATH, testClz, "reverse", addr); + System.out.println("Executing: " + cmd); + return new OutputAnalyzer(new ProcessBuilder(cmd).start()).getOutput(); + } +} diff --git a/test/jdk/java/net/NetworkInterface/NetworkInterfaceRetrievalTests.java b/test/jdk/java/net/NetworkInterface/NetworkInterfaceRetrievalTests.java index 276cf42fe7c..60ba35165c9 100644 --- a/test/jdk/java/net/NetworkInterface/NetworkInterfaceRetrievalTests.java +++ b/test/jdk/java/net/NetworkInterface/NetworkInterfaceRetrievalTests.java @@ -23,12 +23,14 @@ /** * @test + * @library /test/lib * @bug 8179559 */ import java.net.InetAddress; import java.net.NetworkInterface; import java.util.Enumeration; +import jdk.test.lib.Platform; public class NetworkInterfaceRetrievalTests { public static void main(String[] args) throws Exception { @@ -39,6 +41,12 @@ public static void main(String[] args) throws Exception { .getNetworkInterfaces(); while (en.hasMoreElements()) { NetworkInterface ni = en.nextElement(); + + //JDK-8230132: Should not test on Windows with Teredo Tunneling Pseudo-Interface + String dName = ni.getDisplayName(); + if (Platform.isWindows() && dName != null && dName.contains("Teredo")) + continue; + Enumeration addrs = ni.getInetAddresses(); System.out.println("############ Checking network interface + " + ni + " #############"); diff --git a/test/jdk/java/net/PlainSocketImpl/SetOption.java b/test/jdk/java/net/PlainSocketImpl/SetOption.java index 086ef8eeace..a45374b9417 100644 --- a/test/jdk/java/net/PlainSocketImpl/SetOption.java +++ b/test/jdk/java/net/PlainSocketImpl/SetOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -35,8 +35,10 @@ public class SetOption { public static void main(String args[]) throws Exception { - ServerSocket ss = new ServerSocket(0); - Socket s1 = new Socket("localhost", ss.getLocalPort()); + InetAddress loopback = InetAddress.getLoopbackAddress(); + ServerSocket ss = new ServerSocket(0, 0, loopback); + + Socket s1 = new Socket(loopback, ss.getLocalPort()); Socket s2 = ss.accept(); s1.close(); diff --git a/test/jdk/java/net/SctpSanity.java b/test/jdk/java/net/SctpSanity.java new file mode 100644 index 00000000000..b3f8b90f60e --- /dev/null +++ b/test/jdk/java/net/SctpSanity.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 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 8232097 + * @summary Basic sanity for creation of SCTP channels + * @modules jdk.sctp + * @run main/othervm SctpSanity 1 + * @run main/othervm SctpSanity 2 + * @run main/othervm SctpSanity 3 + */ + +import java.io.IOException; +import com.sun.nio.sctp.SctpChannel; +import com.sun.nio.sctp.SctpMultiChannel; +import com.sun.nio.sctp.SctpServerChannel; +import static java.lang.System.out; + +/** + * Tests creation of SCTP channels. The channels should either be created + * or not. The latter throwing an UnsupportedOperationException. No other + * behavior is acceptable. Minimally, exercises the JDK's native library + * loading on operating systems that provide an implementation, even if + * the system-level support is not configured. + */ +public class SctpSanity { + + public static void main(String... args) throws IOException { + switch (Integer.valueOf(args[0])) { + case 1: testSctpChannel(); break; + case 2: testSctpServerChannel(); break; + case 3: testSctpMultiChannel(); break; + default: throw new AssertionError("should not reach here"); + } + } + + static void testSctpChannel() throws IOException { + try (SctpChannel channel = SctpChannel.open()) { + out.println("created SctpChannel:" + channel); + } catch (UnsupportedOperationException uoe) { + // ok - the platform does not support SCTP + out.println("ok, caught:" + uoe); + } + } + + static void testSctpServerChannel() throws IOException { + try (SctpServerChannel channel = SctpServerChannel.open()) { + out.println("created SctpServerChannel:" + channel); + } catch (UnsupportedOperationException uoe) { + // ok - the platform does not support SCTP + out.println("ok, caught:" + uoe); + } + } + + static void testSctpMultiChannel() throws IOException { + try (SctpMultiChannel channel = SctpMultiChannel.open()) { + out.println("created SctpMultiChannel:" + channel); + } catch (UnsupportedOperationException uoe) { + // ok - the platform does not support SCTP + out.println("ok, caught:" + uoe); + } + } +} + diff --git a/test/jdk/java/net/Socket/RST.java b/test/jdk/java/net/Socket/RST.java index cb9c225d07c..a3abe5aa428 100644 --- a/test/jdk/java/net/Socket/RST.java +++ b/test/jdk/java/net/Socket/RST.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -44,8 +44,10 @@ public void run() { } RST() throws Exception { - ServerSocket ss = new ServerSocket(0); - client = new Socket("localhost", ss.getLocalPort()); + InetAddress loopback = InetAddress.getLoopbackAddress(); + ServerSocket ss = new ServerSocket(); + ss.bind(new InetSocketAddress(loopback, 0)); + client = new Socket(loopback, ss.getLocalPort()); Socket server = ss.accept(); Thread thr = new Thread(this); diff --git a/test/jdk/java/net/Socket/Streams.java b/test/jdk/java/net/Socket/Streams.java index e3cae93c341..d092ec16bda 100644 --- a/test/jdk/java/net/Socket/Streams.java +++ b/test/jdk/java/net/Socket/Streams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ import java.io.IOException; import java.lang.reflect.Constructor; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.Phaser; @@ -42,7 +44,9 @@ public class Streams { public static void main(String[] args) throws Exception { - try (ServerSocket ss = new ServerSocket(0)) { + try (ServerSocket ss = new ServerSocket()) { + InetAddress loopback = InetAddress.getLoopbackAddress(); + ss.bind(new InetSocketAddress(loopback, 0)); runTest(OutputStreamGetter.class, ss); runTest(InputStreamGetter.class, ss); } @@ -55,9 +59,12 @@ static void runTest(Class klass, ServerSocket ss) throws Exception { final int port = ss.getLocalPort(); + final InetAddress address = ss.getInetAddress(); Socket[] sockets = new Socket[NUM_THREADS]; for (int i=0; i { @@ -120,8 +126,6 @@ private boolean ensureInet6AddressFamily() throws IOException { @Test(groups = "unit") public void testSocksOverIPv6() throws Exception { - if (!shouldRun) return; - Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("::1", socks.getPort())); URL url = new URL("http://[::1]:" + server.getAddress().getPort()); @@ -136,8 +140,6 @@ public void testSocksOverIPv6() throws Exception { @Test(groups = "unit") public void testSocksOverIPv6Hostname() throws Exception { - if (!shouldRun) return; - InetAddress ipv6Loopback = InetAddress.getByName("::1"); String ipv6Hostname = ipv6Loopback.getHostName(); String ipv6HostAddress = ipv6Loopback.getHostAddress(); diff --git a/test/jdk/java/net/URLConnection/URLConnectionHeaders.java b/test/jdk/java/net/URLConnection/URLConnectionHeaders.java index 50180a440c4..f80db86d180 100644 --- a/test/jdk/java/net/URLConnection/URLConnectionHeaders.java +++ b/test/jdk/java/net/URLConnection/URLConnectionHeaders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -27,12 +27,14 @@ * @summary URLConnection cannot enumerate request properties, * and URLConnection can neither get nor set multiple * request properties w/ same key + * @library /test/lib * */ import java.net.*; import java.util.*; import java.io.*; +import jdk.test.lib.net.URIBuilder; public class URLConnectionHeaders { @@ -77,15 +79,22 @@ public void run() { } } - public static void main(String[] args) { + public static void main(String[] args) throws Exception { try { - ServerSocket serversocket = new ServerSocket (0); - int port = serversocket.getLocalPort (); - XServer server = new XServer (serversocket); - server.start (); - Thread.sleep (200); - URL url = new URL ("http://localhost:"+port+"/index.html"); - URLConnection uc = url.openConnection (); + InetAddress loopback = InetAddress.getLoopbackAddress(); + ServerSocket serversocket = new ServerSocket(); + serversocket.bind(new InetSocketAddress(loopback, 0)); + int port = serversocket.getLocalPort(); + XServer server = new XServer(serversocket); + server.start(); + Thread.sleep(200); + URL url = URIBuilder.newBuilder() + .scheme("http") + .loopback() + .port(port) + .path("/index.html") + .toURL(); + URLConnection uc = url.openConnection(); // add request properties uc.addRequestProperty("Cookie", "cookie1"); @@ -106,6 +115,7 @@ public static void main(String[] args) { } catch (Exception e) { e.printStackTrace(); + throw e; } } } diff --git a/test/jdk/java/net/httpclient/AuthSchemesTest.java b/test/jdk/java/net/httpclient/AuthSchemesTest.java new file mode 100644 index 00000000000..b8d7b8842e1 --- /dev/null +++ b/test/jdk/java/net/httpclient/AuthSchemesTest.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 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 8217237 + * @modules java.net.http + * @run main/othervm AuthSchemesTest + * @summary HttpClient does not deal well with multi-valued WWW-Authenticate challenge headers + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.*; +import java.net.Authenticator; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +public class AuthSchemesTest { + static class BasicServer extends Thread { + + ServerSocket server; + + Socket s; + InputStream is; + OutputStream os; + static final String RESPONSE = "Hello world"; + static final String respLength = Integer.toString(RESPONSE.length()); + static final String realm = "wally world"; + + String reply1 = "HTTP/1.1 401 Unauthorized\r\n"+ + "WWW-Authenticate: BarScheme\r\n" + + "WWW-Authenticate: FooScheme realm=\""+realm+"\"\r\n" + + "WWW-Authenticate: Basic realm=\""+realm+"\"\r\n" + + "WWW-Authenticate: WoofScheme\r\n\r\n"; + + String reply2 = "HTTP/1.1 200 OK\r\n"+ + "Date: Mon, 15 Jan 2001 12:18:21 GMT\r\n" + + "Server: Apache/1.3.14 (Unix)\r\n" + + "Connection: close\r\n" + + "Content-Type: text/html; charset=iso-8859-1\r\n" + + "Content-Length: " + respLength + "\r\n\r\n"; + + BasicServer(ServerSocket s) { + server = s; + } + + String response() { + return RESPONSE; + } + + void readAll(Socket s) throws IOException { + byte[] buf = new byte [128]; + InputStream is = s.getInputStream(); + s.setSoTimeout(1000); + try { + while (is.read(buf) > 0) ; + } catch (SocketTimeoutException x) { } + } + + public void run() { + try { + System.out.println("Server 1: accept"); + s = server.accept(); + System.out.println("accepted"); + os = s.getOutputStream(); + os.write(reply1.getBytes()); + readAll(s); + s.close(); + + System.out.println("Server 2: accept"); + s = server.accept(); + System.out.println("accepted"); + os = s.getOutputStream(); + os.write((reply2+RESPONSE).getBytes()); + readAll(s); + s.close(); + + } + catch (Exception e) { + System.out.println(e); + } + finished(); + } + + boolean isfinished = false; + + public synchronized void finished() { + isfinished = true; + notifyAll(); + } + + public synchronized void waitforfinish() { + while (!isfinished) { + try { + wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + static class Auth extends Authenticator { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication("user", new char[] {'a','b','c'}); + } + } + + public static void main(String[] args) throws Exception { + ServerSocket serversocket = null; + BasicServer server = null; + Auth authenticator = new Auth(); + + serversocket = new ServerSocket(0, 10, InetAddress.getLoopbackAddress()); + int port = serversocket.getLocalPort(); + server = new BasicServer(serversocket); + + HttpClient client = HttpClient.newBuilder() + .authenticator(authenticator) + .build(); + server.start(); + URI uri = URI.create("http://127.0.0.1:" + port + "/foo"); + HttpRequest request = HttpRequest.newBuilder(uri) + .GET() + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() != 200 || !response.body().equals(server.response())) { + System.out.println("Status code = " + response.statusCode()); + serversocket.close(); + throw new RuntimeException("Test failed"); + } + serversocket.close(); + server.waitforfinish(); + System.out.println("OK"); + } +} diff --git a/test/jdk/java/net/ipv6tests/UdpTest.java b/test/jdk/java/net/ipv6tests/UdpTest.java index 3b0e23176ee..f3ad1b14c10 100644 --- a/test/jdk/java/net/ipv6tests/UdpTest.java +++ b/test/jdk/java/net/ipv6tests/UdpTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -24,11 +24,14 @@ /* * @test * @bug 4868820 - * @summary IPv6 support for Windows XP and 2003 server + * @key intermittent + * @summary IPv6 support for Windows XP and 2003 server. + * This test requires binding to the wildcard address and as such + * may fail intermittently on some platforms. * @library /test/lib * @build jdk.test.lib.NetworkConfiguration * jdk.test.lib.Platform - * @run main UdpTest + * @run main UdpTest -d */ import java.net.DatagramPacket; @@ -88,6 +91,7 @@ public static void main (String[] args) throws Exception { /* basic UDP connectivity test using IPv6 only and IPv4/IPv6 together */ static void test1 () throws Exception { + System.out.println("Test1 starting"); s1 = new DatagramSocket (); s2 = new DatagramSocket (); simpleDataExchange (s1, ia4addr, s2, ia4addr); @@ -126,6 +130,7 @@ static void test1 () throws Exception { /* check timeouts on receive */ static void test2 () throws Exception { + System.out.println("Test2 starting"); s1 = new DatagramSocket (); s2 = new DatagramSocket (); s1.setSoTimeout (4000); @@ -176,6 +181,7 @@ public void run () { /* check connected sockets */ static void test3 () throws Exception { + System.out.println("Test3 starting"); s1 = new DatagramSocket (); s2 = new DatagramSocket (); s1.connect (ia6addr, s2.getLocalPort()); @@ -187,6 +193,7 @@ static void test3 () throws Exception { /* check PortUnreachable */ static void test4 () throws Exception { + System.out.println("Test4 starting"); s1 = new DatagramSocket (); s1.connect (ia6addr, 5000); s1.setSoTimeout (3000); diff --git a/test/jdk/java/nio/Buffer/Basic.java b/test/jdk/java/nio/Buffer/Basic.java index 7d5f85e532d..bfbcf465d32 100644 --- a/test/jdk/java/nio/Buffer/Basic.java +++ b/test/jdk/java/nio/Buffer/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -26,7 +26,7 @@ * @bug 4413135 4414911 4416536 4416562 4418782 4471053 4472779 4490253 4523725 * 4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 6231529 * 6221101 6234263 6535542 6591971 6593946 6795561 7190219 7199551 8065556 - * 8149469 + * 8149469 8230665 * @modules java.base/java.nio:open * java.base/jdk.internal.misc * @author Mark Reinhold diff --git a/test/jdk/java/nio/charset/Charset/DefaultCharsetTest.java b/test/jdk/java/nio/charset/Charset/DefaultCharsetTest.java index e7a6197888e..b8eef9ca56b 100644 --- a/test/jdk/java/nio/charset/Charset/DefaultCharsetTest.java +++ b/test/jdk/java/nio/charset/Charset/DefaultCharsetTest.java @@ -54,7 +54,7 @@ public class DefaultCharsetTest { private static final ProcessBuilder pb - = ProcessTools.createJavaProcessBuilder(true, Default.class.getName()); + = ProcessTools.createTestJvm(Default.class.getName()); private static final Map env = pb.environment(); private static String UNSUPPORTED = null; diff --git a/test/jdk/java/nio/charset/coders/SJISMappingPropTest.java b/test/jdk/java/nio/charset/coders/SJISMappingPropTest.java index 9c26bc27081..97d6823d37b 100644 --- a/test/jdk/java/nio/charset/coders/SJISMappingPropTest.java +++ b/test/jdk/java/nio/charset/coders/SJISMappingPropTest.java @@ -81,7 +81,7 @@ public void testWithoutProperty(String locale) throws Exception { } private void runTest(String locale, String... cmd) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmd); + ProcessBuilder pb = ProcessTools.createTestJvm(cmd); Map env = pb.environment(); env.put("LC_ALL", locale); OutputAnalyzer out = ProcessTools.executeProcess(pb) diff --git a/test/jdk/java/nio/file/FileStore/Basic.java b/test/jdk/java/nio/file/FileStore/Basic.java index 3feaef777ae..07d658a01d8 100644 --- a/test/jdk/java/nio/file/FileStore/Basic.java +++ b/test/jdk/java/nio/file/FileStore/Basic.java @@ -124,7 +124,7 @@ static void doTests(Path dir) throws IOException { /** * Test: Enumerate all FileStores */ - if (FileUtils.areFileSystemsAccessible()) { + if (FileUtils.areAllMountPointsAccessible()) { FileStore prev = null; for (FileStore store: FileSystems.getDefault().getFileStores()) { System.out.format("%s (name=%s type=%s)\n", store, store.name(), diff --git a/test/jdk/java/nio/file/Path/MacPathTest.java b/test/jdk/java/nio/file/Path/MacPathTest.java index 00d5eddc045..a65e310ff7f 100644 --- a/test/jdk/java/nio/file/Path/MacPathTest.java +++ b/test/jdk/java/nio/file/Path/MacPathTest.java @@ -41,7 +41,7 @@ public class MacPathTest { public static void main(String args[]) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, MacPath.class.getName()); + ProcessBuilder pb = ProcessTools.createTestJvm(MacPath.class.getName()); pb.environment().put("LC_ALL", "en_US.UTF-8"); ProcessTools.executeProcess(pb) .outputTo(System.out) diff --git a/test/jdk/java/security/KeyRep/RSA.pre.1.5.key b/test/jdk/java/security/KeyRep/RSA.pre.1.5.key deleted file mode 100644 index 0c15a06c9cd..00000000000 Binary files a/test/jdk/java/security/KeyRep/RSA.pre.1.5.key and /dev/null differ diff --git a/test/jdk/java/security/KeyRep/SerialOld.java b/test/jdk/java/security/KeyRep/SerialOld.java index fe8eb32d045..0729883cd2f 100644 --- a/test/jdk/java/security/KeyRep/SerialOld.java +++ b/test/jdk/java/security/KeyRep/SerialOld.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, 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 @@ -23,14 +23,13 @@ /* * @test 1.1, 03/08/13 - * @bug 4532506 + * @bug 4532506 8301126 * @summary Serializing KeyPair on one VM (Sun), * and Deserializing on another (IBM) fails * @run main/othervm/java.security.policy=SerialOld.policy SerialOld */ import java.io.*; -import java.security.*; public class SerialOld { public static void main(String[] args) throws Exception { @@ -40,10 +39,15 @@ public static void main(String[] args) throws Exception { deserializeTigerKey("DSA"); deserializeTigerKey("RSA"); - // verify pre-tiger keys still deserialize in our VM + // verify pre-tiger keys still deserialize in our VM. + + // There used to be a RSA test here, but the serialized file contained + // classes introduced in JDK 5.0 (sun.security.rsa.RSA*). The older + // RSA keys from JDK 1.4.2 were of class JSA_* which were removed when + // sun.security.rsa was introduced. (See JDK-8301126 for more + // details.) The test/data has been removed. deserializeKey("DSA"); - deserializeKey("RSA"); deserializeKey("DH"); deserializeKey("AES"); deserializeKey("Blowfish"); diff --git a/test/jdk/java/security/MessageDigest/ThreadSafetyTest.java b/test/jdk/java/security/MessageDigest/ThreadSafetyTest.java index 41ecbca2677..594e9926eab 100644 --- a/test/jdk/java/security/MessageDigest/ThreadSafetyTest.java +++ b/test/jdk/java/security/MessageDigest/ThreadSafetyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Azul Systems, Inc. All rights reserved. + * Copyright (c) 2020, 2021, Azul Systems, 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 @@ -23,9 +23,9 @@ /* * @test - * @bug 8241960 + * @bug 8241960 8277353 * @summary Confirm that java.security.MessageDigest is thread-safe after clone. - * @run main/othervm ThreadSafetyTest 5 4 + * @run main ThreadSafetyTest 4 2 */ import java.security.MessageDigest; @@ -56,7 +56,7 @@ public static void main(String[] args) throws Exception { duration = Integer.parseInt(args[1]); } int nProcessors = Runtime.getRuntime().availableProcessors(); - int nTasks = nProcessors * threadsFactor; + int nTasks = Math.min(nProcessors, 4) * threadsFactor; System.out.println("Testing with " + nTasks + " threads on " + nProcessors + " processors for " + duration + diff --git a/test/jdk/java/security/Security/ConfigFileTest.java b/test/jdk/java/security/Security/ConfigFileTest.java new file mode 100644 index 00000000000..0b261afed6f --- /dev/null +++ b/test/jdk/java/security/Security/ConfigFileTest.java @@ -0,0 +1,122 @@ +/* + * 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.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.*; + +import java.security.Provider; +import java.security.Security; +import java.util.Arrays; +import java.util.Optional; + +/* + * @test + * @summary Throw error if default java.security file is missing + * @bug 8155246 8292297 + * @library /test/lib + * @run main ConfigFileTest + */ +public class ConfigFileTest { + + public static void main(String[] args) throws Exception { + Path copyJdkDir = Path.of("./jdk-8155246-tmpdir"); + Path copiedJava = Optional.of( + Path.of(copyJdkDir.toString(), "bin", "java")) + .orElseThrow(() -> new RuntimeException("Unable to locate new JDK") + ); + + if (args.length == 1) { + // set up is complete. Run code to exercise loading of java.security + Provider[] provs = Security.getProviders(); + System.out.println(Arrays.toString(provs) + "NumProviders: " + provs.length); + } else { + Files.createDirectory(copyJdkDir); + Path jdkTestDir = Path.of(Optional.of(System.getProperty("test.jdk")) + .orElseThrow(() -> new RuntimeException("Couldn't load JDK Test Dir")) + ); + + copyJDK(jdkTestDir, copyJdkDir); + String extraPropsFile = Path.of(System.getProperty("test.src"), "override.props").toString(); + + // exercise some debug flags while we're here + // regular JDK install - should expect success + exerciseSecurity(0, "java", + copiedJava.toString(), "-cp", System.getProperty("test.classes"), + "-Djava.security.debug=all", "-Djavax.net.debug=all", "ConfigFileTest", "runner"); + + // given an overriding security conf file that doesn't exist, we shouldn't + // overwrite the properties from original/master security conf file + exerciseSecurity(0, "SUN version", + copiedJava.toString(), "-cp", System.getProperty("test.classes"), + "-Djava.security.debug=all", "-Djavax.net.debug=all", + "-Djava.security.properties==file:///" + extraPropsFile + "badFileName", + "ConfigFileTest", "runner"); + + // test JDK launch with customized properties file + exerciseSecurity(0, "NumProviders: 6", + copiedJava.toString(), "-cp", System.getProperty("test.classes"), + "-Djava.security.debug=all", "-Djavax.net.debug=all", + "-Djava.security.properties==file:///" + extraPropsFile, + "ConfigFileTest", "runner"); + + // delete the master conf file + Files.delete(Path.of(copyJdkDir.toString(), "conf", + "security","java.security")); + + // launch JDK without java.security file being present or specified + exerciseSecurity(1, "Error loading java.security file", + copiedJava.toString(), "-cp", System.getProperty("test.classes"), + "-Djava.security.debug=all", "-Djavax.net.debug=all", + "ConfigFileTest", "runner"); + + // test the override functionality also. Should not be allowed since + // "security.overridePropertiesFile=true" Security property is missing. + exerciseSecurity(1, "Error loading java.security file", + copiedJava.toString(), "-cp", System.getProperty("test.classes"), + "-Djava.security.debug=all", "-Djavax.net.debug=all", + "-Djava.security.properties==file:///" + extraPropsFile, "ConfigFileTest", "runner"); + } + } + + private static void exerciseSecurity(int exitCode, String output, String... args) throws Exception { + ProcessBuilder process = new ProcessBuilder(args); + OutputAnalyzer oa = ProcessTools.executeProcess(process); + oa.shouldHaveExitValue(exitCode).shouldContain(output); + } + + private static void copyJDK(Path src, Path dst) throws Exception { + Files.walk(src) + .skip(1) + .forEach(file -> { + try { + Files.copy(file, dst.resolve(src.relativize(file)), StandardCopyOption.COPY_ATTRIBUTES); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + }); + } +} diff --git a/test/jdk/java/security/Security/override.props b/test/jdk/java/security/Security/override.props new file mode 100644 index 00000000000..8b91153ae65 --- /dev/null +++ b/test/jdk/java/security/Security/override.props @@ -0,0 +1,7 @@ +# exercise ServiceLoader and legacy (class load) approach +security.provider.1=sun.security.provider.Sun +security.provider.2=SunRsaSign +security.provider.3=SunJSSE +security.provider.4=com.sun.crypto.provider.SunJCE +security.provider.5=SunJGSS +security.provider.6=SunSASL \ No newline at end of file diff --git a/test/jdk/java/security/misc/TestDefaultRandom.java b/test/jdk/java/security/misc/TestDefaultRandom.java new file mode 100644 index 00000000000..7f9abee0b42 --- /dev/null +++ b/test/jdk/java/security/misc/TestDefaultRandom.java @@ -0,0 +1,229 @@ +/* + * 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 8260274 + * @run main/othervm TestDefaultRandom APG 1 + * @run main/othervm TestDefaultRandom APG 2 + * @run main/othervm TestDefaultRandom KPG 1 + * @run main/othervm TestDefaultRandom KPG 2 + * @run main/othervm TestDefaultRandom CIP 1 + * @run main/othervm TestDefaultRandom CIP 2 + * @run main/othervm TestDefaultRandom CIP 3 + * @run main/othervm TestDefaultRandom CIP 4 + * @run main/othervm TestDefaultRandom KA 1 + * @run main/othervm TestDefaultRandom KA 2 + * @run main/othervm TestDefaultRandom KG 1 + * @run main/othervm TestDefaultRandom KG 2 + * @summary Ensure the default SecureRandom impl is used as the javadoc + * spec stated when none supplied. + */ +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.Map; +import java.security.*; +import java.security.cert.Certificate; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.DSAGenParameterSpec; +import java.security.spec.RSAKeyGenParameterSpec; +import javax.crypto.Cipher; +import javax.crypto.KeyAgreement; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import javax.crypto.spec.IvParameterSpec; + +public class TestDefaultRandom { + + public static void main(String[] argv) throws Exception { + if (argv.length != 2) { + throw new RuntimeException("Error: missing test parameters"); + } + + switch (argv[0]) { + case "APG": + check(AlgorithmParameterGenerator.getInstance("DSA"), argv[1]); + break; + case "KPG": + check(KeyPairGenerator.getInstance("RSA"), argv[1]); + break; + case "CIP": + check(Cipher.getInstance("AES/CBC/NoPadding"), argv[1]); + break; + case "KA": + check(KeyAgreement.getInstance("DH"), argv[1]); + break; + case "KG": + check(KeyGenerator.getInstance("AES"), argv[1]); + break; + default: + throw new RuntimeException("Error: unsupported test type"); + } + } + + private static void check(Object obj, String testNum) { + if (obj == null) throw new NullPointerException(); + + SampleProvider prov = new SampleProvider(); + Security.insertProviderAt(prov, 1); + + int b4Cnt = SampleProvider.count; + + System.out.println("before, count = " + b4Cnt); + // Note that the arguments may not be valid, they just need to be + // non-null to trigger the call for checking if the default + // SecureRandom impl is used + try { + if (obj instanceof AlgorithmParameterGenerator) { + AlgorithmParameterGenerator apg = + (AlgorithmParameterGenerator) obj; + switch (testNum) { + case "1": + apg.init(123); + break; + case "2": + apg.init((AlgorithmParameterSpec) null); + break; + default: + throw new RuntimeException("Error: invalid test#"); + } + } else if (obj instanceof KeyPairGenerator) { + KeyPairGenerator kpg = (KeyPairGenerator) obj; + switch (testNum) { + case "1": + kpg.initialize(123); + break; + case "2": + kpg.initialize((AlgorithmParameterSpec) null); + break; + default: + throw new RuntimeException("Error: invalid test#"); + } + } else if (obj instanceof Cipher) { + Cipher c = (Cipher) obj; + switch (testNum) { + case "1": + c.init(Cipher.ENCRYPT_MODE, (Key) null); + break; + case "2": + c.init(Cipher.ENCRYPT_MODE, (Key) null, + (AlgorithmParameterSpec) null); + break; + case "3": + c.init(Cipher.ENCRYPT_MODE, (Key) null, + (AlgorithmParameters) null); + break; + case "4": + c.init(Cipher.ENCRYPT_MODE, (Certificate)null); + break; + default: + throw new RuntimeException("Error: invalid test#"); + } + } else if (obj instanceof KeyAgreement) { + KeyAgreement ka = (KeyAgreement) obj; + switch (testNum) { + case "1": + ka.init((Key) null); + break; + case "2": + ka.init((Key) null, (AlgorithmParameterSpec) null); + break; + default: + throw new RuntimeException("Error: invalid test#"); + } + } else if (obj instanceof KeyGenerator) { + KeyGenerator kg = (KeyGenerator) obj; + switch (testNum) { + case "1": + kg.init(123); + break; + case "2": + kg.init((AlgorithmParameterSpec) null); + break; + default: + throw new RuntimeException("Error: invalid test#"); + } + } else { + throw new RuntimeException("Error: Unsupported type"); + } + } catch (GeneralSecurityException | InvalidParameterException e) { + // expected; ignore + } + System.out.println("after, count = " + SampleProvider.count); + if (SampleProvider.count == b4Cnt) { + throw new RuntimeException("Test Failed"); + } + } + + private static class SampleProvider extends Provider { + + static int count = 0; + static String SR_ALGO = "Custom"; + + SampleProvider() { + super("Sample", "1.0", "test provider with custom SR impl"); + putService(new SampleService(this, "SecureRandom", SR_ALGO, + "SampleSecureRandom.class" /* stub class name */, + null, null)); + } + + private static class SampleService extends Service { + + SampleService(Provider p, String type, String alg, String cn, + List aliases, Map attrs) { + super(p, type, alg, cn, aliases, attrs); + } + + @Override + public Object newInstance(Object param) + throws NoSuchAlgorithmException { + String alg = getAlgorithm(); + String type = getType(); + + if (type.equals("SecureRandom") && alg.equals(SR_ALGO)) { + SampleProvider.count++; + return new CustomSR(); + } else { + // should never happen + throw new NoSuchAlgorithmException("No support for " + alg); + } + } + } + + private static class CustomSR extends SecureRandomSpi { + @Override + protected void engineSetSeed(byte[] seed) { + } + + @Override + protected void engineNextBytes(byte[] bytes) { + } + + @Override + protected byte[] engineGenerateSeed(int numBytes) { + return new byte[numBytes]; + } + } + } +} diff --git a/test/jdk/java/security/testlibrary/CertificateBuilder.java b/test/jdk/java/security/testlibrary/CertificateBuilder.java index 4ab26d0d12e..b2c39b8ab5b 100644 --- a/test/jdk/java/security/testlibrary/CertificateBuilder.java +++ b/test/jdk/java/security/testlibrary/CertificateBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -322,7 +322,7 @@ public void addExtendedKeyUsageExt(List ekuOids) if (!ekuOids.isEmpty()) { Vector oidVector = new Vector<>(); for (String oid : ekuOids) { - oidVector.add(new ObjectIdentifier(oid)); + oidVector.add(ObjectIdentifier.of(oid)); } addExtension(new ExtendedKeyUsageExtension(oidVector)); } diff --git a/test/jdk/java/security/testlibrary/SimpleOCSPServer.java b/test/jdk/java/security/testlibrary/SimpleOCSPServer.java index 4901e6f2651..1a29bef0c42 100644 --- a/test/jdk/java/security/testlibrary/SimpleOCSPServer.java +++ b/test/jdk/java/security/testlibrary/SimpleOCSPServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -45,11 +45,7 @@ import sun.security.provider.certpath.CertId; import sun.security.provider.certpath.OCSPResponse; import sun.security.provider.certpath.OCSPResponse.ResponseStatus; -import sun.security.util.Debug; -import sun.security.util.DerInputStream; -import sun.security.util.DerOutputStream; -import sun.security.util.DerValue; -import sun.security.util.ObjectIdentifier; +import sun.security.util.*; /** @@ -59,8 +55,8 @@ public class SimpleOCSPServer { private final Debug debug = Debug.getInstance("oserv"); private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID = - ObjectIdentifier.newInternal( - new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1}); + ObjectIdentifier.of(KnownOIDs.OCSPBasicResponse); + private static final SimpleDateFormat utcDateFmt = new SimpleDateFormat("MMM dd yyyy, HH:mm:ss z"); diff --git a/test/jdk/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java b/test/jdk/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java index 7429f013060..b02cc8c0134 100644 --- a/test/jdk/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java +++ b/test/jdk/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -614,7 +614,7 @@ Object[][] data_parseGenericTimeZonePatterns() { @Test(dataProvider = "parseGenericTimeZonePatterns") public void test_appendZoneText_parseGenericTimeZonePatterns(String pattern, LocalDateTime ldt, ZoneId zId, String input) { - DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(); + DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(Locale.US); ZonedDateTime expected = ZonedDateTime.parse(input, df); ZonedDateTime actual = ZonedDateTime.of(ldt, zId); assertEquals(actual, expected); diff --git a/test/jdk/java/util/RandomAccess/Basic.java b/test/jdk/java/util/RandomAccess/Basic.java index 9d710e1ba5d..cc1a30b051f 100644 --- a/test/jdk/java/util/RandomAccess/Basic.java +++ b/test/jdk/java/util/RandomAccess/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -21,111 +21,148 @@ * questions. */ -/* +/** * @test - * @bug 4327164 + * @bug 4327164 8229338 * @summary Basic test for new RandomAccess interface + * @run testng Basic */ -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Random; -import java.util.RandomAccess; -import java.util.Vector; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Function; +import java.util.function.Supplier; public class Basic { - public static void main(String[] args) throws Exception { - List a0 = Arrays.asList(new String[] { "a", "b", "c" }); - List a[] = { a0, new ArrayList(a0), new LinkedList(a0), - new Vector(a0) }; - - if (!(a[0] instanceof RandomAccess)) - throw new Exception("Arrays.asList doesn't implement RandomAccess"); - if (!(a[1] instanceof RandomAccess)) - throw new Exception("ArrayList doesn't implement RandomAccess"); - if (a[2] instanceof RandomAccess) - throw new Exception("LinkedList implements RandomAccess"); - if (!(a[3] instanceof RandomAccess)) - throw new Exception("Vector doesn't implement RandomAccess"); - - for (int i = 0; i < a.length; i++) { - List t = a[i]; - List ut = Collections.unmodifiableList(t); - List st = Collections.synchronizedList(t); - - boolean random = t instanceof RandomAccess; - if ((ut instanceof RandomAccess) != random) - throw new Exception( - "Unmodifiable fails to preserve RandomAccess: " + i); - if ((st instanceof RandomAccess) != random) - throw new Exception( - "Synchronized fails to preserve RandomAccess: " + i); - - while (t.size() > 0) { - t = t.subList(0, t.size() - 1); - if ((t instanceof RandomAccess) != random) - throw new Exception( - "SubList fails to preserve RandomAccess: " + i - + ", " + t.size()); - - ut = ut.subList(0, ut.size() - 1); - if ((ut instanceof RandomAccess) != random) - throw new Exception( - "SubList(unmodifiable) fails to preserve RandomAccess: " - + i + ", " + ut.size()); - - st = st.subList(0, st.size() - 1); - if ((st instanceof RandomAccess) != random) - throw new Exception( - "SubList(synchronized) fails to preserve RandomAccess: " - + i + ", " + st.size()); - } - } - // Test that shuffle works the same on random and sequential access - List al = new ArrayList(); - for (int j = 0; j < 100; j++) - al.add(Integer.valueOf(2 * j)); - List ll = new LinkedList(al); - Random r1 = new Random(666), r2 = new Random(666); + /* + * Lists which implement Random Access interface + */ + @DataProvider(name = "testLists") + public Object[][] testData() { + var intArray = new Integer[100]; + var stack = new Stack<>(); + var random = new Random(); for (int i = 0; i < 100; i++) { - Collections.shuffle(al, r1); - Collections.shuffle(ll, r2); - if (!al.equals(ll)) - throw new Exception("Shuffle failed: " + i); + var r = random.nextInt(100); + stack.push(r); + intArray[i] = r; + } + List list = Arrays.asList(intArray); + return new Object[][]{ + {list, true, "Arrays.asList"}, + {stack, true, "Stack"}, + {new ArrayList<>(list), true, "ArrayList"}, + {new LinkedList<>(list), false, "LinkedList"}, + {new Vector<>(list), true, "Vector"}, + {new CopyOnWriteArrayList<>(list), true, "CopyOnWriteArrayList"} + }; + } + + @Test(dataProvider = "testLists") + public void testRandomAccess(List list, boolean expectedRA, String failMsg) { + + var actualRA = list instanceof RandomAccess; + assertEquals(actualRA, expectedRA, failMsg); + + List unmodList = Collections.unmodifiableList(list); + List syncList = Collections.synchronizedList(list); + assertEquals((unmodList instanceof RandomAccess), actualRA, + "Unmodifiable fails to preserve RandomAccess"); + assertEquals((syncList instanceof RandomAccess), actualRA, + "Synchronized fails to preserve RandomAccess"); + + while (list.size() > 0) { + list = list.subList(0, list.size() - 1); + assertEquals((list instanceof RandomAccess), actualRA, + "SubList fails to preserve RandomAccess: " + list.size()); + + unmodList = unmodList.subList(0, unmodList.size() - 1); + assertEquals((unmodList instanceof RandomAccess), actualRA, + "SubList(unmodifiable) fails to preserve RandomAccess: " + + unmodList.size()); + + syncList = syncList.subList(0, syncList.size() - 1); + assertEquals((syncList instanceof RandomAccess), actualRA, + "SubList(synchronized) fails to preserve RandomAccess: " + + syncList.size()); } + } - // Test that fill works on random & sequential access - List gumbyParade = Collections.nCopies(100, "gumby"); - Collections.fill(al, "gumby"); - if (!al.equals(gumbyParade)) - throw new Exception("ArrayList fill failed"); - Collections.fill(ll, "gumby"); - if (!ll.equals(gumbyParade)) - throw new Exception("LinkedList fill failed"); + @Test(dataProvider = "testLists") + public void testListCopy(List list, boolean expectedRA, String failMsg) { + ArrayList testCollection = new ArrayList<>(Collections.nCopies(100, 0)); + // Test that copy works on random & sequential access + Collections.copy(list, testCollection); + assertEquals(list, testCollection, "Copy failed: " + failMsg); + } + @Test(dataProvider = "testLists") + public void testListFill(List list, boolean expectedRA, String failMsg) { + ArrayList testCollection = new ArrayList<>(Collections.nCopies(100, 0)); // Test that copy works on random & sequential access - List pokeyParade = Collections.nCopies(100, "pokey"); - Collections.copy(al, pokeyParade); - if (!al.equals(pokeyParade)) - throw new Exception("ArrayList copy failed"); - Collections.copy(ll, pokeyParade); - if (!ll.equals(pokeyParade)) - throw new Exception("LinkedList copy failed"); - - // Test that binarySearch works the same on random & sequential access - al = new ArrayList(); - for (int i = 0; i < 10000; i++) - al.add(Integer.valueOf(2 * i)); - ll = new LinkedList(al); + Collections.fill(list, 0); + assertEquals(list, testCollection, "Fill failed: " + failMsg); + } + + /* + * Test that shuffle and binarySearch work the same on random and sequential access lists. + */ + @DataProvider(name = "testFactoryLists") + public Object[][] testDataFactory() { + return new Object[][]{ + {"ArrayList -> LinkedList", supplier(ArrayList::new), copyCtor(LinkedList::new)}, + {"CopyOnWriteArrayList -> Stack", supplier(CopyOnWriteArrayList::new), + copyCtor((list) -> { var s = new Stack();s.addAll(list);return s; })} + }; + } + + private Supplier> supplier(Supplier> supplier) { + return supplier; + } + + private Function, List> copyCtor(Function, List> ctor) { + return ctor; + } + + @Test(dataProvider = "testFactoryLists") + public void testListShuffle(String description, Supplier> randomAccessListSupplier, + Function, List> otherListFactory) { + + //e.g: ArrayList al = new ArrayList<>(); + List l1 = randomAccessListSupplier.get(); + for (int j = 0; j < 100; j++) { + l1.add(Integer.valueOf(2 * j)); + } + // e.g: List ll = new LinkedList<>(al); + List l2 = otherListFactory.apply(l1); + for (int i = 0; i < 100; i++) { + Collections.shuffle(l1, new Random(666)); + Collections.shuffle(l2, new Random(666)); + assertEquals(l1, l2, "Shuffle failed: " + description); + } + } + + @Test(dataProvider = "testFactoryLists") + public void testListBinarySearch(String description, Supplier> randomAccessListSupplier, + Function, List> otherListFactory) { + + //e.g: ArrayList al = new ArrayList<>(); + List l1 = randomAccessListSupplier.get(); + for (int i = 0; i < 10000; i++) { + l1.add(Integer.valueOf(2 * i)); + } + // e.g: List ll = new LinkedList<>(al); + List l2 = otherListFactory.apply(l1); for (int i = 0; i < 500; i++) { - Integer key = Integer.valueOf(r1.nextInt(20000)); - if (Collections.binarySearch(al, key) != Collections - .binarySearch(ll, key)) - throw new Exception("Binary search failed: " + i); + Integer key = Integer.valueOf(new Random(666).nextInt(20000)); + assertEquals(Collections.binarySearch(l1, key), Collections + .binarySearch(l2, key), "Binary search failed: " + description); } } } diff --git a/test/jdk/java/util/concurrent/CompletableFuture/LostInterrupt.java b/test/jdk/java/util/concurrent/CompletableFuture/LostInterrupt.java new file mode 100644 index 00000000000..0f5a462b630 --- /dev/null +++ b/test/jdk/java/util/concurrent/CompletableFuture/LostInterrupt.java @@ -0,0 +1,73 @@ +/* + * 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 java.util.concurrent.CompletableFuture; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ThreadLocalRandom; +import static java.util.concurrent.TimeUnit.DAYS; + +/* + * @test + * @bug 8254350 + * @run main LostInterrupt + * @summary CompletableFuture.get may swallow interrupt status + * @key randomness + */ + +// TODO: Rewrite as a CompletableFuture tck test ? + +/** + * Submits a task that completes immediately, then invokes CompletableFuture.get + * with the interrupt status set. CompletableFuture.get should either complete + * immediately with the interrupt status set, or else throw InterruptedException + * with the interrupt status cleared. + */ +public class LostInterrupt { + static final int ITERATIONS = 10_000; + + public static void main(String[] args) throws Exception { + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + ForkJoinPool executor = new ForkJoinPool(1); + try { + for (int i = 0; i < ITERATIONS; i++) { + CompletableFuture future = new CompletableFuture<>(); + boolean timed = rnd.nextBoolean(); + executor.execute(() -> future.complete("foo")); + + Thread.currentThread().interrupt(); + try { + String result = timed ? future.get(1, DAYS) : future.get(); + + if (!Thread.interrupted()) + throw new AssertionError("lost interrupt, run=" + i); + } catch (InterruptedException expected) { + if (Thread.interrupted()) + throw new AssertionError( + "interrupt status not cleared, run=" + i); + } + } + } finally { + executor.shutdown(); + } + } +} diff --git a/test/jdk/java/util/concurrent/CompletableFuture/SwallowedInterruptedException.java b/test/jdk/java/util/concurrent/CompletableFuture/SwallowedInterruptedException.java new file mode 100644 index 00000000000..93ae7305998 --- /dev/null +++ b/test/jdk/java/util/concurrent/CompletableFuture/SwallowedInterruptedException.java @@ -0,0 +1,89 @@ +/* + * 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 java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ThreadLocalRandom; +import static java.util.concurrent.TimeUnit.DAYS; +import java.util.concurrent.atomic.AtomicReference; + +/* + * @test + * @bug 8254350 + * @run main SwallowedInterruptedException + * @key randomness + */ + +// TODO: incorporate into CompletableFuture tck tests + +public class SwallowedInterruptedException { + static final int ITERATIONS = 100; + + public static void main(String[] args) throws Throwable { + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + for (int i = 1; i <= ITERATIONS; i++) { + boolean timed = rnd.nextBoolean(); + long sleepMillis = rnd.nextLong(10); + + CompletableFuture future = new CompletableFuture<>(); + CountDownLatch threadRunning = new CountDownLatch(1); + AtomicReference fail = new AtomicReference<>(); + + Thread thread = new Thread(() -> { + threadRunning.countDown(); + + try { + Void result = (timed) ? future.get(1, DAYS) : future.get(); + + if (!Thread.currentThread().isInterrupted()) { + fail.set(new AssertionError( + "Future.get completed with interrupt status not set")); + } + } catch (InterruptedException ex) { + if (Thread.currentThread().isInterrupted()) { + fail.set(new AssertionError( + "InterruptedException with interrupt status set")); + } + } catch (Throwable ex) { + fail.set(ex); + } + }); + thread.start(); + threadRunning.await(); + + // interrupt thread, then set result after an optional (random) delay + thread.interrupt(); + if (sleepMillis > 0) + Thread.sleep(sleepMillis); + future.complete(null); + + thread.join(); + if (fail.get() != null) { + throw new AssertionError( + String.format("Test failed at iteration %d with [timed=%s sleepMillis=%d]", + i, timed, sleepMillis), + fail.get()); + } + } + } +} diff --git a/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java b/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java index b969ecfd04e..a4627721c12 100644 --- a/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java +++ b/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4770745 6218846 6218848 6237956 + * @bug 4770745 6218846 6218848 6237956 8313765 * @summary test for correct detection and reporting of corrupted zip files * @author Martin Buchholz */ @@ -113,8 +113,9 @@ public static void main(String[] args) throws Exception { err.println("corrupted CENEXT 1"); bad = good.clone(); - bad[cenpos+CENEXT]++; - checkZipException(bad, ".*invalid zip64 extra data field size.*"); + bad[cenpos+CENEXT] = (byte)0xff; + bad[cenpos+CENEXT+1] = (byte)0xff; + checkZipException(bad, ".*extra data field size too long.*"); err.println("corrupted CENEXT 2"); bad = good.clone(); diff --git a/test/jdk/java/util/zip/ZipFile/ReadNonStandardExtraHeadersTest.java b/test/jdk/java/util/zip/ZipFile/ReadNonStandardExtraHeadersTest.java new file mode 100644 index 00000000000..9c420b30f36 --- /dev/null +++ b/test/jdk/java/util/zip/ZipFile/ReadNonStandardExtraHeadersTest.java @@ -0,0 +1,940 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Formatter; +import java.util.Map; +import java.util.stream.Stream; +import java.util.zip.ZipFile; + +/* @test + * @bug 8313765 + * @summary Validate that a Zip File with an Extra Header with a data size + * of 0 can be read. + * @run main ReadNonStandardExtraHeadersTest + */ +public class ReadNonStandardExtraHeadersTest { + + /* + * Byte array holding a ZIP file which contains an + * Extra field header which has a data size of 0. + * + * ---------------#1-------------------- + * [Central Directory Header] + * 0x664: Signature : 0x02014b50 + * 0x668: Created Zip Spec : 0xa [1.0] + * 0x669: Created OS : 0x0 [MS-DOS] + * 0x66a: VerMadeby : 0xa [0, 1.0] + * 0x66b: VerExtract : 0xa [1.0] + * 0x66c: Flag : 0x800 + * 0x66e: Method : 0x0 [STORED] + * 0x670: Last Mod Time : 0x385ca437 [Thu Feb 28 20:33:46 EST 2008] + * 0x674: CRC : 0x694c6952 + * 0x678: Compressed Size : 0x624 + * 0x67c: Uncompressed Size: 0x624 + * 0x680: Name Length : 0x1b + * 0x682: Extra Length : 0x7 + * ->[tag=cafe, size=0] + * 0x684: Comment Length : 0x0 + * 0x686: Disk Start : 0x0 + * 0x688: Attrs : 0x0 + * 0x68a: AttrsEx : 0x0 + * 0x68e: Loc Header Offset: 0x0 + * 0x692: File Name : res/drawable/size_48x48.jpg + * + * [Local File Header] + * 0x0: Signature : 0x04034b50 + * 0x4: Version : 0xa [1.0] + * 0x6: Flag : 0x800 + * 0x8: Method : 0x0 [STORED] + * 0xa: LastMTime : 0x385ca437 [Thu Feb 28 20:33:46 EST 2008] + * 0xe: CRC : 0x694c6952 + * 0x12: CSize : 0x624 + * 0x16: Size : 0x624 + * 0x1a: Name Length : 0x1b [res/drawable/size_48x48.jpg] + * 0x1c: ExtraLength : 0x7 + * ->[tag=cafe, size=0] + * 0x1e: File Name : [res/drawable/size_48x48.jpg] + * [End Central Directory Header] + * Signature : 0x06054b50 + * ENDCEN Off : 0x6b4 + * Disk Entries: 0x1 + * Total Entries: 0x1 + * CEN Size : 0x50 + * Offset CEN : 0x664 + * Comment Len : 0x0 [] + */ + public static byte[] VALID_APK_FILE = { + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0xa, (byte) 0x0, (byte) 0x0, (byte) 0x8, + (byte) 0x0, (byte) 0x0, (byte) 0x37, (byte) 0xa4, (byte) 0x5c, (byte) 0x38, (byte) 0x52, (byte) 0x69, + (byte) 0x4c, (byte) 0x69, (byte) 0x24, (byte) 0x6, (byte) 0x0, (byte) 0x0, (byte) 0x24, (byte) 0x6, + (byte) 0x0, (byte) 0x0, (byte) 0x1b, (byte) 0x0, (byte) 0x7, (byte) 0x0, (byte) 0x72, (byte) 0x65, + (byte) 0x73, (byte) 0x2f, (byte) 0x64, (byte) 0x72, (byte) 0x61, (byte) 0x77, (byte) 0x61, (byte) 0x62, + (byte) 0x6c, (byte) 0x65, (byte) 0x2f, (byte) 0x73, (byte) 0x69, (byte) 0x7a, (byte) 0x65, (byte) 0x5f, + (byte) 0x34, (byte) 0x38, (byte) 0x78, (byte) 0x34, (byte) 0x38, (byte) 0x2e, (byte) 0x6a, (byte) 0x70, + (byte) 0x67, (byte) 0xfe, (byte) 0xca, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0xff, (byte) 0xd8, (byte) 0xff, (byte) 0xe0, (byte) 0x0, (byte) 0x10, (byte) 0x4a, (byte) 0x46, + (byte) 0x49, (byte) 0x46, (byte) 0x0, (byte) 0x1, (byte) 0x1, (byte) 0x1, (byte) 0x0, (byte) 0x48, + (byte) 0x0, (byte) 0x48, (byte) 0x0, (byte) 0x0, (byte) 0xff, (byte) 0xfe, (byte) 0x0, (byte) 0x16, + (byte) 0x28, (byte) 0x63, (byte) 0x29, (byte) 0x20, (byte) 0x32, (byte) 0x30, (byte) 0x30, (byte) 0x37, + (byte) 0x20, (byte) 0x50, (byte) 0x68, (byte) 0x69, (byte) 0x6c, (byte) 0x20, (byte) 0x44, (byte) 0x75, + (byte) 0x62, (byte) 0x61, (byte) 0x63, (byte) 0x68, (byte) 0xff, (byte) 0xdb, (byte) 0x0, (byte) 0x43, + (byte) 0x0, (byte) 0x6, (byte) 0x4, (byte) 0x5, (byte) 0x6, (byte) 0x5, (byte) 0x4, (byte) 0x6, + (byte) 0x6, (byte) 0x5, (byte) 0x6, (byte) 0x7, (byte) 0x7, (byte) 0x6, (byte) 0x8, (byte) 0xa, + (byte) 0x10, (byte) 0xa, (byte) 0xa, (byte) 0x9, (byte) 0x9, (byte) 0xa, (byte) 0x14, (byte) 0xe, + (byte) 0xf, (byte) 0xc, (byte) 0x10, (byte) 0x17, (byte) 0x14, (byte) 0x18, (byte) 0x18, (byte) 0x17, + (byte) 0x14, (byte) 0x16, (byte) 0x16, (byte) 0x1a, (byte) 0x1d, (byte) 0x25, (byte) 0x1f, (byte) 0x1a, + (byte) 0x1b, (byte) 0x23, (byte) 0x1c, (byte) 0x16, (byte) 0x16, (byte) 0x20, (byte) 0x2c, (byte) 0x20, + (byte) 0x23, (byte) 0x26, (byte) 0x27, (byte) 0x29, (byte) 0x2a, (byte) 0x29, (byte) 0x19, (byte) 0x1f, + (byte) 0x2d, (byte) 0x30, (byte) 0x2d, (byte) 0x28, (byte) 0x30, (byte) 0x25, (byte) 0x28, (byte) 0x29, + (byte) 0x28, (byte) 0xff, (byte) 0xdb, (byte) 0x0, (byte) 0x43, (byte) 0x1, (byte) 0x7, (byte) 0x7, + (byte) 0x7, (byte) 0xa, (byte) 0x8, (byte) 0xa, (byte) 0x13, (byte) 0xa, (byte) 0xa, (byte) 0x13, + (byte) 0x28, (byte) 0x1a, (byte) 0x16, (byte) 0x1a, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, + (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, + (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, + (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, + (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, + (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, + (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0xff, (byte) 0xc0, + (byte) 0x0, (byte) 0x11, (byte) 0x8, (byte) 0x0, (byte) 0x30, (byte) 0x0, (byte) 0x30, (byte) 0x3, + (byte) 0x1, (byte) 0x11, (byte) 0x0, (byte) 0x2, (byte) 0x11, (byte) 0x1, (byte) 0x3, (byte) 0x11, + (byte) 0x1, (byte) 0xff, (byte) 0xc4, (byte) 0x0, (byte) 0x1b, (byte) 0x0, (byte) 0x0, (byte) 0x2, + (byte) 0x2, (byte) 0x3, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x4, (byte) 0x5, + (byte) 0x6, (byte) 0x7, (byte) 0x1, (byte) 0x3, (byte) 0x8, (byte) 0x2, (byte) 0xff, (byte) 0xc4, + (byte) 0x0, (byte) 0x2e, (byte) 0x10, (byte) 0x0, (byte) 0x2, (byte) 0x2, (byte) 0x1, (byte) 0x2, + (byte) 0x4, (byte) 0x4, (byte) 0x5, (byte) 0x4, (byte) 0x3, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x2, (byte) 0x3, (byte) 0x4, (byte) 0x11, + (byte) 0x0, (byte) 0x5, (byte) 0x6, (byte) 0x12, (byte) 0x21, (byte) 0x31, (byte) 0x41, (byte) 0x51, + (byte) 0x61, (byte) 0x71, (byte) 0x7, (byte) 0x13, (byte) 0x22, (byte) 0x42, (byte) 0x91, (byte) 0x33, + (byte) 0x62, (byte) 0x81, (byte) 0xa1, (byte) 0x52, (byte) 0xd1, (byte) 0xf0, (byte) 0xff, (byte) 0xc4, + (byte) 0x0, (byte) 0x1b, (byte) 0x1, (byte) 0x0, (byte) 0x1, (byte) 0x5, (byte) 0x1, (byte) 0x1, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x6, (byte) 0x2, (byte) 0x3, (byte) 0x4, (byte) 0x5, + (byte) 0x7, (byte) 0x1, (byte) 0x0, (byte) 0xff, (byte) 0xc4, (byte) 0x0, (byte) 0x33, (byte) 0x11, + (byte) 0x0, (byte) 0x1, (byte) 0x3, (byte) 0x2, (byte) 0x4, (byte) 0x4, (byte) 0x4, (byte) 0x4, + (byte) 0x5, (byte) 0x5, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x1, (byte) 0x0, (byte) 0x2, (byte) 0x3, (byte) 0x4, (byte) 0x11, (byte) 0x5, (byte) 0x12, + (byte) 0x21, (byte) 0x31, (byte) 0x13, (byte) 0x51, (byte) 0x61, (byte) 0x71, (byte) 0x6, (byte) 0x32, + (byte) 0x41, (byte) 0x81, (byte) 0x91, (byte) 0xa1, (byte) 0xb1, (byte) 0xc1, (byte) 0x7, (byte) 0x14, + (byte) 0x42, (byte) 0xd1, (byte) 0xf0, (byte) 0x22, (byte) 0x33, (byte) 0x62, (byte) 0xa2, (byte) 0xf1, + (byte) 0xff, (byte) 0xda, (byte) 0x0, (byte) 0xc, (byte) 0x3, (byte) 0x1, (byte) 0x0, (byte) 0x2, + (byte) 0x11, (byte) 0x3, (byte) 0x11, (byte) 0x0, (byte) 0x3f, (byte) 0x0, (byte) 0xb4, (byte) 0x11, + (byte) 0xf4, (byte) 0x4c, (byte) 0xa, (byte) 0x12, (byte) 0x7b, (byte) 0x16, (byte) 0x2e, (byte) 0x5d, + (byte) 0xaf, (byte) 0x46, (byte) 0xac, (byte) 0x96, (byte) 0x6e, (byte) 0xcf, (byte) 0x1c, (byte) 0x10, + (byte) 0x46, (byte) 0x32, (byte) 0xd2, (byte) 0x48, (byte) 0xd8, (byte) 0x3, (byte) 0x48, (byte) 0x96, + (byte) 0x46, (byte) 0x44, (byte) 0xd2, (byte) 0xf7, (byte) 0x9b, (byte) 0x0, (byte) 0x91, (byte) 0x5, + (byte) 0x24, (byte) 0xd5, (byte) 0x52, (byte) 0x8, (byte) 0x60, (byte) 0x69, (byte) 0x73, (byte) 0x8e, + (byte) 0xc0, (byte) 0x6f, (byte) 0xfc, (byte) 0xfa, (byte) 0x28, (byte) 0x26, (byte) 0xe5, (byte) 0xf1, + (byte) 0x5f, (byte) 0x6b, (byte) 0x82, (byte) 0x52, (byte) 0x9b, (byte) 0x7d, (byte) 0x3b, (byte) 0x17, + (byte) 0x0, (byte) 0x38, (byte) 0xe7, (byte) 0x62, (byte) 0x22, (byte) 0x53, (byte) 0xea, (byte) 0x32, + (byte) 0x9, (byte) 0xfc, (byte) 0x81, (byte) 0xaa, (byte) 0x19, (byte) 0xfc, (byte) 0x43, (byte) 0x13, + (byte) 0xd, (byte) 0xa3, (byte) 0x69, (byte) 0x77, (byte) 0xcb, (byte) 0xf7, (byte) 0x47, (byte) 0xb4, + (byte) 0x1f, (byte) 0x86, (byte) 0x95, (byte) 0xd3, (byte) 0xb7, (byte) 0x35, (byte) 0x4c, (byte) 0xad, + (byte) 0x8f, (byte) 0xa5, (byte) 0xb3, (byte) 0x1f, (byte) 0x7d, (byte) 0x40, (byte) 0xf8, (byte) 0x12, + (byte) 0x8a, (byte) 0xd9, (byte) 0x7e, (byte) 0x26, (byte) 0x6d, (byte) 0xb7, (byte) 0x98, (byte) 0x8b, + (byte) 0x95, (byte) 0x2c, (byte) 0xd3, (byte) 0x3, (byte) 0xbc, (byte) 0x9f, (byte) 0xaa, (byte) 0x8b, + (byte) 0xee, (byte) 0x40, (byte) 0xc8, (byte) 0xfc, (byte) 0x6b, (byte) 0xb4, (byte) 0xf8, (byte) 0xfc, + (byte) 0x52, (byte) 0x7f, (byte) 0x71, (byte) 0xa5, (byte) 0xbd, (byte) 0x77, (byte) 0x1e, (byte) 0xff, + (byte) 0x0, (byte) 0xf1, (byte) 0x7b, (byte) 0x10, (byte) 0xfc, (byte) 0x34, (byte) 0xc4, (byte) 0x29, + (byte) 0x9b, (byte) 0x9e, (byte) 0x9a, (byte) 0x46, (byte) 0xcb, (byte) 0xd3, (byte) 0xca, (byte) 0xef, + (byte) 0x6b, (byte) 0x92, (byte) 0xf, (byte) 0xc4, (byte) 0x29, (byte) 0xd4, (byte) 0x13, (byte) 0x47, + (byte) 0x62, (byte) 0x14, (byte) 0x9a, (byte) 0x9, (byte) 0x12, (byte) 0x58, (byte) 0x9c, (byte) 0x73, + (byte) 0x2b, (byte) 0xa1, (byte) 0x4, (byte) 0x30, (byte) 0xf3, (byte) 0x7, (byte) 0x57, (byte) 0xac, + (byte) 0x7b, (byte) 0x5e, (byte) 0xd0, (byte) 0xe6, (byte) 0x9b, (byte) 0x82, (byte) 0x80, (byte) 0x24, + (byte) 0x82, (byte) 0x48, (byte) 0x1e, (byte) 0x62, (byte) 0x95, (byte) 0xa5, (byte) 0xae, (byte) 0x1a, + (byte) 0x10, (byte) 0x45, (byte) 0x88, (byte) 0x3d, (byte) 0x42, (byte) 0xf7, (byte) 0x83, (byte) 0xae, + (byte) 0xdd, (byte) 0x75, (byte) 0xa1, (byte) 0x2, (byte) 0xd2, (byte) 0x47, (byte) 0x1a, (byte) 0x33, + (byte) 0xbb, (byte) 0x5, (byte) 0x45, (byte) 0x5, (byte) 0x99, (byte) 0x89, (byte) 0xc0, (byte) 0x0, + (byte) 0x77, (byte) 0x27, (byte) 0x49, (byte) 0xce, (byte) 0x0, (byte) 0xb9, (byte) 0x53, (byte) 0xcc, + (byte) 0x2e, (byte) 0x71, (byte) 0xb0, (byte) 0x17, (byte) 0x25, (byte) 0x73, (byte) 0xff, (byte) 0x0, + (byte) 0x1d, (byte) 0x71, (byte) 0x54, (byte) 0xfc, (byte) 0x4f, (byte) 0xba, (byte) 0x30, (byte) 0x46, + (byte) 0x64, (byte) 0xdb, (byte) 0x21, (byte) 0x62, (byte) 0x2b, (byte) 0xc5, (byte) 0xdb, (byte) 0x3f, + (byte) 0xbd, (byte) 0x87, (byte) 0xf9, (byte) 0x1f, (byte) 0xe8, (byte) 0x74, (byte) 0xf3, (byte) 0xc8, + (byte) 0x46, (byte) 0x25, (byte) 0x5e, (byte) 0xea, (byte) 0xb9, (byte) 0x3f, (byte) 0xc4, (byte) 0x6c, + (byte) 0x3e, (byte) 0xeb, (byte) 0x6d, (byte) 0xf0, (byte) 0xbf, (byte) 0x87, (byte) 0xa3, (byte) 0xc2, + (byte) 0xa0, (byte) 0x5, (byte) 0xc2, (byte) 0xf2, (byte) 0xbb, (byte) 0xcc, (byte) 0x7e, (byte) 0xc3, + (byte) 0xa0, (byte) 0xf9, (byte) 0x9d, (byte) 0x79, (byte) 0x59, (byte) 0xa, (byte) 0x2e, (byte) 0x7, + (byte) 0x4d, (byte) 0x54, (byte) 0x92, (byte) 0x8c, (byte) 0xd8, (byte) 0xdb, (byte) 0x29, (byte) 0x1f, + (byte) 0xe, (byte) 0x55, (byte) 0xbc, (byte) 0x86, (byte) 0x69, (byte) 0xea, (byte) 0x30, (byte) 0xc, + (byte) 0x22, (byte) 0x62, (byte) 0x63, (byte) 0x75, (byte) 0x24, (byte) 0x48, (byte) 0x83, (byte) 0xbe, + (byte) 0x7d, (byte) 0x3b, (byte) 0x75, (byte) 0x3e, (byte) 0x24, (byte) 0xe, (byte) 0xe4, (byte) 0x69, + (byte) 0xe8, (byte) 0xc, (byte) 0x8c, (byte) 0xbb, (byte) 0xd8, (byte) 0xa2, (byte) 0x56, (byte) 0x54, + (byte) 0xd3, (byte) 0x87, (byte) 0x32, (byte) 0x9, (byte) 0x4e, (byte) 0xae, (byte) 0x3a, (byte) 0x5b, + (byte) 0xd3, (byte) 0xaa, (byte) 0x7f, (byte) 0xc0, (byte) 0x7c, (byte) 0x5e, (byte) 0xdb, (byte) 0x2d, + (byte) 0xd1, (byte) 0x5, (byte) 0xd9, (byte) 0x11, (byte) 0x36, (byte) 0xb9, (byte) 0x64, (byte) 0xc3, + (byte) 0x87, (byte) 0x6c, (byte) 0x8, (byte) 0x89, (byte) 0xfb, (byte) 0x86, (byte) 0x7b, (byte) 0xf, + (byte) 0x3d, (byte) 0x59, (byte) 0xe1, (byte) 0x38, (byte) 0x8b, (byte) 0xa0, (byte) 0x7e, (byte) 0x43, + (byte) 0xe5, (byte) 0x3e, (byte) 0x9c, (byte) 0xba, (byte) 0xa1, (byte) 0x6f, (byte) 0x1b, (byte) 0x78, + (byte) 0x6e, (byte) 0x9a, (byte) 0xbe, (byte) 0x98, (byte) 0xd5, (byte) 0x5c, (byte) 0x36, (byte) 0x66, + (byte) 0xd, (byte) 0x9, (byte) 0xb0, (byte) 0xcd, (byte) 0x6f, (byte) 0xd2, (byte) 0x6f, (byte) 0xfe, + (byte) 0xbc, (byte) 0x8f, (byte) 0x4b, (byte) 0xab, (byte) 0xa6, (byte) 0xad, (byte) 0x9a, (byte) 0xf7, + (byte) 0x2b, (byte) 0xa4, (byte) 0xf4, (byte) 0xe7, (byte) 0x86, (byte) 0xc4, (byte) 0xf, (byte) 0xd5, + (byte) 0x65, (byte) 0x85, (byte) 0xc3, (byte) 0xab, (byte) 0x7b, (byte) 0x11, (byte) 0xd0, (byte) 0xe8, + (byte) 0xc5, (byte) 0xaf, (byte) 0xe, (byte) 0x17, (byte) 0x69, (byte) 0xba, (byte) 0xc2, (byte) 0xf2, + (byte) 0x16, (byte) 0x9b, (byte) 0x38, (byte) 0x59, (byte) 0x40, (byte) 0x78, (byte) 0xd6, (byte) 0xf3, + (byte) 0xa7, (byte) 0x8, (byte) 0xee, (byte) 0xe6, (byte) 0x33, (byte) 0xf5, (byte) 0x1a, (byte) 0xec, + (byte) 0xbd, (byte) 0x3c, (byte) 0x8f, (byte) 0x43, (byte) 0xfd, (byte) 0x13, (byte) 0xaa, (byte) 0xea, + (byte) 0xd9, (byte) 0x4f, (byte) 0x1, (byte) 0xe0, (byte) 0x72, (byte) 0x45, (byte) 0x78, (byte) 0x4c, + (byte) 0x2d, (byte) 0xfc, (byte) 0xf4, (byte) 0x39, (byte) 0xb6, (byte) 0xcc, (byte) 0x3e, (byte) 0x5b, + (byte) 0x7c, (byte) 0xd5, (byte) 0xb, (byte) 0x59, (byte) 0xb3, (byte) 0xa0, (byte) 0xd7, (byte) 0x85, + (byte) 0xb5, (byte) 0x53, (byte) 0x3e, (byte) 0xe9, (byte) 0xe6, (byte) 0xc6, (byte) 0x6a, (byte) 0x35, + (byte) 0xe4, (byte) 0x5d, (byte) 0xc1, (byte) 0x9d, (byte) 0x6b, (byte) 0xb0, (byte) 0x21, (byte) 0x9a, + (byte) 0x3c, (byte) 0x64, (byte) 0x7a, (byte) 0x8c, (byte) 0xe9, (byte) 0xa6, (byte) 0xe5, (byte) 0x7, + (byte) 0xfa, (byte) 0xb6, (byte) 0x53, (byte) 0xe5, (byte) 0x74, (byte) 0x9c, (byte) 0x33, (byte) 0xc2, + (byte) 0xf3, (byte) 0x75, (byte) 0x5b, (byte) 0xa5, (byte) 0xdf, (byte) 0x61, (byte) 0xda, (byte) 0x4f, + (byte) 0xc9, (byte) 0xb7, (byte) 0x3d, (byte) 0xc6, (byte) 0x4b, (byte) 0x32, (byte) 0x34, (byte) 0xb, + (byte) 0x65, (byte) 0x47, (byte) 0x53, (byte) 0x0, (byte) 0xc1, (byte) 0x18, (byte) 0xcf, (byte) 0x7f, + (byte) 0xbb, (byte) 0xa7, (byte) 0x99, (byte) 0xf5, (byte) 0x3a, (byte) 0x71, (byte) 0xb1, (byte) 0x49, + (byte) 0x35, (byte) 0xf2, (byte) 0x1d, (byte) 0x96, (byte) 0x6f, (byte) 0x8d, (byte) 0x62, (byte) 0x2f, + (byte) 0xa2, (byte) 0xc5, (byte) 0x44, (byte) 0xf1, (byte) 0x58, (byte) 0x90, (byte) 0xdb, (byte) 0x5b, + (byte) 0x70, (byte) 0xe, (byte) 0xbb, (byte) 0xf5, (byte) 0x6, (byte) 0xc5, (byte) 0x19, (byte) 0xc5, + (byte) 0xd4, (byte) 0xf6, (byte) 0xad, (byte) 0xbe, (byte) 0x18, (byte) 0x2d, (byte) 0x52, (byte) 0x13, + (byte) 0xd9, (byte) 0x2e, (byte) 0x3, (byte) 0x27, (byte) 0x2c, (byte) 0x79, (byte) 0x3c, (byte) 0x84, + (byte) 0x2, (byte) 0xf, (byte) 0x29, (byte) 0x39, (byte) 0xd, (byte) 0xea, (byte) 0x7d, (byte) 0x3b, + (byte) 0x75, (byte) 0xcb, (byte) 0x70, (byte) 0xe7, (byte) 0x75, (byte) 0xe2, (byte) 0x6, (byte) 0xdc, + (byte) 0xfd, (byte) 0x2, (byte) 0x8d, (byte) 0x84, (byte) 0xe2, (byte) 0x74, (byte) 0xfc, (byte) 0x73, + (byte) 0x55, (byte) 0x5d, (byte) 0x1b, (byte) 0xa6, (byte) 0x94, (byte) 0xed, (byte) 0xb1, (byte) 0xb7, + (byte) 0x60, (byte) 0x4f, (byte) 0xc3, (byte) 0x4d, (byte) 0x3d, (byte) 0x2, (byte) 0xb9, (byte) 0xf8, + (byte) 0x3, (byte) 0x88, (byte) 0xdb, (byte) 0x88, (byte) 0xf6, (byte) 0x48, (byte) 0x67, (byte) 0x6d, + (byte) 0xaf, (byte) 0x72, (byte) 0xa5, (byte) 0xcb, (byte) 0x1a, (byte) 0xab, (byte) 0x49, (byte) 0x6e, + (byte) 0x25, (byte) 0x45, (byte) 0x99, (byte) 0x80, (byte) 0xc3, (byte) 0x14, (byte) 0xc3, (byte) 0x12, + (byte) 0x46, (byte) 0x41, (byte) 0xee, (byte) 0x6, (byte) 0x8f, (byte) 0x68, (byte) 0xe7, (byte) 0x32, + (byte) 0xc4, (byte) 0xd2, (byte) 0x79, (byte) 0x6f, (byte) 0xe8, (byte) 0x4a, (byte) 0x2, (byte) 0xc5, + (byte) 0x29, (byte) 0x44, (byte) 0x15, (byte) 0x52, (byte) 0x34, (byte) 0x2, (byte) 0xd1, (byte) 0x72, + (byte) 0x43, (byte) 0x48, (byte) 0xb1, (byte) 0x0, (byte) 0xea, (byte) 0x1, (byte) 0x1d, (byte) 0x88, + (byte) 0x49, (byte) 0xae, (byte) 0xc0, (byte) 0x96, (byte) 0xea, (byte) 0x4f, (byte) 0x5a, (byte) 0x6f, + (byte) 0xd2, (byte) 0x9a, (byte) 0x36, (byte) 0x8d, (byte) 0xbd, (byte) 0x88, (byte) 0xc1, (byte) 0xd4, + (byte) 0x77, (byte) 0x8c, (byte) 0xcd, (byte) 0x2d, (byte) 0x3e, (byte) 0xaa, (byte) 0xce, (byte) 0x37, + (byte) 0x18, (byte) 0x9e, (byte) 0x24, (byte) 0x6e, (byte) 0xe0, (byte) 0xdf, (byte) 0xe0, (byte) 0xb9, + (byte) 0xfa, (byte) 0x4a, (byte) 0xf3, (byte) 0x50, (byte) 0xbd, (byte) 0x3d, (byte) 0x4b, (byte) 0x0, + (byte) 0xac, (byte) 0xd0, (byte) 0xb9, (byte) 0x46, (byte) 0x1e, (byte) 0xa3, (byte) 0xc7, (byte) 0xdb, + (byte) 0x42, (byte) 0xd3, (byte) 0x30, (byte) 0xb4, (byte) 0x90, (byte) 0x56, (byte) 0xaf, (byte) 0x86, + (byte) 0xd4, (byte) 0x89, (byte) 0x58, (byte) 0x1e, (byte) 0xd3, (byte) 0xa1, (byte) 0x4c, (byte) 0x76, + (byte) 0xe1, (byte) 0x1b, (byte) 0xdc, (byte) 0x84, (byte) 0xd9, (byte) 0x23, (byte) 0xe4, (byte) 0x2b, + (byte) 0x7, (byte) 0x91, (byte) 0x73, (byte) 0x8e, (byte) 0x65, (byte) 0x1d, (byte) 0x48, (byte) 0xf7, + (byte) 0x20, (byte) 0x11, (byte) 0xfc, (byte) 0xea, (byte) 0x31, (byte) 0xd1, (byte) 0x59, (byte) 0x55, + (byte) 0x36, (byte) 0x69, (byte) 0x20, (byte) 0x73, (byte) 0x62, (byte) 0x75, (byte) 0x9c, (byte) 0x74, + (byte) 0x1d, (byte) 0x2f, (byte) 0xa5, (byte) 0xfd, (byte) 0xb7, (byte) 0xf6, (byte) 0x52, (byte) 0x7b, + (byte) 0xd3, (byte) 0x52, (byte) 0xde, (byte) 0x52, (byte) 0x2b, (byte) 0x97, (byte) 0xab, (byte) 0x6, + (byte) 0x44, (byte) 0x95, (byte) 0x5a, (byte) 0x34, (byte) 0xce, (byte) 0x3e, (byte) 0x5a, (byte) 0x82, + (byte) 0xa0, (byte) 0x9f, (byte) 0xe, (byte) 0xfd, (byte) 0x7d, (byte) 0x87, (byte) 0xe7, (byte) 0x4c, + (byte) 0xc, (byte) 0xf1, (byte) 0x13, (byte) 0xc2, (byte) 0x36, (byte) 0xb8, (byte) 0x59, (byte) 0xdc, + (byte) 0xf8, (byte) 0x23, (byte) 0xdd, (byte) 0x59, (byte) 0x25, (byte) 0x2d, (byte) 0x35, (byte) 0xdd, + (byte) 0xc3, (byte) 0x0, (byte) 0x9e, (byte) 0xa7, (byte) 0x7b, (byte) 0x77, (byte) 0x20, (byte) 0xe9, + (byte) 0xd9, (byte) 0x1, (byte) 0x7e, (byte) 0xed, (byte) 0xcd, (byte) 0xd4, (byte) 0xc5, (byte) 0x16, + (byte) 0xcc, (byte) 0xcb, (byte) 0x60, (byte) 0xca, (byte) 0xe1, (byte) 0xd, (byte) 0x76, (byte) 0x24, + (byte) 0x16, (byte) 0x70, (byte) 0x70, (byte) 0x1, (byte) 0xfd, (byte) 0xd8, (byte) 0xc7, (byte) 0x5f, + (byte) 0x51, (byte) 0x9e, (byte) 0xd8, (byte) 0xd3, (byte) 0xd1, (byte) 0x42, (byte) 0x1, (byte) 0x11, + (byte) 0xbe, (byte) 0xf7, (byte) 0x3c, (byte) 0xb9, (byte) 0xfd, (byte) 0xd5, (byte) 0x9e, (byte) 0xd, + (byte) 0x1d, (byte) 0x4c, (byte) 0x14, (byte) 0xe7, (byte) 0x10, (byte) 0xa0, (byte) 0x94, (byte) 0x59, + (byte) 0xb7, (byte) 0xce, (byte) 0xc7, (byte) 0xed, (byte) 0xa6, (byte) 0xfa, (byte) 0xfa, (byte) 0x5c, + (byte) 0x6b, (byte) 0xe9, (byte) 0xd4, (byte) 0x9b, (byte) 0x2b, (byte) 0xe3, (byte) 0x82, (byte) 0x23, + (byte) 0x9a, (byte) 0xaf, (byte) 0xc, (byte) 0xd1, (byte) 0xa9, (byte) 0x6a, (byte) 0x8c, (byte) 0xd4, + (byte) 0x6c, (byte) 0x57, (byte) 0x4f, (byte) 0x97, (byte) 0x24, (byte) 0x32, (byte) 0xb2, (byte) 0x3f, + (byte) 0xd5, (byte) 0xdc, (byte) 0xb0, (byte) 0x64, (byte) 0x24, (byte) 0x15, (byte) 0x24, (byte) 0x92, + (byte) 0xe, (byte) 0x7f, (byte) 0x81, (byte) 0xa3, (byte) 0x8a, (byte) 0x48, (byte) 0xf8, (byte) 0x10, + (byte) 0xb6, (byte) 0x2e, (byte) 0x4b, (byte) 0x3c, (byte) 0xc5, (byte) 0xaa, (byte) 0xce, (byte) 0x21, + (byte) 0x5b, (byte) 0x25, (byte) 0x5b, (byte) 0xbf, (byte) 0x59, (byte) 0xbf, (byte) 0x61, (byte) 0xb0, + (byte) 0x1e, (byte) 0xc0, (byte) 0x4, (byte) 0xbe, (byte) 0x6a, (byte) 0xf9, (byte) 0xce, (byte) 0x35, + (byte) 0xe7, (byte) 0x35, (byte) 0x4b, (byte) 0x50, (byte) 0xe, (byte) 0x3c, (byte) 0xe1, (byte) 0x64, + (byte) 0xdc, (byte) 0xe5, (byte) 0x4b, (byte) 0x35, (byte) 0xf1, (byte) 0x15, (byte) 0xe0, (byte) 0x30, + (byte) 0x5b, (byte) 0xc2, (byte) 0x41, (byte) 0xe0, (byte) 0x1b, (byte) 0xfd, (byte) 0xff, (byte) 0x0, + (byte) 0xc2, (byte) 0xae, (byte) 0xae, (byte) 0x97, (byte) 0x89, (byte) 0xa8, (byte) 0xdd, (byte) 0x5d, + (byte) 0x61, (byte) 0x38, (byte) 0xb3, (byte) 0xa8, (byte) 0x8e, (byte) 0x57, (byte) 0x6a, (byte) 0xcf, + (byte) 0xa7, (byte) 0x6f, (byte) 0xd9, (byte) 0x40, (byte) 0xdf, (byte) 0x68, (byte) 0xdc, (byte) 0xab, + (byte) 0x37, (byte) 0x24, (byte) 0xd4, (byte) 0xa6, (byte) 0x38, (byte) 0xf1, (byte) 0x45, (byte) 0xe7, + (byte) 0x1f, (byte) 0x91, (byte) 0xaa, (byte) 0x39, (byte) 0x29, (byte) 0x65, (byte) 0x6e, (byte) 0xed, + (byte) 0x5a, (byte) 0x15, (byte) 0x1e, (byte) 0x37, (byte) 0x47, (byte) 0x30, (byte) 0xd2, (byte) 0x40, + (byte) 0x3b, (byte) 0x9b, (byte) 0x7d, (byte) 0x53, (byte) 0x3d, (byte) 0xaf, (byte) 0x67, (byte) 0xdd, + (byte) 0xf7, (byte) 0x14, (byte) 0x58, (byte) 0xaa, (byte) 0xd1, (byte) 0x9d, (byte) 0xd5, (byte) 0x49, + (byte) 0xc1, (byte) 0x65, (byte) 0xe5, (byte) 0x51, (byte) 0x9c, (byte) 0x7d, (byte) 0xc7, (byte) 0x3, + (byte) 0xc3, (byte) 0x4d, (byte) 0xb2, (byte) 0x92, (byte) 0x69, (byte) 0x8d, (byte) 0x98, (byte) 0xd2, + (byte) 0xa4, (byte) 0x49, (byte) 0x89, (byte) 0x61, (byte) 0x94, (byte) 0xf, (byte) 0x7d, (byte) 0x44, + (byte) 0x92, (byte) 0x0, (byte) 0xe7, (byte) 0xda, (byte) 0xfa, (byte) 0xdc, (byte) 0x9b, (byte) 0x6d, + (byte) 0xa0, (byte) 0xb9, (byte) 0x56, (byte) 0x47, (byte) 0x5, (byte) 0xf0, (byte) 0x2c, (byte) 0x5b, + (byte) 0x4d, (byte) 0x94, (byte) 0xdc, (byte) 0x37, (byte) 0x7, (byte) 0xf9, (byte) 0x97, (byte) 0x81, + (byte) 0xe6, (byte) 0x54, (byte) 0x89, (byte) 0x8a, (byte) 0xa2, (byte) 0x1f, (byte) 0x33, (byte) 0x8c, + (byte) 0x73, (byte) 0x1f, (byte) 0x7e, (byte) 0x9d, (byte) 0x4f, (byte) 0x7d, (byte) 0x5f, (byte) 0xd1, + (byte) 0x61, (byte) 0xdc, (byte) 0x1b, (byte) 0x3e, (byte) 0x53, (byte) 0x72, (byte) 0x36, (byte) 0x1c, + (byte) 0xbf, (byte) 0x9f, (byte) 0xe, (byte) 0xeb, (byte) 0x3a, (byte) 0xc7, (byte) 0xf1, (byte) 0xf8, + (byte) 0xab, (byte) 0x9e, (byte) 0xf6, (byte) 0xd1, (byte) 0x47, (byte) 0x90, (byte) 0x3b, (byte) 0xcc, + (byte) 0xed, (byte) 0x8b, (byte) 0xfb, (byte) 0x81, (byte) 0xa5, (byte) 0xbb, (byte) 0xdc, (byte) 0xf6, + (byte) 0xd4, (byte) 0x2b, (byte) 0x1e, (byte) 0x26, (byte) 0xe6, (byte) 0x41, (byte) 0x9e, (byte) 0xfa, + (byte) 0xb8, (byte) 0xe, (byte) 0xb8, (byte) 0x41, (byte) 0xce, (byte) 0x65, (byte) 0x8a, (byte) 0x5, + (byte) 0xea, (byte) 0x83, (byte) 0xe1, (byte) 0xa7, (byte) 0x4b, (byte) 0x41, (byte) 0x56, (byte) 0x65, + (byte) 0x2d, (byte) 0xbb, (byte) 0xb7, (byte) 0x7, (byte) 0x90, (byte) 0x12, (byte) 0x3c, (byte) 0x34, + (byte) 0xc3, (byte) 0xa3, (byte) 0xd5, (byte) 0x26, (byte) 0xeb, (byte) 0x4c, (byte) 0x5b, (byte) 0x6c, + (byte) 0x68, (byte) 0x73, (byte) 0xca, (byte) 0x33, (byte) 0xa4, (byte) 0xf0, (byte) 0xc0, (byte) 0x49, + (byte) 0x25, (byte) 0x1f, (byte) 0x14, (byte) 0x41, (byte) 0x40, (byte) 0xd7, (byte) 0x53, (byte) 0x64, + (byte) 0x22, (byte) 0x54, (byte) 0x79, (byte) 0x69, (byte) 0x4, (byte) 0xaf, (byte) 0x6, (byte) 0xa2, + (byte) 0xe2, (byte) 0xfa, (byte) 0x53, (byte) 0xd7, (byte) 0x5d, (byte) 0x1a, (byte) 0x4, (byte) 0xd3, + (byte) 0x85, (byte) 0xca, (byte) 0xff, (byte) 0xd9, (byte) 0x50, (byte) 0x4b, (byte) 0x1, (byte) 0x2, + (byte) 0xa, (byte) 0x0, (byte) 0xa, (byte) 0x0, (byte) 0x0, (byte) 0x8, (byte) 0x0, (byte) 0x0, + (byte) 0x37, (byte) 0xa4, (byte) 0x5c, (byte) 0x38, (byte) 0x52, (byte) 0x69, (byte) 0x4c, (byte) 0x69, + (byte) 0x24, (byte) 0x6, (byte) 0x0, (byte) 0x0, (byte) 0x24, (byte) 0x6, (byte) 0x0, (byte) 0x0, + (byte) 0x1b, (byte) 0x0, (byte) 0x7, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x72, (byte) 0x65, (byte) 0x73, (byte) 0x2f, (byte) 0x64, (byte) 0x72, + (byte) 0x61, (byte) 0x77, (byte) 0x61, (byte) 0x62, (byte) 0x6c, (byte) 0x65, (byte) 0x2f, (byte) 0x73, + (byte) 0x69, (byte) 0x7a, (byte) 0x65, (byte) 0x5f, (byte) 0x34, (byte) 0x38, (byte) 0x78, (byte) 0x34, + (byte) 0x38, (byte) 0x2e, (byte) 0x6a, (byte) 0x70, (byte) 0x67, (byte) 0xfe, (byte) 0xca, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x5, (byte) 0x6, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x1, (byte) 0x0, + (byte) 0x50, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x64, (byte) 0x6, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, + }; + + /* + * Jar file created by Apache Commons-Compress which creates + * a CEN entry with a Zip64 extra header entry with a size of 0 + * ----------------#1-------------------- + * [Central Directory Header] + * 0x52b: Signature : 0x02014b50 + * 0x52f: Created Zip Spec : 0x2d [4.5] + * 0x530: Created OS : 0x3 [UNIX] + * 0x531: VerMadeby : 0x32d [3, 4.5] + * 0x532: VerExtract : 0x2d [4.5] + * 0x533: Flag : 0x800 + * 0x535: Method : 0x0 [STORED] + * 0x537: Last Mod Time : 0x570169c0 [Tue Aug 01 13:14:00 EDT 2023] + * 0x53b: CRC : 0x0 + * 0x53f: Compressed Size : 0x0 + * 0x543: Uncompressed Size: 0x0 + * 0x547: Name Length : 0x9 + * 0x549: Extra Length : 0x8 + * [tag=0x0001, sz=0, data= ] + * ->ZIP64: + * [tag=0xcafe, sz=0, data= ] + * ->[tag=cafe, size=0] + * 0x54b: Comment Length : 0x0 + * 0x54d: Disk Start : 0x0 + * 0x54f: Attrs : 0x0 + * 0x551: AttrsEx : 0x41ed0010 + * 0x555: Loc Header Offset: 0x0 + * 0x559: File Name : META-INF/ + */ + public static byte[] COMMONS_COMPRESS_JAR = { + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x8, + (byte) 0x0, (byte) 0x0, (byte) 0xc0, (byte) 0x69, (byte) 0x1, (byte) 0x57, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0x9, (byte) 0x0, (byte) 0x18, (byte) 0x0, (byte) 0x4d, (byte) 0x45, + (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0x1, + (byte) 0x0, (byte) 0x10, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xfe, (byte) 0xca, (byte) 0x0, (byte) 0x0, (byte) 0x50, + (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x8, (byte) 0x8, + (byte) 0x0, (byte) 0xbd, (byte) 0x69, (byte) 0x1, (byte) 0x57, (byte) 0x71, (byte) 0xa7, (byte) 0x16, + (byte) 0x53, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0x14, (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x4d, (byte) 0x45, (byte) 0x54, + (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0x4d, (byte) 0x41, + (byte) 0x4e, (byte) 0x49, (byte) 0x46, (byte) 0x45, (byte) 0x53, (byte) 0x54, (byte) 0x2e, (byte) 0x4d, + (byte) 0x46, (byte) 0x1, (byte) 0x0, (byte) 0x10, (byte) 0x0, (byte) 0x68, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x5b, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xf3, (byte) 0x4d, (byte) 0xcc, + (byte) 0xcb, (byte) 0x4c, (byte) 0x4b, (byte) 0x2d, (byte) 0x2e, (byte) 0xd1, (byte) 0xd, (byte) 0x4b, + (byte) 0x2d, (byte) 0x2a, (byte) 0xce, (byte) 0xcc, (byte) 0xcf, (byte) 0xb3, (byte) 0x52, (byte) 0x30, + (byte) 0xd4, (byte) 0x33, (byte) 0xe0, (byte) 0xe5, (byte) 0x72, (byte) 0xcc, (byte) 0x43, (byte) 0x12, + (byte) 0x71, (byte) 0x2c, (byte) 0x48, (byte) 0x4c, (byte) 0xce, (byte) 0x48, (byte) 0x55, (byte) 0x0, + (byte) 0x8a, (byte) 0x1, (byte) 0x25, (byte) 0xd, (byte) 0xd, (byte) 0xf4, (byte) 0x2c, (byte) 0x78, + (byte) 0xb9, (byte) 0x9c, (byte) 0x8b, (byte) 0x52, (byte) 0x13, (byte) 0x4b, (byte) 0x52, (byte) 0x53, + (byte) 0x74, (byte) 0x9d, (byte) 0x2a, (byte) 0x81, (byte) 0x1a, (byte) 0x2c, (byte) 0xf4, (byte) 0xc, + (byte) 0xf4, (byte) 0x80, (byte) 0x12, (byte) 0xda, (byte) 0x46, (byte) 0xba, (byte) 0x66, (byte) 0xa, + (byte) 0x1a, (byte) 0xfe, (byte) 0x45, (byte) 0x89, (byte) 0xc9, (byte) 0x39, (byte) 0xa9, (byte) 0xa, + (byte) 0xce, (byte) 0xf9, (byte) 0x45, (byte) 0x5, (byte) 0xf9, (byte) 0x45, (byte) 0x89, (byte) 0x25, + (byte) 0x40, (byte) 0x3, (byte) 0x34, (byte) 0x79, (byte) 0xb9, (byte) 0x78, (byte) 0xb9, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0x61, (byte) 0x69, (byte) 0x1, (byte) 0x57, (byte) 0x16, (byte) 0x64, + (byte) 0x9c, (byte) 0xc5, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0x19, (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x5a, (byte) 0x69, + (byte) 0x70, (byte) 0x46, (byte) 0x69, (byte) 0x6c, (byte) 0x65, (byte) 0x50, (byte) 0x72, (byte) 0x6f, + (byte) 0x70, (byte) 0x65, (byte) 0x72, (byte) 0x74, (byte) 0x79, (byte) 0x54, (byte) 0x65, (byte) 0x73, + (byte) 0x74, (byte) 0x2e, (byte) 0x63, (byte) 0x6c, (byte) 0x61, (byte) 0x73, (byte) 0x73, (byte) 0x1, + (byte) 0x0, (byte) 0x10, (byte) 0x0, (byte) 0xf, (byte) 0x7, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x4, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x85, (byte) 0x55, (byte) 0xcf, (byte) 0x53, (byte) 0xdb, + (byte) 0x46, (byte) 0x14, (byte) 0xfe, (byte) 0xd6, (byte) 0x3f, (byte) 0x90, (byte) 0x2d, (byte) 0x8b, + (byte) 0x38, (byte) 0x36, (byte) 0x21, (byte) 0xc1, (byte) 0x34, (byte) 0x4, (byte) 0x12, (byte) 0x70, + (byte) 0x63, (byte) 0xb0, (byte) 0x8d, (byte) 0xdb, (byte) 0x42, (byte) 0xd3, (byte) 0x36, (byte) 0xa6, + (byte) 0xf9, (byte) 0x45, (byte) 0x42, (byte) 0xb, (byte) 0x35, (byte) 0xe0, (byte) 0x62, (byte) 0x87, + (byte) 0xd4, (byte) 0xa4, (byte) 0x6d, (byte) 0x22, (byte) 0xdb, (byte) 0x4a, (byte) 0x22, (byte) 0x2a, + (byte) 0x4b, (byte) 0x1a, (byte) 0x49, (byte) 0x2e, (byte) 0x49, (byte) 0x67, (byte) 0x7a, (byte) 0xe8, + (byte) 0x4c, (byte) 0xcf, (byte) 0x9d, (byte) 0x69, (byte) 0xfe, (byte) 0x82, (byte) 0xde, (byte) 0x38, + (byte) 0xf5, (byte) 0x40, (byte) 0xe, (byte) 0x86, (byte) 0x94, (byte) 0x49, (byte) 0x73, (byte) 0xcb, + (byte) 0x21, (byte) 0xff, (byte) 0x51, (byte) 0x2f, (byte) 0xa5, (byte) 0x6f, (byte) 0x25, (byte) 0xc0, + (byte) 0x86, (byte) 0x98, (byte) 0x29, (byte) 0xcc, (byte) 0x68, (byte) 0x77, (byte) 0xdf, (byte) 0xee, + (byte) 0xf7, (byte) 0xbd, (byte) 0xf7, (byte) 0xbe, (byte) 0xf7, (byte) 0x76, (byte) 0xfd, (byte) 0xf6, + (byte) 0xdf, (byte) 0xbf, (byte) 0xfe, (byte) 0x6, (byte) 0x70, (byte) 0xb, (byte) 0xf, (byte) 0x45, + (byte) 0xf8, (byte) 0xe0, (byte) 0x17, (byte) 0x10, (byte) 0x90, (byte) 0x10, (byte) 0x44, (byte) 0xf, + (byte) 0xc3, (byte) 0xe9, (byte) 0x75, (byte) 0xf9, (byte) 0x47, (byte) 0x39, (byte) 0xa7, (byte) 0xc9, + (byte) 0xfa, (byte) 0xe3, (byte) 0xdc, (byte) 0x72, (byte) 0x75, (byte) 0x5d, (byte) 0xa9, (byte) 0x39, + (byte) 0xc, (byte) 0x3d, (byte) 0x33, (byte) 0xaa, (byte) 0xae, (byte) 0x3a, (byte) 0xd7, (byte) 0x18, + (byte) 0xfc, (byte) 0xa9, (byte) 0xf1, (byte) 0x55, (byte) 0x1, (byte) 0x21, (byte) 0x86, (byte) 0xbe, + (byte) 0x35, (byte) 0xd5, (byte) 0x9c, (byte) 0x53, (byte) 0x35, (byte) 0xa5, (byte) 0x68, (byte) 0x19, + (byte) 0xa6, (byte) 0x62, (byte) 0x39, (byte) 0xcf, (byte) 0xca, (byte) 0x8a, (byte) 0xed, (byte) 0x88, + (byte) 0x10, (byte) 0xe0, (byte) 0xe7, (byte) 0x9f, (byte) 0x88, (byte) 0x4, (byte) 0x89, (byte) 0x33, + (byte) 0x9d, (byte) 0xb2, (byte) 0x14, (byte) 0xb9, (byte) 0x5e, (byte) 0x52, (byte) 0xf5, (byte) 0xc7, + (byte) 0x9a, (byte) 0xc2, (byte) 0xcf, (byte) 0xa, (byte) 0x38, (byte) 0xc5, (byte) 0xd0, (byte) 0xef, + (byte) 0xb2, (byte) 0x37, (byte) 0x1d, (byte) 0x55, (byte) 0xcb, (byte) 0xfd, (byte) 0xa4, (byte) 0x9a, + (byte) 0xb9, (byte) 0x7d, (byte) 0x9a, (byte) 0x10, (byte) 0x4e, (byte) 0x33, (byte) 0x64, (byte) 0x72, + (byte) 0x77, (byte) 0x6d, (byte) 0xc5, (byte) 0xb2, (byte) 0x73, (byte) 0xda, (byte) 0xba, (byte) 0xac, + (byte) 0xd7, (byte) 0xf9, (byte) 0xe4, (byte) 0xb6, (byte) 0xb1, (byte) 0xa1, (byte) 0x6b, (byte) 0x86, + (byte) 0x5c, (byte) 0xb7, (byte) 0x73, (byte) 0x1b, (byte) 0xb5, (byte) 0x29, (byte) 0xab, (byte) 0x6e, + (byte) 0xca, (byte) 0xe4, (byte) 0x48, (byte) 0x53, (byte) 0xab, (byte) 0xf6, (byte) 0xe4, (byte) 0xba, + (byte) 0x6c, (byte) 0x89, (byte) 0xe8, (byte) 0x45, (byte) 0x9c, (byte) 0x47, (byte) 0xdc, (byte) 0x47, + (byte) 0x9c, (byte) 0xa9, (byte) 0x42, (byte) 0x3b, (byte) 0xe6, (byte) 0x92, (byte) 0x63, (byte) 0x91, + (byte) 0xc7, (byte) 0xfc, (byte) 0xf8, (byte) 0x6a, (byte) 0x18, (byte) 0xfd, (byte) 0x38, (byte) 0x2b, + (byte) 0xe0, (byte) 0x9c, (byte) 0x84, (byte) 0x1, (byte) 0x24, (byte) 0x8e, (byte) 0xa4, (byte) 0x55, + (byte) 0x7a, (byte) 0x66, (byte) 0x3b, (byte) 0x4a, (byte) 0x83, (byte) 0xb2, (byte) 0x31, (byte) 0x9a, + (byte) 0x94, (byte) 0x5c, (byte) 0xbf, (byte) 0x7, (byte) 0x56, (byte) 0x8d, (byte) 0x5c, (byte) 0x91, + (byte) 0x90, (byte) 0xe, (byte) 0xe1, (byte) 0x15, (byte) 0xb9, (byte) 0x91, (byte) 0xf, (byte) 0xe1, + (byte) 0x3d, (byte) 0xc2, (byte) 0xf0, (byte) 0xd8, (byte) 0x46, (byte) 0x92, (byte) 0xf6, (byte) 0x8, + (byte) 0x25, (byte) 0xa9, (byte) 0x2b, (byte) 0xf5, (byte) 0xa4, (byte) 0x2e, (byte) 0x62, (byte) 0x8, + (byte) 0x17, (byte) 0x4, (byte) 0xc, (byte) 0x4b, (byte) 0x18, (byte) 0xc1, (byte) 0x45, (byte) 0x52, + (byte) 0xa1, (byte) 0xb, (byte) 0x92, (byte) 0xd4, (byte) 0x32, (byte) 0xf9, (byte) 0xea, (byte) 0x11, + (byte) 0xc3, (byte) 0x4c, (byte) 0x97, (byte) 0xb8, (byte) 0xee, (byte) 0x17, (byte) 0x8e, (byte) 0xcb, + (byte) 0x9b, (byte) 0x1f, (byte) 0xef, (byte) 0x1a, (byte) 0x0, (byte) 0x4f, (byte) 0x70, (byte) 0x54, + (byte) 0xc2, (byte) 0x18, (byte) 0x17, (byte) 0x32, (byte) 0x58, (byte) 0xd3, (byte) 0xc, (byte) 0x9b, + (byte) 0xf4, (byte) 0x7b, (byte) 0xff, (byte) 0xc0, (byte) 0xa5, (byte) 0xb, (byte) 0x2f, (byte) 0x3f, + (byte) 0xb1, (byte) 0x8c, (byte) 0xd, (byte) 0xb9, (byte) 0xaa, (byte) 0x29, (byte) 0x22, (byte) 0x92, + (byte) 0x48, (byte) 0x49, (byte) 0x18, (byte) 0xc7, (byte) 0x4, (byte) 0x43, (byte) 0xaf, (byte) 0x5c, + (byte) 0xaf, (byte) 0x97, (byte) 0x9a, (byte) 0xa6, (byte) 0x69, (byte) 0x29, (byte) 0xb6, (byte) 0xad, + (byte) 0xd4, (byte) 0x19, (byte) 0x6, (byte) 0x3a, (byte) 0x63, (byte) 0x38, (byte) 0x44, (byte) 0xe4, + (byte) 0x79, (byte) 0x19, (byte) 0x33, (byte) 0x1d, (byte) 0x9, (byte) 0xcc, (byte) 0x2f, (byte) 0xdf, + (byte) 0x79, (byte) 0x5a, (byte) 0x53, (byte) 0x4c, (byte) 0x47, (byte) 0x35, (byte) 0x74, (byte) 0x1, + (byte) 0x93, (byte) 0xc, (byte) 0x83, (byte) 0x6d, (byte) 0xd0, (byte) 0x4a, (byte) 0x53, (byte) 0x77, + (byte) 0xd4, (byte) 0x86, (byte) 0x72, (byte) 0xb8, (byte) 0x2f, (byte) 0x22, (byte) 0x8b, (byte) 0xf, + (byte) 0xb8, (byte) 0xf2, (byte) 0x13, (byte) 0x2, (byte) 0x3e, (byte) 0x3a, (byte) 0xaa, (byte) 0xab, + (byte) 0x9b, (byte) 0x62, (byte) 0x4, (byte) 0xd3, (byte) 0xf8, (byte) 0x58, (byte) 0xc0, (byte) 0x15, + (byte) 0x9, (byte) 0x9f, (byte) 0xe0, (byte) 0x53, (byte) 0x86, (byte) 0xb8, (byte) 0xbb, (byte) 0xaf, + (byte) 0x93, (byte) 0x8f, (byte) 0x47, (byte) 0x24, (byte) 0x66, (byte) 0xae, (byte) 0x28, (byte) 0x3b, + (byte) 0x4f, (byte) 0x18, (byte) 0x7c, (byte) 0x6, (byte) 0xc9, (byte) 0x93, (byte) 0xff, (byte) 0x1f, + (byte) 0x79, (byte) 0xe, (byte) 0x2a, (byte) 0x59, (byte) 0x78, (byte) 0x97, (byte) 0x21, (byte) 0x1f, + (byte) 0xc1, (byte) 0x55, (byte) 0xe4, (byte) 0x5, (byte) 0xcc, (byte) 0x70, (byte) 0x27, (byte) 0x9f, + (byte) 0x53, (byte) 0xd6, (byte) 0xed, (byte) 0xae, (byte) 0x5a, (byte) 0x94, (byte) 0x4d, (byte) 0x86, + (byte) 0x58, (byte) 0x6a, (byte) 0x1f, (byte) 0x75, (byte) 0x60, (byte) 0x22, (byte) 0x39, (byte) 0xaf, + (byte) 0xe3, (byte) 0x86, (byte) 0x80, (byte) 0x9b, (byte) 0x12, (byte) 0x75, (byte) 0xfc, (byte) 0x2c, + (byte) 0x43, (byte) 0xe2, (byte) 0x28, (byte) 0x27, (byte) 0xaf, (byte) 0xb3, (byte) 0xd7, (byte) 0x15, + (byte) 0x36, (byte) 0x91, (byte) 0xe9, (byte) 0xca, (byte) 0x46, (byte) 0xdb, (byte) 0xc0, (byte) 0x70, + (byte) 0x3d, (byte) 0xd5, (byte) 0x2d, (byte) 0x82, (byte) 0x63, (byte) 0xfc, (byte) 0xc7, (byte) 0xa3, + (byte) 0x6c, (byte) 0x13, (byte) 0x50, (byte) 0x2b, (byte) 0xdd, (byte) 0x61, (byte) 0x88, (byte) 0x74, + (byte) 0x74, (byte) 0x11, (byte) 0x57, (byte) 0xe8, (byte) 0xb, (byte) 0x9, (byte) 0x5f, (byte) 0x62, + (byte) 0x9e, (byte) 0xee, (byte) 0x88, (byte) 0x63, (byte) 0xdc, (byte) 0xac, (byte) 0xda, (byte) 0x86, + (byte) 0xd6, (byte) 0x74, (byte) 0x14, (byte) 0x4f, (byte) 0x9a, (byte) 0xb3, (byte) 0xa9, (byte) 0x13, + (byte) 0x12, (byte) 0x9e, (byte) 0xc6, (byte) 0x57, (byte) 0x12, (byte) 0xa, (byte) 0x58, (byte) 0x64, + (byte) 0x8, (byte) 0x39, (byte) 0x86, (byte) 0xa7, (byte) 0xd, (byte) 0xc3, (byte) 0x99, (byte) 0x83, + (byte) 0xd3, (byte) 0x9d, (byte) 0x8a, (byte) 0x89, (byte) 0x58, (byte) 0xc6, (byte) 0xa8, (byte) 0x80, + (byte) 0x22, (byte) 0x55, (byte) 0xff, (byte) 0xa4, (byte) 0xa0, (byte) 0x42, (byte) 0x58, (byte) 0xa1, + (byte) 0x22, (byte) 0x27, (byte) 0x75, (byte) 0xfe, (byte) 0x3f, (byte) 0x46, (byte) 0x7f, (byte) 0xbc, + (byte) 0xc9, (byte) 0x97, (byte) 0x96, (byte) 0xcb, (byte) 0x1d, (byte) 0x8d, (byte) 0x9e, (byte) 0x46, + (byte) 0x59, (byte) 0xc2, (byte) 0x5d, (byte) 0xde, (byte) 0x7d, (byte) 0x51, (byte) 0xd3, (byte) 0x6b, + (byte) 0x4b, (byte) 0xb9, (byte) 0xf6, (byte) 0x43, (byte) 0xd9, (byte) 0x92, (byte) 0x6b, (byte) 0xa, + (byte) 0x5, (byte) 0xb0, (byte) 0x36, (byte) 0x5f, (byte) 0x7c, (byte) 0x30, (byte) 0x37, (byte) 0x5f, + (byte) 0xa0, (byte) 0xbc, (byte) 0xe2, (byte) 0xef, (byte) 0xba, (byte) 0x27, (byte) 0x5, (byte) 0x67, + (byte) 0xd, (byte) 0xdd, (byte) 0x76, (byte) 0x64, (byte) 0xdd, (byte) 0x59, (byte) 0x95, (byte) 0xb5, + (byte) 0x26, (byte) 0x9d, (byte) 0xf, (byte) 0xcc, (byte) 0x1a, (byte) 0x75, (byte) 0x1a, (byte) 0xa2, + (byte) 0x5, (byte) 0x55, (byte) 0x57, (byte) 0x96, (byte) 0x9a, (byte) 0x8d, (byte) 0xaa, (byte) 0x62, + (byte) 0x95, (byte) 0x79, (byte) 0x17, (byte) 0xd2, (byte) 0x46, (byte) 0x43, (byte) 0x56, (byte) 0x75, + (byte) 0x9e, (byte) 0x73, (byte) 0xb7, (byte) 0xba, (byte) 0xaf, (byte) 0x12, (byte) 0x91, (byte) 0xeb, + (byte) 0x95, (byte) 0xf4, (byte) 0xdd, (byte) 0x3f, (byte) 0x2f, (byte) 0x96, (byte) 0x8c, (byte) 0xa6, + (byte) 0x55, (byte) 0x73, (byte) 0x5f, (byte) 0x13, (byte) 0x4a, (byte) 0xae, (byte) 0xcb, (byte) 0x1b, + (byte) 0x34, (byte) 0xc9, (byte) 0x69, (byte) 0x70, (byte) 0x91, (byte) 0x1e, (byte) 0x21, (byte) 0x1f, + (byte) 0x3d, (byte) 0x6e, (byte) 0x54, (byte) 0x67, (byte) 0xac, (byte) 0xe2, (byte) 0x1e, (byte) 0x8d, + (byte) 0xdf, (byte) 0xd0, (byte) 0xca, (byte) 0x87, (byte) 0x28, (byte) 0xfc, (byte) 0x34, (byte) 0xa7, + (byte) 0x57, (byte) 0x8e, (byte) 0xbe, (byte) 0x15, (byte) 0xb2, (byte) 0xc, (byte) 0xd1, (byte) 0xc8, + (byte) 0x68, (byte) 0xc, (byte) 0x4e, (byte) 0x6c, (byte) 0x83, (byte) 0x6d, (byte) 0xb9, (byte) 0x80, + (byte) 0x35, (byte) 0xfa, (byte) 0xf6, (byte) 0xb8, (byte) 0xc6, (byte) 0x10, (byte) 0xc2, (byte) 0xb8, + (byte) 0x8f, (byte) 0x6f, (byte) 0xf7, (byte) 0x8f, (byte) 0x5e, (byte) 0x26, (byte) 0x38, (byte) 0xb7, + (byte) 0x46, (byte) 0x76, (byte) 0x21, (byte) 0x54, (byte) 0xb6, (byte) 0x11, (byte) 0x6e, (byte) 0x41, + (byte) 0x6c, (byte) 0x3, (byte) 0x44, (byte) 0xd7, (byte) 0x9b, (byte) 0x4, (byte) 0x7e, (byte) 0x67, + (byte) 0x7d, (byte) 0xfc, (byte) 0xed, (byte) 0xf3, (byte) 0x40, (byte) 0xec, (byte) 0xf, (byte) 0x9a, + (byte) 0x5, (byte) 0x69, (byte) 0xe7, (byte) 0xc5, (byte) 0x2e, (byte) 0x7a, (byte) 0x2b, (byte) 0xf1, + (byte) 0xe8, (byte) 0x36, (byte) 0x62, (byte) 0x85, (byte) 0x17, (byte) 0x38, (byte) 0x13, (byte) 0x1f, + (byte) 0xc, (byte) 0xbc, (byte) 0x82, (byte) 0xaf, (byte) 0xe2, (byte) 0x8f, (byte) 0x47, (byte) 0x4b, + (byte) 0x2d, (byte) 0x9c, (byte) 0xbf, (byte) 0x97, (byte) 0x6e, (byte) 0xe1, (byte) 0xd2, (byte) 0x26, + (byte) 0xfa, (byte) 0x16, (byte) 0xbd, (byte) 0x31, (byte) 0xbc, (byte) 0x94, (byte) 0xc9, (byte) 0xb6, + (byte) 0x70, (byte) 0x39, (byte) 0xf3, (byte) 0x7a, (byte) 0x13, (byte) 0xbd, (byte) 0x85, (byte) 0x5d, + (byte) 0x64, (byte) 0x2b, (byte) 0xe9, (byte) 0x6d, (byte) 0xe4, (byte) 0x5e, (byte) 0xc7, (byte) 0xa3, + (byte) 0xfe, (byte) 0x57, (byte) 0xf8, (byte) 0x70, (byte) 0x7, (byte) 0x53, (byte) 0x85, (byte) 0xf4, + (byte) 0xe, (byte) 0x3e, (byte) 0xdb, (byte) 0xc1, (byte) 0xb5, (byte) 0x45, (byte) 0xce, (byte) 0x73, + (byte) 0xdb, (byte) 0xe3, (byte) 0x49, (byte) 0xbf, (byte) 0xc4, (byte) 0x1c, (byte) 0xc3, (byte) 0x4b, + (byte) 0x2c, (byte) 0x30, (byte) 0xb8, (byte) 0x84, (byte) 0x99, (byte) 0x37, (byte) 0x18, (byte) 0xc9, + (byte) 0xb4, (byte) 0xb0, (byte) 0xb4, (byte) 0x89, (byte) 0xc4, (byte) 0x12, (byte) 0xcd, (byte) 0xe3, + (byte) 0xde, (byte) 0x3c, (byte) 0x72, (byte) 0x35, (byte) 0x90, (byte) 0x4d, (byte) 0x4, (byte) 0x88, + (byte) 0x3a, (byte) 0x4b, (byte) 0xd4, (byte) 0xa3, (byte) 0x2e, (byte) 0xfe, (byte) 0xeb, (byte) 0x13, + (byte) 0xf0, (byte) 0x2d, (byte) 0x94, (byte) 0xb6, (byte) 0x28, (byte) 0x72, (byte) 0x11, (byte) 0xe7, + (byte) 0x31, (byte) 0x4a, (byte) 0x4f, (byte) 0xcb, (byte) 0x18, (byte) 0x52, (byte) 0xd4, (byte) 0xd, + (byte) 0x49, (byte) 0xca, (byte) 0x63, (byte) 0xa, (byte) 0x57, (byte) 0x68, (byte) 0xb6, (byte) 0x82, + (byte) 0x6, (byte) 0x9e, (byte) 0xd2, (byte) 0xfa, (byte) 0x67, (byte) 0xfc, (byte) 0x82, (byte) 0x5f, + (byte) 0x69, (byte) 0x5c, (byte) 0xc0, (byte) 0x6f, (byte) 0xf8, (byte) 0x9d, (byte) 0xec, (byte) 0x3e, + (byte) 0x57, (byte) 0x8b, (byte) 0x39, (byte) 0xc4, (byte) 0xe8, (byte) 0x1b, (byte) 0x23, (byte) 0xf4, + (byte) 0x39, (byte) 0xc2, (byte) 0xf, (byte) 0x10, (byte) 0x43, (byte) 0x8c, (byte) 0x70, (byte) 0x83, + (byte) 0x84, (byte) 0x1c, (byte) 0xa0, (byte) 0xbb, (byte) 0x9a, (byte) 0xc0, (byte) 0xd, (byte) 0xb2, + (byte) 0x2e, (byte) 0x90, (byte) 0xf2, (byte) 0x2b, (byte) 0xb8, (byte) 0x40, (byte) 0x3c, (byte) 0xc3, + (byte) 0xc4, (byte) 0x34, (byte) 0x44, (byte) 0xf8, (byte) 0x4b, (byte) 0xc4, (byte) 0x30, (byte) 0x8c, + (byte) 0xe7, (byte) 0xf4, (byte) 0xac, (byte) 0xfe, (byte) 0x49, (byte) 0xd5, (byte) 0xdb, (byte) 0x22, + (byte) 0xd4, (byte) 0x77, (byte) 0xc4, (byte) 0xf2, (byte) 0x10, (byte) 0xd2, (byte) 0x1e, (byte) 0x4d, + (byte) 0x7d, (byte) 0x2, (byte) 0x4, (byte) 0x81, (byte) 0xa4, (byte) 0x65, (byte) 0x2, (byte) 0x92, + (byte) 0x7b, (byte) 0xfc, (byte) 0x47, (byte) 0xc6, (byte) 0x5b, (byte) 0xd3, (byte) 0xca, (byte) 0x35, + (byte) 0x5, (byte) 0xff, (byte) 0x1, (byte) 0xbb, (byte) 0x25, (byte) 0x20, (byte) 0x1d, (byte) 0xde, + (byte) 0x23, (byte) 0x7, (byte) 0xde, (byte) 0xde, (byte) 0xb4, (byte) 0x40, (byte) 0x57, (byte) 0xc0, + (byte) 0x3b, (byte) 0x1e, (byte) 0x41, (byte) 0xe0, (byte) 0xd0, (byte) 0x74, (byte) 0x80, (byte) 0x10, + (byte) 0xf6, (byte) 0x11, (byte) 0xc3, (byte) 0x54, (byte) 0xa7, (byte) 0xef, (byte) 0xdd, (byte) 0xce, + (byte) 0x78, (byte) 0xf0, (byte) 0x1f, (byte) 0x50, (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x2d, + (byte) 0x3, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x8, (byte) 0x0, (byte) 0x0, (byte) 0xc0, + (byte) 0x69, (byte) 0x1, (byte) 0x57, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x9, + (byte) 0x0, (byte) 0x8, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x10, (byte) 0x0, (byte) 0xed, (byte) 0x41, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x4d, (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, + (byte) 0x46, (byte) 0x2f, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xfe, (byte) 0xca, + (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x2d, (byte) 0x3, + (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0xbd, (byte) 0x69, + (byte) 0x1, (byte) 0x57, (byte) 0x71, (byte) 0xa7, (byte) 0x16, (byte) 0x53, (byte) 0x5b, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x68, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x14, (byte) 0x0, + (byte) 0x4, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0xa4, (byte) 0x81, (byte) 0x3f, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x4d, (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, + (byte) 0x2f, (byte) 0x4d, (byte) 0x41, (byte) 0x4e, (byte) 0x49, (byte) 0x46, (byte) 0x45, (byte) 0x53, + (byte) 0x54, (byte) 0x2e, (byte) 0x4d, (byte) 0x46, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x2d, (byte) 0x3, (byte) 0x2d, (byte) 0x0, + (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0x61, (byte) 0x69, (byte) 0x1, (byte) 0x57, + (byte) 0x16, (byte) 0x64, (byte) 0x9c, (byte) 0xc5, (byte) 0x0, (byte) 0x4, (byte) 0x0, (byte) 0x0, + (byte) 0xf, (byte) 0x7, (byte) 0x0, (byte) 0x0, (byte) 0x19, (byte) 0x0, (byte) 0x4, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0xa4, (byte) 0x81, (byte) 0xe0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x5a, (byte) 0x69, + (byte) 0x70, (byte) 0x46, (byte) 0x69, (byte) 0x6c, (byte) 0x65, (byte) 0x50, (byte) 0x72, (byte) 0x6f, + (byte) 0x70, (byte) 0x65, (byte) 0x72, (byte) 0x74, (byte) 0x79, (byte) 0x54, (byte) 0x65, (byte) 0x73, + (byte) 0x74, (byte) 0x2e, (byte) 0x63, (byte) 0x6c, (byte) 0x61, (byte) 0x73, (byte) 0x73, (byte) 0x1, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x6, (byte) 0x6, (byte) 0x2c, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x2d, + (byte) 0x0, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x3, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x3, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xd0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x2b, (byte) 0x5, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x6, (byte) 0x7, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xfb, (byte) 0x5, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, + (byte) 0x4b, (byte) 0x5, (byte) 0x6, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x3, + (byte) 0x0, (byte) 0x3, (byte) 0x0, (byte) 0xd0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x2b, + (byte) 0x5, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + }; + + /* + * Jar file created by Ant specifying zip64mode="always" and createUnicodeExtraFields="always" + * ----------------#1-------------------- + * [Central Directory Header] + * 0x51b: Signature : 0x02014b50 + * 0x51f: Created Zip Spec : 0x2d [4.5] + * 0x520: Created OS : 0x3 [UNIX] + * 0x521: VerMadeby : 0x32d [3, 4.5] + * 0x522: VerExtract : 0x2d [4.5] + * 0x523: Flag : 0x800 + * 0x525: Method : 0x8 [DEFLATED] + * 0x527: Last Mod Time : 0x570b3767 [Fri Aug 11 06:59:14 EDT 2023] + * 0x52b: CRC : 0x5e4fa53f + * 0x52f: Compressed Size : 0xffffffff + * 0x533: Uncompressed Size: 0xffffffff + * 0x537: Name Length : 0x10 + * 0x539: Extra Length : 0x35 + * Extra data:[01, 00, 18, 00, 87, 04, 00, 00, 00, 00, 00, 00, c7, 02, 00, 00, 00, 00, 00, 00, 15, 01, 00, 00, 00, 00, 00, 00, 75, 70, 15, 00, 01, 94, 82, 60, 61, 52, 65, 61, 64, 41, 6e, 74, 4a, 61, 72, 2e, 63, 6c, 61, 73, 73] + * [tag=0x0001, sz=24] + * ->ZIP64: size *0x487 csize *0x2c7 LOC Off *0x115 + * [data= 87 04 00 00 00 00 00 00 c7 02 00 00 00 00 00 00 15 01 00 00 00 00 00 00 ] + * [tag=0x7075, sz=21] + * ->[Unknown tag] + * [data= 01 94 82 60 61 52 65 61 64 41 6e 74 4a 61 72 2e 63 6c 61 73 73 ] + * 0x53b: Comment Length : 0x0 + * 0x53d: Disk Start : 0x0 + * 0x53f: Attrs : 0x0 + * 0x541: AttrsEx : 0x81a40000 + * 0x545: Loc Header Offset: 0xffffffff + * 0x549: File Name : ReadAntJar.class + */ + public static byte[] ANT_ZIP64_UNICODE_EXTRA_JAR = { + + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x8, + (byte) 0x0, (byte) 0x0, (byte) 0x18, (byte) 0x7e, (byte) 0xe, (byte) 0x57, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0x9, (byte) 0x0, (byte) 0x2a, (byte) 0x0, (byte) 0x4d, (byte) 0x45, + (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0x1, + (byte) 0x0, (byte) 0x10, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xfe, (byte) 0xca, (byte) 0x0, (byte) 0x0, (byte) 0x75, + (byte) 0x70, (byte) 0xe, (byte) 0x0, (byte) 0x1, (byte) 0x8, (byte) 0xa1, (byte) 0x8c, (byte) 0x13, + (byte) 0x4d, (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, + (byte) 0x2f, (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x2d, (byte) 0x0, (byte) 0x0, + (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0x17, (byte) 0x7e, (byte) 0xe, (byte) 0x57, (byte) 0x31, + (byte) 0x59, (byte) 0x76, (byte) 0x4d, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x14, (byte) 0x0, (byte) 0x31, (byte) 0x0, (byte) 0x4d, + (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, + (byte) 0x4d, (byte) 0x41, (byte) 0x4e, (byte) 0x49, (byte) 0x46, (byte) 0x45, (byte) 0x53, (byte) 0x54, + (byte) 0x2e, (byte) 0x4d, (byte) 0x46, (byte) 0x1, (byte) 0x0, (byte) 0x10, (byte) 0x0, (byte) 0x6e, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x61, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x75, + (byte) 0x70, (byte) 0x19, (byte) 0x0, (byte) 0x1, (byte) 0x85, (byte) 0x85, (byte) 0x84, (byte) 0x2, + (byte) 0x4d, (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, + (byte) 0x2f, (byte) 0x4d, (byte) 0x41, (byte) 0x4e, (byte) 0x49, (byte) 0x46, (byte) 0x45, (byte) 0x53, + (byte) 0x54, (byte) 0x2e, (byte) 0x4d, (byte) 0x46, (byte) 0xf3, (byte) 0x4d, (byte) 0xcc, (byte) 0xcb, + (byte) 0x4c, (byte) 0x4b, (byte) 0x2d, (byte) 0x2e, (byte) 0xd1, (byte) 0xd, (byte) 0x4b, (byte) 0x2d, + (byte) 0x2a, (byte) 0xce, (byte) 0xcc, (byte) 0xcf, (byte) 0xb3, (byte) 0x52, (byte) 0x30, (byte) 0xd4, + (byte) 0x33, (byte) 0xe0, (byte) 0xe5, (byte) 0x72, (byte) 0xcc, (byte) 0x43, (byte) 0x12, (byte) 0x71, + (byte) 0x2c, (byte) 0x48, (byte) 0x4c, (byte) 0xce, (byte) 0x48, (byte) 0x55, (byte) 0x0, (byte) 0x8a, + (byte) 0x1, (byte) 0x25, (byte) 0xd, (byte) 0xd, (byte) 0xf4, (byte) 0xc, (byte) 0x4d, (byte) 0x12, + (byte) 0x73, (byte) 0xa, (byte) 0x32, (byte) 0x12, (byte) 0x79, (byte) 0xb9, (byte) 0x9c, (byte) 0x8b, + (byte) 0x52, (byte) 0x13, (byte) 0x4b, (byte) 0x52, (byte) 0x53, (byte) 0x74, (byte) 0x9d, (byte) 0x2a, + (byte) 0x81, (byte) 0xda, (byte) 0x2c, (byte) 0xf4, (byte) 0x80, (byte) 0x32, (byte) 0x7a, (byte) 0x86, + (byte) 0xda, (byte) 0x46, (byte) 0xba, (byte) 0x66, (byte) 0xa, (byte) 0x1a, (byte) 0xfe, (byte) 0x45, + (byte) 0x89, (byte) 0xc9, (byte) 0x39, (byte) 0xa9, (byte) 0xa, (byte) 0xce, (byte) 0xf9, (byte) 0x45, + (byte) 0x5, (byte) 0xf9, (byte) 0x45, (byte) 0x89, (byte) 0x25, (byte) 0x40, (byte) 0x63, (byte) 0x34, + (byte) 0x79, (byte) 0xb9, (byte) 0x78, (byte) 0xb9, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x3, + (byte) 0x4, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0x67, + (byte) 0x37, (byte) 0xb, (byte) 0x57, (byte) 0x3f, (byte) 0xa5, (byte) 0x4f, (byte) 0x5e, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x10, + (byte) 0x0, (byte) 0x2d, (byte) 0x0, (byte) 0x52, (byte) 0x65, (byte) 0x61, (byte) 0x64, (byte) 0x41, + (byte) 0x6e, (byte) 0x74, (byte) 0x4a, (byte) 0x61, (byte) 0x72, (byte) 0x2e, (byte) 0x63, (byte) 0x6c, + (byte) 0x61, (byte) 0x73, (byte) 0x73, (byte) 0x1, (byte) 0x0, (byte) 0x10, (byte) 0x0, (byte) 0x87, + (byte) 0x4, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xc7, + (byte) 0x2, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x75, + (byte) 0x70, (byte) 0x15, (byte) 0x0, (byte) 0x1, (byte) 0x94, (byte) 0x82, (byte) 0x60, (byte) 0x61, + (byte) 0x52, (byte) 0x65, (byte) 0x61, (byte) 0x64, (byte) 0x41, (byte) 0x6e, (byte) 0x74, (byte) 0x4a, + (byte) 0x61, (byte) 0x72, (byte) 0x2e, (byte) 0x63, (byte) 0x6c, (byte) 0x61, (byte) 0x73, (byte) 0x73, + (byte) 0x75, (byte) 0x53, (byte) 0x5b, (byte) 0x57, (byte) 0x12, (byte) 0x51, (byte) 0x18, (byte) 0xdd, + (byte) 0x3, (byte) 0xc3, (byte) 0x1c, (byte) 0x18, (byte) 0x47, (byte) 0x41, (byte) 0xcc, (byte) 0xb, + (byte) 0x96, (byte) 0x89, (byte) 0x25, (byte) 0x89, (byte) 0x17, (byte) 0xa0, (byte) 0x8b, (byte) 0x76, + (byte) 0x41, (byte) 0x33, (byte) 0xab, (byte) 0x95, (byte) 0x99, (byte) 0x21, (byte) 0xb4, (byte) 0x84, + (byte) 0x65, (byte) 0x8b, (byte) 0x7a, (byte) 0x1a, (byte) 0x61, (byte) 0xb2, (byte) 0x51, (byte) 0x98, + (byte) 0x99, (byte) 0x35, (byte) 0xc, (byte) 0x76, (byte) 0x79, (byte) 0xea, (byte) 0xa1, (byte) 0x7e, + (byte) 0x8b, (byte) 0xcf, (byte) 0xf6, (byte) 0x80, (byte) 0x6b, (byte) 0xe5, (byte) 0x2a, (byte) 0xdf, + (byte) 0x7c, (byte) 0xe8, (byte) 0x47, (byte) 0x65, (byte) 0xdf, (byte) 0x19, (byte) 0x50, (byte) 0xb0, + (byte) 0x65, (byte) 0x33, (byte) 0x8b, (byte) 0xef, (byte) 0x70, (byte) 0xbe, (byte) 0xb3, (byte) 0xf7, + (byte) 0xfe, (byte) 0x6e, (byte) 0x73, (byte) 0x7e, (byte) 0xff, (byte) 0xf9, (byte) 0xf1, (byte) 0xb, + (byte) 0xc0, (byte) 0x2c, (byte) 0x1e, (byte) 0xc9, (byte) 0x90, (byte) 0x31, (byte) 0xc6, (byte) 0x70, + (byte) 0x4d, (byte) 0x86, (byte) 0x7, (byte) 0x63, (byte) 0xdc, (byte) 0x5c, (byte) 0xf7, (byte) 0x63, + (byte) 0x9c, (byte) 0x21, (byte) 0x26, (byte) 0x43, (byte) 0xc2, (byte) 0x8d, (byte) 0x0, (byte) 0x26, + (byte) 0x10, (byte) 0xf7, (byte) 0x63, (byte) 0x92, (byte) 0x61, (byte) 0x4a, (byte) 0xc6, (byte) 0x34, + (byte) 0x66, (byte) 0xb8, (byte) 0x33, (byte) 0xc1, (byte) 0x90, (byte) 0x94, (byte) 0xd1, (byte) 0x8d, + (byte) 0x14, (byte) 0xc3, (byte) 0x4d, (byte) 0x3f, (byte) 0x6e, (byte) 0xc9, (byte) 0x8, (byte) 0xe2, + (byte) 0xb6, (byte) 0x0, (byte) 0x69, (byte) 0x41, (byte) 0x37, (byte) 0x74, (byte) 0x67, (byte) 0x51, + (byte) 0x80, (byte) 0x37, (byte) 0x3e, (byte) 0xb9, (byte) 0x21, (byte) 0x40, (byte) 0x7c, (byte) 0x6a, + (byte) 0x96, (byte) 0x35, (byte) 0x1, (byte) 0xc1, (byte) 0x8c, (byte) 0x6e, (byte) 0x68, (byte) 0xd9, + (byte) 0x7a, (byte) 0x75, (byte) 0x53, (byte) 0xb3, (byte) 0xb, (byte) 0xea, (byte) 0x66, (byte) 0x85, + (byte) 0x3c, (byte) 0x62, (byte) 0x55, (byte) 0xd5, (byte) 0xd, (byte) 0x1, (byte) 0x3, (byte) 0xf1, + (byte) 0xb7, (byte) 0x99, (byte) 0x6d, (byte) 0x75, (byte) 0x57, (byte) 0x4d, (byte) 0x55, (byte) 0x54, + (byte) 0x63, (byte) 0x2b, (byte) 0x95, (byte) 0x77, (byte) 0x6c, (byte) 0xdd, (byte) 0xd8, (byte) 0x9a, + (byte) 0xe7, (byte) 0x44, (byte) 0xbf, (byte) 0xad, (byte) 0xa9, (byte) 0xe5, (byte) 0x55, (byte) 0xd5, + (byte) 0xae, (byte) 0x9, (byte) 0xe8, (byte) 0xce, (byte) 0x3b, (byte) 0x6a, (byte) 0x69, (byte) 0x67, + (byte) 0x4d, (byte) 0xb5, (byte) 0x5c, (byte) 0x2a, (byte) 0xa5, (byte) 0xc8, (byte) 0x70, (byte) 0x87, + (byte) 0x12, (byte) 0xa3, (byte) 0xf0, (byte) 0x14, (byte) 0x59, (byte) 0x80, (byte) 0x9c, (byte) 0x37, + (byte) 0xeb, (byte) 0x76, (byte) 0x49, (byte) 0x5b, (byte) 0xd6, (byte) 0xb9, (byte) 0x6c, (byte) 0x70, + (byte) 0x9d, (byte) 0x68, (byte) 0x8f, (byte) 0xd, (byte) 0x87, (byte) 0x98, (byte) 0x49, (byte) 0xae, + (byte) 0xab, (byte) 0x20, (byte) 0x8c, (byte) 0x3e, (byte) 0xc2, (byte) 0xb4, (byte) 0xdd, (byte) 0xa, + (byte) 0x86, (byte) 0xb8, (byte) 0xa7, (byte) 0x47, (byte) 0x35, (byte) 0x9c, (byte) 0x6d, (byte) 0xd5, + (byte) 0x76, (byte) 0xb4, (byte) 0x9a, (byte) 0x43, (byte) 0x40, (byte) 0x5b, (byte) 0x40, (byte) 0xbf, + (byte) 0x9b, (byte) 0x46, (byte) 0xdd, (byte) 0xd1, (byte) 0x2b, (byte) 0xa9, (byte) 0xcf, (byte) 0xba, + (byte) 0x95, (byte) 0x7a, (byte) 0xa3, (byte) 0x5b, (byte) 0x5c, (byte) 0x91, (byte) 0xf3, (byte) 0x67, + (byte) 0x19, (byte) 0xe6, (byte) 0x14, (byte) 0xdc, (byte) 0xc5, (byte) 0x3d, (byte) 0x1, (byte) 0x83, + (byte) 0xb1, (byte) 0x5a, (byte) 0xd4, (byte) 0xb4, (byte) 0x34, (byte) 0x43, (byte) 0x2b, (byte) 0x47, + (byte) 0x77, (byte) 0x75, (byte) 0x35, (byte) 0xda, (byte) 0x2, (byte) 0xc5, (byte) 0xa8, (byte) 0x90, + (byte) 0x50, (byte) 0xbb, (byte) 0x8a, (byte) 0xdc, (byte) 0xe6, (byte) 0xb6, (byte) 0x56, (byte) 0x72, + (byte) 0x18, (byte) 0xee, (byte) 0x2b, (byte) 0x78, (byte) 0x80, (byte) 0xb4, (byte) 0x82, (byte) 0x79, + (byte) 0x1e, (byte) 0xaf, (byte) 0xaf, (byte) 0x7d, (byte) 0x5e, (byte) 0x78, (byte) 0x6f, (byte) 0x9b, + (byte) 0x1f, (byte) 0x78, (byte) 0x29, (byte) 0xa, (byte) 0x16, (byte) 0xf0, (byte) 0xf0, (byte) 0xf4, + (byte) 0x48, (byte) 0x37, (byte) 0x53, (byte) 0x2f, (byte) 0x72, (byte) 0xcf, (byte) 0x3e, (byte) 0x96, + (byte) 0x34, (byte) 0xcb, (byte) 0xd1, (byte) 0x4d, (byte) 0x12, (byte) 0x1c, (byte) 0x8e, (byte) 0x19, + (byte) 0xfc, (byte) 0x1d, (byte) 0xa7, (byte) 0x27, (byte) 0x4a, (byte) 0x51, (byte) 0xb3, (byte) 0xb9, + (byte) 0x42, (byte) 0x2b, (byte) 0x72, (byte) 0xcc, (byte) 0x50, (byte) 0xb0, (byte) 0xc8, (byte) 0x25, + (byte) 0x43, (byte) 0xff, (byte) 0x36, (byte) 0x8e, (byte) 0x8a, (byte) 0x88, (byte) 0x5f, (byte) 0xdc, + (byte) 0xcd, (byte) 0x4e, (byte) 0xe8, (byte) 0xa7, (byte) 0x9a, (byte) 0xa3, (byte) 0x55, (byte) 0x69, + (byte) 0x3e, (byte) 0x66, (byte) 0xdd, (byte) 0x21, (byte) 0x42, (byte) 0xe6, (byte) 0x34, (byte) 0xf8, + (byte) 0x2b, (byte) 0x2, (byte) 0x3b, (byte) 0x44, (byte) 0xd1, (byte) 0xd4, (byte) 0xea, (byte) 0x7c, + (byte) 0x47, (byte) 0x4e, (byte) 0x1d, (byte) 0x6e, (byte) 0x1a, (byte) 0xae, (byte) 0xc5, (byte) 0x77, + (byte) 0xef, (byte) 0x4, (byte) 0x2c, (byte) 0x5c, (byte) 0x10, (byte) 0xa7, (byte) 0x73, (byte) 0x90, + (byte) 0xcd, (byte) 0x16, (byte) 0xcc, (byte) 0x4f, (byte) 0xfe, (byte) 0x47, (byte) 0xdd, (byte) 0x57, + (byte) 0xaa, (byte) 0x98, (byte) 0x35, (byte) 0x9a, (byte) 0x56, (byte) 0xb7, (byte) 0x5a, (byte) 0x2e, + (byte) 0xe7, (byte) 0xeb, (byte) 0x96, (byte) 0x65, (byte) 0x6b, (byte) 0xb5, (byte) 0x9a, (byte) 0x56, + (byte) 0x16, (byte) 0x30, (byte) 0xd4, (byte) 0x29, (byte) 0x7b, (byte) 0xd6, (byte) 0x26, (byte) 0xb7, + (byte) 0x82, (byte) 0xa0, (byte) 0xd5, (byte) 0x54, (byte) 0xa0, (byte) 0x2f, (byte) 0xa1, (byte) 0x60, + (byte) 0xab, (byte) 0x25, (byte) 0xd, (byte) 0x63, (byte) 0xf4, (byte) 0x89, (byte) 0xca, (byte) 0xe0, + (byte) 0x8f, (byte) 0x17, (byte) 0x2, (byte) 0x9f, (byte) 0x32, (byte) 0xd9, (byte) 0x4b, (byte) 0xb4, + (byte) 0x1b, (byte) 0xa1, (byte) 0x55, (byte) 0xa0, (byte) 0xd5, (byte) 0x37, (byte) 0x75, (byte) 0x0, + (byte) 0x61, (byte) 0x9f, (byte) 0xfe, (byte) 0x50, (byte) 0x91, (byte) 0x64, (byte) 0x25, (byte) 0xd7, + (byte) 0x29, (byte) 0x21, (byte) 0x80, (byte) 0x1, (byte) 0xc, (byte) 0xb6, (byte) 0xa0, (byte) 0x13, + (byte) 0x24, (byte) 0xc1, (byte) 0xbd, (byte) 0x5d, (byte) 0x87, (byte) 0xf0, (byte) 0x14, (byte) 0xf, + (byte) 0xe0, (byte) 0x6d, (byte) 0x40, (byte) 0x6c, (byte) 0x13, (byte) 0xf8, (byte) 0x15, (byte) 0x0, + (byte) 0xfc, (byte) 0xb4, (byte) 0x6, (byte) 0xc8, (byte) 0x33, (byte) 0x74, (byte) 0xaa, (byte) 0x2f, + (byte) 0xac, (byte) 0x92, (byte) 0x8, (byte) 0xa3, (byte) 0x93, (byte) 0x6f, (byte) 0x61, (byte) 0x5f, + (byte) 0xe6, (byte) 0x10, (byte) 0x52, (byte) 0x71, (byte) 0xfa, (byte) 0x0, (byte) 0x6c, (byte) 0x4d, + (byte) 0xc8, (byte) 0x7e, (byte) 0x87, (byte) 0x3f, (byte) 0x1c, (byte) 0x10, (byte) 0x7f, (byte) 0x42, + (byte) 0x2e, (byte) 0x7a, (byte) 0xa7, (byte) 0xf3, (byte) 0xd, (byte) 0x74, (byte) 0xbd, (byte) 0x9e, + (byte) 0x39, (byte) 0xc6, (byte) 0xcb, (byte) 0xc4, (byte) 0x31, (byte) 0xfa, (byte) 0x67, (byte) 0x1a, + (byte) 0x50, (byte) 0xf6, (byte) 0xb0, (byte) 0x94, (byte) 0x16, (byte) 0x13, (byte) 0x11, (byte) 0xb1, + (byte) 0x81, (byte) 0x9e, (byte) 0x3d, (byte) 0xcc, (byte) 0x35, (byte) 0x3d, (byte) 0xc9, (byte) 0xb4, + (byte) 0x18, (byte) 0x11, (byte) 0xb3, (byte) 0x11, (byte) 0xf1, (byte) 0x28, (byte) 0xed, (byte) 0x23, + (byte) 0xe8, (byte) 0x48, (byte) 0x1b, (byte) 0x1a, (byte) 0x4e, (byte) 0x4b, (byte) 0x89, (byte) 0x88, + (byte) 0xe4, (byte) 0x42, (byte) 0x19, (byte) 0xf7, (byte) 0x44, (byte) 0x7c, (byte) 0x47, (byte) 0x7b, + (byte) 0x88, (byte) 0xac, (byte) 0xf1, (byte) 0x0, (byte) 0xa1, (byte) 0x73, (byte) 0x1, (byte) 0x1a, + (byte) 0xe8, (byte) 0xdd, (byte) 0xa7, (byte) 0x64, (byte) 0x26, (byte) 0xe8, (byte) 0x42, (byte) 0x26, + (byte) 0xe9, (byte) 0x1e, (byte) 0xf6, (byte) 0x60, (byte) 0x14, (byte) 0x4b, (byte) 0xad, (byte) 0x75, + (byte) 0x85, (byte) 0x12, (byte) 0x5c, (byte) 0xc7, (byte) 0x6, (byte) 0x8a, (byte) 0xb4, (byte) 0x5f, + (byte) 0xc2, (byte) 0xaa, (byte) 0xbb, (byte) 0xf7, (byte) 0x62, (byte) 0x7, (byte) 0x6, (byte) 0x5d, + (byte) 0x52, (byte) 0x8f, (byte) 0x5b, (byte) 0x5e, (byte) 0x12, (byte) 0x5d, (byte) 0x64, (byte) 0x15, + (byte) 0xf2, (byte) 0x72, (byte) 0x6, (byte) 0xe7, (byte) 0x4, (byte) 0x5d, (byte) 0xf6, (byte) 0xa, + (byte) 0xad, (byte) 0x3b, (byte) 0xd4, (byte) 0x4e, (byte) 0x8e, (byte) 0x34, (byte) 0x11, (byte) 0xc2, + (byte) 0x17, (byte) 0xf4, (byte) 0xe2, (byte) 0x2b, (byte) 0x15, (byte) 0x1e, (byte) 0x21, (byte) 0x74, + (byte) 0xe, (byte) 0xf2, (byte) 0x9, (byte) 0x11, (byte) 0x45, (byte) 0x86, (byte) 0x61, (byte) 0x86, + (byte) 0xcb, (byte) 0xc, (byte) 0x57, (byte) 0x18, (byte) 0xef, (byte) 0x36, (byte) 0x19, (byte) 0x79, + (byte) 0x99, (byte) 0xcc, (byte) 0x73, (byte) 0xfa, (byte) 0x9d, (byte) 0x10, (byte) 0x43, (byte) 0x3a, + (byte) 0x77, (byte) 0x7c, (byte) 0x6, (byte) 0xf1, (byte) 0x9e, (byte) 0x50, (byte) 0x64, (byte) 0x4f, + (byte) 0xf3, (byte) 0xc, (byte) 0x78, (byte) 0xc2, (byte) 0x70, (byte) 0xb5, (byte) 0x9f, (byte) 0x3a, + (byte) 0x3a, (byte) 0x4a, (byte) 0xb2, (byte) 0x1e, (byte) 0x44, (byte) 0xff, (byte) 0x2, (byte) 0x50, + (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x2d, (byte) 0x3, (byte) 0x2d, (byte) 0x0, (byte) 0x0, + (byte) 0x8, (byte) 0x0, (byte) 0x0, (byte) 0x18, (byte) 0x7e, (byte) 0xe, (byte) 0x57, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x9, (byte) 0x0, (byte) 0x32, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x10, (byte) 0x0, (byte) 0xed, + (byte) 0x41, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x4d, (byte) 0x45, (byte) 0x54, + (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0x1, (byte) 0x0, + (byte) 0x18, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0xfe, (byte) 0xca, (byte) 0x0, (byte) 0x0, (byte) 0x75, (byte) 0x70, + (byte) 0xe, (byte) 0x0, (byte) 0x1, (byte) 0x8, (byte) 0xa1, (byte) 0x8c, (byte) 0x13, (byte) 0x4d, + (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, + (byte) 0x50, (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x2d, (byte) 0x3, (byte) 0x2d, (byte) 0x0, + (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0x17, (byte) 0x7e, (byte) 0xe, (byte) 0x57, + (byte) 0x31, (byte) 0x59, (byte) 0x76, (byte) 0x4d, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x14, (byte) 0x0, (byte) 0x39, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0xa4, (byte) 0x81, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x4d, (byte) 0x45, + (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0x4d, + (byte) 0x41, (byte) 0x4e, (byte) 0x49, (byte) 0x46, (byte) 0x45, (byte) 0x53, (byte) 0x54, (byte) 0x2e, + (byte) 0x4d, (byte) 0x46, (byte) 0x1, (byte) 0x0, (byte) 0x18, (byte) 0x0, (byte) 0x6e, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x61, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x51, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x75, (byte) 0x70, + (byte) 0x19, (byte) 0x0, (byte) 0x1, (byte) 0x85, (byte) 0x85, (byte) 0x84, (byte) 0x2, (byte) 0x4d, + (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, + (byte) 0x4d, (byte) 0x41, (byte) 0x4e, (byte) 0x49, (byte) 0x46, (byte) 0x45, (byte) 0x53, (byte) 0x54, + (byte) 0x2e, (byte) 0x4d, (byte) 0x46, (byte) 0x50, (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x2d, + (byte) 0x3, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0x67, + (byte) 0x37, (byte) 0xb, (byte) 0x57, (byte) 0x3f, (byte) 0xa5, (byte) 0x4f, (byte) 0x5e, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x10, + (byte) 0x0, (byte) 0x35, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xa4, (byte) 0x81, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0x52, (byte) 0x65, (byte) 0x61, (byte) 0x64, (byte) 0x41, (byte) 0x6e, (byte) 0x74, + (byte) 0x4a, (byte) 0x61, (byte) 0x72, (byte) 0x2e, (byte) 0x63, (byte) 0x6c, (byte) 0x61, (byte) 0x73, + (byte) 0x73, (byte) 0x1, (byte) 0x0, (byte) 0x18, (byte) 0x0, (byte) 0x87, (byte) 0x4, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xc7, (byte) 0x2, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x15, (byte) 0x1, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x75, (byte) 0x70, (byte) 0x15, + (byte) 0x0, (byte) 0x1, (byte) 0x94, (byte) 0x82, (byte) 0x60, (byte) 0x61, (byte) 0x52, (byte) 0x65, + (byte) 0x61, (byte) 0x64, (byte) 0x41, (byte) 0x6e, (byte) 0x74, (byte) 0x4a, (byte) 0x61, (byte) 0x72, + (byte) 0x2e, (byte) 0x63, (byte) 0x6c, (byte) 0x61, (byte) 0x73, (byte) 0x73, (byte) 0x50, (byte) 0x4b, + (byte) 0x6, (byte) 0x6, (byte) 0x2c, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x2d, (byte) 0x0, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x3, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x3, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x57, (byte) 0x1, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x37, (byte) 0x4, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, + (byte) 0x6, (byte) 0x7, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x8e, (byte) 0x5, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x5, (byte) 0x6, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x3, (byte) 0x0, (byte) 0x3, (byte) 0x0, (byte) 0x57, (byte) 0x1, + (byte) 0x0, (byte) 0x0, (byte) 0x37, (byte) 0x4, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + }; + + /* + * ----------------#1-------------------- + * [Central Directory Header] + * 0x47: Signature : 0x02014b50 + * 0x4b: Created Zip Spec : 0x2d [4.5] + * 0x4c: Created OS : 0x3 [UNIX] + * 0x4d: VerMadeby : 0x32d [3, 4.5] + * 0x4e: VerExtract : 0x2d [4.5] + * 0x4f: Flag : 0x800 + * 0x51: Method : 0x8 [DEFLATED] + * 0x53: Last Mod Time : 0x570375bc [Thu Aug 03 14:45:56 EDT 2023] + * 0x57: CRC : 0x0 + * 0x5b: Compressed Size : 0x2 + * 0x5f: Uncompressed Size: 0x0 + * * 0x63: Name Length : 0x5 + * 0x65: Extra Length : 0x12 + * Extra data:[01, 00, 00, 00, 75, 70, 0a, 00, 01, ba, f7, eb, c1, 61, 2e, 74, 78, 74] + * [tag=0x0001, sz=0] + * ->ZIP64: + * [tag=0x7075, sz=10] + * ->[Unknown tag] + * [data= 01 ba f7 eb c1 61 2e 74 78 74 ] + * 0x67: Comment Length : 0x0 + * 0x69: Disk Start : 0x0 + * 0x6b: Attrs : 0x0 + * 0x6d: AttrsEx : 0x81a40000 + * 0x71: Loc Header Offset: 0x0 + * 0x75: File Name : a.txt + */ + public static byte[] ANT_ZIP64_UNICODE_EXTRA_ZIP= { + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0xbc, (byte) 0x75, (byte) 0x3, (byte) 0x57, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0x5, (byte) 0x0, (byte) 0x22, (byte) 0x0, (byte) 0x61, (byte) 0x2e, + (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0x1, (byte) 0x0, (byte) 0x10, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x2, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x75, + (byte) 0x70, (byte) 0xa, (byte) 0x0, (byte) 0x1, (byte) 0xba, (byte) 0xf7, (byte) 0xeb, (byte) 0xc1, + (byte) 0x61, (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0x3, (byte) 0x0, (byte) 0x50, + (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x2d, (byte) 0x3, (byte) 0x2d, (byte) 0x0, (byte) 0x0, + (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0xbc, (byte) 0x75, (byte) 0x3, (byte) 0x57, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x2, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x5, (byte) 0x0, (byte) 0x12, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xa4, + (byte) 0x81, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x61, (byte) 0x2e, (byte) 0x74, + (byte) 0x78, (byte) 0x74, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x75, (byte) 0x70, + (byte) 0xa, (byte) 0x0, (byte) 0x1, (byte) 0xba, (byte) 0xf7, (byte) 0xeb, (byte) 0xc1, (byte) 0x61, + (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0x50, (byte) 0x4b, (byte) 0x6, (byte) 0x6, + (byte) 0x2c, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x2d, (byte) 0x0, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x45, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x47, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x6, (byte) 0x7, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x8c, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x5, (byte) 0x6, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x1, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x45, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x47, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + }; + + // Name of Zip file and Jar File used by the test + public static final Path VALID_APK = Path.of("working-apk.zip"); + public static final Path VALID_APACHE_COMPRESS_JAR = + Path.of("valid-apache-compress.jar"); + public static final Path VALID_ANT_JAR = + Path.of("valid-ant-zip64-unicode-extrafields.jar"); + public static final Path VALID_ANT_ZIP = + Path.of("valid-ant-zip64-unicode-extrafields.zip"); + /** + * Setup method used to create the Zip and Jar files used by the test + * @throws IOException if an error occurs + */ + public static void setup() throws IOException { + Files.deleteIfExists(VALID_APK); + Files.deleteIfExists(VALID_APACHE_COMPRESS_JAR); + Files.deleteIfExists(VALID_ANT_JAR); + Files.deleteIfExists(VALID_ANT_ZIP); + + // Create the Zip file to read + Files.write(VALID_APK, VALID_APK_FILE); + Files.write(VALID_APACHE_COMPRESS_JAR, COMMONS_COMPRESS_JAR); + Files.write(VALID_ANT_JAR, ANT_ZIP64_UNICODE_EXTRA_JAR); + Files.write(VALID_ANT_ZIP, ANT_ZIP64_UNICODE_EXTRA_ZIP); + + } + + /** + * Zip and Jars files to validate we can open + */ + private static Stream zipFilesToTest() { + return Stream.of(VALID_APK, VALID_APACHE_COMPRESS_JAR, VALID_ANT_JAR, VALID_ANT_ZIP); + } + + /** + * Validate that a Zip file which contains an extra header with a data size + * 0f 0 can be opened using ZipFile + * @throws IOException if an error occurs + */ + public void zipFilesToTest(Path jar) throws IOException { + try (ZipFile zf = new ZipFile(jar.toFile())) { + System.out.printf("%s opened%n", jar.toAbsolutePath()); + } catch (IOException ie) { + System.out.printf("%n%n%n$$$$ %s NOT opened%n", jar.toAbsolutePath()); + throw ie; + } + } + + /** + * Validate that a Zip file which contains an extra header with a data size + * 0f 0 can be opened using ZipFS + * @throws IOException if an error occurs + */ + public void readZipFSTest(Path jar) throws IOException { + URI uri = URI.create("jar:" + jar.toUri()); + try (FileSystem fs = FileSystems.newFileSystem(uri, Map.of())) { + System.out.printf("%s opened%n", jar.toAbsolutePath()); + } catch (IOException ie) { + System.out.printf("%n%n%n$$$$ %s NOT opened%n", jar.toAbsolutePath()); + throw ie; + } + } + /** + * Utility method which takes a byte array and converts to byte array + * declaration. For example: + *
          +     *     {@code
          +     *        var fooJar = Files.readAllBytes(Path.of("foo.jar"));
          +     *        var result = createByteArray(fooJar, "FOOBYTES");
          +     *        System.out.println(result);
          +     *      }
          +     * 
          + * + * @param bytes A byte array used to create a byte array declaration + * @param name Name to be used in the byte array declaration + * @return The formatted byte array declaration + */ + public static String createByteArray(byte[] bytes, String name) { + StringBuilder sb = new StringBuilder(bytes.length * 5); + Formatter fmt = new Formatter(sb); + fmt.format(" public static byte[] %s = {", name); + final int linelen = 8; + for (int i = 0; i < bytes.length; i++) { + if (i % linelen == 0) { + fmt.format("%n "); + } + fmt.format(" (byte) 0x%x,", bytes[i] & 0xff); + } + fmt.format("%n };%n"); + return sb.toString(); + } + + public static void main(String[] args) throws Exception { + setup(); + var test = new ReadNonStandardExtraHeadersTest(); + zipFilesToTest().forEach(path -> { + try { + test.zipFilesToTest(path); + test.readZipFSTest(path); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } +} + diff --git a/test/jdk/javax/accessibility/MaximumAccessibleValueTest.java b/test/jdk/javax/accessibility/MaximumAccessibleValueTest.java new file mode 100644 index 00000000000..2b7ea24fbe6 --- /dev/null +++ b/test/jdk/javax/accessibility/MaximumAccessibleValueTest.java @@ -0,0 +1,71 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 4422362 + * @summary Wrong Max Accessible Value with BoundedRangeModel components + * @run main MaximumAccessibleValueTest + */ + +import javax.swing.JProgressBar; +import javax.swing.JScrollBar; +import javax.swing.JSlider; +import javax.swing.SwingUtilities; + +public class MaximumAccessibleValueTest { + + public static void doTest() { + + JScrollBar jScrollBar = new JScrollBar(); + JProgressBar jProgressBar = new JProgressBar(); + JSlider jSlider = new JSlider(); + + if (((Integer) jScrollBar.getAccessibleContext().getAccessibleValue() + .getMaximumAccessibleValue()).intValue() != jScrollBar.getMaximum() + - jScrollBar.getVisibleAmount()) { + throw new RuntimeException( + "Wrong MaximumAccessibleValue returned by JScrollBar"); + } + + if (((Integer) jProgressBar.getAccessibleContext().getAccessibleValue() + .getMaximumAccessibleValue().intValue()) != (jProgressBar + .getMaximum() - jProgressBar.getModel().getExtent())) { + throw new RuntimeException( + "Wrong MaximumAccessibleValue returned by JProgressBar"); + } + + if (((Integer) jSlider.getAccessibleContext().getAccessibleValue() + .getMaximumAccessibleValue()).intValue() != jSlider.getMaximum() + - jSlider.getModel().getExtent()) { + throw new RuntimeException( + "Wrong MaximumAccessibleValue returned by JSlider"); + } + } + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> doTest()); + System.out.println("Test Passed"); + } +} + diff --git a/test/jdk/javax/accessibility/SetCurrentAccessibleValueTest.java b/test/jdk/javax/accessibility/SetCurrentAccessibleValueTest.java new file mode 100644 index 00000000000..ad405de994e --- /dev/null +++ b/test/jdk/javax/accessibility/SetCurrentAccessibleValueTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002, 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 4422535 + * @summary setCurrentAccessibleValue returns true only for an Integer + * @run main SetCurrentAccessibleValueTest + */ + +import java.math.BigDecimal; +import java.math.BigInteger; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JInternalFrame; +import javax.swing.JProgressBar; +import javax.swing.JScrollBar; +import javax.swing.JSlider; +import javax.swing.JSplitPane; +import javax.swing.SwingUtilities; + +public class SetCurrentAccessibleValueTest { + + public static void doTest() { + JComponent[] jComponents = + { new JButton(), new JInternalFrame(), new JSplitPane(), + new JScrollBar(), new JProgressBar(), new JSlider() }; + + for (JComponent jComponent : jComponents) { + testIt(jComponent, (Float.valueOf(5))); + testIt(jComponent, (Double.valueOf(37.266))); + testIt(jComponent, (Integer.valueOf(10))); + testIt(jComponent, (Long.valueOf(123L))); + testIt(jComponent, (Short.valueOf((short) 123))); + testIt(jComponent, (BigInteger.ONE)); + testIt(jComponent, (new BigDecimal(BigInteger.ONE))); + } + + } + + static void testIt(JComponent jComponent, Number number) { + if (!jComponent.getAccessibleContext().getAccessibleValue() + .setCurrentAccessibleValue(number)) { + throw new RuntimeException(jComponent.getClass().getName() + + " Accessible Value implementation doesn't accept " + + number.getClass().getName()); + } + } + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> doTest()); + System.out.println("Test Passed"); + } +} + diff --git a/test/jdk/javax/crypto/SecretKeyFactory/security.properties b/test/jdk/javax/crypto/SecretKeyFactory/security.properties index f855f12b990..c71970526bd 100644 --- a/test/jdk/javax/crypto/SecretKeyFactory/security.properties +++ b/test/jdk/javax/crypto/SecretKeyFactory/security.properties @@ -1,6 +1,3 @@ -# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. -# ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - jdk.security.provider.preferred= jdk.jar.disabledAlgorithms= diff --git a/test/jdk/javax/print/attribute/SidesAttributeTest.java b/test/jdk/javax/print/attribute/SidesAttributeTest.java new file mode 100644 index 00000000000..60454f30407 --- /dev/null +++ b/test/jdk/javax/print/attribute/SidesAttributeTest.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, BELLSOFT. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 JDK-8311033 + * @summary [macos] PrinterJob does not take into account Sides attribute + * @run main/manual SidesAttributeTest + */ + +import javax.print.PrintService; +import javax.print.attribute.Attribute; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.Sides; +import javax.swing.*; +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +public class SidesAttributeTest { + + private static final long TIMEOUT = 10 * 60_000; + private static volatile boolean testPassed = true; + private static volatile boolean testFinished = false; + private static volatile boolean timeout = false; + + private static volatile int testCount; + private static volatile int testTotalCount; + + public static void main(String[] args) throws Exception { + + SwingUtilities.invokeLater(() -> { + + Set supportedSides = getSupportedSidesAttributes(); + if (supportedSides.size() > 1) { + testTotalCount = supportedSides.size(); + testPrint(Sides.ONE_SIDED, supportedSides); + testPrint(Sides.DUPLEX, supportedSides); + testPrint(Sides.TUMBLE, supportedSides); + } + testFinished = true; + }); + + long time = System.currentTimeMillis() + TIMEOUT; + + while (System.currentTimeMillis() < time) { + if (!testPassed || testFinished) { + break; + } + Thread.sleep(500); + } + + timeout = true; + + closeDialogs(); + + if (!testPassed) { + throw new Exception("Test failed!"); + } + + if (testCount != testTotalCount) { + throw new Exception( + "Timeout: " + testCount + " tests passed out from " + testTotalCount); + } + } + + private static void print(Sides sides) throws PrinterException { + PrintRequestAttributeSet attr = new HashPrintRequestAttributeSet(); + attr.add(sides); + + for (Attribute attribute : attr.toArray()) { + System.out.printf("Used print request attribute: %s%n", attribute); + } + + PrinterJob job = PrinterJob.getPrinterJob(); + job.setPrintable(new SidesAttributePrintable(sides)); + + job.print(attr); + } + + private static class SidesAttributePrintable implements Printable { + + private final Sides sidesAttr; + + public SidesAttributePrintable(Sides sidesAttr) { + this.sidesAttr = sidesAttr; + } + + @Override + public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { + + if (pageIndex >= 2) { + return NO_SUCH_PAGE; + } + + int x = (int) (pageFormat.getImageableX() + pageFormat.getImageableWidth() / 10); + int y = (int) (pageFormat.getImageableY() + pageFormat.getImageableHeight() / 5); + + Graphics2D g = (Graphics2D) graphics; + String text = getPageText(sidesAttr, pageIndex + 1); + g.drawString(text, x, y); + return PAGE_EXISTS; + } + } + + private static String getPageText(Sides sides, int page) { + return String.format("Page: %d - %s", page, getSidesText(sides)); + } + + private static String getSidesText(Sides sides) { + if (Sides.ONE_SIDED.equals(sides)) { + return "ONE_SIDED"; + } else if (Sides.TWO_SIDED_SHORT_EDGE.equals(sides)) { + return "TWO_SIDED_SHORT_EDGE (TUMBLE)"; + } else if (Sides.TWO_SIDED_LONG_EDGE.equals(sides)) { + return "TWO_SIDED_LONG_EDGE (DUPLEX)"; + } + throw new RuntimeException("Unknown sides attribute: " + sides); + } + + private static String getSidesDescription(Sides sides) { + if (Sides.ONE_SIDED.equals(sides)) { + return "a one-sided document"; + } else if (Sides.TWO_SIDED_SHORT_EDGE.equals(sides)) { + return "double-sided document along the short edge of the paper"; + } else if (Sides.TWO_SIDED_LONG_EDGE.equals(sides)) { + return "double-sided document along the long edge of the paper"; + } + throw new RuntimeException("Unknown sides attribute: " + sides); + } + + private static Set getSupportedSidesAttributes() { + Set supportedSides = new HashSet<>(); + + PrinterJob printerJob = PrinterJob.getPrinterJob(); + PrintService service = printerJob.getPrintService(); + + Object obj = service.getSupportedAttributeValues(Sides.class, null, null); + if (obj instanceof Attribute[]) { + Attribute[] attr = (Attribute[]) obj; + Collections.addAll(supportedSides, attr); + } + + return supportedSides; + } + + private static void pass() { + testCount++; + } + + private static void fail(Sides sides) { + System.out.printf("Failed test: %s%n", getSidesText(sides)); + testPassed = false; + } + + private static void runPrint(Sides sides) { + try { + print(sides); + } catch (PrinterException e) { + fail(sides); + e.printStackTrace(); + } + } + + private static void testPrint(Sides sides, Set supportedSides) { + + if (!supportedSides.contains(sides) || !testPassed || timeout) { + return; + } + + String[] instructions = { + "Up to " + testTotalCount + " tests will run and it will test all the cases", + "supported by the printer.", + "", + "The test is " + (testCount + 1) + " from " + testTotalCount + ".", + "", + "On-screen inspection is not possible for this printing-specific", + "test therefore its only output is two printed pages (one or two sided).", + "To be able to run this test it is required to have a default", + "printer configured in your user environment.", + "", + "Visual inspection of the printed pages is needed.", + "A passing test will print 2 pages:", + " - the first page with the text: " + getPageText(sides, 1), + " - the second page with the text: " + getPageText(sides, 2), + "", + "The test fails if the pages are not printed according to the tested", + getSidesText(sides) + " attribute where " + getSidesDescription(sides), + "needs to be printed.", + "", + }; + + String title = String.format("Print %s sides test: %d from %d", + getSidesText(sides), testCount + 1, testTotalCount); + final JDialog dialog = new JDialog((Frame) null, title, Dialog.ModalityType.DOCUMENT_MODAL); + JTextArea textArea = new JTextArea(String.join("\n", instructions)); + textArea.setEditable(false); + final JButton testButton = new JButton("Start Test"); + final JButton passButton = new JButton("PASS"); + passButton.setEnabled(false); + passButton.addActionListener((e) -> { + pass(); + dialog.dispose(); + }); + final JButton failButton = new JButton("FAIL"); + failButton.setEnabled(false); + failButton.addActionListener((e) -> { + fail(sides); + dialog.dispose(); + }); + testButton.addActionListener((e) -> { + testButton.setEnabled(false); + runPrint(sides); + passButton.setEnabled(true); + failButton.setEnabled(true); + }); + + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(textArea, BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(new FlowLayout()); + buttonPanel.add(testButton); + buttonPanel.add(passButton); + buttonPanel.add(failButton); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + dialog.add(mainPanel); + dialog.pack(); + dialog.setVisible(true); + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.out.println("Dialog closing"); + fail(sides); + } + }); + } + + private static void closeDialogs() { + for (Window w : Dialog.getWindows()) { + w.dispose(); + } + } +} diff --git a/test/jdk/javax/security/auth/callback/Mutability.java b/test/jdk/javax/security/auth/callback/Mutability.java new file mode 100644 index 00000000000..3a0dff0ce6e --- /dev/null +++ b/test/jdk/javax/security/auth/callback/Mutability.java @@ -0,0 +1,96 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8242330 + * @library /test/lib + * @summary Arrays should be cloned in several JAAS Callback classes + */ + +import javax.security.auth.callback.ChoiceCallback; +import javax.security.auth.callback.ConfirmationCallback; + +import static jdk.test.lib.Asserts.assertEQ; + +public class Mutability { + public static void main(String[] args) { + + // #1. ConfirmationCallback.new(3) + String[] i11 = {"1", "2"}; + ConfirmationCallback c1 = new ConfirmationCallback( + ConfirmationCallback.INFORMATION, + i11, + 0); + + // Modify argument of constructor + i11[0] = "x"; + String[] o11 = c1.getOptions(); + assertEQ(o11[0], "1"); + // Modify output + o11[0] = "y"; + String[] o12 = c1.getOptions(); + assertEQ(o12[0], "1"); + + // #2. ConfirmationCallback.new(4) + String[] i21 = {"1", "2"}; + ConfirmationCallback c2 = new ConfirmationCallback( + "Hi", + ConfirmationCallback.INFORMATION, + i21, + 0); + + // Modify argument of constructor + i21[0] = "x"; + assertEQ(c2.getOptions()[0], "1"); + + // #3. ChoiceCallback.new + String[] i31 = {"1", "2"}; + ChoiceCallback c3 = new ChoiceCallback( + "Hi", + i31, + 0, + true); + + // Modify argument of constructor + i31[0] = "x"; + String[] o31 = c3.getChoices(); + assertEQ(o31[0], "1"); + // Modify output of getChoices + o31[0] = "y"; + String[] o32 = c3.getChoices(); + assertEQ(o32[0], "1"); + + int[] s31 = {0, 1}; + c3.setSelectedIndexes(s31); + + // Modify argument of setSelectedIndexes + s31[0] = 1; + int[] s32 = c3.getSelectedIndexes(); + assertEQ(s32[0], 0); + // Modify output of getSelectedIndexes + s32[1] = 0; + int[] s33 = c3.getSelectedIndexes(); + assertEQ(s33[1], 1); + } +} diff --git a/test/jdk/javax/security/auth/callback/PasswordCallback/CheckCleanerBound.java b/test/jdk/javax/security/auth/callback/PasswordCallback/CheckCleanerBound.java new file mode 100644 index 00000000000..cc995893f65 --- /dev/null +++ b/test/jdk/javax/security/auth/callback/PasswordCallback/CheckCleanerBound.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8284910 + * @summary Check that the cleaner is not bound to the PasswordCallback object + */ + +import javax.security.auth.callback.PasswordCallback; +import java.util.WeakHashMap; + +public final class CheckCleanerBound { + private final static WeakHashMap weakHashMap = + new WeakHashMap<>(); + + public static void main(String[] args) throws Exception { + // Create an object + PasswordCallback passwordCallback = + new PasswordCallback("Password: ", false); + passwordCallback.setPassword("ThisIsAPassword".toCharArray()); + + weakHashMap.put(passwordCallback, null); + passwordCallback = null; + + // Check if the PasswordCallback object could be collected. + // Wait to trigger the cleanup. + for (int i = 0; i < 10 && weakHashMap.size() != 0; i++) { + System.gc(); + } + + // Check if the object has been collected. The collection will not + // happen if the cleaner implementation in PasswordCallback is bound + // to the PasswordCallback object. + if (weakHashMap.size() > 0) { + throw new RuntimeException( + "PasswordCallback object is not released"); + } + } +} + diff --git a/test/jdk/javax/security/auth/callback/PasswordCallback/PasswordCleanup.java b/test/jdk/javax/security/auth/callback/PasswordCallback/PasswordCleanup.java new file mode 100644 index 00000000000..ea8b1d1c145 --- /dev/null +++ b/test/jdk/javax/security/auth/callback/PasswordCallback/PasswordCleanup.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8284910 + * @summary Check that PasswordCallback.clearPassword() clears the password + */ + +import javax.security.auth.callback.PasswordCallback; +import java.util.Arrays; + +public final class PasswordCleanup { + public static void main(String[] args) throws Exception { + // Create an object + PasswordCallback passwordCallback = + new PasswordCallback("Password: ", false); + passwordCallback.setPassword("ThisIsAPassword".toCharArray()); + char[] originPassword = passwordCallback.getPassword(); + + // Use password clear method. + passwordCallback.clearPassword(); + + // Check that the password is cleared. + char[] clearedPassword = passwordCallback.getPassword(); + if (Arrays.equals(originPassword, clearedPassword)) { + throw new RuntimeException( + "PasswordCallback.clearPassword() does not clear passwords"); + } + } +} + diff --git a/test/jdk/javax/sound/sampled/Clip/SetPositionHang.java b/test/jdk/javax/sound/sampled/Clip/SetPositionHang.java index e6d924a7505..0805dfc45a0 100644 --- a/test/jdk/javax/sound/sampled/Clip/SetPositionHang.java +++ b/test/jdk/javax/sound/sampled/Clip/SetPositionHang.java @@ -28,7 +28,7 @@ /** * @test - * @bug 8266421 + * @bug 8266421 8269091 * @summary Tests that Clip.setFramePosition/setMicrosecondPosition do not hang. */ public final class SetPositionHang implements Runnable { diff --git a/test/jdk/javax/swing/JComboBox/bug4167850.java b/test/jdk/javax/swing/JComboBox/bug4167850.java new file mode 100644 index 00000000000..5d3ed76c8b1 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4167850.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4167850 + @summary Verify no exception removing items from an empty list. +*/ + +import javax.swing.JComboBox; + +public class bug4167850 { + + public static void main(String[] args) { + JComboBox comboBox = new JComboBox( + new Object[] { + "Coma Berenices", + "Triangulum", + "Camelopardis", + "Cassiopea"}); + + comboBox.removeAllItems(); + comboBox.removeAllItems(); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4171464.java b/test/jdk/javax/swing/JComboBox/bug4171464.java new file mode 100644 index 00000000000..aa7962d97c2 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4171464.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 4171464 + @summary JComboBox should not throw InternalError +*/ + +import javax.swing.ComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.event.ListDataListener; + +public class bug4171464 { + + public static void main(String args[]) { + ComboBoxModel model = new ComboBoxModel() { + public void setSelectedItem(Object anItem) {} + public Object getSelectedItem() {return null;} + public int getSize() {return 0;} + public Object getElementAt(int index) {return null;} + public void addListDataListener(ListDataListener l) {} + public void removeListDataListener(ListDataListener l) {} + }; + JComboBox comboBox = new JComboBox(); + comboBox.setModel(model); + try { + comboBox.addItem(new Object() {}); + } catch (InternalError e) { + // InternalError not suitable if app supplies non-mutable model. + throw new RuntimeException("4171464 TEST FAILED"); + } catch (Exception e) { + // Expected exception due to non-mutable model. + } + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4209474.java b/test/jdk/javax/swing/JComboBox/bug4209474.java new file mode 100644 index 00000000000..d3f060cbc8f --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4209474.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 4209474 + @summary setSelectedItem(int) should only fire events if selection changed - avoid recursive calls +*/ + +import javax.swing.JComboBox; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class bug4209474 { + + public static void main(String[] args) { + + JComboBox comboBox = new JComboBox( + new Object[] { + "Coma Berenices", + "Triangulum", + "Camelopardis", + "Cassiopea"}); + + ActionListener listener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + comboBox.setSelectedIndex(0); + } + }; + + comboBox.addActionListener(listener); + comboBox.setSelectedIndex(0); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4234119.java b/test/jdk/javax/swing/JComboBox/bug4234119.java new file mode 100644 index 00000000000..b24f3ac5da9 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4234119.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4234119 + @summary Tests if adding items to ComboBox is slow +*/ + +import javax.swing.JComboBox; + +public class bug4234119 { + + public static void main(String args[]) { + JComboBox jComboBox1 = new JComboBox(); + long startTime = System.currentTimeMillis(); + for (int i = 0 ; i < 500; i++) { + jComboBox1.addItem(Integer.valueOf(i)); + } + long deltaTime = System.currentTimeMillis() - startTime; + if (deltaTime > 20000) { + throw new Error("Test failed: adding items to ComboBox is SLOW! (it took " + deltaTime + " ms"); + } + System.out.println("Elapsed time: " + deltaTime); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4244614.java b/test/jdk/javax/swing/JComboBox/bug4244614.java new file mode 100644 index 00000000000..56231987ca5 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4244614.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4244614 + @summary Tests that JComboBox has setAction(Action) constructor +*/ + +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeListener; +import javax.swing.Action; +import javax.swing.JComboBox; + +public class bug4244614 { + +/** Auxiliary class implementing Action + */ + static class NullAction implements Action { + public void addPropertyChangeListener( + PropertyChangeListener listener) {} + public void removePropertyChangeListener( + PropertyChangeListener listener) {} + public void putValue(String key, Object value) {} + public void setEnabled(boolean b) {} + public void actionPerformed(ActionEvent e) {} + + public Object getValue(String key) { return null; } + public boolean isEnabled() { return false; } + } + + public static void main(String[] argv) { + Object[] comboData = {"First", "Second", "Third"}; + JComboBox combo = new JComboBox(comboData); + Action action = new NullAction(); + combo.setAction(action); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4276920.java b/test/jdk/javax/swing/JComboBox/bug4276920.java new file mode 100644 index 00000000000..f5de26091b3 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4276920.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 4276920 + @summary Tests that BasicComboPopup.hide() doesn't cause unnecessary repaints + @key headful +*/ + +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +public class bug4276920 { + + static volatile TestComboBox combo; + static volatile JFrame frame; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(bug4276920::createUI); + Thread.sleep(2000); + int before = combo.getRepaintCount(); + SwingUtilities.invokeAndWait(combo::hidePopup); + int after = combo.getRepaintCount(); + if (after > before) { + throw new Error("Failed 4276920: BasicComboPopup.hide() caused unnecessary repaint()"); + } + } finally { + if (frame != null) { + SwingUtilities.invokeAndWait(frame::dispose); + } + } + } + + static void createUI() { + combo = new TestComboBox(new String[] {"Why am I so slow?"}); + frame = new JFrame("bug4276920"); + frame.getContentPane().add(combo); + frame.pack(); + frame.validate(); + frame.setVisible(true); + } + + static class TestComboBox extends JComboBox { + int count = 0; + + TestComboBox(Object[] content) { + super(content); + } + + public void repaint() { + super.repaint(); + count++; + } + + int getRepaintCount() { + return count; + } + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4890345.java b/test/jdk/javax/swing/JComboBox/bug4890345.java new file mode 100644 index 00000000000..8a535f4f332 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4890345.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4890345 + @requires (os.family == "windows") + @summary 1.4.2 REGRESSION: JComboBox has problem in JTable in Windows L&F + @key headful +*/ + +import java.util.Vector; +import java.awt.BorderLayout; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableModel; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; + +public class bug4890345 { + + volatile boolean passed = false; + volatile boolean isLafOk = true; + + volatile JFrame mainFrame; + volatile JTable tbl; + + public static void main(String[] args) throws Exception { + bug4890345 test = new bug4890345(); + try { + SwingUtilities.invokeAndWait(test::createUI); + if (!test.isLafOk) { + throw new RuntimeException("Could not create Win L&F"); + } + test.test(); + } finally { + JFrame f = test.mainFrame; + if (f != null) { + SwingUtilities.invokeAndWait(() -> f.dispose()); + } + } + } + + void createUI() { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + } catch (Exception ex) { + System.err.println("Can not initialize Windows L&F. Testing skipped."); + isLafOk = false; + } + + if (isLafOk) { + mainFrame = new JFrame("Bug4890345"); + String[] items = {"tt", "aa", "gg", "zz", "dd", "ll" }; + JComboBox comboBox = new JComboBox(items); + + tbl = new JTable(); + JScrollPane panel = new JScrollPane(tbl); + TableModel tm = createTableModel(); + tbl.setModel(tm); + tbl.setRowHeight(20); + tbl.getColumnModel().getColumn(1).setCellEditor( + new DefaultCellEditor(comboBox)); + + comboBox.addPopupMenuListener(new PopupMenuListener() { + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + passed = true; + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {} + public void popupMenuCanceled(PopupMenuEvent e) {} + }); + + mainFrame.setLayout(new BorderLayout()); + mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + mainFrame.add(panel, BorderLayout.CENTER); + mainFrame.pack(); + mainFrame.setLocationRelativeTo(null); + mainFrame.setVisible(true); + } + } + + public void test() throws Exception { + Robot robo = new Robot(); + robo.setAutoDelay(50); + robo.delay(1000); + tbl.editCellAt(0,0); + + robo.keyPress(KeyEvent.VK_TAB); + robo.keyRelease(KeyEvent.VK_TAB); + + robo.keyPress(KeyEvent.VK_TAB); + robo.keyRelease(KeyEvent.VK_TAB); + + robo.keyPress(KeyEvent.VK_F2); + robo.keyRelease(KeyEvent.VK_F2); + + robo.keyPress(KeyEvent.VK_DOWN); + robo.keyRelease(KeyEvent.VK_DOWN); + + robo.keyPress(KeyEvent.VK_ENTER); + robo.keyRelease(KeyEvent.VK_ENTER); + + robo.delay(1000); + + if (!passed) { + throw new RuntimeException("Popup was not shown after VK_DOWN press. Test failed."); + } + } + + private TableModel createTableModel() { + Vector hdr = new Vector(); + hdr.add("One"); + hdr.add("Two"); + Vector data = new Vector(); + Vector row = new Vector(); + row.add("tt"); + row.add("dd"); + data.add(row); + row = new Vector(); + row.add("ll"); + row.add("jj"); + data.add(row); + return new DefaultTableModel(data, hdr); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4924758.java b/test/jdk/javax/swing/JComboBox/bug4924758.java new file mode 100644 index 00000000000..d8f77396159 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4924758.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 4924758 + @summary 1.4 REGRESSION: In Motif L&F JComboBox doesn't react when spacebar is pressed + @key headful +*/ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.event.PopupMenuListener; +import javax.swing.event.PopupMenuEvent; +import java.awt.event.KeyEvent; + +public class bug4924758 { + + static volatile boolean passed = false; + volatile boolean isLafOk = true; + + volatile JFrame mainFrame; + volatile JComboBox comboBox; + + public static void main(String[] args) throws Exception { + bug4924758 test = new bug4924758(); + try { + SwingUtilities.invokeAndWait(test::createUI); + if (!test.isLafOk) { + throw new RuntimeException("Could not create Win L&F"); + } + test.test(); + if (!passed) { + throw new RuntimeException( + "Popup was not closed after VK_SPACE press. Test failed."); + } + } finally { + JFrame f = test.mainFrame; + if (f != null) { + SwingUtilities.invokeAndWait(() -> f.dispose()); + } + } + } + + void createUI() { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + } catch (Exception ex) { + System.err.println("Can not initialize Motif L&F. Testing skipped."); + isLafOk = false; + return; + } + + mainFrame = new JFrame("Bug4924758"); + String[] items = {"One", "Two", "Three"}; + comboBox = new JComboBox(items); + comboBox.addPopupMenuListener(new PopupMenuListener() { + public void popupMenuWillBecomeVisible(PopupMenuEvent e) {} + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + passed = true; + } + + public void popupMenuCanceled(PopupMenuEvent e) {} + }); + mainFrame.setLayout(new BorderLayout()); + mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + mainFrame.add(comboBox, BorderLayout.CENTER); + mainFrame.pack(); + mainFrame.setLocationRelativeTo(null); + mainFrame.setVisible(true); + } + + void test() throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.delay(2000); + Point p = comboBox.getLocationOnScreen(); + Dimension size = comboBox.getSize(); + p.x += size.width / 2; + p.y += size.height / 2; + robot.mouseMove(p.x, p.y); + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + robot.keyPress(KeyEvent.VK_SPACE); + robot.keyRelease(KeyEvent.VK_SPACE); + robot.delay(2000); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4996503.java b/test/jdk/javax/swing/JComboBox/bug4996503.java new file mode 100644 index 00000000000..8e12a3e5743 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4996503.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4996503 + @summary REGRESSION: NotSerializableException: javax.swing.plaf.basic.BasicComboPopup+1 + @key headful +*/ + +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; +import java.io.IOException; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import java.awt.event.InputEvent; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +public class bug4996503 { + + static volatile JFrame frame = null; + static volatile JComboBox comboBox = null; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("bug4996503"); + String[] items = { "item0", "item1", "item2" }; + comboBox = new JComboBox(items); + frame.add(comboBox); + frame.pack(); + frame.validate(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.delay(1000); + Point p = comboBox.getLocationOnScreen(); + Dimension size = comboBox.getSize(); + p.x += size.width / 2; + p.y += size.height / 2; + robot.mouseMove(p.x, p.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + + ObjectOutputStream out = null; + + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + try { + out = new ObjectOutputStream(byteStream); + } catch (IOException e) {} + if (out != null) { + try { + out.writeObject(comboBox); + } catch (Exception e) { + System.out.println(e); + throw new Error("Serialization exception. Test failed."); + } + } + } finally { + if (frame != null) { + SwingUtilities.invokeAndWait(frame::dispose); + } + } + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug5029504.java b/test/jdk/javax/swing/JComboBox/bug5029504.java new file mode 100644 index 00000000000..af0bf7db471 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug5029504.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 5029504 + @summary Empty JComboBox drop-down list is unexpectedly high + @key headful +*/ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.plaf.basic.BasicComboBoxUI; +import javax.swing.plaf.basic.BasicComboPopup; +import javax.swing.event.PopupMenuListener; +import javax.swing.event.PopupMenuEvent; + +public class bug5029504 { + + static volatile boolean passed = true; + static volatile JFrame mainFrame; + static volatile JComboBox comboBox; + static volatile BasicComboPopup ourPopup = null; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(bug5029504::createUI); + runTest(); + if (!passed) { + throw new RuntimeException( + "Popup of empty JComboBox is too high. Test failed."); + } + } finally { + if (mainFrame != null) { + SwingUtilities.invokeAndWait(mainFrame::dispose); + } + } + } + + static void createUI() { + mainFrame = new JFrame("Bug4924758"); + comboBox = new JComboBox(); + comboBox.setUI(new MyComboBoxUI()); + comboBox.addPopupMenuListener(new PopupMenuListener() { + public void popupMenuWillBecomeVisible(PopupMenuEvent e) {} + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + if (ourPopup != null) { + int comboHeight = comboBox.getHeight(); + int popupHeight = ourPopup.getHeight(); + if (popupHeight > comboHeight*2) { + passed = false; + } + } + } + + public void popupMenuCanceled(PopupMenuEvent e) {} + }); + mainFrame.setLayout(new BorderLayout()); + mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + mainFrame.add(comboBox, BorderLayout.CENTER); + mainFrame.pack(); + mainFrame.setLocationRelativeTo(null); + mainFrame.validate(); + mainFrame.setVisible(true); + } + + static void runTest() throws Exception { + Robot robot = new Robot(); + robot.delay(2000); + Point p = comboBox.getLocationOnScreen(); + Dimension size = comboBox.getSize(); + p.x += size.width / 2; + p.y += size.height / 2; + robot.mouseMove(p.x, p.y); + robot.keyPress(KeyEvent.VK_ENTER); + robot.delay(50); + robot.keyRelease(KeyEvent.VK_ENTER); + robot.delay(2000); + } + + static class MyComboBoxUI extends BasicComboBoxUI { + public void setPopupVisible(JComboBox c, boolean v) { + if (popup instanceof BasicComboPopup) { + ourPopup = (BasicComboPopup) popup; + } + super.setPopupVisible(c, v); + } + } +} diff --git a/test/jdk/javax/swing/JRadioButton/bug4380543.java b/test/jdk/javax/swing/JRadioButton/bug4380543.java new file mode 100644 index 00000000000..91f11094808 --- /dev/null +++ b/test/jdk/javax/swing/JRadioButton/bug4380543.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2002, 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 4380543 + * @key headful + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary setMargin() does not work for AbstractButton + * @run main/manual bug4380543 +*/ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.Insets; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +public class bug4380543 { + static TestFrame testObj; + static String instructions + = + "INSTRUCTIONS:\n" + + " 1. Check if the Left inset(margin) is set visually\n" + + " similar to other three sides around the Radio Button\n" + + " and CheckBox (insets set to 20 on all 4 sides).\n" + + " 2. Rendering depends on OS and supported Look and Feels.\n" + + " Verify only with those L&F where margins are visible.\n" + + " 3. If the Left inset(margin) appears too small, press Fail,\n" + + " else press Pass." + ; + static PassFailJFrame passFailJFrame; + + public static void main(String[] args) throws Exception { + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + passFailJFrame = new PassFailJFrame(instructions); + testObj = new TestFrame(); + //Adding the Test Frame to handle dispose + PassFailJFrame.addTestFrame(testObj); + PassFailJFrame.positionTestFrame(testObj, PassFailJFrame.Position.HORIZONTAL); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + passFailJFrame.awaitAndCheck(); + } +} + +class TestFrame extends JFrame implements ActionListener { + public TestFrame() { + initComponents(); + } + + public void initComponents() { + JPanel p = new JPanel(); + JPanel buttonsPanel = new JPanel(); + buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.Y_AXIS)); + + JRadioButton rb = new JRadioButton("JRadioButton"); + rb.setMargin(new Insets(20, 20, 20, 20)); + rb.setBackground(Color.GREEN); + rb.setAlignmentX(0.5f); + buttonsPanel.add(rb); + + JCheckBox cb = new JCheckBox("JCheckBox"); + cb.setMargin(new Insets(20, 20, 20, 20)); + cb.setBackground(Color.YELLOW); + cb.setAlignmentX(0.5f); + buttonsPanel.add(cb); + + getContentPane().add(buttonsPanel); + UIManager.LookAndFeelInfo[] lookAndFeel = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo look : lookAndFeel) { + JButton btn = new JButton(look.getName()); + btn.setActionCommand(look.getClassName()); + btn.addActionListener(this); + p.add(btn); + } + + getContentPane().add(p,BorderLayout.SOUTH); + + setSize(500, 300); + setVisible(true); + } + + private static void setLookAndFeel(String laf) { + try { + UIManager.setLookAndFeel(laf); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Unsupported L&F: " + laf); + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + //Changing the Look and Feel on user selection + public void actionPerformed(ActionEvent e) { + setLookAndFeel(e.getActionCommand()); + SwingUtilities.updateComponentTreeUI(this); + } +} diff --git a/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java b/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java index cff2ea73c93..560c5d82331 100644 --- a/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java +++ b/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java @@ -89,6 +89,12 @@ public void runTest() throws Exception { buttonPressed = false; String lafName = laf.getClassName(); System.out.println("Testing L&F: " + lafName); + + // Ignore obsolete/deprecated Motif + if (lafName.contains("Motif")) { + System.out.println("Skipped Motif"); + continue; + } SwingUtilities.invokeAndWait(() -> { setLookAndFeel(lafName); createUI(); diff --git a/test/jdk/javax/swing/JSpinner/4788637/bug4788637.java b/test/jdk/javax/swing/JSpinner/4788637/bug4788637.java index 597f5962587..3afddc3e37a 100644 --- a/test/jdk/javax/swing/JSpinner/4788637/bug4788637.java +++ b/test/jdk/javax/swing/JSpinner/4788637/bug4788637.java @@ -21,11 +21,16 @@ * questions. */ +import java.io.File; + +import java.awt.image.BufferedImage; +import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Point; import java.awt.Rectangle; import java.awt.Robot; +import java.awt.Toolkit; import java.awt.event.InputEvent; import javax.swing.JFrame; @@ -38,8 +43,10 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import javax.imageio.ImageIO; import static javax.swing.UIManager.getInstalledLookAndFeels; + /** * @test * @bug 4788637 7124307 @@ -52,15 +59,15 @@ public final class bug4788637 { private static JFrame fr; private static Robot robot; - private int step; - private boolean spinnerValueChanged[] = {false, false, false}; + private int step = 0; + private volatile boolean spinnerValueChanged[] = {false, false, false}; - private static Point p; - private static Rectangle rect; + private static volatile Point p; + private static volatile Rectangle rect; public static void main(final String[] args) throws Exception { robot = new Robot(); - robot.setAutoDelay(50); + robot.setAutoDelay(100); robot.setAutoWaitForIdle(true); for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) { SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); @@ -68,6 +75,7 @@ public static void main(final String[] args) throws Exception { try { SwingUtilities.invokeAndWait(app::createAndShowGUI); robot.waitForIdle(); + robot.delay(1000); SwingUtilities.invokeAndWait(()-> { spinner.requestFocus(); p = spinner.getLocationOnScreen(); @@ -106,9 +114,11 @@ public void stateChanged(ChangeEvent e) { public void start() { try { Thread.sleep(1000); + System.out.println("p " + p + " rect " + rect); // Move mouse to the up arrow button robot.mouseMove(p.x+rect.width-3, p.y+3); - robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + synchronized (bug4788637.this) { if (!spinnerValueChanged[step]) { bug4788637.this.wait(3000); @@ -123,6 +133,7 @@ public void start() { bug4788637.this.wait(3000); } } + robot.waitForIdle(); // Move mouse to the up arrow button robot.mouseMove(p.x+rect.width-3, p.y+3); @@ -132,8 +143,10 @@ public void start() { bug4788637.this.wait(3000); } } + robot.waitForIdle(); - robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); } catch(Throwable t) { throw new RuntimeException(t); } @@ -145,6 +158,15 @@ public void destroy() { if (!spinnerValueChanged[0] || spinnerValueChanged[1] || !spinnerValueChanged[2]) { + System.out.println("!spinnerValueChanged[0] " + !spinnerValueChanged[0] + + " spinnerValueChanged[1] " + spinnerValueChanged[1] + + " !spinnerValueChanged[2] " + !spinnerValueChanged[2]); + try { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Rectangle screen = new Rectangle(0, 0, (int) screenSize.getWidth(), (int) screenSize.getHeight()); + BufferedImage fullScreen = robot.createScreenCapture(screen); + ImageIO.write(fullScreen, "png", new File("fullScreen.png")); + } catch (Exception e) {} throw new Error("JSpinner buttons don't conform to most platform conventions"); } } diff --git a/test/jdk/javax/swing/JSpinner/JSpinnerFocusTest.java b/test/jdk/javax/swing/JSpinner/JSpinnerFocusTest.java new file mode 100644 index 00000000000..903d4ef6a39 --- /dev/null +++ b/test/jdk/javax/swing/JSpinner/JSpinnerFocusTest.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2002, 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 headful + * @bug 4516019 + * @summary Verify that clicking on the increment/decrement buttons + * of the spinner gives focus to the spinner. + * @run main JSpinnerFocusTest + */ + +import java.awt.BorderLayout; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.InputEvent; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JSpinner; +import javax.swing.JSpinner.DefaultEditor; +import javax.swing.SwingUtilities; + +public class JSpinnerFocusTest { + + JFrame jFrame; + JButton jButton; + JSpinner jSpinner; + Robot robot; + + volatile Rectangle bounds; + volatile boolean jTextFieldFocusStatus = false; + + private void createGUI() { + jFrame = new JFrame(); + jButton = new JButton(); + jSpinner = new JSpinner(); + + jFrame.setLayout(new BorderLayout()); + jFrame.add(jButton, BorderLayout.NORTH); + jFrame.add(jSpinner, BorderLayout.CENTER); + jFrame.setLocationRelativeTo(null); + jFrame.setSize(300, 300); + jFrame.setVisible(true); + } + + public void doTest() throws Exception { + try { + robot = new Robot(); + robot.setAutoDelay(400); + + SwingUtilities.invokeAndWait(() -> createGUI()); + + robot.waitForIdle(); + runTest(); + + robot.waitForIdle(); + SwingUtilities.invokeAndWait(() -> { + jTextFieldFocusStatus = ((DefaultEditor) jSpinner.getEditor()) + .getTextField().isFocusOwner(); + }); + if (!jTextFieldFocusStatus) { + throw new RuntimeException( + "Clicking on JSpinner buttons did not" + + " shift focus to the JSpinner"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (jFrame != null) { + jFrame.dispose(); + } + }); + } + } + + private void runTest() throws Exception { + SwingUtilities.invokeAndWait(() -> { + bounds = new Rectangle(jSpinner.getLocationOnScreen(), + jSpinner.getSize()); + }); + + // Move cursor to place it in the spinner editor + robot.mouseMove(bounds.x + bounds.width / 2, + bounds.y + bounds.height / 2); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + // Move cursor to click spinner up arrow button + robot.mouseMove(bounds.x + bounds.width - 2, + bounds.y + bounds.height / 4); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } + + public static void main(String[] args) throws Exception { + new JSpinnerFocusTest().doTest(); + System.out.println("Test Passed"); + } +} diff --git a/test/jdk/javax/swing/JTable/4170447/bug4170447.java b/test/jdk/javax/swing/JTable/4170447/bug4170447.java new file mode 100644 index 00000000000..b49b5422495 --- /dev/null +++ b/test/jdk/javax/swing/JTable/4170447/bug4170447.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4170447 + @summary JTable: non-Icon data in Icon column. + @key headful +*/ + +import java.io.File; +import java.awt.Component; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableModel; + +public class bug4170447 { + + static volatile boolean failed = false; + static volatile JFrame frame = null; + + public static void main(String args[]) throws Exception { + SwingUtilities.invokeAndWait(bug4170447::createUI); + Thread.sleep(5000); + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + if (failed) { + throw new RuntimeException("Some exception occurred..."); + } + } + + static void createUI() { + String imgDir = System.getProperty("test.src", "."); + String imgPath = imgDir + File.separator + "swing.small.gif"; + ImageIcon icn = new ImageIcon(imgPath,"test"); + final Object data[][] = { + {"CELL 0 0", icn}, + {"CELL 1 0", "String"} + }; + String[] str = {"Column 0", "Column 1"}; + + TableModel dataModel = new AbstractTableModel() { + public int getColumnCount() { return 2; } + public int getRowCount() { return 2; } + public Object getValueAt(int row, int col) {return data[row][col];} + public Class getColumnClass(int c) {return getValueAt(0, c).getClass();} + public boolean isCellEditable(int row, int col) {return getColumnClass(col) == String.class;} + public void setValueAt(Object aValue, int row, int column) {data[row][column] = aValue;} + }; + + MyTable tbl = new MyTable(dataModel); + JScrollPane sp = new JScrollPane(tbl); + frame = new JFrame("bug4170447"); + frame.getContentPane().add(sp); + frame.pack(); + frame.setVisible(true); + } + + static class MyTable extends JTable { + public MyTable(TableModel tm) { + super(tm); + } + + public Component prepareRenderer(TableCellRenderer rend, int row, int col) { + try { + return super.prepareRenderer(rend, row, col); + } catch (Exception e) { + e.printStackTrace(); + failed = true; + return null; + } + } + } +} diff --git a/test/jdk/javax/swing/JTable/4170447/swing.small.gif b/test/jdk/javax/swing/JTable/4170447/swing.small.gif new file mode 100644 index 00000000000..14a489ff4e7 Binary files /dev/null and b/test/jdk/javax/swing/JTable/4170447/swing.small.gif differ diff --git a/test/jdk/javax/swing/JTable/bug4098201.java b/test/jdk/javax/swing/JTable/bug4098201.java new file mode 100644 index 00000000000..8aecb14e672 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4098201.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4098201 + @summary Tests setRowHeight(int row, int height). +*/ + +import javax.swing.JTable; + +public class bug4098201 { + + public static void main(String args[]) { + JTable table = new JTable(4,3); + table.setRowHeight(1, table.getRowHeight()*2); + if (table.getRowHeight(0) * 2 != table.getRowHeight(1)) { + throw new Error("Can't set height for specified row..."); + } + } +} diff --git a/test/jdk/javax/swing/JTable/bug4130356.java b/test/jdk/javax/swing/JTable/bug4130356.java new file mode 100644 index 00000000000..0236e551114 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4130356.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4130356 + @summary JTable.setRowSelectionInterval(int, int) shouldn't accept invalid range +*/ + +import javax.swing.JTable; +import javax.swing.ListSelectionModel; + +public class bug4130356 { + + public static void main(String[] argv) { + JTable table = new JTable(4,3); + table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + try { + table.setRowSelectionInterval(10,13); + throw new Error("Invalid arguments supported!!!"); + } catch (IllegalArgumentException iae) {} + } +} diff --git a/test/jdk/javax/swing/JTable/bug4159300.java b/test/jdk/javax/swing/JTable/bug4159300.java new file mode 100644 index 00000000000..36d9b179502 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4159300.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4159300 + @summary Tests that JTable processes tableChanged events quickly + @key headful +*/ + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Rectangle; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.DefaultTableModel; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class bug4159300 { + + static volatile JFrame frame = null; + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(bug4159300::createUI); + Thread.sleep(3000); + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + static void createUI() { + frame = new JFrame("bug4159300"); + Container c = frame.getContentPane(); + c.setLayout(new BorderLayout()); + // create table + Object[] columnNames = {"only column"}; + DefaultTableModel model = new DefaultTableModel(columnNames, 0); + Object[] row = makeRow(model.getRowCount()); + model.addRow(row); + + JTable table = new JTable(model); + c.add(new JScrollPane(table), BorderLayout.CENTER); + + // create button + JButton immediateButton = new JButton("Add row"); + immediateButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int rowCount = model.getRowCount(); + Object[] row = makeRow(rowCount); + model.addRow(row); + int rows = model.getRowCount(); + int lastRow = rows - 1; + table.setRowSelectionInterval(lastRow, lastRow); + Rectangle r = table.getCellRect(lastRow, 0, false); + table.scrollRectToVisible(r); + } + }); + c.add(immediateButton, BorderLayout.SOUTH); + frame.pack(); + frame.setVisible(true); + } + + static Object[] makeRow(int rowNumber) { + Object[] row = { ""+rowNumber }; + return row; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4243159.java b/test/jdk/javax/swing/JTable/bug4243159.java new file mode 100644 index 00000000000..7259cb3425d --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4243159.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4243159 + @summary Tests that JTable() do not throw ArrayIndexOutOfBoundsException +*/ + +import javax.swing.JTable; + +public class bug4243159 { + + /* Looks boring, but tests the no-args constructor works */ + public static void main(String[] argv) { + JTable table = new JTable(); + } +} diff --git a/test/jdk/javax/swing/JTable/bug4243313.java b/test/jdk/javax/swing/JTable/bug4243313.java new file mode 100644 index 00000000000..079fed93814 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4243313.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4243313 + @summary Tests that instantiating JTable through reflection + does not throw ClassNotFoundException +*/ + +import java.beans.Beans; + +public class bug4243313 { + + public static void main(String[] argv) throws Exception { + Object table = Beans.instantiate(null, "javax.swing.JTable"); + } +} diff --git a/test/jdk/javax/swing/JTable/bug4247487.java b/test/jdk/javax/swing/JTable/bug4247487.java new file mode 100644 index 00000000000..3a5cfcfdcd8 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4247487.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + @test + @bug 4247487 + @summary Tests that the following methods of JTable are public: + int getAccessibleColumnAtIndex(int) + int getAccessibleRowAtIndex(int) + int getAccessibleIndexAt(int, int) +*/ + +import javax.swing.JTable; + +public class bug4247487 { + + static class TestTable extends JTable { + + public TestTable() { + super(new Object[][]{{"one", "two"}}, + new Object[]{"A", "B"}); + } + + public void test() { + int[] rowIndices = {0, 0, 1, 1}; + int[] colIndices = {0, 1, 0, 1}; + JTable.AccessibleJTable at = + (JTable.AccessibleJTable)getAccessibleContext(); + + for (int i=0; i<4; i++) { + if (at.getAccessibleRowAtIndex(i) != rowIndices[i]) { + throw new Error("Failed: wrong row index"); + } + if (at.getAccessibleColumnAtIndex(i) != colIndices[i]) { + throw new Error("Failed: wrong column index"); + } + } + if (at.getAccessibleIndexAt(0,0) != 0 || + at.getAccessibleIndexAt(0,1) != 1 || + at.getAccessibleIndexAt(1,0) != 2 || + at.getAccessibleIndexAt(1,1) != 3) { + + throw new Error("Failed: wrong index"); + } + } + } + + public static void main(String[] argv) { + TestTable test = new TestTable(); + test.test(); + } +} diff --git a/test/jdk/javax/swing/JTable/bug4248070.java b/test/jdk/javax/swing/JTable/bug4248070.java new file mode 100644 index 00000000000..ffb0a2097b2 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4248070.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 4248070 + @summary cellEditor bound in JTable. +*/ + +import javax.swing.JTable; +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; + +public class bug4248070 { + + public static void main(String[] argv) { + + BeanInfo bi = null; + + try { + bi = Introspector.getBeanInfo(JTable.class); + } catch (IntrospectionException e) { + } + + PropertyDescriptor[] pd = bi.getPropertyDescriptors(); + int i; + for (i=0; i { + frame = new JFrame(); + frame.setUndecorated(true); - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JTableHeader th = new JTableHeader(); @@ -56,21 +70,33 @@ public void run() { frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + point = frame.getLocationOnScreen(); + width = frame.getWidth(); + height = frame.getHeight(); + }); + int shift = 10; + int x = point.x; + int y = point.y + height/2; + for(int i = -shift; i < width + 2*shift; i++) { + robot.mouseMove(x++, y); + robot.waitForIdle(); } - }); - robot.waitForIdle(); - Point point = frame.getLocationOnScreen(); - int shift = 10; - int x = point.x; - int y = point.y + frame.getHeight()/2; - for(int i = -shift; i < frame.getWidth() + 2*shift; i++) { - robot.mouseMove(x++, y); - } - robot.waitForIdle(); - // 9 is a magic test number - if (MyTableHeaderUI.getTestValue() != 9) { - throw new RuntimeException("Unexpected test number " - + MyTableHeaderUI.getTestValue()); + robot.waitForIdle(); + // 9 is a magic test number + if (MyTableHeaderUI.getTestValue() != 9) { + throw new RuntimeException("Unexpected test number " + + MyTableHeaderUI.getTestValue()); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); } System.out.println("ok"); } @@ -83,6 +109,15 @@ protected void rolloverColumnUpdated(int oldColumn, int newColumn) { Cursor cursor = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR); if (oldColumn != -1 && newColumn != -1 && header.getCursor() != cursor) { + try { + Dimension screenSize = + Toolkit.getDefaultToolkit().getScreenSize(); + Rectangle screen = new Rectangle(0, 0, + (int) screenSize.getWidth(), + (int) screenSize.getHeight()); + BufferedImage img = robot.createScreenCapture(screen); + ImageIO.write(img, "png", new java.io.File("image.png")); + } catch (Exception e) {} throw new RuntimeException("Wrong type of cursor!"); } } diff --git a/test/jdk/javax/swing/JTextField/JapaneseReadingAttributes/JapaneseReadingAttributes.java b/test/jdk/javax/swing/JTextField/JapaneseReadingAttributes/JapaneseReadingAttributes.java index 81d9b478a2d..00d3afc293b 100644 --- a/test/jdk/javax/swing/JTextField/JapaneseReadingAttributes/JapaneseReadingAttributes.java +++ b/test/jdk/javax/swing/JTextField/JapaneseReadingAttributes/JapaneseReadingAttributes.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 @@ -98,7 +98,7 @@ public static void main(String[] args) throws Exception { private static void setupUI() { String description = " 1. Go to \"Language Preferences -> Add a Language" + "\" and add \"Japanese\"\n" - + " 2. Set current IM to \"Japanese\" \n" + + " 2. Set current IM to \"Japanese\" and IME option to \"Full width Katakana\" \n" + " 3. Try typing in the text field to ensure" + " that Japanese IME has been successfully" + " selected \n" diff --git a/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java b/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java index fa4f44162db..d53c9b20309 100644 --- a/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java +++ b/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java @@ -56,7 +56,7 @@ public int read() throws IOException { return is.read(); } }; - var t = new AbstractWindowsTerminal(out, "test", "vt100", null, -1, false, SignalHandler.SIG_DFL, isWrapper) { + var t = new AbstractWindowsTerminal(out, "test", "vt100", null, false, SignalHandler.SIG_DFL, isWrapper) { @Override protected int getConsoleMode() { return -1; diff --git a/test/jdk/jdk/internal/jline/KeyConversionTest.java b/test/jdk/jdk/internal/jline/KeyConversionTest.java index 4eadb9a1bf3..aed9a726715 100644 --- a/test/jdk/jdk/internal/jline/KeyConversionTest.java +++ b/test/jdk/jdk/internal/jline/KeyConversionTest.java @@ -59,7 +59,7 @@ void run() throws Exception { void checkKeyConversion(KeyEvent event, String expected) throws IOException { StringBuilder result = new StringBuilder(); new AbstractWindowsTerminal(new StringWriter(), "", "windows", Charset.forName("UTF-8"), - 0, true, SignalHandler.SIG_DFL, in -> in) { + true, SignalHandler.SIG_DFL, in -> in) { @Override protected int getConsoleMode() { return 0; diff --git a/test/jdk/jdk/internal/jline/OSUtilsTest.java b/test/jdk/jdk/internal/jline/OSUtilsTest.java new file mode 100644 index 00000000000..0494ac24d90 --- /dev/null +++ b/test/jdk/jdk/internal/jline/OSUtilsTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8304498 + * @summary Verify the OSUtils class is initialized properly + * @modules jdk.internal.le/jdk.internal.org.jline.utils + */ + +import jdk.internal.org.jline.utils.OSUtils; + +public class OSUtilsTest { + public static void main(String... args) throws Exception { + new OSUtilsTest().run(); + } + + void run() throws Exception { + runTestTest(); + } + + void runTestTest() throws Exception { + if (OSUtils.IS_WINDOWS) { + return ; //skip on Windows + } + + Process p = new ProcessBuilder(OSUtils.TEST_COMMAND, "-z", "").inheritIO().start(); + if (p.waitFor() != 0) { + throw new AssertionError("Unexpected result!"); + } + } +} diff --git a/test/jdk/jdk/jfr/event/sampling/TestNative.java b/test/jdk/jdk/jfr/event/sampling/TestNative.java index 9e4ecf875a3..85729207e56 100644 --- a/test/jdk/jdk/jfr/event/sampling/TestNative.java +++ b/test/jdk/jdk/jfr/event/sampling/TestNative.java @@ -57,7 +57,7 @@ public class TestNative { public static void main(String[] args) throws Exception { String lib = System.getProperty("test.nativepath"); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-Djava.library.path=" + lib, "jdk.jfr.event.sampling.TestNative$Test"); + ProcessBuilder pb = ProcessTools.createTestJvm("-Djava.library.path=" + lib, "jdk.jfr.event.sampling.TestNative$Test"); OutputAnalyzer output = ProcessTools.executeProcess(pb); output.shouldHaveExitValue(0); diff --git a/test/jdk/jdk/jfr/event/security/TestX509CertificateEvent.java b/test/jdk/jdk/jfr/event/security/TestX509CertificateEvent.java index 7d771d5ab2d..e7e905830a4 100644 --- a/test/jdk/jdk/jfr/event/security/TestX509CertificateEvent.java +++ b/test/jdk/jdk/jfr/event/security/TestX509CertificateEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ package jdk.jfr.event.security; -import java.security.cert.CertificateFactory; import java.util.List; import jdk.jfr.Recording; @@ -31,36 +30,63 @@ import jdk.test.lib.Asserts; import jdk.test.lib.jfr.EventNames; import jdk.test.lib.jfr.Events; +import jdk.test.lib.jfr.VoidFunction; import jdk.test.lib.security.TestCertificate; /* * @test - * @bug 8148188 + * @bug 8148188 8292033 * @summary Enhance the security libraries to record events of interest * @key jfr * @requires vm.hasJFR + * @modules java.base/sun.security.x509 java.base/sun.security.tools.keytool * @library /test/lib * @run main/othervm jdk.jfr.event.security.TestX509CertificateEvent */ public class TestX509CertificateEvent { - public static void main(String[] args) throws Exception { + public static void main(String[] args) throws Throwable { + testCall(() -> { + // test regular cert construction + TestCertificate.ONE.certificate(); + TestCertificate.TWO.certificate(); + // Generate twice to make sure we (now) capture all generate cert events + TestCertificate.ONE.certificate(); + TestCertificate.TWO.certificate(); + }, 4, true); + + testCall(() -> { + // test generateCertificates method + TestCertificate.certificates(); + }, 2, true); + + testCall(() -> { + // test generateCertPath method + TestCertificate.certPath(); + }, 4, true); + + testCall(() -> { + // test keytool cert generation with JFR enabled + // The keytool test will load the dedicated keystore + // and call CertificateFactory.generateCertificate + // cacerts + TestCertificate.keyToolTest(); + }, -1, false); + } + + private static void testCall(VoidFunction f, int expected, boolean runAsserts) throws Throwable { try (Recording recording = new Recording()) { recording.enable(EventNames.X509Certificate); recording.start(); - - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - TestCertificate.ONE.generate(cf); - TestCertificate.TWO.generate(cf); - // Generate twice to make sure only one event per certificate is generated - TestCertificate.ONE.generate(cf); - TestCertificate.TWO.generate(cf); - + f.run(); recording.stop(); - List events = Events.fromRecording(recording); - Asserts.assertEquals(events.size(), 2, "Incorrect number of X509Certificate events"); - assertEvent(events, TestCertificate.ONE); - assertEvent(events, TestCertificate.TWO); + if (expected >= 0) { + Asserts.assertEquals(events.size(), expected, "Incorrect number of events"); + } + if (runAsserts) { + assertEvent(events, TestCertificate.ONE); + assertEvent(events, TestCertificate.TWO); + } } } diff --git a/test/jdk/jdk/jfr/event/security/TestX509ValidationEvent.java b/test/jdk/jdk/jfr/event/security/TestX509ValidationEvent.java index 14fbca926b8..d8ff12359a8 100644 --- a/test/jdk/jdk/jfr/event/security/TestX509ValidationEvent.java +++ b/test/jdk/jdk/jfr/event/security/TestX509ValidationEvent.java @@ -42,7 +42,7 @@ * @key jfr * @requires vm.hasJFR * @library /test/lib - * @modules jdk.jfr/jdk.jfr.events + * @modules jdk.jfr/jdk.jfr.events java.base/sun.security.x509 java.base/sun.security.tools.keytool * @run main/othervm jdk.jfr.event.security.TestX509ValidationEvent */ public class TestX509ValidationEvent { @@ -50,8 +50,8 @@ public static void main(String[] args) throws Exception { try (Recording recording = new Recording()) { recording.enable(EventNames.X509Validation); recording.start(); - // intermeditate certificate test - TestCertificate.generateChain(false); + // intermediate certificate test + TestCertificate.generateChain(false, true); recording.stop(); List events = Events.fromRecording(recording); Asserts.assertEquals(events.size(), 3, "Incorrect number of events"); @@ -62,12 +62,23 @@ public static void main(String[] args) throws Exception { recording.enable(EventNames.X509Validation); recording.start(); // self signed certificate test - TestCertificate.generateChain(true); + TestCertificate.generateChain(true, true); recording.stop(); List events = Events.fromRecording(recording); Asserts.assertEquals(events.size(), 2, "Incorrect number of events"); assertEvent2(events); } + + try (Recording recording = new Recording()) { + recording.enable(EventNames.X509Validation); + recording.start(); + // intermediate certificate test, with no Cert for trust anchor + TestCertificate.generateChain(true, false); + recording.stop(); + List events = Events.fromRecording(recording); + Asserts.assertEquals(events.size(), 2, "Incorrect number of events"); + assertEvent3(events); + } } private static void assertEvent1(List events) throws Exception { @@ -111,4 +122,26 @@ private static void assertEvent2(List events) throws Exception { } } } + /* + * Self signed certificate test + */ + private static void assertEvent3(List events) throws Exception { + for (RecordedEvent e : events) { + int pos = e.getInt("certificatePosition"); + switch (pos) { + // use public key of cert provided in TrustAnchor + case 1: + Asserts.assertEquals(e.getLong("certificateId"), + Long.valueOf(TestCertificate.ROOT_CA.certificate().getPublicKey().hashCode())); + break; + case 2: + Events.assertField(e, "certificateId") + .equal(TestCertificate.ROOT_CA.certId); + break; + default: + System.out.println(events); + throw new Exception("Unexpected position:" + pos); + } + } + } } diff --git a/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java b/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java index 77667547f35..b84e94f18f0 100644 --- a/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java +++ b/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java @@ -91,7 +91,7 @@ public static void main(String[] args) throws Exception { private static long runProcess(String crasher, String signal, boolean disk) throws Exception { System.out.println("Test case for crasher " + crasher); final String flightRecordingOptions = "dumponexit=true,disk=" + Boolean.toString(disk); - Process p = ProcessTools.createJavaProcessBuilder(true, + Process p = ProcessTools.createTestJvm( "-Xmx64m", "-XX:-TransmitErrorReport", "-XX:-CreateCoredumpOnCrash", diff --git a/test/jdk/jdk/jfr/jvm/TestJfrJavaBase.java b/test/jdk/jdk/jfr/jvm/TestJfrJavaBase.java index 71806c63bd9..f3bbc590f1d 100644 --- a/test/jdk/jdk/jfr/jvm/TestJfrJavaBase.java +++ b/test/jdk/jdk/jfr/jvm/TestJfrJavaBase.java @@ -51,7 +51,7 @@ private static void checkOutput(OutputAnalyzer output) { public static void main(String[] args) throws Exception { OutputAnalyzer output; if (args.length == 0) { - output = ProcessTools.executeProcess(ProcessTools.createJavaProcessBuilder(false, + output = ProcessTools.executeProcess(ProcessTools.createJavaProcessBuilder( "-Dtest.jdk=" + System.getProperty("test.jdk"), "--limit-modules", "java.base", "-cp", System.getProperty("java.class.path"), TestJfrJavaBase.class.getName(), "runtest")); diff --git a/test/jdk/jdk/jfr/startupargs/TestDumpOnExit.java b/test/jdk/jdk/jfr/startupargs/TestDumpOnExit.java index ee404d9d9dc..b4b9a03826d 100644 --- a/test/jdk/jdk/jfr/startupargs/TestDumpOnExit.java +++ b/test/jdk/jdk/jfr/startupargs/TestDumpOnExit.java @@ -94,7 +94,7 @@ private static Path findJFRFileInCurrentDirectory() { } private static void testDumponExit(Supplier p,String... args) throws Exception, IOException { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, args); + ProcessBuilder pb = ProcessTools.createTestJvm(args); OutputAnalyzer output = ProcessTools.executeProcess(pb); System.out.println(output.getOutput()); output.shouldHaveExitValue(0); diff --git a/test/jdk/jdk/jfr/startupargs/TestMemoryOptions.java b/test/jdk/jdk/jfr/startupargs/TestMemoryOptions.java index 168ec73d1e4..03411a1e6e7 100644 --- a/test/jdk/jdk/jfr/startupargs/TestMemoryOptions.java +++ b/test/jdk/jdk/jfr/startupargs/TestMemoryOptions.java @@ -485,21 +485,19 @@ private static void launchTestVM(TestCase tc) throws Exception { final String flightRecorderOptions = tc.getTestString(); ProcessBuilder pb; if (flightRecorderOptions != null) { - pb = ProcessTools.createJavaProcessBuilder(true, - "--add-exports=jdk.jfr/jdk.jfr.internal=ALL-UNNAMED", - "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", - flightRecorderOptions, - "-XX:StartFlightRecording", - SUT.class.getName(), - tc.getTestName()); + pb = ProcessTools.createTestJvm("--add-exports=jdk.jfr/jdk.jfr.internal=ALL-UNNAMED", + "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", + flightRecorderOptions, + "-XX:StartFlightRecording", + SUT.class.getName(), + tc.getTestName()); } else { // default, no FlightRecorderOptions passed - pb = ProcessTools.createJavaProcessBuilder(true, - "--add-exports=jdk.jfr/jdk.jfr.internal=ALL-UNNAMED", - "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", - "-XX:StartFlightRecording", - SUT.class.getName(), - tc.getTestName()); + pb = ProcessTools.createTestJvm("--add-exports=jdk.jfr/jdk.jfr.internal=ALL-UNNAMED", + "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", + "-XX:StartFlightRecording", + SUT.class.getName(), + tc.getTestName()); } System.out.println("Driver launching SUT with string: " + flightRecorderOptions != null ? flightRecorderOptions : "default"); diff --git a/test/jdk/jdk/jfr/startupargs/TestMultipleStartupRecordings.java b/test/jdk/jdk/jfr/startupargs/TestMultipleStartupRecordings.java index de3589f9aac..19b8734f55f 100644 --- a/test/jdk/jdk/jfr/startupargs/TestMultipleStartupRecordings.java +++ b/test/jdk/jdk/jfr/startupargs/TestMultipleStartupRecordings.java @@ -57,14 +57,14 @@ private static void test(ProcessBuilder pb, String... expectedOutputs) throws Ex private static void launchUnary(String options) throws Exception { String recording1 = START_FLIGHT_RECORDING + (options != null ? options : ""); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, recording1, MainClass.class.getName()); + ProcessBuilder pb = ProcessTools.createTestJvm(recording1, MainClass.class.getName()); test(pb, "Started recording 1"); } private static void launchBinary(String options1, String options2) throws Exception { String recording1 = START_FLIGHT_RECORDING + (options1 != null ? options1 : ""); String recording2 = START_FLIGHT_RECORDING + (options2 != null ? options2 : ""); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, recording1, recording2, MainClass.class.getName()); + ProcessBuilder pb = ProcessTools.createTestJvm(recording1, recording2, MainClass.class.getName()); test(pb, "Started recording 1", "Started recording 2"); } @@ -72,7 +72,7 @@ private static void launchTernary(String options1, String options2, String optio String recording1 = START_FLIGHT_RECORDING + (options1 != null ? options1 : ""); String recording2 = START_FLIGHT_RECORDING + (options2 != null ? options2 : ""); String recording3 = START_FLIGHT_RECORDING + (options3 != null ? options3 : ""); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, recording1, recording2, recording3, MainClass.class.getName()); + ProcessBuilder pb = ProcessTools.createTestJvm(recording1, recording2, recording3, MainClass.class.getName()); test(pb, "Started recording 1", "Started recording 2", "Started recording 3"); } @@ -96,7 +96,7 @@ private static void testWithFlightRecorderOptions() throws Exception { String flightRecorderOptions = FLIGHT_RECORDER_OPTIONS + "=maxchunksize=8m"; String recording1 = START_FLIGHT_RECORDING + "=filename=recording1.jfr"; String recording2 = START_FLIGHT_RECORDING + "=name=myrecording,filename=recording2.jfr"; - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, flightRecorderOptions, recording1, recording2, MainClass.class.getName()); + ProcessBuilder pb = ProcessTools.createTestJvm(flightRecorderOptions, recording1, recording2, MainClass.class.getName()); test(pb, "Started recording 1", "Started recording 2"); } diff --git a/test/jdk/jdk/jfr/startupargs/TestRetransformUsingLog.java b/test/jdk/jdk/jfr/startupargs/TestRetransformUsingLog.java index 902be7d5277..9c76bc2e92d 100644 --- a/test/jdk/jdk/jfr/startupargs/TestRetransformUsingLog.java +++ b/test/jdk/jdk/jfr/startupargs/TestRetransformUsingLog.java @@ -106,7 +106,7 @@ private static void startApp(boolean recording, boolean retransform, Consumer env) throws Exception { final URI uri = URI.create("jar:" + ZIP_FILE.toUri() ); final byte[] chunk = new byte[1024]; - new Random().nextBytes(chunk); + // fill it with some fixed content (the fixed content will later on help ease + // the verification of the content written out) + Arrays.fill(chunk, (byte) 42); try (final FileSystem zipfs = FileSystems.newFileSystem(uri, env)) { // create the zip with varying sized entries for (final Map.Entry entry : ZIP_ENTRIES.entrySet()) { @@ -98,9 +100,12 @@ public void testOutputStream(final Map env) throws Exception { if (entryPath.getParent() != null) { Files.createDirectories(entryPath.getParent()); } + long start = System.currentTimeMillis(); try (final OutputStream os = Files.newOutputStream(entryPath)) { writeAsChunks(os, chunk, entry.getValue()); } + System.out.println("Wrote entry " + entryPath + " of bytes " + entry.getValue() + + " in " + (System.currentTimeMillis() - start) + " milli seconds"); } } // now verify the written content @@ -111,15 +116,15 @@ public void testOutputStream(final Map env) throws Exception { final byte[] buf = new byte[chunk.length]; int numRead; long totalRead = 0; + long start = System.currentTimeMillis(); while ((numRead = is.read(buf)) != -1) { totalRead += numRead; // verify the content - for (int i = 0, chunkoffset = (int) ((totalRead - numRead) % chunk.length); - i < numRead; i++, chunkoffset++) { - Assert.assertEquals(buf[i], chunk[chunkoffset % chunk.length], - "Unexpected content in " + entryPath); - } + Assert.assertEquals(Arrays.mismatch(buf, 0, numRead, chunk, 0, numRead), -1, + "Unexpected content in " + entryPath); } + System.out.println("Read entry " + entryPath + " of bytes " + totalRead + + " in " + (System.currentTimeMillis() - start) + " milli seconds"); Assert.assertEquals(totalRead, (long) entry.getValue(), "Unexpected number of bytes read from zip entry " + entryPath); } diff --git a/test/jdk/jdk/security/logging/TestX509CertificateLog.java b/test/jdk/jdk/security/logging/TestX509CertificateLog.java index 215e62f4a3e..018ec60181d 100644 --- a/test/jdk/jdk/security/logging/TestX509CertificateLog.java +++ b/test/jdk/jdk/security/logging/TestX509CertificateLog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ package jdk.security.logging; -import java.security.cert.CertificateFactory; import jdk.test.lib.security.TestCertificate; /* @@ -31,6 +30,7 @@ * @bug 8148188 * @summary Enhance the security libraries to record events of interest * @library /test/lib /test/jdk + * @modules java.base/sun.security.x509 java.base/sun.security.tools.keytool * @run main/othervm jdk.security.logging.TestX509CertificateLog LOGGING_ENABLED * @run main/othervm jdk.security.logging.TestX509CertificateLog LOGGING_DISABLED */ @@ -58,9 +58,8 @@ public static void main(String[] args) throws Exception { public static class GenerateX509Certicate { public static void main(String[] args) throws Exception { - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - TestCertificate.ONE.generate(cf); - TestCertificate.TWO.generate(cf); + TestCertificate.ONE.certificate(); + TestCertificate.TWO.certificate(); } } } diff --git a/test/jdk/jdk/security/logging/TestX509ValidationLog.java b/test/jdk/jdk/security/logging/TestX509ValidationLog.java index 7fe659764b8..805cd546729 100644 --- a/test/jdk/jdk/security/logging/TestX509ValidationLog.java +++ b/test/jdk/jdk/security/logging/TestX509ValidationLog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 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 @@ -30,6 +30,7 @@ * @bug 8148188 * @summary Enhance the security libraries to record events of interest * @library /test/lib /test/jdk + * @modules java.base/sun.security.x509 java.base/sun.security.tools.keytool * @run main/othervm jdk.security.logging.TestX509ValidationLog LOGGING_ENABLED * @run main/othervm jdk.security.logging.TestX509ValidationLog LOGGING_DISABLED */ @@ -43,14 +44,19 @@ public static void main(String[] args) throws Exception { l.addExpected("FINE: ValidationChain: " + TestCertificate.ROOT_CA.certId + ", " + TestCertificate.ROOT_CA.certId); + l.addExpected("FINE: ValidationChain: " + + TestCertificate.ROOT_CA.certificate().getPublicKey().hashCode() + + ", " + TestCertificate.ROOT_CA.certId); l.testExpected(); } public static class GenerateCertificateChain { public static void main(String[] args) throws Exception { - TestCertificate.generateChain(false); + TestCertificate.generateChain(false, true); // self signed test - TestCertificate.generateChain(true); + TestCertificate.generateChain(true, true); + // no cert for trust anchor + TestCertificate.generateChain(true, false); } } } diff --git a/test/jdk/sanity/client/SwingSet/src/ToolTipDemoTest.java b/test/jdk/sanity/client/SwingSet/src/ToolTipDemoTest.java index 5c8c159a6b2..ecfc8ee5e97 100644 --- a/test/jdk/sanity/client/SwingSet/src/ToolTipDemoTest.java +++ b/test/jdk/sanity/client/SwingSet/src/ToolTipDemoTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 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 @@ -38,6 +38,7 @@ import org.jtregext.GuiTestListener; import org.netbeans.jemmy.ClassReference; +import org.netbeans.jemmy.JemmyProperties; import org.netbeans.jemmy.operators.JComponentOperator; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JLabelOperator; @@ -79,12 +80,20 @@ public class ToolTipDemoTest { @Test(dataProvider = "availableLookAndFeels", dataProviderClass = TestHelpers.class) public void test(String lookAndFeel) throws Exception { UIManager.setLookAndFeel(lookAndFeel); + + JemmyProperties.setCurrentDispatchingModel(JemmyProperties.ROBOT_MODEL_MASK | + JemmyProperties.SMOOTH_ROBOT_MODEL_MASK); + new ClassReference(ToolTipDemo.class.getCanonicalName()).startApplication(); JFrameOperator frameOperator = new JFrameOperator(DEMO_TITLE); frameOperator.setComparator(EXACT_STRING_COMPARATOR); // Setting the tooltip dismiss delay ToolTipManager.sharedInstance().setDismissDelay(TOOLTIP_DISMISS_DELAY); + //activate window + frameOperator.clickMouse(); + frameOperator.moveMouse(-1, -1); + // Verifying the plain tooltip properties checkToolTip(frameOperator, PLAIN_TOOLTIP_COMP_TITLE, PLAIN_TOOLTIP_TEXT); @@ -116,18 +125,15 @@ public void test(String lookAndFeel) throws Exception { */ private void checkToolTip(JFrameOperator frameOperator, String compTitle, String toolTipText) { - JLabelOperator toolTipHostComp = new JLabelOperator(frameOperator, compTitle); JToolTipOperator toolTipOperator = new JToolTipOperator(toolTipHostComp.showToolTip()); toolTipOperator.waitTipText(toolTipText); checkToolTipLocation(toolTipHostComp, toolTipOperator); - - // Dismissing the tooltip by mouse click - toolTipHostComp.clickMouse(); + // Dismissing the tooltip by moving the mouse out + toolTipHostComp.moveMouse(-1, -1); toolTipOperator.waitComponentShowing(false); - } private void checkToolTipLocation(JComponentOperator componentOpertor, diff --git a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java index e76210b16d1..cd1db71c418 100644 --- a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java +++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,221 +33,185 @@ /* * Obtain test artifacts for Actalis CA from: * - * Test web site with *active *TLS Server certificate: - * https://ssltest-a.actalis.it:8443 - * If doesn't work then use certificate of https://www.actalis.it + * Test website with *active* TLS Server certificate: + * https://ssltest-active.actalis.it/ * - * Test web site with *revoked *TLS Server certificate: - * https://ssltest-r.actalis.it:8444 + * Test website with *revoked* TLS Server certificate: + * https://ssltest-revoked.actalis.it/ * - * Test web site with *expired *TLS Server certificate: - * https://ssltest-e.actalis.it:8445 + * Test website with *expired* TLS Server certificate: + * https://ssltest-expired.actalis.it/ */ public class ActalisCA { - // Owner: CN=Actalis Extended Validation Server CA G1, - // O=Actalis S.p.A./03358520967, L=Milano, ST=Milano, C=IT - // Issuer: CN=Actalis Authentication Root CA, O=Actalis S.p.A./03358520967, - // L=Milan, C=IT - private static final String INT_VALID = "-----BEGIN CERTIFICATE-----\n" - + "MIIGTDCCBDSgAwIBAgIIMtYr/GdQGsswDQYJKoZIhvcNAQELBQAwazELMAkGA1UE\n" - + "BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w\n" - + "MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290\n" - + "IENBMB4XDTE1MDUxNDA3MDAzOFoXDTMwMDUxNDA3MDAzOFowgYcxCzAJBgNVBAYT\n" - + "AklUMQ8wDQYDVQQIDAZNaWxhbm8xDzANBgNVBAcMBk1pbGFubzEjMCEGA1UECgwa\n" - + "QWN0YWxpcyBTLnAuQS4vMDMzNTg1MjA5NjcxMTAvBgNVBAMMKEFjdGFsaXMgRXh0\n" - + "ZW5kZWQgVmFsaWRhdGlvbiBTZXJ2ZXIgQ0EgRzEwggEiMA0GCSqGSIb3DQEBAQUA\n" - + "A4IBDwAwggEKAoIBAQD1Ygc1CwmqXqjd3dTEKMLUwGdb/3+00ytg0uBb4RB+89/O\n" - + "4K/STFZcGUjcCq6Job5cmxZBGyRRBYfCEn4vg8onedFztkO0NvD04z4wLFyxjSRT\n" - + "bcMm2d+/Xci5XLA3Q9wG8TGzHTVQKmdvFpQ7b7EsmOc0uXA7w3UGhLjb2EYpu/Id\n" - + "uZ1LUTyEOHc3XHXI3a3udkRBDs/bObTcbte80DPbNetRFB+jHbIw5sH171IeBFGN\n" - + "PB92Iebp01yE8g3X9RqPXrrV7ririEtwFMYp+KgA8BRHxsoNV3xZmhdzJm0AMzC2\n" - + "waLM3H562xPM0UntAYh2pRrAUUtgURRizCT1kr6tAgMBAAGjggHVMIIB0TBBBggr\n" - + "BgEFBQcBAQQ1MDMwMQYIKwYBBQUHMAGGJWh0dHA6Ly9vY3NwMDUuYWN0YWxpcy5p\n" - + "dC9WQS9BVVRILVJPT1QwHQYDVR0OBBYEFGHB5IYeTW10dLzZlzsxcXjLP5/cMA8G\n" - + "A1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbtifN7OHCUyQICNtAw\n" - + "RQYDVR0gBD4wPDA6BgRVHSAAMDIwMAYIKwYBBQUHAgEWJGh0dHBzOi8vd3d3LmFj\n" - + "dGFsaXMuaXQvYXJlYS1kb3dubG9hZDCB4wYDVR0fBIHbMIHYMIGWoIGToIGQhoGN\n" - + "bGRhcDovL2xkYXAwNS5hY3RhbGlzLml0L2NuJTNkQWN0YWxpcyUyMEF1dGhlbnRp\n" - + "Y2F0aW9uJTIwUm9vdCUyMENBLG8lM2RBY3RhbGlzJTIwUy5wLkEuJTJmMDMzNTg1\n" - + "MjA5NjcsYyUzZElUP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q7YmluYXJ5MD2g\n" - + "O6A5hjdodHRwOi8vY3JsMDUuYWN0YWxpcy5pdC9SZXBvc2l0b3J5L0FVVEgtUk9P\n" - + "VC9nZXRMYXN0Q1JMMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEA\n" - + "OD8D2Z2fw76+GIu+mDEgygH/y7F9K4I6rZOc3LqGBecO3C0fGcIuuG7APtxGGk7Y\n" - + "nk97Qt+3pDoek9EP65/1u128pRncZcjEAeMgKb7UuJxwoR6Sj5zhOadotKcCQqmF\n" - + "Si99ExNo6dTq5Eyp1KrqepLmezbO9owx4Q44mtNpfKLMgzDqOn/dwNMo/pGYbMfP\n" - + "DjhxEnta1HXgcEcgCk1Au16xkdzapwY4sXpKuwB24phfWF+cveKAQ0Rncmvrm34i\n" - + "9B6leZUkSHDe4mRkbO5nObhKHYRmVSr0Q/wvGCmTgGTKuw/Gj8+RFb5MEkOKEcJn\n" - + "I32CPohpiW/jlpeLaFBIgJnXuZTxmfTX55sqtXDlKxRxFwq1W3kML4UfGZsgjx1l\n" - + "hX5fQ1QlEZeO9CyPpgGO5Py2KXXKhUxCtF7tawAYimWwslxvPCjHDND/WhM1Fz9e\n" - + "2yqwHcSQAOUVv5mk9uYc6/NSLwLb5in3R728GNEpHHhbx5QZhtdqR8mb56uJUDKI\n" - + "AwnnZckcR+SLGL2Agx7hY7YCMOQhSsO6PA81M/mGW2hGCiZw3GULJe9ejL/vdS0I\n" - + "PWrp7YLnXUa6mtXVSBKGrVrlbpJaN10+fB4Yrlk4O2sF4WNUAHMBn9T+zOXaBAhj\n" - + "vNlMU7+elLkTcKIB7qJJuSZChxzoevM2ciO3BpGuRxg=\n" - + "-----END CERTIFICATE-----"; + // Owner: CN=Actalis Organization Validated Server CA G3, O=Actalis S.p.A., + // L=Ponte San Pietro, ST=Bergamo, C=IT + // Issuer: CN=Actalis Authentication Root CA, O=Actalis S.p.A ./03358520967, + // L=Milan, C=IT + // Serial number: 5c3b3f37adfc28fe0fcfd3abf83f8551 + // Valid from: Mon Jul 06 00:20:55 PDT 2020 until: Sun Sep 22 04:22:02 PDT 2030 + private static final String INT = "-----BEGIN CERTIFICATE-----\n" + + "MIIHdTCCBV2gAwIBAgIQXDs/N638KP4Pz9Or+D+FUTANBgkqhkiG9w0BAQsFADBr\n" + + "MQswCQYDVQQGEwJJVDEOMAwGA1UEBwwFTWlsYW4xIzAhBgNVBAoMGkFjdGFsaXMg\n" + + "Uy5wLkEuLzAzMzU4NTIwOTY3MScwJQYDVQQDDB5BY3RhbGlzIEF1dGhlbnRpY2F0\n" + + "aW9uIFJvb3QgQ0EwHhcNMjAwNzA2MDcyMDU1WhcNMzAwOTIyMTEyMjAyWjCBiTEL\n" + + "MAkGA1UEBhMCSVQxEDAOBgNVBAgMB0JlcmdhbW8xGTAXBgNVBAcMEFBvbnRlIFNh\n" + + "biBQaWV0cm8xFzAVBgNVBAoMDkFjdGFsaXMgUy5wLkEuMTQwMgYDVQQDDCtBY3Rh\n" + + "bGlzIE9yZ2FuaXphdGlvbiBWYWxpZGF0ZWQgU2VydmVyIENBIEczMIICIjANBgkq\n" + + "hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs73Ch+t2owm3ayTkyqy0OPuCTiybxTyS\n" + + "4cU4y0t2RGSwCNjLh/rcutO0yoriZxVtPrNMcIRQ544BQhHFt/ypW7e+t8wWKrHa\n" + + "r3BkKwSUbqNwpDWP1bXs7IJTVhHXWGAm7Ak1FhrrBmtXk8QtdzTzDDuxfFBK7sCL\n" + + "N0Jdqoqb1V1z3wsWqAvr4KlSCFW05Nh4baWm/kXOmb8U+XR6kUmuoVvia3iBhotR\n" + + "TzAHTO9SWWkgjTcir/nhBvyL2RoqkgYyP/k50bznaVOGFnFWzfl0XnrM/salfCBh\n" + + "O0/1vNaoU8elR6AtbdCFAupgQy95GuFIRVS8n/cF0QupfPjUl+kGSLzvGAc+6oNE\n" + + "alpAhKIS/+P0uODzRrS9Eq0WX1iSj6KHtQMNN4ZKsS4nsuvYCahnAc0QwQyoduAW\n" + + "iU/ynhU9WTIEe1VIoEDE79NPOI2/80RqbZqdpAKUaf0FvuqVXhEcjiJJu+d0w9YN\n" + + "b7gurd6xkaSXemW/fP4idBiNkd8aCVAdshGQYn6yh+na0Lu5IG88Z2kSIFcXDtwy\n" + + "zjcxkW86pwkO6GekEomVBNKcv0Cey2Smf8uhpZk15TSCeyFDrZBWH9OsDst/Tnhz\n" + + "pN156Huw3M3RRdEegt33fcyPykgt0HThxrEv9DwOzhs6lCQ5RNQJO7ZvZF1ZiqgT\n" + + "FOJ6vs1xMqECAwEAAaOCAfQwggHwMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgw\n" + + "FoAUUtiIOsifeGbtifN7OHCUyQICNtAwQQYIKwYBBQUHAQEENTAzMDEGCCsGAQUF\n" + + "BzABhiVodHRwOi8vb2NzcDA1LmFjdGFsaXMuaXQvVkEvQVVUSC1ST09UMEUGA1Ud\n" + + "IAQ+MDwwOgYEVR0gADAyMDAGCCsGAQUFBwIBFiRodHRwczovL3d3dy5hY3RhbGlz\n" + + "Lml0L2FyZWEtZG93bmxvYWQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMB\n" + + "MIHjBgNVHR8EgdswgdgwgZaggZOggZCGgY1sZGFwOi8vbGRhcDA1LmFjdGFsaXMu\n" + + "aXQvY24lM2RBY3RhbGlzJTIwQXV0aGVudGljYXRpb24lMjBSb290JTIwQ0EsbyUz\n" + + "ZEFjdGFsaXMlMjBTLnAuQS4lMmYwMzM1ODUyMDk2NyxjJTNkSVQ/Y2VydGlmaWNh\n" + + "dGVSZXZvY2F0aW9uTGlzdDtiaW5hcnkwPaA7oDmGN2h0dHA6Ly9jcmwwNS5hY3Rh\n" + + "bGlzLml0L1JlcG9zaXRvcnkvQVVUSC1ST09UL2dldExhc3RDUkwwHQYDVR0OBBYE\n" + + "FJ+KsbXxsd6C9Cd8vojN3qlDgaNLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0B\n" + + "AQsFAAOCAgEAJbygMnKJ5M6byr5Ectq05ODqwNMtky8TEF3O55g6RHhxblf6OegZ\n" + + "4ui4+ElHNOIXjycbeuUGuFA4LScCC9fnI1Rnn8TI2Q7OP5YWifEfnrdp99t/tJzQ\n" + + "hfdi7ZTdRRZZGV9x+grfR/RtjT2C3Lt9X4lcbuSxTea3PHAwwi0A3bYRR1L5ciPm\n" + + "eAnYtG9kpat8/RuC22oxiZZ5FdjU6wrRWkASRLiIwNcFIYfvpUbMWElaCUhqaB2y\n" + + "YvWF8o02pnaYb4bvTCg4cVabVnojUuuXH81LeQhhsSXLwcdwSdew0NL4zCiNCn2Q\n" + + "iDZpz2biCWDggibmWxsUUF6AbqMHnwsdS8vsKXiFQJHeAdNAhA+kwpqYAdhUiCdj\n" + + "RTUdtRNUucLvZEN1OAvVYyog9xYCfhtkqgXQROMANP+Z/+yaZahaP/Vgak/V00se\n" + + "Hdh7F+B6h5HVdwdh+17E2jl+aMTfyvBFcg2H/9Qjyl4TY8NW/6v0DPK52sVt8a35\n" + + "I+7xLGLPohAl4z6pEf2OxgjMNfXXCXS33smRgz1dLQFo8UpAb3rf84zkXaqEI6Qi\n" + + "2P+5pibVFQigRbn4RcE+K2a/nm2M/o+WZTSio+E+YXacnNk71VcO82biOof+jBKT\n" + + "iC3Xi7rAlypmme+QFBw9F1J89ig3smV/HaN8tO0lfTpvm7Zvzd5TkMs=\n" + + "-----END CERTIFICATE-----"; - // Owner: OID.1.3.6.1.4.1.311.60.2.1.3=IT, STREET=Via S. Clemente 53, - // OID.2.5.4.15=Private Organization, CN=www.actalis.it, - // SERIALNUMBER=03358520967, O=Actalis S.p.A., L=Ponte San Pietro, ST=Bergamo, C=IT - // Issuer: CN=Actalis Extended Validation Server CA G1, - // O=Actalis S.p.A./03358520967, L=Milano, ST=Milano, C=IT - // Serial number: eeeee6d6463bde2 - // Valid from: Sat Jun 17 05:59:17 PDT 2017 until: Mon Jun 17 05:59:17 PDT 2019 - private static final String VALID = "-----BEGIN CERTIFICATE-----\n" - + "MIIHwTCCBqmgAwIBAgIIDu7ubWRjveIwDQYJKoZIhvcNAQELBQAwgYcxCzAJBgNV\n" - + "BAYTAklUMQ8wDQYDVQQIDAZNaWxhbm8xDzANBgNVBAcMBk1pbGFubzEjMCEGA1UE\n" - + "CgwaQWN0YWxpcyBTLnAuQS4vMDMzNTg1MjA5NjcxMTAvBgNVBAMMKEFjdGFsaXMg\n" - + "RXh0ZW5kZWQgVmFsaWRhdGlvbiBTZXJ2ZXIgQ0EgRzEwHhcNMTcwNjE3MTI1OTE3\n" - + "WhcNMTkwNjE3MTI1OTE3WjCB0zELMAkGA1UEBhMCSVQxEDAOBgNVBAgMB0Jlcmdh\n" - + "bW8xGTAXBgNVBAcMEFBvbnRlIFNhbiBQaWV0cm8xFzAVBgNVBAoMDkFjdGFsaXMg\n" - + "Uy5wLkEuMRQwEgYDVQQFEwswMzM1ODUyMDk2NzEXMBUGA1UEAwwOd3d3LmFjdGFs\n" - + "aXMuaXQxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRswGQYDVQQJDBJW\n" - + "aWEgUy4gQ2xlbWVudGUgNTMxEzARBgsrBgEEAYI3PAIBAxMCSVQwggEiMA0GCSqG\n" - + "SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwZ3++4pQYGfhXSqin1CKRJ6SOqkTcX3O0\n" - + "6b4jZbSNomyqyn6aHOz6ztOlj++fPzxmIzErEySOTd3G0pr+iwpYQVdeg1Y27KL8\n" - + "OiwwUrlV4ZMa8KKXr4BnWlDbFIo+eIcSew5V7CiodDyxpj9zjqJK497LF1jxgXtr\n" - + "IoMRwrh2Y0NbJCZGUCL30sQr/W4xBnO1+pi2DbCieGe/XoK8yEtx9FdnEFvyT9qn\n" - + "zYyrXvnTvfVSwzwtEIn+akjomI4WfCFLBF0M7v4dAHypfnPAAoW1c0BBqNB32zf0\n" - + "rYwNnD7UwZlcDihEYlgC70Dfy7bPsdq2spmOMk/VUqb3U0LHRVM3AgMBAAGjggPh\n" - + "MIID3TB9BggrBgEFBQcBAQRxMG8wOgYIKwYBBQUHMAKGLmh0dHA6Ly9jYWNlcnQu\n" - + "YWN0YWxpcy5pdC9jZXJ0cy9hY3RhbGlzLWF1dGV2ZzEwMQYIKwYBBQUHMAGGJWh0\n" - + "dHA6Ly9vY3NwMDUuYWN0YWxpcy5pdC9WQS9BVVRIRVYtRzEwHQYDVR0OBBYEFK9y\n" - + "954QoY/5XV6TayD1gWVy0gQOMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUYcHk\n" - + "hh5NbXR0vNmXOzFxeMs/n9wwUAYDVR0gBEkwRzA8BgYrgR8BEQEwMjAwBggrBgEF\n" - + "BQcCARYkaHR0cHM6Ly93d3cuYWN0YWxpcy5pdC9hcmVhLWRvd25sb2FkMAcGBWeB\n" - + "DAEBMIHvBgNVHR8EgecwgeQwgaKggZ+ggZyGgZlsZGFwOi8vbGRhcDA1LmFjdGFs\n" - + "aXMuaXQvY24lM2RBY3RhbGlzJTIwRXh0ZW5kZWQlMjBWYWxpZGF0aW9uJTIwU2Vy\n" - + "dmVyJTIwQ0ElMjBHMSxvJTNkQWN0YWxpcyUyMFMucC5BLi8wMzM1ODUyMDk2Nyxj\n" - + "JTNkSVQ/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5hcnkwPaA7oDmGN2h0\n" - + "dHA6Ly9jcmwwNS5hY3RhbGlzLml0L1JlcG9zaXRvcnkvQVVUSEVWLUcxL2dldExh\n" - + "c3RDUkwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\n" - + "BQcDAjAZBgNVHREEEjAQgg53d3cuYWN0YWxpcy5pdDCCAX4GCisGAQQB1nkCBAIE\n" - + "ggFuBIIBagFoAHYApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFc\n" - + "tiwHywAABAMARzBFAiEA7GC5/kja3l8cBw1/wBpHl/AKH6eL1MKpmICtf5G09c4C\n" - + "IBM887DQEwD2E4Xx/IP+33NMvUOhSwZ4XODgqFVXsz0wAHYA7ku9t3XOYLrhQmkf\n" - + "q+GeZqMPfl+wctiDAMR7iXqo/csAAAFctiwIqwAABAMARzBFAiEAwwiR95ozXdKs\n" - + "+uULfrzgENbHc2rLgGIac6ZMv0xHDLACIFLQVpvQBRQfys2KVRGHQKGxqAeghQZw\n" - + "9nJL+U5huzfaAHYA3esdK3oNT6Ygi4GtgWhwfi6OnQHVXIiNPRHEzbbsvswAAAFc\n" - + "tiwMqwAABAMARzBFAiEAifV9ocxbO6b3I22jb2zxBvG2e83hXHitOhYXkHdSmZkC\n" - + "IDJLuPvGOczF9axgphImlUbT9dX3wRpjEi5IeV+pxMiYMA0GCSqGSIb3DQEBCwUA\n" - + "A4IBAQB5U6k1Onv9Y7POHGnUOI0ATHevbpbS/7r68DZQ6cRmDIpsZyjW6PxYs9nc\n" - + "3ob3Pjomm+S7StDl9ehI7rYLlZC52QlXlsq1fzEQ9xSkf+VSD70A91dPIFAdI/jQ\n" - + "aWvIUvQEbhfUZc0ihIple0VyWGH5bza0DLW+C8ttF8KqICUfL8S8mZgjbXvVg2fY\n" - + "HLW9lWR/Pkco2yRc8gZyr9FGkXOcmJ8aFaCuJnGm/IVRCieYp60If4DoAKz49xpF\n" - + "CF6RjOAJ//UGSp/ySjHMmT8PLO7NvhsT4XDDGTSeIYYpO++tbEIcLcjW9m2k5Gnh\n" - + "kmEenr0hdcpeLgsP3Fsy7JxyQNpL\n" - + "-----END CERTIFICATE-----"; + // Owner: CN=ssltest-active.actalis.it, O=Actalis S.p.A., L=Ponte San Pietro, + // ST=Bergamo, C=IT + // Issuer: CN=Actalis Organization Validated Server CA G3, O=Actalis S.p A., + // L=Ponte San Pietro, ST=Bergamo, C=IT + // Serial number: 4a49e2afcd448af3b7f5f14e1cd5954 + // Valid from: Tue Mar 08 08:00:57 PST 2022 until: Wed Mar 08 08:00:57 PST 2023 + private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + + "MIIH0jCCBbqgAwIBAgIQBKSeKvzUSK87f18U4c1ZVDANBgkqhkiG9w0BAQsFADCB\n" + + "iTELMAkGA1UEBhMCSVQxEDAOBgNVBAgMB0JlcmdhbW8xGTAXBgNVBAcMEFBvbnRl\n" + + "IFNhbiBQaWV0cm8xFzAVBgNVBAoMDkFjdGFsaXMgUy5wLkEuMTQwMgYDVQQDDCtB\n" + + "Y3RhbGlzIE9yZ2FuaXphdGlvbiBWYWxpZGF0ZWQgU2VydmVyIENBIEczMB4XDTIy\n" + + "MDMwODE2MDA1N1oXDTIzMDMwODE2MDA1N1owdzELMAkGA1UEBhMCSVQxEDAOBgNV\n" + + "BAgMB0JlcmdhbW8xGTAXBgNVBAcMEFBvbnRlIFNhbiBQaWV0cm8xFzAVBgNVBAoM\n" + + "DkFjdGFsaXMgUy5wLkEuMSIwIAYDVQQDDBlzc2x0ZXN0LWFjdGl2ZS5hY3RhbGlz\n" + + "Lml0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsJnlOatNNth7gfqZ\n" + + "WN8HMfp9qlkDf/YW8ReNXyTtqFEy2xZrVVmAV2XIqL1lJDYJz86mdVsz3AqIMTzo\n" + + "GxPlmn/oEnF0YeRYQ1coKRdwP7hWSwqyMMhh+C7r5zMA9gQQVXV5wWR5U+bgvt23\n" + + "Y/55DOqk3Fp5Odt6Lyu6xA45MwHrj2Gr/nMKe8L7f8UYPWT98MJa1+TXB24yllOw\n" + + "rZE8gZByLBCVzDkVwRwTgu+HgY6zm5sJTvBT4tyJy4QD8u2xLWoZ5sXodrU0Z3Nf\n" + + "xU9keMFp6CIh1t+akqFgpW81b/HWkfUO0+L6PH4hgaSPtiwp2dVFsF9v5p4on9qA\n" + + "2j1d9QIDAQABo4IDRTCCA0EwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBSfirG1\n" + + "8bHegvQnfL6Izd6pQ4GjSzB+BggrBgEFBQcBAQRyMHAwOwYIKwYBBQUHMAKGL2h0\n" + + "dHA6Ly9jYWNlcnQuYWN0YWxpcy5pdC9jZXJ0cy9hY3RhbGlzLWF1dGhvdmczMDEG\n" + + "CCsGAQUFBzABhiVodHRwOi8vb2NzcDA5LmFjdGFsaXMuaXQvVkEvQVVUSE9WLUcz\n" + + "MCQGA1UdEQQdMBuCGXNzbHRlc3QtYWN0aXZlLmFjdGFsaXMuaXQwUQYDVR0gBEow\n" + + "SDA8BgYrgR8BFAEwMjAwBggrBgEFBQcCARYkaHR0cHM6Ly93d3cuYWN0YWxpcy5p\n" + + "dC9hcmVhLWRvd25sb2FkMAgGBmeBDAECAjAdBgNVHSUEFjAUBggrBgEFBQcDAgYI\n" + + "KwYBBQUHAwEwSAYDVR0fBEEwPzA9oDugOYY3aHR0cDovL2NybDA5LmFjdGFsaXMu\n" + + "aXQvUmVwb3NpdG9yeS9BVVRIT1YtRzMvZ2V0TGFzdENSTDAdBgNVHQ4EFgQUIbcm\n" + + "54DVM6gC8DYhvnZg8ILaLrAwDgYDVR0PAQH/BAQDAgWgMIIBfQYKKwYBBAHWeQIE\n" + + "AgSCAW0EggFpAWcAdQCt9776fP8QyIudPZwePhhqtGcpXc+xDCTKhYY069yCigAA\n" + + "AX9qTFEkAAAEAwBGMEQCIFB4RW+Fca/jj96sFg9JtZVe/CAQq74HAezTi2AD07qL\n" + + "AiBej8APns5uKmaHNYbU6lel6kdowIaUY/+iqX82e2KhrAB2AOg+0No+9QY1MudX\n" + + "KLyJa8kD08vREWvs62nhd31tBr1uAAABf2pMUVMAAAQDAEcwRQIgcopYpSUDiQ2C\n" + + "7j06vgbfsn3ux4REvpbrbWatifLtfVMCIQCi96i+4EhAUOw4dumA7hJwlG+qD/+5\n" + + "uSL3aKB9KR7apAB2AG9Tdqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAAB\n" + + "f2pMUYEAAAQDAEcwRQIgdCNjaV7nQcCiVefX28u1vtQMy+rqT4F4i9EVJ2xbqbQC\n" + + "IQCrpcYqt53tX/rSMoGnjFhDGnMhnYyc2AqzpokfhmdcVTANBgkqhkiG9w0BAQsF\n" + + "AAOCAgEAfXISBKP1dZQv1kkWZVDXiVY/fv+068DKq2e8hgBcsN6b9a2rlVfBU2iq\n" + + "W9KqFNET5GDWf1wjM71Itjau8b1A3+apcNdEGQk3eqIOymK5kVtVvAI2ahp4926x\n" + + "Kkt/sexmi1pJGA+eLfTixkCoaESh5P8U7HDW/vUFXm2AtLQih+oT5OVoYt5e9pXr\n" + + "hr8oadm/ZDJxiyDL1vcTIsl2TM4/Fpo2IWxYzUC+YshnuLiRwWI840maJmWFx/lJ\n" + + "Pzdik3P51Uef7VsCSBhTxER09/B4IrEUMDAhVgG5QNbcFSHvnmpV8JLrNuBKUROU\n" + + "xnDsWieKlb5YO6S6PjGOncOrd+k4RCIYRaekSnx52WBKkpqxMEv/rjY1Glx4Cota\n" + + "mpNiYDvZHGzrRQtY2eH17XhFatBxEEbJMA+0QPbFksHcKxAxJgMDncqag4TDq5fT\n" + + "I2NUxqiB51F5w0x+++lyLnUZ+z4BJFZ73VdtfoJ2fsuRhemOoZjHPi/V2exXpAfb\n" + + "pomha3KCrTcuFv1lj8mPx5L4ciNPxuDFgjeXEaTGjS8IvdNoJIrgdHdahMwkwS/y\n" + + "wei7FJ1Ey0maqRUpUlAY6sIQPQ/KDltTuKX/C94C5pYLI0JXCScr5xg6C+r2ckbA\n" + + "rjhpn3C/NptVyZgT8bL4XT5ITrAjwPciBj0yxYzUkrLZO1wKQSQ=\n" + + "-----END CERTIFICATE-----"; - // Owner: CN=Actalis Authentication CA G3, O=Actalis S.p.A./03358520967, L=Milano, ST=Milano, C=IT - // Issuer: CN=Actalis Authentication Root CA, O=Actalis S.p.A./03358520967, L=Milan, C=IT - // SN: 741d584a 72fc06bc - // Valid from: Wed Feb 12 22:32:23 PST 2014 - // Valid till: Mon Feb 12 22:32:23 PST 2024 - private static final String INT_REVOKED = "-----BEGIN CERTIFICATE-----\n" - + "MIIGTTCCBDWgAwIBAgIIdB1YSnL8BrwwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE\n" - + "BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w\n" - + "MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290\n" - + "IENBMB4XDTE0MDIxMzE1MDIyM1oXDTI0MDIxMzE1MDIyM1owezELMAkGA1UEBhMC\n" - + "SVQxDzANBgNVBAgMBk1pbGFubzEPMA0GA1UEBwwGTWlsYW5vMSMwIQYDVQQKDBpB\n" - + "Y3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzElMCMGA1UEAwwcQWN0YWxpcyBBdXRo\n" - + "ZW50aWNhdGlvbiBDQSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" - + "AMzhDjmhNDym6ze3PegbIKmiavXpAjgVCZ344k1DOtdSCV6k3h3rqfHqFn3mrayA\n" - + "btmJ0NeC886WxUUsJwHJ3bOnNBQZIHxLV+1RVD/6TQqb6/bPJu4rDwEfhbJSmErc\n" - + "29wUJWqxXMhSAWTHi3Pq0vrkx59e5KTEyfB2kHo6InlR72sCCRdtCL9aDuDm8nYK\n" - + "pTSAJr36ultwME5NyCNSyN2JIK0wYbEi7MVNbp5KN9MusTp3cOMDoVBreYulmnEu\n" - + "TNazmoAv0K8oLS7iX7c9x+zGjUUAucFEuSlRn3sL6hFAiKjy4PDClvnyqQHBBdZr\n" - + "/3JOxAcgXv7aZ4/STeXeDXsCAwEAAaOCAeMwggHfMEEGCCsGAQUFBwEBBDUwMzAx\n" - + "BggrBgEFBQcwAYYlaHR0cDovL3BvcnRhbC5hY3RhbGlzLml0L1ZBL0FVVEgtUk9P\n" - + "VDAdBgNVHQ4EFgQUqqr9yowdTfEug+EG/PqO6g4jrj0wDwYDVR0TAQH/BAUwAwEB\n" - + "/zAfBgNVHSMEGDAWgBRS2Ig6yJ94Zu2J83s4cJTJAgI20DBUBgNVHSAETTBLMEkG\n" - + "BFUdIAAwQTA/BggrBgEFBQcCARYzaHR0cHM6Ly9wb3J0YWwuYWN0YWxpcy5pdC9S\n" - + "ZXBvc2l0b3J5L1BvbGljeS9TU0wvQ1BTMIHiBgNVHR8EgdowgdcwgZSggZGggY6G\n" - + "gYtsZGFwOi8vbGRhcC5hY3RhbGlzLml0L2NuJTNkQWN0YWxpcyUyMEF1dGhlbnRp\n" - + "Y2F0aW9uJTIwUm9vdCUyMENBLG8lM2RBY3RhbGlzJTIwUy5wLkEuJTJmMDMzNTg1\n" - + "MjA5NjcsYyUzZElUP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q7YmluYXJ5MD6g\n" - + "PKA6hjhodHRwOi8vcG9ydGFsLmFjdGFsaXMuaXQvUmVwb3NpdG9yeS9BVVRILVJP\n" - + "T1QvZ2V0TGFzdENSTDAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIB\n" - + "ABP93l+9QBgzHF0Clf3gMAelGqwXT25DwZVFIkBw6YyqOPcaqzw1XKHJJEMQ8xOp\n" - + "8uuiPLP/ObxEXBBvH7ofNW7nRUIzGsuLPhzdfJhdzilCVAvz4WRsX44nWOQS4Qu0\n" - + "npo7dbq/KxFUCUO9yNEJp6YxNloy8XFIlazkHFTKGJqoUpsGoc7B9YmPchhE2FPb\n" - + "OZiOCg4Y2Qp43UJfnENgZ3gJFh16juQE1uS8Q/JJI7ZzJfJ/W0uQoDnCprOPUpLF\n" - + "G03e0asFxwQqhL84Jvf7rJZaWvwydHP4hH47nzpHWEGXwfJLXXoO7LHgqVB7K9Ar\n" - + "Zf3pY0S/3Fs+AN/PrEY3Z3rb7ypQLRiot1oJLl8matiGEF4aFL5DDkr9wfRAZ8S8\n" - + "WT69vN68ENGgEwyeZSlQxn+4g6quHRav0fmF2fGnLaq7tteSPVocT7XaMEpkHqNs\n" - + "x1q/PJbr39s/1QVZtS9CrdoCr0QAnBaX//PPB6ansSLFcvEqM9QcV9xQZex88ToX\n" - + "nk3TcHtA0ezWJlCkg626MhdQZrhHbkauHfIGSOmCkn3zHp0BZQ6Vo7UOdRMT7QS7\n" - + "y7AkET9Qmapwh2CFUdCJSXklVRd+06XhhOB37NQU0pGJQJ3xjEPrILZ8kLhW3Tyq\n" - + "Iv30LW7MXZ4yQn/JHEZbuiOOb4R45hsPZxe6gOq/e+sf\n" - + "-----END CERTIFICATE-----"; - - // Owner: CN=ssltest-r.actalis.it, O=Actalis S.p.A., L=Ponte San Pietro, ST=Bergamo, C=IT - // Issuer: CN=Actalis Authentication CA G3, O=Actalis S.p.A./03358520967, L=Milano, ST=Milano, C=IT - // SN: 0455de97 5c71c96f - // Valid from: Thu Jan 28 16:23:52 PST 2016 - // Valid till: Mon Jan 28 16:23:52 PST 2019 - private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" - + "MIIFmDCCBICgAwIBAgIIBFXel1xxyW8wDQYJKoZIhvcNAQELBQAwezELMAkGA1UE\n" - + "BhMCSVQxDzANBgNVBAgMBk1pbGFubzEPMA0GA1UEBwwGTWlsYW5vMSMwIQYDVQQK\n" - + "DBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzElMCMGA1UEAwwcQWN0YWxpcyBB\n" - + "dXRoZW50aWNhdGlvbiBDQSBHMzAeFw0xNjAxMjkwODUzNTJaFw0xOTAxMjkwODUz\n" - + "NTJaMHIxCzAJBgNVBAYTAklUMRAwDgYDVQQIDAdCZXJnYW1vMRkwFwYDVQQHDBBQ\n" - + "b250ZSBTYW4gUGlldHJvMRcwFQYDVQQKDA5BY3RhbGlzIFMucC5BLjEdMBsGA1UE\n" - + "AwwUc3NsdGVzdC1yLmFjdGFsaXMuaXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\n" - + "ggEKAoIBAQClbzoXCvD21FD7Oy/TKZu4fmDFJrISrNfasLlC3krLHkgb1vg23Z1P\n" - + "+7rIymDgrJSzjvYmisl+VM7xXxTsyI2pp9Qp/uzTMAMML9ISd/s0LaMBiNN5iPyj\n" - + "W91gGzGe30Jc319afKwFBaveSv7NO3DWsmHw9koezWkKUug2dnQCVXk1uTSdobnq\n" - + "wOgwxdd86LpZnFLxBIYdU68S4vogAQZjdja/S1+tF6JnfvY6o/xRJmQckVtNmUs6\n" - + "Dj3KoN2o/8BEgSCYcJz8tfoZcVazVkWOp/u6moUnm1/IKSYNgtHnB1ub0fB2AttW\n" - + "Vi7cs3SG/tDMMP8yc1kWScWf8CYj/AI1AgMBAAGjggInMIICIzA/BggrBgEFBQcB\n" - + "AQQzMDEwLwYIKwYBBQUHMAGGI2h0dHA6Ly9vY3NwMDMuYWN0YWxpcy5pdC9WQS9B\n" - + "VVRILUczMB0GA1UdDgQWBBRIKN5WmrjivlnT1rDzsH1WZ+PuvTAMBgNVHRMBAf8E\n" - + "AjAAMB8GA1UdIwQYMBaAFKqq/cqMHU3xLoPhBvz6juoOI649MGAGA1UdIARZMFcw\n" - + "SwYGK4EfARQBMEEwPwYIKwYBBQUHAgEWM2h0dHBzOi8vcG9ydGFsLmFjdGFsaXMu\n" - + "aXQvUmVwb3NpdG9yeS9Qb2xpY3kvU1NML0NQUzAIBgZngQwBAgIwgd8GA1UdHwSB\n" - + "1zCB1DCBlKCBkaCBjoaBi2xkYXA6Ly9sZGFwMDMuYWN0YWxpcy5pdC9jbiUzZEFj\n" - + "dGFsaXMlMjBBdXRoZW50aWNhdGlvbiUyMENBJTIwRzMsbyUzZEFjdGFsaXMlMjBT\n" - + "LnAuQS4lMmYwMzM1ODUyMDk2NyxjJTNkSVQ/Y2VydGlmaWNhdGVSZXZvY2F0aW9u\n" - + "TGlzdDtiaW5hcnkwO6A5oDeGNWh0dHA6Ly9jcmwwMy5hY3RhbGlzLml0L1JlcG9z\n" - + "aXRvcnkvQVVUSC1HMy9nZXRMYXN0Q1JMMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE\n" - + "FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHwYDVR0RBBgwFoIUc3NsdGVzdC1yLmFj\n" - + "dGFsaXMuaXQwDQYJKoZIhvcNAQELBQADggEBAHZLND53/CZoMlDtfln0ZByCEhoF\n" - + "/XtA9cYy2azRGgS/VY4WUccvg99MM50cwn5GPRsJpoaFXeDrjV3DkOUK1jERzjx4\n" - + "5y83K/AkCGe7uU17aS+tweETizBAfHNj78oHmZDmkDSEY2STaeuHNDJ9ft0v3QTb\n" - + "VW54R5W3OBU7L/sJoEUdRxzGN7vO82PboGvyApMCWDRLKE7bPP4genQtF3XPcaFl\n" - + "ekuSiEVYS+KnM2v9tCWHqw6x7raWHFB9w1kAKNwv0hbEJkeC+a2bCdPwv8hs//sa\n" - + "gUF4p61mIpf+5qmQ6gcZOClPWyrbYdQdfCvKgbEdKhwB0v5KS0NIRRn41SE=\n" - + "-----END CERTIFICATE-----"; + // Owner: CN=ssltest-revoked.actalis.it, O=Actalis S.p.A., L=Ponte San Pietro, ST=Bergamo, C=IT + // Issuer: CN=Actalis Organization Validated Server CA G3, O=Actalis S.p.A., + // L=Ponte San Pietro, ST=Bergamo, C=IT + // Serial number: 320955171b78d49507508910da2c5bc4 + // Valid from: Tue Sep 27 03:40:43 PDT 2022 until: Wed Sep 27 03:40:43 PDT 2023 + private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + + "MIIH1TCCBb2gAwIBAgIQMglVFxt41JUHUIkQ2ixbxDANBgkqhkiG9w0BAQsFADCB\n" + + "iTELMAkGA1UEBhMCSVQxEDAOBgNVBAgMB0JlcmdhbW8xGTAXBgNVBAcMEFBvbnRl\n" + + "IFNhbiBQaWV0cm8xFzAVBgNVBAoMDkFjdGFsaXMgUy5wLkEuMTQwMgYDVQQDDCtB\n" + + "Y3RhbGlzIE9yZ2FuaXphdGlvbiBWYWxpZGF0ZWQgU2VydmVyIENBIEczMB4XDTIy\n" + + "MDkyNzEwNDA0M1oXDTIzMDkyNzEwNDA0M1oweDELMAkGA1UEBhMCSVQxEDAOBgNV\n" + + "BAgMB0JlcmdhbW8xGTAXBgNVBAcMEFBvbnRlIFNhbiBQaWV0cm8xFzAVBgNVBAoM\n" + + "DkFjdGFsaXMgUy5wLkEuMSMwIQYDVQQDDBpzc2x0ZXN0LXJldm9rZWQuYWN0YWxp\n" + + "cy5pdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKdBnbeFtw/Ejp1U\n" + + "gr86BQ5rqgGXWWXb7fsOhPb5On9RXTojg6oaeIV4GxHsMZhEDKQdcZ6JWAo2dbtp\n" + + "/7ereFEDWG/YJahLHFZ/ihXG4AmfObYEhoGbKitW75fOs/aWC7Veck/sXsw7cjLW\n" + + "GY623ybcF9DBExg3S4uLRaSkv5hXUDu/CzphUgwiEd5YNBZjcryOiS8+Y5EQ+2q+\n" + + "g+tdRG9m5G5YxeHWgQz2HDDwLDsJhWkb8/RsUurU/I+avHPhYk13K5Ysf311gww8\n" + + "bAsplfdJ2gdn8Is+EAEH4GJHqMybC95YDh1w5dY7dk/lIoNX4hYUIQimirIr3OW8\n" + + "Svkj1G8CAwEAAaOCA0cwggNDMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUn4qx\n" + + "tfGx3oL0J3y+iM3eqUOBo0swfgYIKwYBBQUHAQEEcjBwMDsGCCsGAQUFBzAChi9o\n" + + "dHRwOi8vY2FjZXJ0LmFjdGFsaXMuaXQvY2VydHMvYWN0YWxpcy1hdXRob3ZnMzAx\n" + + "BggrBgEFBQcwAYYlaHR0cDovL29jc3AwOS5hY3RhbGlzLml0L1ZBL0FVVEhPVi1H\n" + + "MzAlBgNVHREEHjAcghpzc2x0ZXN0LXJldm9rZWQuYWN0YWxpcy5pdDBRBgNVHSAE\n" + + "SjBIMDwGBiuBHwEUATAyMDAGCCsGAQUFBwIBFiRodHRwczovL3d3dy5hY3RhbGlz\n" + + "Lml0L2FyZWEtZG93bmxvYWQwCAYGZ4EMAQICMB0GA1UdJQQWMBQGCCsGAQUFBwMC\n" + + "BggrBgEFBQcDATBIBgNVHR8EQTA/MD2gO6A5hjdodHRwOi8vY3JsMDkuYWN0YWxp\n" + + "cy5pdC9SZXBvc2l0b3J5L0FVVEhPVi1HMy9nZXRMYXN0Q1JMMB0GA1UdDgQWBBS6\n" + + "o8qJpg3ixoyA2QBayptaTfc+5DAOBgNVHQ8BAf8EBAMCBaAwggF+BgorBgEEAdZ5\n" + + "AgQCBIIBbgSCAWoBaAB2AK33vvp8/xDIi509nB4+GGq0Zyldz7EMJMqFhjTr3IKK\n" + + "AAABg36SGRYAAAQDAEcwRQIgDXxSCQGfcIYroxNiDJg08IX38Y9+r5CC6T4NeW14\n" + + "FzgCIQDdEhEYsGIWpwyrnTLr4RFB5CMEq+84dByNT07UYkiVwwB2AHoyjFTYty22\n" + + "IOo44FIe6YQWcDIThU070ivBOlejUutSAAABg36SGTUAAAQDAEcwRQIgL2ig9RrM\n" + + "FPWESGRYGJJJYRHdcayHev66jawrf98saN8CIQD/CInlI3Vo7SBzzN/4uykjYsFZ\n" + + "u9RypT6AYv6AHPlNdQB2AG9Tdqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kT\n" + + "AAABg36SGU0AAAQDAEcwRQIhAOCD/dOs4HjyC+GQaQRh4U+/mUwWyu+CnlHdebmD\n" + + "hAvFAiAvBE0rbxgm8TpZLG2TaMk3dqZj7Q6FFdLlqTsvwhKa3jANBgkqhkiG9w0B\n" + + "AQsFAAOCAgEAEnPALMVp1pySJgHhugLWAUgiD6stpDWCKfaBxPr+jf34A5wS+m5r\n" + + "2VhYyNQpOwIQB76K2RSJQrdpg7Dg2L6EiUnbbClSTrOkZ4XX5ggBIjldDEx4ZxhI\n" + + "zwSw4KB6+DDAVMwsCL0q0E7AAPOMaZ0RDLteusqQYIYm08TXfJPWD8LjQPt/8Uie\n" + + "LOqm1eLUuwJc+eHFWV+Xr8Uea6SFwqNEj7qPHb2MElctET/MhSIIUKI1ObmrFwyB\n" + + "ElKEPaUh9L0HXpnuD8IWc7tw2mdvnWJhuGG8G6JkasTGvtZ4gKIDBdTrJcuj7MCS\n" + + "amz3ZBCY47tP1ohgImjqwg4ITYjX6UQXgj/nBVDdu+nXkEhx16uPJkTYWaun9Nio\n" + + "8RjYIOxXmDD39QbGUElP0Epsr2wcVT9tIFYMGzUpIO51mCk3Aq1AmiQZwZZhqOIN\n" + + "RDx7lGESPj3IgdVfJi9Ing/OUNtS46Ug9DSuDcGqdY7KnTYEUdWGsUJNtnpjd4lS\n" + + "U6oIAeW1aKuOve6iNg1vsFAN57aJNh1ih3BOup58J9ve42bNlAYWN8wiNxM+Aeba\n" + + "ArUSTnH/QEYCyMRD0XqIREVR9VhNODgSZbL3XedYBAW9wImi1whp+u+8aReXd7lC\n" + + "Q3kD9KRyfZ9Kk05Glf3DsZMWvp1N2ZZWaU2Ms5U3ijUheCiBrqrs8a8=\n" + + "-----END CERTIFICATE-----"; public static void main(String[] args) throws Exception { ValidatePathWithParams pathValidator = new ValidatePathWithParams(null); - boolean ocspEnabled = false; if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) { pathValidator.enableCRLCheck(); } else { // OCSP check by default pathValidator.enableOCSPCheck(); - ocspEnabled = true; } // Validate valid - pathValidator.validate(new String[]{VALID, INT_VALID}, + pathValidator.validate(new String[]{VALID, INT}, ValidatePathWithParams.Status.GOOD, null, System.out); - // Revoked certificate is using SHA1 signature - if (ocspEnabled) { - // Revoked test certificate is expired - // and backdated revocation check is only possible with OCSP - pathValidator.setValidationDate("July 01, 2016"); - } - // Validate Revoked - pathValidator.validate(new String[]{REVOKED, INT_REVOKED}, + pathValidator.validate(new String[]{REVOKED, INT}, ValidatePathWithParams.Status.REVOKED, - "Fri Jan 29 01:06:42 PST 2016", System.out); - - // reset validation date back to current date - pathValidator.resetValidationDate(); + "Tue Sep 27 03:52:40 PDT 2022", System.out); } } diff --git a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java index 6cb50066b6d..dec0ff8872a 100644 --- a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java +++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,291 +51,325 @@ public class AmazonCA { public static void main(String[] args) throws Exception { ValidatePathWithParams pathValidator = new ValidatePathWithParams(null); - boolean ocspEnabled = false; if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) { pathValidator.enableCRLCheck(); } else { // OCSP check by default pathValidator.enableOCSPCheck(); - ocspEnabled = true; } - new AmazonCA_1().runTest(pathValidator, ocspEnabled); - new AmazonCA_2().runTest(pathValidator, ocspEnabled); - new AmazonCA_3().runTest(pathValidator, ocspEnabled); - new AmazonCA_4().runTest(pathValidator, ocspEnabled); + new AmazonCA_1().runTest(pathValidator); + new AmazonCA_2().runTest(pathValidator); + new AmazonCA_3().runTest(pathValidator); + new AmazonCA_4().runTest(pathValidator); } } class AmazonCA_1 { - // Owner: CN=Amazon, OU=Server CA 1A, O=Amazon, C=US + // Owner: CN=Amazon RSA 2048 M02, O=Amazon, C=US // Issuer: CN=Amazon Root CA 1, O=Amazon, C=US - // Serial number: 67f9457508c648c09ca652e71791830e72592 - // Valid from: Wed Oct 21 17:00:00 PDT 2015 until: Sat Oct 18 17:00:00 PDT 2025 - private static final String INT = "-----BEGIN CERTIFICATE-----\n" + - "MIIERzCCAy+gAwIBAgITBn+UV1CMZIwJymUucXkYMOclkjANBgkqhkiG9w0BAQsF\n" + + // Serial number: 773124a4bcbd44ec7b53beaf194842d3a0fa1 + // Valid from: Tue Aug 23 15:25:30 PDT 2022 until: Fri Aug 23 15:25:30 PDT 2030 + private static final String INT_VALID = "-----BEGIN CERTIFICATE-----\n" + + "MIIEXjCCA0agAwIBAgITB3MSSkvL1E7HtTvq8ZSELToPoTANBgkqhkiG9w0BAQsF\n" + + "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" + + "b24gUm9vdCBDQSAxMB4XDTIyMDgyMzIyMjUzMFoXDTMwMDgyMzIyMjUzMFowPDEL\n" + + "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEcMBoGA1UEAxMTQW1hem9uIFJT\n" + + "QSAyMDQ4IE0wMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALtDGMZa\n" + + "qHneKei1by6+pUPPLljTB143Si6VpEWPc6mSkFhZb/6qrkZyoHlQLbDYnI2D7hD0\n" + + "sdzEqfnuAjIsuXQLG3A8TvX6V3oFNBFVe8NlLJHvBseKY88saLwufxkZVwk74g4n\n" + + "WlNMXzla9Y5F3wwRHwMVH443xGz6UtGSZSqQ94eFx5X7Tlqt8whi8qCaKdZ5rNak\n" + + "+r9nUThOeClqFd4oXych//Rc7Y0eX1KNWHYSI1Nk31mYgiK3JvH063g+K9tHA63Z\n" + + "eTgKgndlh+WI+zv7i44HepRZjA1FYwYZ9Vv/9UkC5Yz8/yU65fgjaE+wVHM4e/Yy\n" + + "C2osrPWE7gJ+dXMCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYD\n" + + "VR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNV\n" + + "HQ4EFgQUwDFSzVpQw4J8dHHOy+mc+XrrguIwHwYDVR0jBBgwFoAUhBjMhTTsvAyU\n" + + "lC4IWZzHshBOCggwewYIKwYBBQUHAQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8v\n" + + "b2NzcC5yb290Y2ExLmFtYXpvbnRydXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDov\n" + + "L2NydC5yb290Y2ExLmFtYXpvbnRydXN0LmNvbS9yb290Y2ExLmNlcjA/BgNVHR8E\n" + + "ODA2MDSgMqAwhi5odHRwOi8vY3JsLnJvb3RjYTEuYW1hem9udHJ1c3QuY29tL3Jv\n" + + "b3RjYTEuY3JsMBMGA1UdIAQMMAowCAYGZ4EMAQIBMA0GCSqGSIb3DQEBCwUAA4IB\n" + + "AQAtTi6Fs0Azfi+iwm7jrz+CSxHH+uHl7Law3MQSXVtR8RV53PtR6r/6gNpqlzdo\n" + + "Zq4FKbADi1v9Bun8RY8D51uedRfjsbeodizeBB8nXmeyD33Ep7VATj4ozcd31YFV\n" + + "fgRhvTSxNrrTlNpWkUk0m3BMPv8sg381HhA6uEYokE5q9uws/3YkKqRiEz3TsaWm\n" + + "JqIRZhMbgAfp7O7FUwFIb7UIspogZSKxPIWJpxiPo3TcBambbVtQOcNRWz5qCQdD\n" + + "slI2yayq0n2TXoHyNCLEH8rpsJRVILFsg0jc7BaFrMnF462+ajSehgj12IidNeRN\n" + + "4zl+EoNaWdpnWndvSpAEkq2P\n" + + "-----END CERTIFICATE-----"; + + // Owner: CN=Amazon RSA 2048 M01, O=Amazon, C=US + // Issuer: CN=Amazon Root CA 1, O=Amazon, C=US + // Serial number: 77312380b9d6688a33b1ed9bf9ccda68e0e0f + // Valid from: Tue Aug 23 15:21:28 PDT 2022 until: Fri Aug 23 15:21:28 PDT 2030 + private static final String INT_REVOKED = "-----BEGIN CERTIFICATE-----\n" + + "MIIEXjCCA0agAwIBAgITB3MSOAudZoijOx7Zv5zNpo4ODzANBgkqhkiG9w0BAQsF\n" + "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" + - "b24gUm9vdCBDQSAxMB4XDTE1MTAyMjAwMDAwMFoXDTI1MTAxOTAwMDAwMFowRjEL\n" + - "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEVMBMGA1UECxMMU2VydmVyIENB\n" + - "IDFBMQ8wDQYDVQQDEwZBbWF6b24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\n" + - "AoIBAQCeQM3XCsIZunv8bSJxOqkc/ed87uL76FDB7teBNThDRB+1J7aITuadbNfH\n" + - "5ZfZykrdZ1qQLKxP6DwHOmJr9u2b4IxjUX9qUMuq4B02ghD2g6yU3YivEosZ7fpo\n" + - "srD2TBN29JpgPGrOrpOE+ArZuIpBjdKFinemu6fTDD0NCeQlfyHXd1NOYyfYRLTa\n" + - "xlpDqr/2M41BgSkWQfSPHHyRWNQgWBiGsIQaS8TK0g8OWi1ov78+2K9DWT+AHgXW\n" + - "AanjZK91GfygPXJYSlAGxSiBAwH/KhAMifhaoFYAbH0Yuohmd85B45G2xVsop4TM\n" + - "Dsl007U7qnS7sdJ4jYGzEvva/a95AgMBAAGjggE5MIIBNTASBgNVHRMBAf8ECDAG\n" + - "AQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUYtRCXoZwdWqQvMa40k1g\n" + - "wjS6UTowHwYDVR0jBBgwFoAUhBjMhTTsvAyUlC4IWZzHshBOCggwewYIKwYBBQUH\n" + - "AQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8vb2NzcC5yb290Y2ExLmFtYXpvbnRy\n" + - "dXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDovL2NydC5yb290Y2ExLmFtYXpvbnRy\n" + - "dXN0LmNvbS9yb290Y2ExLmNlcjA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3Js\n" + - "LnJvb3RjYTEuYW1hem9udHJ1c3QuY29tL3Jvb3RjYTEuY3JsMBEGA1UdIAQKMAgw\n" + - "BgYEVR0gADANBgkqhkiG9w0BAQsFAAOCAQEAMHbSWHRFMzGNIE0qhN6gnRahTrTU\n" + - "CDPwe7l9/q0IA+QBlrpUHnlAreetYeH1jB8uF3qXXzy22gpBU7NqulTkqSPByT1J\n" + - "xOhpT2FpO5R3VAdMPdWfSEgtrED0jkmyUQrR1T+/A+nBLdJZeQcl+OqLgeY790JM\n" + - "JJTsJnnI6FBWeTGhcDI4Y+n3KS3QCVePeWI7jx1dhrHcXH+QDX8Ywe31hV7YENdr\n" + - "HDpUXrjK6eHN8gazy8G6pndXHFwHp4auiZbJbYAk/q1peOTRagD2JojcLkm+i3cD\n" + - "843t4By6YT/PVlePU2PCWejkrJQnKQAPOov7IA8kuO2RDWuzE/zF6Hotdg==\n" + + "b24gUm9vdCBDQSAxMB4XDTIyMDgyMzIyMjEyOFoXDTMwMDgyMzIyMjEyOFowPDEL\n" + + "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEcMBoGA1UEAxMTQW1hem9uIFJT\n" + + "QSAyMDQ4IE0wMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOtxLKnL\n" + + "H4gokjIwr4pXD3i3NyWVVYesZ1yX0yLI2qIUZ2t88Gfa4gMqs1YSXca1R/lnCKeT\n" + + "epWSGA+0+fkQNpp/L4C2T7oTTsddUx7g3ZYzByDTlrwS5HRQQqEFE3O1T5tEJP4t\n" + + "f+28IoXsNiEzl3UGzicYgtzj2cWCB41eJgEmJmcf2T8TzzK6a614ZPyq/w4CPAff\n" + + "nAV4coz96nW3AyiE2uhuB4zQUIXvgVSycW7sbWLvj5TDXunEpNCRwC4kkZjK7rol\n" + + "jtT2cbb7W2s4Bkg3R42G3PLqBvt2N32e/0JOTViCk8/iccJ4sXqrS1uUN4iB5Nmv\n" + + "JK74csVl+0u0UecCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYD\n" + + "VR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNV\n" + + "HQ4EFgQUgbgOY4qJEhjl+js7UJWf5uWQE4UwHwYDVR0jBBgwFoAUhBjMhTTsvAyU\n" + + "lC4IWZzHshBOCggwewYIKwYBBQUHAQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8v\n" + + "b2NzcC5yb290Y2ExLmFtYXpvbnRydXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDov\n" + + "L2NydC5yb290Y2ExLmFtYXpvbnRydXN0LmNvbS9yb290Y2ExLmNlcjA/BgNVHR8E\n" + + "ODA2MDSgMqAwhi5odHRwOi8vY3JsLnJvb3RjYTEuYW1hem9udHJ1c3QuY29tL3Jv\n" + + "b3RjYTEuY3JsMBMGA1UdIAQMMAowCAYGZ4EMAQIBMA0GCSqGSIb3DQEBCwUAA4IB\n" + + "AQCtAN4CBSMuBjJitGuxlBbkEUDeK/pZwTXv4KqPK0G50fOHOQAd8j21p0cMBgbG\n" + + "kfMHVwLU7b0XwZCav0h1ogdPMN1KakK1DT0VwA/+hFvGPJnMV1Kx2G4S1ZaSk0uU\n" + + "5QfoiYIIano01J5k4T2HapKQmmOhS/iPtuo00wW+IMLeBuKMn3OLn005hcrOGTad\n" + + "hcmeyfhQP7Z+iKHvyoQGi1C0ClymHETx/chhQGDyYSWqB/THwnN15AwLQo0E5V9E\n" + + "SJlbe4mBlqeInUsNYugExNf+tOiybcrswBy8OFsd34XOW3rjSUtsuafd9AWySa3h\n" + + "xRRrwszrzX/WWGm6wyB+f7C4\n" + "-----END CERTIFICATE-----"; - // Owner: CN=good.sca1a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \ - // SERIALNUMBER=5846743, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \ - // OID.1.3.6.1.4.1.311.60.2.1.3=US - // Issuer: CN=Amazon, OU=Server CA 1A, O=Amazon, C=US - // Serial number: 703e4e4bbd78e2b6db5634f36c4ee944cb1a4 - // Valid from: Mon Jul 29 16:53:36 PDT 2019 until: Sat Aug 29 16:53:36 PDT 2020 + // Owner: CN=valid.rootca1.demo.amazontrust.com + // Issuer: CN=Amazon RSA 2048 M02, O=Amazon, C=US + // Serial number: 60c6e837b2e7586d8464eb34f4a85fe + // Valid from: Tue May 09 17:00:00 PDT 2023 until: Fri Jun 07 16:59:59 PDT 2024 private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + - "MIIFEzCCA/ugAwIBAgITBwPk5LvXjitttWNPNsTulEyxpDANBgkqhkiG9w0BAQsF\n" + - "ADBGMQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2\n" + - "ZXIgQ0EgMUExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTA3MjkyMzUzMzZaFw0yMDA4\n" + - "MjkyMzUzMzZaMIHaMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwC\n" + - "AQITCERlbGF3YXJlMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjEQMA4G\n" + - "A1UEBRMHNTg0Njc0MzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x\n" + - "EDAOBgNVBAcTB1NlYXR0bGUxHjAcBgNVBAoTFUFtYXpvbiBUcnVzdCBTZXJ2aWNl\n" + - "czEjMCEGA1UEAxMaZ29vZC5zY2ExYS5hbWF6b250cnVzdC5jb20wggEiMA0GCSqG\n" + - "SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQyuJ83c2Zf9k29f6iLqd8nJSuHSk1v+SS\n" + - "0sYyG8tjscfCC1HcOdNj37vtiNN65sXh/e/kBKH9wvzhCLOJbBqVKRHOZuHdJEpH\n" + - "35R6C/PbcV/tp49g6mNmBe+lcmm/cwwCtYvkL0rgL/OKB0liFhhRIqy2TPg08op/\n" + - "RlY2DdbgBA2B3g7wdMo0hK3SO56/QUccUtLRm43km9Yd4E3U+CEUyDd0Bmc/YbPa\n" + - "htuXVsXJwiwlwooomujIIENhFw3htdcsu2apRj8EYUrKL8Mvvn+h16gDyobj0f01\n" + - "jWXlUgmH2lzUzca5eGuphfvmWN/ME/yqC2mMvWGnWySycqtT8VdJAgMBAAGjggFj\n" + - "MIIBXzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0OBBYEFFENOZBwFkjVdQX0iK32c77z\n" + - "SUl6MB8GA1UdIwQYMBaAFGLUQl6GcHVqkLzGuNJNYMI0ulE6MB0GA1UdJQQWMBQG\n" + - "CCsGAQUFBwMBBggrBgEFBQcDAjB1BggrBgEFBQcBAQRpMGcwLQYIKwYBBQUHMAGG\n" + - "IWh0dHA6Ly9vY3NwLnNjYTFhLmFtYXpvbnRydXN0LmNvbTA2BggrBgEFBQcwAoYq\n" + - "aHR0cDovL2NydC5zY2ExYS5hbWF6b250cnVzdC5jb20vc2NhMWEuY2VyMCUGA1Ud\n" + - "EQQeMByCGmdvb2Quc2NhMWEuYW1hem9udHJ1c3QuY29tMFAGA1UdIARJMEcwDQYL\n" + - "YIZIAYb9bgEHGAMwNgYFZ4EMAQEwLTArBggrBgEFBQcCARYfaHR0cHM6Ly93d3cu\n" + - "YW1hem9udHJ1c3QuY29tL2NwczANBgkqhkiG9w0BAQsFAAOCAQEAmn7z6Ub1sL77\n" + - "wyUEaCq/Odqm+2RtYYMJ1MeW6nTXTfAgZ/iLx/6hStafd9AK9gHiTCggBpj6KgnF\n" + - "UsGMDeX879jP675fH6SEk710QPDhIrfAzwE0pF/eUNsd7pLwne32zHX0ouCoAt4d\n" + - "KwBCZkKNUkdj4U+bpOJzvtcTP9JlzziLp9IFRjjQh3xKgfblx57CmRJbqH3fT5JJ\n" + - "IAIDVTz3ZUcqhPTFAnNsO1oNBEyrO5X9rwCiSy7aRijY/11R75mIIvyA9zyd9ss1\n" + - "kvrrER0GWMTDvC84FZD2vhkXgPTFrB1Dn9f3QgO5APT9GCFY5hdpqqPEXOSdRzQo\n" + - "h9j4OQAqtA==\n" + + "MIIGKDCCBRCgAwIBAgIQBgxug3sudYbYRk6zT0qF/jANBgkqhkiG9w0BAQsFADA8\n" + + "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g\n" + + "UlNBIDIwNDggTTAyMB4XDTIzMDUxMDAwMDAwMFoXDTI0MDYwNzIzNTk1OVowLTEr\n" + + "MCkGA1UEAxMidmFsaWQucm9vdGNhMS5kZW1vLmFtYXpvbnRydXN0LmNvbTCCASIw\n" + + "DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3hA+omhUcO8nYO8/+dkpbYz8WI\n" + + "1ms7Y7JA2pPFfp2N/aWcf6m5ORm1BkyGLOttjTu318Qpa9eahQ1Pi3RNe3BtqjD9\n" + + "jcHncpwAFMsXy1beZA7sZ7AA4vKltA3t6yrU5ruTLUGQwUndeIBBSTW5QpdT9I/p\n" + + "EM7d+Miwre63kofbJ1lVPAJvN/udMVqGWNF8V5qscklUUHoSKA3FWWsiCyIgnthg\n" + + "G3u6R1KH66Qionp0ho/ttvrBCI0C/bdrdH+wybFv8oFFvAW2U9xn2Azt47/2kHHm\n" + + "tTRjrgufhDbcz/MLR6hwBXAJuwVvJZmSqe7B4IILFexu6wjxZfyqVm2FMr8CAwEA\n" + + "AaOCAzMwggMvMB8GA1UdIwQYMBaAFMAxUs1aUMOCfHRxzsvpnPl664LiMB0GA1Ud\n" + + "DgQWBBSkrnsTnjwYhDRAeLy/9FXm/7hApDBlBgNVHREEXjBcgiJ2YWxpZC5yb290\n" + + "Y2ExLmRlbW8uYW1hem9udHJ1c3QuY29tghpnb29kLnNjYTBhLmFtYXpvbnRydXN0\n" + + "LmNvbYIaZ29vZC5zY2ExYS5hbWF6b250cnVzdC5jb20wDgYDVR0PAQH/BAQDAgWg\n" + + "MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA7BgNVHR8ENDAyMDCgLqAs\n" + + "hipodHRwOi8vY3JsLnIybTAyLmFtYXpvbnRydXN0LmNvbS9yMm0wMi5jcmwwEwYD\n" + + "VR0gBAwwCjAIBgZngQwBAgEwdQYIKwYBBQUHAQEEaTBnMC0GCCsGAQUFBzABhiFo\n" + + "dHRwOi8vb2NzcC5yMm0wMi5hbWF6b250cnVzdC5jb20wNgYIKwYBBQUHMAKGKmh0\n" + + "dHA6Ly9jcnQucjJtMDIuYW1hem9udHJ1c3QuY29tL3IybTAyLmNlcjAMBgNVHRMB\n" + + "Af8EAjAAMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgDuzdBk1dsazsVct520\n" + + "zROiModGfLzs3sNRSFlGcR+1mwAAAYgHvXWVAAAEAwBHMEUCICAs74qT1f9ufSr5\n" + + "PgQqtQFiXBbmbb3i4xwVV78USU5NAiEA/iJEfnTG+hZZaHYv2wVbg6tUY8fQgIhI\n" + + "2rbl6PrD9FIAdgBIsONr2qZHNA/lagL6nTDrHFIBy1bdLIHZu7+rOdiEcwAAAYgH\n" + + "vXWWAAAEAwBHMEUCIQDf2nWyee/5+vSgk/O8P0BFvXYu89cyAugZHyd919BdAgIg\n" + + "UnGGpQtZmWnPMmdgpzI7jrCLuC370Tn0i7Aktdzj2X8AdgDatr9rP7W2Ip+bwrtc\n" + + "a+hwkXFsu1GEhTS9pD0wSNf7qwAAAYgHvXVpAAAEAwBHMEUCIGN6cT+6uwDospXe\n" + + "gMa8b38oXouXUT66X2gOiJ0SoRyQAiEAjDMu2vEll5tRpUvU8cD4gR2xV4hqoDxx\n" + + "Q+QGW+PvJxcwDQYJKoZIhvcNAQELBQADggEBACtxC3LlQvULeI3lt7ZYFSWndEhm\n" + + "tNUotoeKSXJXdoIpqSr10bzMPX9SHvemgOUtzP3JNqWPHw1uW9YFyeDE6yWj/B13\n" + + "Xj1hv1cqYIwyaOZBerU/9PT5PaCn20AC9DHbc7iBv+zs+DYiqlAFJ1GVaprwLul4\n" + + "8wp3gnC3Hjb8NykydCo6vw0AJ2UzjpjiTyVZ93jITzLOiboOUa1gQGnojzWlYaet\n" + + "sXe+RDylBp/Wuj1ZS7v/etltzYm5GanPi4y/p7Ta3Uky6std/GM6XbPRdBEFboFR\n" + + "B2IP0divd9c74Q+tLgpsAz5yXm9LtYPMcEPC2YRN2PgBg67c5+A7eIOluuw=\n" + "-----END CERTIFICATE-----"; - // Owner: CN=revoked.sca1a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \ - // SERIALNUMBER=5846743, OID.2.5.4.15=PrivateOrganization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \ - // OID.1.3.6.1.4.1.311.60.2.1.3=US - // Issuer: CN=Amazon, OU=Server CA 1A, O=Amazon, C=US - // Serial number: 6f1d774ad5e7b6d251d217661782bbdb6f37d - // Valid from: Mon Jan 28 15:34:38 PST 2019 until: Thu Apr 28 16:34:38 PDT 2022 + // Owner: CN=revoked.rootca1.demo.amazontrust.com + // Issuer: CN=Amazon RSA 2048 M01, O=Amazon, C=US + // Serial number: e1023665b1268d788cc25bf69a9d05e + // Valid from: Tue May 09 17:00:00 PDT 2023 until: Fri Jun 07 16:59:59 PDT 2024 private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + - "MIIE2zCCA8OgAwIBAgITBvHXdK1ee20lHSF2YXgrvbbzfTANBgkqhkiG9w0BAQsF\n" + - "ADBGMQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2\n" + - "ZXIgQ0EgMUExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTAxMjgyMzM0MzhaFw0yMjA0\n" + - "MjgyMzM0MzhaMIHcMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwC\n" + - "AQITCERlbGF3YXJlMRwwGgYDVQQPExNQcml2YXRlT3JnYW5pemF0aW9uMRAwDgYD\n" + - "VQQFEwc1ODQ2NzQzMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ\n" + - "MA4GA1UEBxMHU2VhdHRsZTEeMBwGA1UEChMVQW1hem9uIFRydXN0IFNlcnZpY2Vz\n" + - "MSYwJAYDVQQDEx1yZXZva2VkLnNjYTFhLmFtYXpvbnRydXN0LmNvbTCCASIwDQYJ\n" + - "KoZIhvcNAQEBBQADggEPADCCAQoCggEBANUoHop9sW+QlgVsdtacioraTAWHcSTd\n" + - "MNkOkOEMgJIFPyfdcDvW/H2NvpdYeIQqzaCgT2kcsONWTZTPJMirCPnzl1ohHOZU\n" + - "uTnOVkamGxvNmQCURLBXmlCMRTCI5RY3CuYntFFbSPAnbumsF+K/gKqcE6ME53Bw\n" + - "PAwn4qwavB0i5Ib7Jk8XYzxSYXC9l8QLxt6fshPJRlecpXzfmVFvMAm3IbaLcpuv\n" + - "AtD+8I2KwjNtBPRPNYeFsWxwsgUGAyHEGa61oTGUqqAXu5YmPfyK+YTOJdoofsh4\n" + - "Tf3K7AKxnPWuvY3RNTs1pzEVwJYZqSsNwbgyKJJ4+0Xe4iP7qB8SYf8CAwEAAaOC\n" + - "ASkwggElMA4GA1UdDwEB/wQEAwIFoDAdBgNVHQ4EFgQUGHreoz+LP/Wr+RKzuexO\n" + - "V8ICtmEwHwYDVR0jBBgwFoAUYtRCXoZwdWqQvMa40k1gwjS6UTowHQYDVR0lBBYw\n" + - "FAYIKwYBBQUHAwEGCCsGAQUFBwMCMHUGCCsGAQUFBwEBBGkwZzAtBggrBgEFBQcw\n" + - "AYYhaHR0cDovL29jc3Auc2NhMWEuYW1hem9udHJ1c3QuY29tMDYGCCsGAQUFBzAC\n" + - "hipodHRwOi8vY3J0LnNjYTFhLmFtYXpvbnRydXN0LmNvbS9zY2ExYS5jZXIwKAYD\n" + - "VR0RBCEwH4IdcmV2b2tlZC5zY2ExYS5hbWF6b250cnVzdC5jb20wEwYDVR0gBAww\n" + - "CjAIBgZngQwBAgEwDQYJKoZIhvcNAQELBQADggEBABSbe1UCLL7Qay6XK5wD8B5a\n" + - "wvR1XG3UrggpVIz/w5cutEm/yE71hzE0gag/3YPbNYEnaLbJH+9jz4YW9wd/cEPj\n" + - "xSK5PErAQjCd+aA4LKN1xqkSysgYknl0y47hJBXGnWf+hxvBBHeSoUzM0KIC21pC\n" + - "ZyXrmfaPCQAz13ruYIYdQaETqXGVORmKbf/a+Zn18/tfQt0LeeCYVoSopbXWQvcJ\n" + - "gUMtdIqYQmb8aVj0pdZXwKl4yZ2DtlS3Z9MpWNgQNlhRPmiYlu28y2yTtZ9SwD6m\n" + - "2f+cwc19aJrDT4Y280px+jRU7dIE6oZVJU+yBRVIZYpUFAB7extCMVxnTkCf8Dk=\n" + + "MIIGMjCCBRqgAwIBAgIQDhAjZlsSaNeIzCW/aanQXjANBgkqhkiG9w0BAQsFADA8\n" + + "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g\n" + + "UlNBIDIwNDggTTAxMB4XDTIzMDUxMDAwMDAwMFoXDTI0MDYwNzIzNTk1OVowLzEt\n" + + "MCsGA1UEAxMkcmV2b2tlZC5yb290Y2ExLmRlbW8uYW1hem9udHJ1c3QuY29tMIIB\n" + + "IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxSPd1PWACxZohFCAJT1JWuXK\n" + + "GY29wZZ9yY0zoiq6+qYiUIU0crktytUNNI1ZpW/3qXpEw2ZQkM6WF1LshXtwGwrA\n" + + "zJwSeX1L9T5rOKhoBvoFeqfX7xu4VBM1/fDGt5X+NRFfD9Op9UfK5OsnL05TYach\n" + + "rdnfOA5wKGvMgFiN5CeOD0AtumXSuAnTZC85ojJTHjPF+hqV893WvrrUxLyyxtvh\n" + + "lq/WttFOjhfQu2IkfyDAFiH939uzUi0WSTAdsbsHuko5mDTDnOfMRbaaWZu0At01\n" + + "EgaIPeK+kGdi7EYwVndIwTKLeQ4mjIM8aj8Heg/y2hZ0kOmfCUZdUmJFlNoCIQID\n" + + "AQABo4IDOzCCAzcwHwYDVR0jBBgwFoAUgbgOY4qJEhjl+js7UJWf5uWQE4UwHQYD\n" + + "VR0OBBYEFMeBhIOkuWUY4DYqFrfgbD2eUeFtMG0GA1UdEQRmMGSCJHJldm9rZWQu\n" + + "cm9vdGNhMS5kZW1vLmFtYXpvbnRydXN0LmNvbYIdcmV2b2tlZC5zY2EwYS5hbWF6\n" + + "b250cnVzdC5jb22CHXJldm9rZWQuc2NhMWEuYW1hem9udHJ1c3QuY29tMA4GA1Ud\n" + + "DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwOwYDVR0f\n" + + "BDQwMjAwoC6gLIYqaHR0cDovL2NybC5yMm0wMS5hbWF6b250cnVzdC5jb20vcjJt\n" + + "MDEuY3JsMBMGA1UdIAQMMAowCAYGZ4EMAQIBMHUGCCsGAQUFBwEBBGkwZzAtBggr\n" + + "BgEFBQcwAYYhaHR0cDovL29jc3AucjJtMDEuYW1hem9udHJ1c3QuY29tMDYGCCsG\n" + + "AQUFBzAChipodHRwOi8vY3J0LnIybTAxLmFtYXpvbnRydXN0LmNvbS9yMm0wMS5j\n" + + "ZXIwDAYDVR0TAQH/BAIwADCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHYA7s3Q\n" + + "ZNXbGs7FXLedtM0TojKHRny87N7DUUhZRnEftZsAAAGIB72TggAABAMARzBFAiAZ\n" + + "naLbRHRuaRrE304GSuWX/79MU/e+SSlr0cNJ0kNNaAIhAPnz9HayL4txhkTEZiMs\n" + + "nttNnNqD17I0J17JLVOF4i/4AHYASLDja9qmRzQP5WoC+p0w6xxSActW3SyB2bu/\n" + + "qznYhHMAAAGIB72TmwAABAMARzBFAiEAgEqT7CYGQ/u36/3YcxBH78QfknI9kgcY\n" + + "sgJLkurUF6cCIFZZ/b803+ek6o+bmdV/uVx2UlskAyyolZ2okBAb6IscAHYA2ra/\n" + + "az+1tiKfm8K7XGvocJFxbLtRhIU0vaQ9MEjX+6sAAAGIB72TbQAABAMARzBFAiEA\n" + + "6z2RSoK263hvYF71rj1d0TpC70/6zagSRR4glHOT6IACICYvaMAnrCNSTSiZ20Wz\n" + + "Ju5roTippO3BWKhQYrTKZuu4MA0GCSqGSIb3DQEBCwUAA4IBAQB4S1JGulFpMIaP\n" + + "NtLUJmjWz8eexQdWLDVF+H8dd6xpZgpiYtig/Ynphzuk1IIF8DkT3CeK/9vrezgI\n" + + "igNjneN9B4eIuzi/rJzIKeUwpZ2k5D+36Ab4esseoc+TopmNerw8hidt2g818jER\n" + + "D71ppSMakeQFPGe/Hs2/cVa/G1DNVcU2XAut45yRZ/+xsZ0/mcBDVsG9P5uGCN5O\n" + + "7SAp4J959WnKDqgVuU9WowPE5IjmS9BAv2gjniFYdDV2yksyf7+8edHd1KfSVX06\n" + + "pLx6CuCVZGJFG4Q2Aa1YAh1Wvt9hqWeXXpNRO2/wChL5rhT4GajsrGepsk4bjxYX\n" + + "Wf2iZ8mX\n" + "-----END CERTIFICATE-----"; - public void runTest(ValidatePathWithParams pathValidator, boolean ocspEnabled) throws Exception { - // EE certificates don't have CRLDP extension - if (!ocspEnabled){ - pathValidator.validate(new String[]{INT}, - ValidatePathWithParams.Status.GOOD, null, System.out); - - return; - } + public void runTest(ValidatePathWithParams pathValidator) throws Exception { // Validate valid - pathValidator.validate(new String[]{VALID, INT}, + pathValidator.validate(new String[]{VALID, INT_VALID}, ValidatePathWithParams.Status.GOOD, null, System.out); // Validate Revoked - pathValidator.validate(new String[]{REVOKED, INT}, + pathValidator.validate(new String[]{REVOKED, INT_REVOKED}, ValidatePathWithParams.Status.REVOKED, - "Mon Jan 28 15:35:56 PST 2019", System.out); + "Mon May 15 13:36:57 PDT 2023", System.out); } } class AmazonCA_2 { - // Owner: CN=Amazon, OU=Server CA 2A, O=Amazon, C=US + // Owner: CN=Amazon RSA 4096 M02, O=Amazon, C=US // Issuer: CN=Amazon Root CA 2, O=Amazon, C=US - // Serial number: 67f945755f187a91f8163f3e624620177ff38 - // Valid from: Wed Oct 21 17:00:00 PDT 2015 until: Sat Oct 18 17:00:00 PDT 2025 + // Serial number: 773125b0c34c3c940299a9f04a39e5a52ccd9 + // Valid from: Tue Aug 23 15:29:13 PDT 2022 until: Fri Aug 23 15:29:13 PDT 2030 private static final String INT = "-----BEGIN CERTIFICATE-----\n" + - "MIIGRzCCBC+gAwIBAgITBn+UV1Xxh6kfgWPz5iRiAXf/ODANBgkqhkiG9w0BAQwF\n" + + "MIIGXjCCBEagAwIBAgITB3MSWww0w8lAKZqfBKOeWlLM2TANBgkqhkiG9w0BAQwF\n" + "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" + - "b24gUm9vdCBDQSAyMB4XDTE1MTAyMjAwMDAwMFoXDTI1MTAxOTAwMDAwMFowRjEL\n" + - "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEVMBMGA1UECxMMU2VydmVyIENB\n" + - "IDJBMQ8wDQYDVQQDEwZBbWF6b24wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK\n" + - "AoICAQC0P8hSLewmrZ41CCPBQytZs5NBFMq5ztbnMf+kZUp9S25LPfjNW3zgC/6E\n" + - "qCTWNVMMHhq7ez9IQJk48qbfBTLlZkuKnUWbA9vowrDfcxUN0mRE4B/TJbveXyTf\n" + - "vE91iDlqDrERecE9D8sdjzURrtHTp27lZdRkXFvfEVCq4hl3sHkzjodisaQthLp1\n" + - "gLsiA7vKt+8zcL4Aeq52UyYb8r4/jdZ3KaQp8O/T4VwDCRKm8ey3kttpJWaflci7\n" + - "eRzNjY7gE3NMANVXCeQwOBfH2GjINFCObmPsqiBuoAnsv2k5aQLNoU1OZk08ClXm\n" + - "mEZ2rI5qZUTX1HuefBJnpMkPugFCw8afaHnB13SkLE7wxX8SZRdDIe5WiwyDL1tR\n" + - "2+8lpz4JsMoFopHmD3GaHyjbN+hkOqHgLltwewOsiyM0u3CZphypN2KeD+1FLjnY\n" + - "TgdIAd1FRgK2ZXDDrEdjnsSEfShKf0l4mFPSBs9E3U6sLmubDRXKLLLpa/dF4eKu\n" + - "LEKS1bXYT28iM6D5gSCnzho5G4d18jQD/slmc5XmRo5Pig0RyBwDaLuxeIZuiJ0A\n" + - "J6YFhffbrLYF5dEQl0cU+t3VBK5u/o1WkWXsZawU038lWn/AXerodT/pAcrtWA4E\n" + - "NQEN09WEKMhZVPhqdwhF/Gusr04mQtKt7T2v6UMQvtVglv5E7wIDAQABo4IBOTCC\n" + - "ATUwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYE\n" + - "FNpDStD8AcBLv1gnjHbNCoHzlC70MB8GA1UdIwQYMBaAFLAM8Eww9AVYAkj9M+VS\n" + - "r0uE42ZSMHsGCCsGAQUFBwEBBG8wbTAvBggrBgEFBQcwAYYjaHR0cDovL29jc3Au\n" + - "cm9vdGNhMi5hbWF6b250cnVzdC5jb20wOgYIKwYBBQUHMAKGLmh0dHA6Ly9jcnQu\n" + - "cm9vdGNhMi5hbWF6b250cnVzdC5jb20vcm9vdGNhMi5jZXIwPwYDVR0fBDgwNjA0\n" + - "oDKgMIYuaHR0cDovL2NybC5yb290Y2EyLmFtYXpvbnRydXN0LmNvbS9yb290Y2Ey\n" + - "LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggIBAEO5W+iF\n" + - "yChjDyyrmiwFupVWQ0Xy2ReFNQiZq7XKVHvsLQe01moSLnxcBxioOPBKt1KkZO7w\n" + - "Gcbmke0+7AxLaG/F5NPnzRtK1/pRhXQ0XdU8pVh/1/h4GoqRlZ/eN0JDarUhZPkV\n" + - "kSr96LUYDTxcsAidF7zkzWfmtcJg/Aw8mi14xKVEa6aVyKu54c8kKkdlt0WaigOv\n" + - "Z/xYhxp24AfoFKaIraDNdsD8q2N7eDYeN4WGLzNSlil+iFjzflI9mq1hTuI/ZNjV\n" + - "rbvob6FUQ8Cc524gMjbpZCNuZ1gfXzwwhGp0AnQF6CJsWF9uwPpZEVFnnnfiWH3M\n" + - "oup41EvBhqaAqOlny0sm5pI82nRUCAE3DLkJ1+eAtdQaYblZQkQrRyTuPmJEm+5y\n" + - "QwdDVw6uHc5OsSj/tyhh8zJ2Xq3zgh3dMONGjJEysxGaCoIb+61PWwMy2dIarVwI\n" + - "r+c+AY+3PrhgBspNdWZ87JzNHii7ksdjUSVGTTy1vGXgPYrv0lp0IMnKaZP58xiw\n" + - "rDx7uTlQuPVWNOZvCaT3ZcoxTsNKNscIUe+WJjWx5hdzpv/oksDPY5ltZ0j3hlDS\n" + - "D+Itk95/cNJVRM/0HpxI1SX9MTZtOSJoEDdUtOpVaOuBAvEK4gvTzdt0r5L+fuI6\n" + - "o5LAuRo/LO1xVRH49KFRoaznzU3Ch9+kbPb3\n" + + "b24gUm9vdCBDQSAyMB4XDTIyMDgyMzIyMjkxM1oXDTMwMDgyMzIyMjkxM1owPDEL\n" + + "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEcMBoGA1UEAxMTQW1hem9uIFJT\n" + + "QSA0MDk2IE0wMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMGMl/pZ\n" + + "1OsxHY9gw/YfdON4mmrANkPwi7z2djHA5ELt/vRI3Su0le6OoipLf03iyoCnYy4Y\n" + + "rpfTbhyDriE8NJpps2ODJ5W1h0rz6FM1Q5Jt35wfk+4CEfATBTegHVlUJ0rJgzK5\n" + + "Yl/jrk12ZsC4ZeRn54shszcK6bHj4LZIHXhrYIIfetBMMD8V7hlhd54AclEWutUV\n" + + "eBEjkSCzDSk+pQKIjCL0crqvRSPvUNry/BV65zfGmceSYxpcLmV7k7Spwpo+1z8w\n" + + "+Odfnx2vsm7olPldfaThqk6fXBtInORl4Ef32xF3VDT13UeXtQPolFhnp8UOci64\n" + + "bW+R8tbtGpUXIA8Dhr8SgYPH6NW4jhUD4+AG8yer8ctA1Hl9tq+6tYr26q3yuCLu\n" + + "5rwJdfMG634fWIRXSj+GJi8SfAdGtPyXwu5799NWesV4vUkrkSXdIBK4TQCuK+jx\n" + + "aJ5Y+Zo2l3GFsWyMPNORLjoQXbjF6KAyjTyICLq9VzoQKhyx4Ll2CNrQv8CxqtDC\n" + + "GvXi9kREJYAF6lscOB0xglAAF5lndcaNkVHEVOMdg9ZZtdJywHWm8Qed1Wty2qr+\n" + + "hmA7booWQNRE12nW1niC5D4cP2ykPK9HSgb7xWdUF32VidUc9tNKM6xKjSd/R/tP\n" + + "p+XAybNSwEooPt3/OvyhpVRjLuWoqqbClTKdAgMBAAGjggFaMIIBVjASBgNVHRMB\n" + + "Af8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcD\n" + + "AQYIKwYBBQUHAwIwHQYDVR0OBBYEFJ5xHxodk6nZLY7MSFM/A1TznuZmMB8GA1Ud\n" + + "IwQYMBaAFLAM8Eww9AVYAkj9M+VSr0uE42ZSMHsGCCsGAQUFBwEBBG8wbTAvBggr\n" + + "BgEFBQcwAYYjaHR0cDovL29jc3Aucm9vdGNhMi5hbWF6b250cnVzdC5jb20wOgYI\n" + + "KwYBBQUHMAKGLmh0dHA6Ly9jcnQucm9vdGNhMi5hbWF6b250cnVzdC5jb20vcm9v\n" + + "dGNhMi5jZXIwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NybC5yb290Y2EyLmFt\n" + + "YXpvbnRydXN0LmNvbS9yb290Y2EyLmNybDATBgNVHSAEDDAKMAgGBmeBDAECATAN\n" + + "BgkqhkiG9w0BAQwFAAOCAgEAl1GgKXOn0j1MWT1KJVSewQ28SGbie3UwZj1dMsjJ\n" + + "amCrQPn2ngSNbLm9+ulFiBDU8xKR9Zx3tZps55IUKWLUPkfMC+vkV7asDBqqzzE0\n" + + "F/MkekgPfOjx1V9S6Wfg3sSg+9KcluurXFElruqKfOm4cqmkV776X1G+AaaQ7mlU\n" + + "giCYi6NqRQSyhn8zrKkNnbO6QL5a9ICC47kiZYRAR/hRvZOt11QUK5tCMXJXo0iO\n" + + "4XKkMu+jdnehP1kh4xuZhYznIgKK6MJIITFI/Jj89U4SOPncyuS94sUuE2EqvvO/\n" + + "t81qeoey6wThz5iRbU/0CvDFnTMgebWGUZ2UZJ+az/rb3KYXGfVWasLIonkvYT7z\n" + + "vHOGNAA9oQ8TTgPOmPfSVyfpplKtO/aybWp5QSH2csIwuvw5dkmpkc42iD57XHob\n" + + "5LbMJg99z3vQBmod/ipmOpND95/BeA2mllBZgZ53S0nvDXDzbzR9Fd81PAz9Qruo\n" + + "dOJKcD6plKQjZjkLzNh1v/RoCFO8kiJGE4UBMTM8FUk0DXH4bALII4wwmDelrSUu\n" + + "lKvDTDxZvPF4dbEXICNPd51EMGPgETxwboOV+bzWFVI0IWQ8PhZ2VuMPDk2taOMp\n" + + "NsuLtlYc2twPb9r/Hvgv7G6+ItpBHZwOVt1oI3pHbjMp7P3pOZSPr6G1WkNy9mX8\n" + + "rVc=\n" + "-----END CERTIFICATE-----"; - // Owner: CN=good.sca2a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \ - // SERIALNUMBER=5846743, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \ - // OID.1.3.6.1.4.1.311.60.2.1.3=US - // Issuer: CN=Amazon, OU=Server CA 2A, O=Amazon, C=US - // Serial number: 703e4e70616c90d611fd04a5ecc635665184e - // Valid from: Mon Jul 29 16:54:06 PDT 2019 until: Sat Aug 29 16:54:06 PDT 2020 + // Owner: CN=valid.rootca2.demo.amazontrust.com + // Issuer: CN=Amazon RSA 4096 M02, O=Amazon, C=US + // Serial number: 662f7646d76193cbb76946d111e49fa + // Valid from: Tue May 09 17:00:00 PDT 2023 until: Fri Jun 07 16:59:59 PDT 2024 private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + - "MIIHEzCCBPugAwIBAgITBwPk5wYWyQ1hH9BKXsxjVmUYTjANBgkqhkiG9w0BAQwF\n" + - "ADBGMQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2\n" + - "ZXIgQ0EgMkExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTA3MjkyMzU0MDZaFw0yMDA4\n" + - "MjkyMzU0MDZaMIHaMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwC\n" + - "AQITCERlbGF3YXJlMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjEQMA4G\n" + - "A1UEBRMHNTg0Njc0MzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x\n" + - "EDAOBgNVBAcTB1NlYXR0bGUxHjAcBgNVBAoTFUFtYXpvbiBUcnVzdCBTZXJ2aWNl\n" + - "czEjMCEGA1UEAxMaZ29vZC5zY2EyYS5hbWF6b250cnVzdC5jb20wggIiMA0GCSqG\n" + - "SIb3DQEBAQUAA4ICDwAwggIKAoICAQC+XjOB3ZCFX+b9y9reP+e6EAQz4ytiMSqU\n" + - "O4s5MyYLkY6n4BIZHmgWeQ2IgW1VrH8ho+Iu3UsTiuhd3/L/q/w+T0OJfcrWngTs\n" + - "uVcIuvUr32ObPeeWbg/m/lkN7hqH1jY62iybYVrFXiLo1+0G92PUazcyNvyA20+G\n" + - "HsvGG5jlArWNgRLdc8KUXxvnDUxx5vu4jeHEZnqSwuulV1h9ve0UutkmoK0Sk7Rz\n" + - "HMxYK0LmUT5OvcNQSkUi5nLi+M1FxnYYgsELwSiKSSEDfEdgxooMAiVTgw51Q/DB\n" + - "lTOjAIDL3K3J0yGfIG3bwLvE1qz2Z5yWn8f3JibIah7LrC4PiZDDLHFM6V9l+YqU\n" + - "RqimJ5BltSyAx7bxQNZ1AW3Lxvvm894i4k6/Vdf1CDovRuTMPCDAQmKA/A/AQ7TN\n" + - "q3bBimX6UyuJu0I8RyvAYKzFhOOqe4vXrbndTbje/jnzTNQPeIIcuRa9cgXTOrbw\n" + - "86FTUKj6AZXihRWjKWsQpDwdgE0tQETZ3ynCXfbBKfFmn0MSjeX0CEEAZdYHR8EV\n" + - "F271Yt7UJjS/FP702aHTOWk7zFbIRfFQODvBhn0I8p/Stk2sDq4/YsbXVZOe3+ad\n" + - "YavoiODGSAH6ZcZzULumgK9eii0koAOPB/xqXnkcTS63gEHOKjLQl3hqdVZRCugv\n" + - "1CwUXLvoSwIDAQABo4IBYzCCAV8wDgYDVR0PAQH/BAQDAgWgMB0GA1UdDgQWBBTa\n" + - "j6dHgPdOxTGLcwaNDeaMnlSxNjAfBgNVHSMEGDAWgBTaQ0rQ/AHAS79YJ4x2zQqB\n" + - "85Qu9DAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYIKwYBBQUHAQEE\n" + - "aTBnMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5zY2EyYS5hbWF6b250cnVzdC5j\n" + - "b20wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuc2NhMmEuYW1hem9udHJ1c3QuY29t\n" + - "L3NjYTJhLmNlcjAlBgNVHREEHjAcghpnb29kLnNjYTJhLmFtYXpvbnRydXN0LmNv\n" + - "bTBQBgNVHSAESTBHMA0GC2CGSAGG/W4BBxgDMDYGBWeBDAEBMC0wKwYIKwYBBQUH\n" + - "AgEWH2h0dHBzOi8vd3d3LmFtYXpvbnRydXN0LmNvbS9jcHMwDQYJKoZIhvcNAQEM\n" + - "BQADggIBAE6RwZAZvN0i9ygwzqoX9DhSPtvZ3xIO0G0Bhgjkb986+p8XJstU3gEM\n" + - "8P2i1J/YthXCnRGedm+Odxx+31G6xIYfP5S5g7HyRGkj/aXNXy4s3KjH8HJgOY9N\n" + - "ra3XfC05OKq5FpyZQDZ+hxCdLrH3Gs+UxREbu+LuIKUpI7nMVEjn9XynKyOdKN21\n" + - "Kq5VsuI0fDWCYvUN1M+lI/LgE5HbNJVQJs+dB7g1/kaOeaLia7Wk1ys+uRzB58rp\n" + - "FKAoLk++HWTfNDkbN8vKRfHhJ/xhI9ju3TWcci6EyFVAym1C62UkJNI0KHgQ+zc7\n" + - "nl1tv/ytj8N/eJoysyp23lJ5qrVetlQORfgXryGkWBMYBvYF8zbBb/f+UXHDKVWt\n" + - "9l1lL6HQGY/tTo253pj6/FgDD35bZdjLQeUVmbnz679S5oUmoH5ZtSdnpUTghU3p\n" + - "bae9adBFY9S1pm50Q3ckRVBAwNqNmI0KKUh14Ms8KSAUHg19NvGsBonqwOT2rdbv\n" + - "xZ47N6c2eCl/cjMvzre0v0NoUO+3og2GHeAoOwVos6480YDbMqp739tOFPxBcsII\n" + - "6SjpDVh+14dkSW6kEKeaCFLR+eChqutri1VQbQ49nmADQWw9Al8vBytSnPv0YN6W\n" + - "XfIE1Qj7YmHu/UuoeKVsqDqoP/no29+96dtfd4afJqlIoyZUqXpt\n" + + "MIIICzCCBfOgAwIBAgIQBmL3ZG12GTy7dpRtER5J+jANBgkqhkiG9w0BAQwFADA8\n" + + "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g\n" + + "UlNBIDQwOTYgTTAyMB4XDTIzMDUxMDAwMDAwMFoXDTI0MDYwNzIzNTk1OVowLTEr\n" + + "MCkGA1UEAxMidmFsaWQucm9vdGNhMi5kZW1vLmFtYXpvbnRydXN0LmNvbTCCAiIw\n" + + "DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAON5EbEKoBiujI7Ja8mLZLJbaY7f\n" + + "RtoWIjU/F0l9ueWFogXmEaA1jWsl97F3WTHTyGKz6ChCjPMSyoXXpY+yoE90QUyX\n" + + "w35uWEhNrc40drMJkyN+QXitSrH346GCOKvpYVvu18UD4W8hDhg8vvbOQYhtmSf7\n" + + "Rfrs7/qUdXpzpvR9VjWktbQAzJT8fB/jFNjNQJTknynjGiYO5GF51+peOCLK6qw8\n" + + "9kKYEigR4K8/aWL283rC4xRxZqVioy433VG02l/Fwdv8o/vL9YYIqkyspCB9fpFw\n" + + "Q50yYrwEomxuOz7rXhmdfeNaFYuyTtOUSKff6p2oqO0S7pcLujUVMlO4dYBDELQF\n" + + "cabByNjwblviCtGKJMIzD6Thkgamp3iXQgcU498+P5r7N5CYbMmkJEdcuILg+bgJ\n" + + "/LUUTT+IMt2txYlO/ld3N0EHlgVt7rztW5mtm6Ba8jN7cLSh7ZWu6Fr1+oK7bl5T\n" + + "wPxSfqT5W3BwQKS3YptIoKEWUb+VNnS/dYx/7IspF9+z6kw4g+V2EY9M4ZYNakzM\n" + + "AI7KIj4thMFoWeYrJq0dUMZ297QCBPRdAwh9hhkq2LYi2x8tMUtcBnhb/q75sO+E\n" + + "icPqFVv7iMDZ/8Xep+0UoClF3JGmZW3UNtwcbi7Pn/OqtaMi7E8xnHUgc4ZchtXO\n" + + "v8VtVvDeZAlY5TjVAgMBAAGjggMWMIIDEjAfBgNVHSMEGDAWgBSecR8aHZOp2S2O\n" + + "zEhTPwNU857mZjAdBgNVHQ4EFgQUnGekBRKIZBYgCEajbpCMC24bp2owSQYDVR0R\n" + + "BEIwQIIidmFsaWQucm9vdGNhMi5kZW1vLmFtYXpvbnRydXN0LmNvbYIaZ29vZC5z\n" + + "Y2EyYS5hbWF6b250cnVzdC5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQG\n" + + "CCsGAQUFBwMBBggrBgEFBQcDAjA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8vY3Js\n" + + "LnI0bTAyLmFtYXpvbnRydXN0LmNvbS9yNG0wMi5jcmwwEwYDVR0gBAwwCjAIBgZn\n" + + "gQwBAgEwdQYIKwYBBQUHAQEEaTBnMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5y\n" + + "NG0wMi5hbWF6b250cnVzdC5jb20wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQucjRt\n" + + "MDIuYW1hem9udHJ1c3QuY29tL3I0bTAyLmNlcjAMBgNVHRMBAf8EAjAAMIIBfQYK\n" + + "KwYBBAHWeQIEAgSCAW0EggFpAWcAdgDuzdBk1dsazsVct520zROiModGfLzs3sNR\n" + + "SFlGcR+1mwAAAYgHvX9QAAAEAwBHMEUCIQD8qPPCLL2Grd+/YNALWqAq7LC7YBaa\n" + + "dNg5+6Q4kRDEqgIgEkf/UMsMNfTRaOZvoOgAK9/F0xX/CfdcUTjULhmoA+cAdQBI\n" + + "sONr2qZHNA/lagL6nTDrHFIBy1bdLIHZu7+rOdiEcwAAAYgHvX8UAAAEAwBGMEQC\n" + + "IBVFDtapMMWJOqyu8Cv6XEhFmbU8N33c2owed//pa80xAiAT9T6Wba3B9DFUmrL5\n" + + "cCGKLqciIEUPhPbvjCuUepelrAB2ANq2v2s/tbYin5vCu1xr6HCRcWy7UYSFNL2k\n" + + "PTBI1/urAAABiAe9ft8AAAQDAEcwRQIhAP2XDC/RlmVtH4WrfSwVosR/f/WXRhG5\n" + + "mk9Nwq+ZOIriAiAopPXSH7VwXa3bEAIiTwcV1l10QIDZaIPCU5olknU5CjANBgkq\n" + + "hkiG9w0BAQwFAAOCAgEAFuwMIJdP5rgz6cqOIj2EgF2OU8CUGi/wJ45BomXWv4Rv\n" + + "U5mOKB+jHOGZZC9dncjAMa44RwoF2I7/8Y3qLVaoNm46ObvvS+6UvzTcyQqXM7JU\n" + + "cSmdlf9DkspjKPDvMBokVrM4ak5AoxUjuru5qaia3nvbxq7XKO9/FGUaUaU8Xlsd\n" + + "V6Fo8VmNwFc88VCqOp8eI/IicHxMDLl8TKXMvr3CYh8A9nCeFGcV+4CL+7JF2t5K\n" + + "YvV5r074Wyk0QMlRVYMNDl0t+VAEoDJ7RRE+kEvplWcsX9S2wvr4HhkA4iChpwFm\n" + + "2UDTppHskSWyLsuNQvipn0zTzZ8RIxXd/ei0qCdhKmkV7x9cgbTiyXgaI7iJEtdo\n" + + "RvYNcXc2RmitWjY5Av8yJGOk0eYpCwRrBv6ughbtJe3NMrqUeTyrKidIEo9KnRSA\n" + + "rMokRbHunkroS97VkoK/9j9pNJki+qAH9XTLYWcm/5+cTSGRsN+escRgZwV6KWg/\n" + + "JQQe5LbwU2HHzNqWuk63GC/ngVlWXjaVFfbNVmYEKZFFazcZchesN1YyDu+WndOx\n" + + "+rTcuke2feOvQ4EnVviM0k85JZNiqPDH2iafAWyqZFUYTnb7XK3HhJflAniv/SLq\n" + + "DQfbJmtQtNHdJYgVmC1u2RT9gbJDIAj0ZI4vU2WVB5Hmd9F31un6jundEuG4+S4=\n" + "-----END CERTIFICATE-----"; - // Owner: CN=revoked.sca2a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \ - // SERIALNUMBER=5846743, OID.2.5.4.15=PrivateOrganization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \ - // OID.1.3.6.1.4.1.311.60.2.1.3=US - //Issuer: CN=Amazon, OU=Server CA 2A, O=Amazon, C=US - //Serial number: 6f1d782c0aa2f4866b7b522c279b939b92369 - //Valid from: Mon Jan 28 15:37:45 PST 2019 until: Thu Apr 28 16:37:45 PDT 2022 + // Owner: CN=revoked.rootca2.demo.amazontrust.com + // Issuer: CN=Amazon RSA 4096 M02, O=Amazon, C=US + // Serial number: 788baa8f47bc5b1c624424216240fd3 + // Valid from: Tue May 09 17:00:00 PDT 2023 until: Fri Jun 07 16:59:59 PDT 2024 private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + - "MIIG2zCCBMOgAwIBAgITBvHXgsCqL0hmt7Uiwnm5ObkjaTANBgkqhkiG9w0BAQwF\n" + - "ADBGMQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2\n" + - "ZXIgQ0EgMkExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTAxMjgyMzM3NDVaFw0yMjA0\n" + - "MjgyMzM3NDVaMIHcMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwC\n" + - "AQITCERlbGF3YXJlMRwwGgYDVQQPExNQcml2YXRlT3JnYW5pemF0aW9uMRAwDgYD\n" + - "VQQFEwc1ODQ2NzQzMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ\n" + - "MA4GA1UEBxMHU2VhdHRsZTEeMBwGA1UEChMVQW1hem9uIFRydXN0IFNlcnZpY2Vz\n" + - "MSYwJAYDVQQDEx1yZXZva2VkLnNjYTJhLmFtYXpvbnRydXN0LmNvbTCCAiIwDQYJ\n" + - "KoZIhvcNAQEBBQADggIPADCCAgoCggIBAKFm418X8hN1YTgD2XpMb4sp78mw8k3j\n" + - "Dq/vnpX48evVUzNpHpy4qRz/ZHBR4HUJO4lhfnX+CO0uRqqqx4F0JZRQB3KevaU8\n" + - "QGWHdJGhEddnurDhrgOUa+ZroqUnMCsTJfbyGtC6aiEXeu/eMhEUFkuBxJH1JtwD\n" + - "dQXMXuMjG07SVjOkhTkbMDzA/YbUqkDeOIybifDuvA5LEsl+kReY0b6RYFo2Tt/M\n" + - "dPhJD8q3Wsu+XCiCnbpcwlEVGxiD2RVRXJJ9o3ALGOxqU69V+lYS0kkwNHT7oV9J\n" + - "rhgt7iOCq0aoTAxu2j4FCp0JHNhGoW9pXoMXnmS6kK80hzLNYDxvKEaVaKkiYHw5\n" + - "CV0Vwii05ICa14nrStH/jcRNLyU+gp+6OeerPV3jpKWshGKWewF+2UiWU2WHTSrd\n" + - "Wis0/qEfFK/kSraAxpd+KavEEavKeudoMAHIxMACOk9E/fF5zhd2y4G1q1BdoRlR\n" + - "KP4GIV2v6qH6Ru2mNSuge9il6kDXxFNucrYKLDbAqkqalohkvDavcPoG9gZT3etv\n" + - "4IcgJriIWRxbJwKPpwJM+6wa6RpwoeJMuEp3ZBP7KDaQ8YX4rlf4zXLAsOKCNA9K\n" + - "OS/qYQ/I4g0E1WhfgEKClaLPS2u7jeVR6s1t4txGo4vq5Dkt17KTCew/WsX3rckf\n" + - "a2p5zvFcfpCNAgMBAAGjggEpMIIBJTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0OBBYE\n" + - "FAF8N1wV8EoYFkMXH6tEnmR/7vI+MB8GA1UdIwQYMBaAFNpDStD8AcBLv1gnjHbN\n" + - "CoHzlC70MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BggrBgEFBQcB\n" + - "AQRpMGcwLQYIKwYBBQUHMAGGIWh0dHA6Ly9vY3NwLnNjYTJhLmFtYXpvbnRydXN0\n" + - "LmNvbTA2BggrBgEFBQcwAoYqaHR0cDovL2NydC5zY2EyYS5hbWF6b250cnVzdC5j\n" + - "b20vc2NhMmEuY2VyMCgGA1UdEQQhMB+CHXJldm9rZWQuc2NhMmEuYW1hem9udHJ1\n" + - "c3QuY29tMBMGA1UdIAQMMAowCAYGZ4EMAQIBMA0GCSqGSIb3DQEBDAUAA4ICAQBC\n" + - "VwR1NFk1IYIF4cjU7ML1aj8OIn+8mtakGQnuSJLK6ypSysINJBS48ZDdP6XZXvyD\n" + - "iTS0xEAPjAZHTqrABdNYmvJeL2RnN99DIwVzBpZp4NLTXbiSW7jb0Y5cEPDGJMOo\n" + - "SUAAM6fsiPRfz5vX4XVPznbcF2AwE/NVV+L3n9LVRt7qv2VqIEvLioR56Dq+5ofR\n" + - "4bw0BVlEYWF4Gsy7WDDTL1iLNBUwZTqBHwTv0fgDRiPqb/odmLQuRANwcJy8B8Zr\n" + - "s/yX4SeESaRdA82lAlQilksQitXS2qvQN06GEDOgUxYE6EabFdgklV5JypKqdOly\n" + - "vzpaDpF3z5W8Bj3D4fns1Kjrh1pPh5JRvg+616diKnQRt4X5q+EtmnXhDvIGMISI\n" + - "FuGwj57CNQ2x2MY2HHKWPrOccpQfEEvoSNR+ntYWrtSSttZq948O+zZBk1TXWuXV\n" + - "TVXllqTg8lp6d5cfKgvtHKgt98WkpPOcLVrNuVnMAIfDw6ar54dVKqrvkeEcF6mJ\n" + - "7oMKjJX/Vu9lYoGViBIfdeqcCPWSI8BpnCKaG7dTQO3Q1ObGmLdGBRlsRh+d+S5l\n" + - "Fq326ckbjx537e5/ai31lOR7OwVh9TDweKLqIACjs987C0EJSEfoOue25WRww2va\n" + - "iX9SrTPm4GxQ2OJgYwx0+HbezJXFN+dhaOFUavTSFw==\n" + + "MIIIEjCCBfqgAwIBAgIQB4i6qPR7xbHGJEJCFiQP0zANBgkqhkiG9w0BAQwFADA8\n" + + "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g\n" + + "UlNBIDQwOTYgTTAyMB4XDTIzMDUxMDAwMDAwMFoXDTI0MDYwNzIzNTk1OVowLzEt\n" + + "MCsGA1UEAxMkcmV2b2tlZC5yb290Y2EyLmRlbW8uYW1hem9udHJ1c3QuY29tMIIC\n" + + "IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzJfddWdrWhA9dSJdmy23veN9\n" + + "oLvSqpM4YaXGZmPtKUmbFMLs2I3vCKrzflRKeOpl3MCc2hh6TH/3z+Q/fGugXLsY\n" + + "H8QcjSbiIOd15n+3dUFTLKaoWMyseMcWiOIVaN5rCDVXiAHdt1pc147wyFQIzqNK\n" + + "J/xiV1u9eT2MFue+4bd7kUNAcmI8M+SXruhto4jtAV8ugpTEChTDlyO/l8xmaM1Q\n" + + "HkijsHX7Aq72Q/3PH/U+wbJ9pmpTp4x2AEJoo45IGfB/NKDTrv5otLBuiP8Y0M7b\n" + + "K7irRPDFBqMNZw7S7p39SnC+V/WibJQk5Bo/8vcwDJX+WnDkw1QD/uXu3ugDzSDD\n" + + "iBDViMOdN+3K47s4x2kdssoh4WWScMlAVb4vyN7IA3J4TnwA/1uCWhw4LE1WvY7N\n" + + "etekhVP1eWF8IzNY0oo2u2ie79777xvBtmtp7RnvYLGv7I+xVhjH5qGNzn9fRCUm\n" + + "QDego5HAfJ0PLlMEagdW8asCak1WaC117adnibL6WPtFA2FD2i6gNalTvhXhK2Ex\n" + + "alGxrVd/BCseT3bMp783jqScJO1g6xRHu0Qx+RyrOGVvcKZa6Y0DcAc8psRpkHaO\n" + + "HZY+lE8O2CIxpAJlwSnD6BoDNo8sg1IqFNkECw3wqfeMPBcg38k6zjAxwRDcIx6U\n" + + "SwDl4d3sjrmy3gOFFXMCAwEAAaOCAxswggMXMB8GA1UdIwQYMBaAFJ5xHxodk6nZ\n" + + "LY7MSFM/A1TznuZmMB0GA1UdDgQWBBQXpWT7gMHO+HKoHM1gU1VQVnylRzBOBgNV\n" + + "HREERzBFgiRyZXZva2VkLnJvb3RjYTIuZGVtby5hbWF6b250cnVzdC5jb22CHXJl\n" + + "dm9rZWQuc2NhMmEuYW1hem9udHJ1c3QuY29tMA4GA1UdDwEB/wQEAwIFoDAdBgNV\n" + + "HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwOwYDVR0fBDQwMjAwoC6gLIYqaHR0\n" + + "cDovL2NybC5yNG0wMi5hbWF6b250cnVzdC5jb20vcjRtMDIuY3JsMBMGA1UdIAQM\n" + + "MAowCAYGZ4EMAQIBMHUGCCsGAQUFBwEBBGkwZzAtBggrBgEFBQcwAYYhaHR0cDov\n" + + "L29jc3AucjRtMDIuYW1hem9udHJ1c3QuY29tMDYGCCsGAQUFBzAChipodHRwOi8v\n" + + "Y3J0LnI0bTAyLmFtYXpvbnRydXN0LmNvbS9yNG0wMi5jZXIwDAYDVR0TAQH/BAIw\n" + + "ADCCAX0GCisGAQQB1nkCBAIEggFtBIIBaQFnAHYA7s3QZNXbGs7FXLedtM0TojKH\n" + + "Rny87N7DUUhZRnEftZsAAAGIB72CzgAABAMARzBFAiEA2vPYIPfGJeynPaZHq/c0\n" + + "GGvyT6MpvFGMW0s0woLRT28CIEFbZbFSCnKugaqw9QDNi7vYmIF3Gyi3s6G2cCxY\n" + + "4RJXAHYASLDja9qmRzQP5WoC+p0w6xxSActW3SyB2bu/qznYhHMAAAGIB72DDgAA\n" + + "BAMARzBFAiAvfNcgtFEwk5C9dvMUYANbIAv0IOdF1new8Umn3cM+JwIhALbs/3L9\n" + + "0ndF7sRKDZmfronNruptFlrI528P5Qi2P528AHUA2ra/az+1tiKfm8K7XGvocJFx\n" + + "bLtRhIU0vaQ9MEjX+6sAAAGIB72CxQAABAMARjBEAiBKUns2FPbs0cThb6e7SnyL\n" + + "y4/qP3V1Q/ASt/ZDRTeEQQIgWSQO4Gsz32srtqYuTM9AsFd92WA44kJHincdcGVX\n" + + "XbIwDQYJKoZIhvcNAQEMBQADggIBAAnaNbn2wXylTCS7dtgB3rWdUf6hja1UDuvB\n" + + "uZEL2dUOvyXfVFLNxKdeWBPzqpwEBNNwPQXhoI97TXlyu2x60jLzQamoGoRQ3s0P\n" + + "NLhasLGEIQH/oYdMV/yp8EI8fUuRVE3xyw39FRqOrmsUFAnxNQmBO/09JM7sLcvS\n" + + "wwh14p9dFTTolJHgnL4ZEtmZxSddFG+GBSTJ/A7dVSmwIudwzd+goA6173BI6yeT\n" + + "hhQumLctQiOM7y1MzFeV8rL+oIpd2xuzyhKKT1EgvU6/wyt0Ib8QqsFsrXPnUOKk\n" + + "HAq3SeZyq35QUaTKoaH9L1iZMbSCG9Jm6FMb12SdAz53653tYvAiUS76oD8Jot13\n" + + "RZu5NUlWAVLLq0OaEtuGp0bh+cVtzVnCC9m1qa46YpY0SojpvSbakgQMMGIgDlT3\n" + + "wFE7tST4WlsDC1f/m+H9V5qz/j0U8D3eNNdowxPqx/JZq/sk9ZK5KyMFARrvM+fh\n" + + "YrVYjKt91mu7JaS4pPOyZmJ8OQ14EvrN7BXc7IkNrI1reeaRFe49k5DAETB8VmP5\n" + + "2F0SWou2KkgtJvU4Z7YjlZ2HNHnpjTK5KdPNpRSt7EUy2zn9NCNoyQhnws70FyXv\n" + + "oPFyG92lnUQOKaAUhVRwTr9fvnkdMOzSKg/spxi2Ogdzym5Jw68eguwi0dVqX2+9\n" + + "3zViP2aH\n" + "-----END CERTIFICATE-----"; - public void runTest(ValidatePathWithParams pathValidator, boolean ocspEnabled) throws Exception { - // EE certificates don't have CRLDP extension - if (!ocspEnabled){ - pathValidator.validate(new String[]{INT}, - ValidatePathWithParams.Status.GOOD, null, System.out); - - return; - } + public void runTest(ValidatePathWithParams pathValidator) throws Exception { // Validate valid pathValidator.validate(new String[]{VALID, INT}, @@ -344,201 +378,228 @@ public void runTest(ValidatePathWithParams pathValidator, boolean ocspEnabled) t // Validate Revoked pathValidator.validate(new String[]{REVOKED, INT}, ValidatePathWithParams.Status.REVOKED, - "Mon Jan 28 15:38:57 PST 2019", System.out); + "Mon May 15 13:38:54 PDT 2023", System.out); } } class AmazonCA_3 { - // Owner: CN=Amazon, OU=Server CA 3A, O=Amazon, C=US + // Owner: CN=Amazon ECDSA 256 M02, O=Amazon, C=US // Issuer: CN=Amazon Root CA 3, O=Amazon, C=US - // Serial number: 67f945758fe55b9ee3f75831d47f07d226c8a - // Valid from: Wed Oct 21 17:00:00 PDT 2015 until: Sat Oct 18 17:00:00 PDT 2025 - private static final String INT = "-----BEGIN CERTIFICATE-----\n" + - "MIICuzCCAmGgAwIBAgITBn+UV1j+VbnuP3WDHUfwfSJsijAKBggqhkjOPQQDAjA5\n" + + // Serial number: 773126de2c2fafd2c47ad88b1566e0182046d + // Valid from: Tue Aug 23 15:33:24 PDT 2022 until: Fri Aug 23 15:33:24 PDT 2030 + private static final String INT_VALID = "-----BEGIN CERTIFICATE-----\n" + + "MIIC1DCCAnmgAwIBAgITB3MSbeLC+v0sR62IsVZuAYIEbTAKBggqhkjOPQQDAjA5\n" + + "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" + + "Um9vdCBDQSAzMB4XDTIyMDgyMzIyMzMyNFoXDTMwMDgyMzIyMzMyNFowPTELMAkG\n" + + "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEdMBsGA1UEAxMUQW1hem9uIEVDRFNB\n" + + "IDI1NiBNMDIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS9vQLD4W/Kg4AnFRl8\n" + + "x/FUbLqtd5ICYjUijGsytF9hmgb/Dyk+Ebt4cw6rAlGbaiOLapSJKZiZr+UQdh3I\n" + + "QOr+o4IBWjCCAVYwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYw\n" + + "HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBS7eJrXaDMy\n" + + "nRq7bP2xNEwB3svQdTAfBgNVHSMEGDAWgBSrttvXBp43rDCGB5Fwx5zEGbF4wDB7\n" + + "BggrBgEFBQcBAQRvMG0wLwYIKwYBBQUHMAGGI2h0dHA6Ly9vY3NwLnJvb3RjYTMu\n" + + "YW1hem9udHJ1c3QuY29tMDoGCCsGAQUFBzAChi5odHRwOi8vY3J0LnJvb3RjYTMu\n" + + "YW1hem9udHJ1c3QuY29tL3Jvb3RjYTMuY2VyMD8GA1UdHwQ4MDYwNKAyoDCGLmh0\n" + + "dHA6Ly9jcmwucm9vdGNhMy5hbWF6b250cnVzdC5jb20vcm9vdGNhMy5jcmwwEwYD\n" + + "VR0gBAwwCjAIBgZngQwBAgEwCgYIKoZIzj0EAwIDSQAwRgIhAKSYEcDcp3kcPMzh\n" + + "OIYDWZOLu4InPod4fQhRTmc2zBAgAiEAmwdGE4AuNWhw9N8REhf82rJLNm7h9Myg\n" + + "TsR9Wu0bQYU=\n" + + "-----END CERTIFICATE-----"; + + // Owner: CN=Amazon ECDSA 256 M01, O=Amazon, C=US + // Issuer: CN=Amazon Root CA 3, O=Amazon, C=US + // Serial number: 773126684d577c0fcf8d3a342bea86f94fc8f + // Valid from: Tue Aug 23 15:31:46 PDT 2022 until: Fri Aug 23 15:31:46 PDT 2030 + private static final String INT_REVOKED = "-----BEGIN CERTIFICATE-----\n" + + "MIIC0zCCAnmgAwIBAgITB3MSZoTVd8D8+NOjQr6ob5T8jzAKBggqhkjOPQQDAjA5\n" + "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" + - "Um9vdCBDQSAzMB4XDTE1MTAyMjAwMDAwMFoXDTI1MTAxOTAwMDAwMFowRjELMAkG\n" + - "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEVMBMGA1UECxMMU2VydmVyIENBIDNB\n" + - "MQ8wDQYDVQQDEwZBbWF6b24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATYcYsK\n" + - "mYdR0Gj8Xz45E/lfcTTnXhg2EtAIYBIHyXv/ZQyyyCas1aptX/I5T1coT6XK181g\n" + - "nB8hADuKfWlNoIYRo4IBOTCCATUwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8B\n" + - "Af8EBAMCAYYwHQYDVR0OBBYEFATc4JXl6LlrlKHvjFsxHhN+VZfaMB8GA1UdIwQY\n" + - "MBaAFKu229cGnjesMIYHkXDHnMQZsXjAMHsGCCsGAQUFBwEBBG8wbTAvBggrBgEF\n" + - "BQcwAYYjaHR0cDovL29jc3Aucm9vdGNhMy5hbWF6b250cnVzdC5jb20wOgYIKwYB\n" + - "BQUHMAKGLmh0dHA6Ly9jcnQucm9vdGNhMy5hbWF6b250cnVzdC5jb20vcm9vdGNh\n" + - "My5jZXIwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NybC5yb290Y2EzLmFtYXpv\n" + - "bnRydXN0LmNvbS9yb290Y2EzLmNybDARBgNVHSAECjAIMAYGBFUdIAAwCgYIKoZI\n" + - "zj0EAwIDSAAwRQIgOl/vux0qfxNm05W3eofa9lKwz6oKvdu6g6Sc0UlwgRcCIQCS\n" + - "WSQ6F6JHLoeOWLyFFF658eNKEKbkEGMHz34gLX/N3g==\n" + + "Um9vdCBDQSAzMB4XDTIyMDgyMzIyMzE0NloXDTMwMDgyMzIyMzE0NlowPTELMAkG\n" + + "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEdMBsGA1UEAxMUQW1hem9uIEVDRFNB\n" + + "IDI1NiBNMDEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT80w+2RwNHzyXmVUM/\n" + + "OUKBZpJkTzHyCKDl4sBrUfjzVjot/lNba9kYzMKSHYv95CUDoMaF2h2KAqx65uLQ\n" + + "Y8ago4IBWjCCAVYwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYw\n" + + "HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBRPWfy8BhYo\n" + + "v6LI2wj7zxMkumlCXDAfBgNVHSMEGDAWgBSrttvXBp43rDCGB5Fwx5zEGbF4wDB7\n" + + "BggrBgEFBQcBAQRvMG0wLwYIKwYBBQUHMAGGI2h0dHA6Ly9vY3NwLnJvb3RjYTMu\n" + + "YW1hem9udHJ1c3QuY29tMDoGCCsGAQUFBzAChi5odHRwOi8vY3J0LnJvb3RjYTMu\n" + + "YW1hem9udHJ1c3QuY29tL3Jvb3RjYTMuY2VyMD8GA1UdHwQ4MDYwNKAyoDCGLmh0\n" + + "dHA6Ly9jcmwucm9vdGNhMy5hbWF6b250cnVzdC5jb20vcm9vdGNhMy5jcmwwEwYD\n" + + "VR0gBAwwCjAIBgZngQwBAgEwCgYIKoZIzj0EAwIDSAAwRQIhALRfxq3SQIhj5xA4\n" + + "S5UAY/KlKqayZDpnbBdCDH8Kqmf/AiAUVZddALefnqRe+ifxN2FUp461LL6/cgVM\n" + + "EH3Ty27f1Q==\n" + "-----END CERTIFICATE-----"; - // Owner: CN=good.sca3a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \ - // SERIALNUMBER=5846743, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \ - // OID.1.3.6.1.4.1.311.60.2.1.3=US - // Issuer: CN=Amazon, OU=Server CA 3A, O=Amazon, C=US - // Serial number: 703e4e9bbc2605f37967a0e95f31f4789a677 - // Valid from: Mon Jul 29 16:54:43 PDT 2019 until: Sat Aug 29 16:54:43 PDT 2020 + // Owner: CN=valid.rootca3.demo.amazontrust.com + // Issuer: CN=Amazon ECDSA 256 M02, O=Amazon, C=US + // Serial number: 8e2f14864fb28e4a1da0f15a5118cc8 + // Valid from: Tue May 09 17:00:00 PDT 2023 until: Fri Jun 07 16:59:59 PDT 2024 private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + - "MIIDhzCCAy2gAwIBAgITBwPk6bvCYF83lnoOlfMfR4mmdzAKBggqhkjOPQQDAjBG\n" + - "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2ZXIg\n" + - "Q0EgM0ExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTA3MjkyMzU0NDNaFw0yMDA4Mjky\n" + - "MzU0NDNaMIHaMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQIT\n" + - "CERlbGF3YXJlMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjEQMA4GA1UE\n" + - "BRMHNTg0Njc0MzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO\n" + - "BgNVBAcTB1NlYXR0bGUxHjAcBgNVBAoTFUFtYXpvbiBUcnVzdCBTZXJ2aWNlczEj\n" + - "MCEGA1UEAxMaZ29vZC5zY2EzYS5hbWF6b250cnVzdC5jb20wWTATBgcqhkjOPQIB\n" + - "BggqhkjOPQMBBwNCAARl4yxf8XcvWR0LZ+YuBC0CpkwtU2NiMdlIM7eX0lxhQp53\n" + - "NpLlCrPRNzOWrjCJDdn21D0u7PrtN94UHLHOg9X0o4IBYzCCAV8wDgYDVR0PAQH/\n" + - "BAQDAgeAMB0GA1UdDgQWBBT2cHmOJFLWfg1Op7xAdAnqYcwaPzAfBgNVHSMEGDAW\n" + - "gBQE3OCV5ei5a5Sh74xbMR4TflWX2jAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\n" + - "BQUHAwIwdQYIKwYBBQUHAQEEaTBnMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5z\n" + - "Y2EzYS5hbWF6b250cnVzdC5jb20wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuc2Nh\n" + - "M2EuYW1hem9udHJ1c3QuY29tL3NjYTNhLmNlcjAlBgNVHREEHjAcghpnb29kLnNj\n" + - "YTNhLmFtYXpvbnRydXN0LmNvbTBQBgNVHSAESTBHMA0GC2CGSAGG/W4BBxgDMDYG\n" + - "BWeBDAEBMC0wKwYIKwYBBQUHAgEWH2h0dHBzOi8vd3d3LmFtYXpvbnRydXN0LmNv\n" + - "bS9jcHMwCgYIKoZIzj0EAwIDSAAwRQIgURdcqJVr4PWNIkmWcSKmzgZ1i94hQpGe\n" + - "mWbE9osk4m0CIQDhxIguihwvDa5RsBwdM0aRDgGKLNHigGqJoKqgH0d2qg==\n" + + "MIIEfjCCBCWgAwIBAgIQCOLxSGT7KOSh2g8VpRGMyDAKBggqhkjOPQQDAjA9MQsw\n" + + "CQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMR0wGwYDVQQDExRBbWF6b24gRUNE\n" + + "U0EgMjU2IE0wMjAeFw0yMzA1MTAwMDAwMDBaFw0yNDA2MDcyMzU5NTlaMC0xKzAp\n" + + "BgNVBAMTInZhbGlkLnJvb3RjYTMuZGVtby5hbWF6b250cnVzdC5jb20wWTATBgcq\n" + + "hkjOPQIBBggqhkjOPQMBBwNCAAQfWc7gBGBBBmseCb2XWWRQVhCUQDVml3mVgvj5\n" + + "RmnP1y5wpifUTFqu8ELdI7YGZ4JMSnetiKNmLtg5yhTEjzCQo4IDFTCCAxEwHwYD\n" + + "VR0jBBgwFoAUu3ia12gzMp0au2z9sTRMAd7L0HUwHQYDVR0OBBYEFHCE8orvZDUK\n" + + "5TI9MYadzxWR9CZGMEkGA1UdEQRCMECCInZhbGlkLnJvb3RjYTMuZGVtby5hbWF6\n" + + "b250cnVzdC5jb22CGmdvb2Quc2NhM2EuYW1hem9udHJ1c3QuY29tMA4GA1UdDwEB\n" + + "/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwOwYDVR0fBDQw\n" + + "MjAwoC6gLIYqaHR0cDovL2NybC5lMm0wMi5hbWF6b250cnVzdC5jb20vZTJtMDIu\n" + + "Y3JsMBMGA1UdIAQMMAowCAYGZ4EMAQIBMHUGCCsGAQUFBwEBBGkwZzAtBggrBgEF\n" + + "BQcwAYYhaHR0cDovL29jc3AuZTJtMDIuYW1hem9udHJ1c3QuY29tMDYGCCsGAQUF\n" + + "BzAChipodHRwOi8vY3J0LmUybTAyLmFtYXpvbnRydXN0LmNvbS9lMm0wMi5jZXIw\n" + + "DAYDVR0TAQH/BAIwADCCAXwGCisGAQQB1nkCBAIEggFsBIIBaAFmAHUA7s3QZNXb\n" + + "Gs7FXLedtM0TojKHRny87N7DUUhZRnEftZsAAAGIB71y/gAABAMARjBEAiAEAXIb\n" + + "aOVR26HgFaI+qoIasCb8w2sOqVxGAxf5iPgX6QIgdAlMjqeoihi1arnJpzN8Bqxy\n" + + "5ULMUO7GK3JEgcogJHMAdgBIsONr2qZHNA/lagL6nTDrHFIBy1bdLIHZu7+rOdiE\n" + + "cwAAAYgHvXLkAAAEAwBHMEUCIF7wDDmWxTHwBZM7Me8eOCM1aQ/g1c1rJg/I+NJa\n" + + "HkZYAiEA8p+IviuY5piHBELjUtVlZLiS9XSSMxpQNhUerqC/YFoAdQDatr9rP7W2\n" + + "Ip+bwrtca+hwkXFsu1GEhTS9pD0wSNf7qwAAAYgHvXKvAAAEAwBGMEQCIFLskZDs\n" + + "UG4+/88D/5/QbD9zT6ZmZlwXiPZ6H2YR/KiJAiBvi4vvNsb9KNAhJMgI2T2iCg9U\n" + + "CIru+US6y3ua7dKKDTAKBggqhkjOPQQDAgNHADBEAiAzvgzKV/kvBbKWCT1NNUBD\n" + + "AF9okIEcJx/ukFgzmYMwUQIgXeJeVf3izkxsgiEUSknwHsErLFs/cEme2PSRj2AW\n" + + "dYA=\n" + "-----END CERTIFICATE-----"; - // Owner: CN=revoked.sca3a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \ - // SERIALNUMBER=5846743, OID.2.5.4.15=PrivateOrganization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \ - // OID.1.3.6.1.4.1.311.60.2.1.3=US - // Issuer: CN=Amazon, OU=Server CA 3A, O=Amazon, C=US - // Serial number: 6f1d78cf0ca64ce7f551a6f2a0715cc0e8b50 - // Valid from: Mon Jan 28 15:40:01 PST 2019 until: Thu Apr 28 16:40:01 PDT 2022 + // Owner: CN=revoked.rootca3.demo.amazontrust.com + // Issuer: CN=Amazon ECDSA 256 M01, O=Amazon, C=US + // Serial number: c458bfaeedae16a5e61fe64773fc898 + // Valid from: Tue May 09 17:00:00 PDT 2023 until: Fri Jun 07 16:59:59 PDT 2024 private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + - "MIIDTzCCAvWgAwIBAgITBvHXjPDKZM5/VRpvKgcVzA6LUDAKBggqhkjOPQQDAjBG\n" + - "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2ZXIg\n" + - "Q0EgM0ExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTAxMjgyMzQwMDFaFw0yMjA0Mjgy\n" + - "MzQwMDFaMIHcMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQIT\n" + - "CERlbGF3YXJlMRwwGgYDVQQPExNQcml2YXRlT3JnYW5pemF0aW9uMRAwDgYDVQQF\n" + - "Ewc1ODQ2NzQzMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G\n" + - "A1UEBxMHU2VhdHRsZTEeMBwGA1UEChMVQW1hem9uIFRydXN0IFNlcnZpY2VzMSYw\n" + - "JAYDVQQDEx1yZXZva2VkLnNjYTNhLmFtYXpvbnRydXN0LmNvbTBZMBMGByqGSM49\n" + - "AgEGCCqGSM49AwEHA0IABJNl90Jq0wddpFj+JbLtmvGR/1geL5t1tvV406jGpYn2\n" + - "C5lAFjwASFy7pAnazZbfSkIDUU2i2XU0+7Cs+j1S/EOjggEpMIIBJTAOBgNVHQ8B\n" + - "Af8EBAMCB4AwHQYDVR0OBBYEFPhX3dYays5Sps0xTgouLkZzYLg4MB8GA1UdIwQY\n" + - "MBaAFATc4JXl6LlrlKHvjFsxHhN+VZfaMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr\n" + - "BgEFBQcDAjB1BggrBgEFBQcBAQRpMGcwLQYIKwYBBQUHMAGGIWh0dHA6Ly9vY3Nw\n" + - "LnNjYTNhLmFtYXpvbnRydXN0LmNvbTA2BggrBgEFBQcwAoYqaHR0cDovL2NydC5z\n" + - "Y2EzYS5hbWF6b250cnVzdC5jb20vc2NhM2EuY2VyMCgGA1UdEQQhMB+CHXJldm9r\n" + - "ZWQuc2NhM2EuYW1hem9udHJ1c3QuY29tMBMGA1UdIAQMMAowCAYGZ4EMAQIBMAoG\n" + - "CCqGSM49BAMCA0gAMEUCICLb16/50S4fOAFafi5lagdx7q6EDPPm596g19eQDMXk\n" + - "AiEAksCMLypRB4t30FABlsEjhVCBIxay0iIer2OcCIrhfEI=\n" + + "MIIEhzCCBC2gAwIBAgIQDEWL+u7a4WpeYf5kdz/ImDAKBggqhkjOPQQDAjA9MQsw\n" + + "CQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMR0wGwYDVQQDExRBbWF6b24gRUNE\n" + + "U0EgMjU2IE0wMTAeFw0yMzA1MTAwMDAwMDBaFw0yNDA2MDcyMzU5NTlaMC8xLTAr\n" + + "BgNVBAMTJHJldm9rZWQucm9vdGNhMy5kZW1vLmFtYXpvbnRydXN0LmNvbTBZMBMG\n" + + "ByqGSM49AgEGCCqGSM49AwEHA0IABAsSs5kW5TZlS0SDrMb9iUQAqEaKa12Fc6SN\n" + + "9UR6qtOFdW/1UuziDq3Hl5dqsAYZJkbJSPCIsD2HTP/EGTMKITCjggMbMIIDFzAf\n" + + "BgNVHSMEGDAWgBRPWfy8BhYov6LI2wj7zxMkumlCXDAdBgNVHQ4EFgQUeE55ET2e\n" + + "i8KbY7KHTxOuvCkRpTowTgYDVR0RBEcwRYIkcmV2b2tlZC5yb290Y2EzLmRlbW8u\n" + + "YW1hem9udHJ1c3QuY29tgh1yZXZva2VkLnNjYTNhLmFtYXpvbnRydXN0LmNvbTAO\n" + + "BgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMDsG\n" + + "A1UdHwQ0MDIwMKAuoCyGKmh0dHA6Ly9jcmwuZTJtMDEuYW1hem9udHJ1c3QuY29t\n" + + "L2UybTAxLmNybDATBgNVHSAEDDAKMAgGBmeBDAECATB1BggrBgEFBQcBAQRpMGcw\n" + + "LQYIKwYBBQUHMAGGIWh0dHA6Ly9vY3NwLmUybTAxLmFtYXpvbnRydXN0LmNvbTA2\n" + + "BggrBgEFBQcwAoYqaHR0cDovL2NydC5lMm0wMS5hbWF6b250cnVzdC5jb20vZTJt\n" + + "MDEuY2VyMAwGA1UdEwEB/wQCMAAwggF9BgorBgEEAdZ5AgQCBIIBbQSCAWkBZwB2\n" + + "AHb/iD8KtvuVUcJhzPWHujS0pM27KdxoQgqf5mdMWjp0AAABiAe9lQ8AAAQDAEcw\n" + + "RQIgZVFAX5WPZRBpEOqk620v4Rbzxh/3wrJ5QBMBJ0Mb8B0CIQC0oxFVLfs+PAv7\n" + + "25wawOu2VgDXG9lJAJtCwk3gN8BshQB2AEiw42vapkc0D+VqAvqdMOscUgHLVt0s\n" + + "gdm7v6s52IRzAAABiAe9lQ4AAAQDAEcwRQIhAIPVMj6IfjAUKeGYbpG9s0DRdWbc\n" + + "b8OzsOf+kRqk03NMAiB777hfoFCUMPrN0g8o5v6zp3T3qOhRnYY0TZN4q4NnMgB1\n" + + "ANq2v2s/tbYin5vCu1xr6HCRcWy7UYSFNL2kPTBI1/urAAABiAe9lN4AAAQDAEYw\n" + + "RAIgL0qoVbKLFD+Y3f/V6Rw+euZrPO6d1HEVPQGo7wLzkl8CIGHp3PQmmrEofl76\n" + + "4da7bY0L+csFW0sB8clN0KziMfe6MAoGCCqGSM49BAMCA0gAMEUCIQC+6VdX9X5g\n" + + "x3NSUmJ7py01Zxf26TNBv1ildxqesvZ/7wIgIrefriRzPiIFDHCUbdjk0VlmMwZR\n" + + "VzXXHINsGCiCKOs=\n" + "-----END CERTIFICATE-----"; - public void runTest(ValidatePathWithParams pathValidator, boolean ocspEnabled) throws Exception { - // EE certificates don't have CRLDP extension - if (!ocspEnabled){ - pathValidator.validate(new String[]{INT}, - ValidatePathWithParams.Status.GOOD, null, System.out); - - return; - } + public void runTest(ValidatePathWithParams pathValidator) throws Exception { // Validate valid - pathValidator.validate(new String[]{VALID, INT}, + pathValidator.validate(new String[]{VALID, INT_VALID}, ValidatePathWithParams.Status.GOOD, null, System.out); // Validate Revoked - pathValidator.validate(new String[]{REVOKED, INT}, + pathValidator.validate(new String[]{REVOKED, INT_REVOKED}, ValidatePathWithParams.Status.REVOKED, - "Mon Jan 28 15:40:35 PST 2019", System.out); + "Mon May 15 13:41:22 PDT 2023", System.out); } } class AmazonCA_4 { - // Owner: CN=Amazon, OU=Server CA 4A, O=Amazon, C=US + // Owner: CN=Amazon ECDSA 384 M02, O=Amazon, C=US // Issuer: CN=Amazon Root CA 4, O=Amazon, C=US - // Serial number: 67f94575a8862a9072e3239c37ceba1274e18 - // Valid from: Wed Oct 21 17:00:00 PDT 2015 until: Sat Oct 18 17:00:00 PDT 2025 + // Serial number: 773127dfaa6b9e2b95538aa76dde4307f17c4 + // Valid from: Tue Aug 23 15:36:58 PDT 2022 until: Fri Aug 23 15:36:58 PDT 2030 private static final String INT = "-----BEGIN CERTIFICATE-----\n" + - "MIIC+TCCAn6gAwIBAgITBn+UV1qIYqkHLjI5w3zroSdOGDAKBggqhkjOPQQDAzA5\n" + + "MIIDETCCApagAwIBAgITB3MSffqmueK5VTiqdt3kMH8XxDAKBggqhkjOPQQDAzA5\n" + "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" + - "Um9vdCBDQSA0MB4XDTE1MTAyMjAwMDAwMFoXDTI1MTAxOTAwMDAwMFowRjELMAkG\n" + - "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEVMBMGA1UECxMMU2VydmVyIENBIDRB\n" + - "MQ8wDQYDVQQDEwZBbWF6b24wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASRP0kIW0Ha\n" + - "7+ORvEVhIS5gIgkH66X5W9vBRTX14oG/1elIyI6LbFZ+E5KAufL0XoWJGI1WbPRm\n" + - "HW246FKSzF0wOEZZyxEROz6tuaVsnXRHRE76roS/Wr064uJpKH+Lv+SjggE5MIIB\n" + - "NTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU\n" + - "pSHN2+tTIZmqytlnQpQlsnv0wuMwHwYDVR0jBBgwFoAU0+zHOmVuzOHadppW+5zz\n" + - "hm1X5YEwewYIKwYBBQUHAQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8vb2NzcC5y\n" + - "b290Y2E0LmFtYXpvbnRydXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDovL2NydC5y\n" + - "b290Y2E0LmFtYXpvbnRydXN0LmNvbS9yb290Y2E0LmNlcjA/BgNVHR8EODA2MDSg\n" + - "MqAwhi5odHRwOi8vY3JsLnJvb3RjYTQuYW1hem9udHJ1c3QuY29tL3Jvb3RjYTQu\n" + - "Y3JsMBEGA1UdIAQKMAgwBgYEVR0gADAKBggqhkjOPQQDAwNpADBmAjEA59RAOBaj\n" + - "uh0rT/OOTWPEv6TBnb9XEadburBaXb8SSrR8il+NdkfS9WXRAzbwrG7LAjEA3ukD\n" + - "1HrQq+WXHBM5sIuViJI/Zh7MOjsc159Q+dn36PBqLRq03AXqE/lRjnv8C5nj\n" + + "Um9vdCBDQSA0MB4XDTIyMDgyMzIyMzY1OFoXDTMwMDgyMzIyMzY1OFowPTELMAkG\n" + + "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEdMBsGA1UEAxMUQW1hem9uIEVDRFNB\n" + + "IDM4NCBNMDIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATNYzWQDXV0NoNmR0hJPwJq\n" + + "hjYOOS9z0B2Z7MQudxg5x3Vsib6N+tJkq8dljRq5o6K0bbh/kRVfoi9wfKhB03Yz\n" + + "gkerrwRCH7Z9gU5nbBY+Y5+EtImq4yOB0n7JQgQxWemjggFaMIIBVjASBgNVHRMB\n" + + "Af8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcD\n" + + "AQYIKwYBBQUHAwIwHQYDVR0OBBYEFKbZqzuHmTP/6Gj4i2GDbNCyuq+9MB8GA1Ud\n" + + "IwQYMBaAFNPsxzplbszh2naaVvuc84ZtV+WBMHsGCCsGAQUFBwEBBG8wbTAvBggr\n" + + "BgEFBQcwAYYjaHR0cDovL29jc3Aucm9vdGNhNC5hbWF6b250cnVzdC5jb20wOgYI\n" + + "KwYBBQUHMAKGLmh0dHA6Ly9jcnQucm9vdGNhNC5hbWF6b250cnVzdC5jb20vcm9v\n" + + "dGNhNC5jZXIwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NybC5yb290Y2E0LmFt\n" + + "YXpvbnRydXN0LmNvbS9yb290Y2E0LmNybDATBgNVHSAEDDAKMAgGBmeBDAECATAK\n" + + "BggqhkjOPQQDAwNpADBmAjEA2zCG6x0xMlgSXWEGLN8+1XN+OCYF5vj0Z1jtVy+A\n" + + "pdLlzuxNt9HBWn3hvqvO2W8KAjEApNdsZOCmk5uZBYiuCSBnDH3jyKhN6dWyuuHW\n" + + "9Wj7SxKnOU5+wYWZA0BQAv1KT62i\n" + "-----END CERTIFICATE-----"; - // Owner: CN=good.sca4a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \ - // SERIALNUMBER=5846743, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \ - // OID.1.3.6.1.4.1.311.60.2.1.3=US - // Issuer: CN=Amazon, OU=Server CA 4A, O=Amazon, C=US - // Serial number: 703e4ec57c72d5669efbc98875c3f6bc3f934 - // Valid from: Mon Jul 29 16:55:17 PDT 2019 until: Sat Aug 29 16:55:17 PDT 2020 + // Owner: CN=valid.rootca4.demo.amazontrust.com + // Issuer: CN=Amazon ECDSA 384 M02, O=Amazon, C=US + // Serial number: f579bed3369f1a147ea5d0e8e6532d3 + // Valid from: Tue May 09 17:00:00 PDT 2023 until: Fri Jun 07 16:59:59 PDT 2024 private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + - "MIIDxTCCA0qgAwIBAgITBwPk7FfHLVZp77yYh1w/a8P5NDAKBggqhkjOPQQDAzBG\n" + - "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2ZXIg\n" + - "Q0EgNEExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTA3MjkyMzU1MTdaFw0yMDA4Mjky\n" + - "MzU1MTdaMIHaMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQIT\n" + - "CERlbGF3YXJlMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjEQMA4GA1UE\n" + - "BRMHNTg0Njc0MzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO\n" + - "BgNVBAcTB1NlYXR0bGUxHjAcBgNVBAoTFUFtYXpvbiBUcnVzdCBTZXJ2aWNlczEj\n" + - "MCEGA1UEAxMaZ29vZC5zY2E0YS5hbWF6b250cnVzdC5jb20wdjAQBgcqhkjOPQIB\n" + - "BgUrgQQAIgNiAAS9fqMYfOBsdXMSsPjqOlTgIGOlOQWA7Wg6XwVvHTr0+UN+XTeC\n" + - "yZN+XjLbEDQ0CF5eryRZ535sDpwh3qNe0lYFO1n1+2iDtDI1jhhLNYNxBpVnR2BU\n" + - "2l9EuRmgRbQpDCajggFjMIIBXzAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFMd0\n" + - "itH5IcE6DpM1uTSBV/6DLmK7MB8GA1UdIwQYMBaAFKUhzdvrUyGZqsrZZ0KUJbJ7\n" + - "9MLjMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BggrBgEFBQcBAQRp\n" + - "MGcwLQYIKwYBBQUHMAGGIWh0dHA6Ly9vY3NwLnNjYTRhLmFtYXpvbnRydXN0LmNv\n" + - "bTA2BggrBgEFBQcwAoYqaHR0cDovL2NydC5zY2E0YS5hbWF6b250cnVzdC5jb20v\n" + - "c2NhNGEuY2VyMCUGA1UdEQQeMByCGmdvb2Quc2NhNGEuYW1hem9udHJ1c3QuY29t\n" + - "MFAGA1UdIARJMEcwDQYLYIZIAYb9bgEHGAMwNgYFZ4EMAQEwLTArBggrBgEFBQcC\n" + - "ARYfaHR0cHM6Ly93d3cuYW1hem9udHJ1c3QuY29tL2NwczAKBggqhkjOPQQDAwNp\n" + - "ADBmAjEA2RBD1F+rnm394VkqA3ncysM3deoyfWqaoAO5923MNisswPnHfVqnfeXf\n" + - "ZwTAvVTBAjEAiiaPx9GRjEk8IBKvCSbTp9rPogVTN7zDDQGrwA83O0pRP7A0dxtT\n" + - "pn/0K5Sj8otp\n" + + "MIIEvjCCBESgAwIBAgIQD1eb7TNp8aFH6l0OjmUy0zAKBggqhkjOPQQDAzA9MQsw\n" + + "CQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMR0wGwYDVQQDExRBbWF6b24gRUNE\n" + + "U0EgMzg0IE0wMjAeFw0yMzA1MTAwMDAwMDBaFw0yNDA2MDcyMzU5NTlaMC0xKzAp\n" + + "BgNVBAMTInZhbGlkLnJvb3RjYTQuZGVtby5hbWF6b250cnVzdC5jb20wdjAQBgcq\n" + + "hkjOPQIBBgUrgQQAIgNiAAT6/95JFuvx5t9MVeRZmBtXq63Q2fXZnSwEy2U2F4Qc\n" + + "ejhDwcYfD2HmT6S6GrKqLNJMa5n2YOvet4LZpKJLFF+BQo6FJt5cXkzHHxZ1I4z3\n" + + "8pGU79CpCgFOFy6QUlF68NajggMXMIIDEzAfBgNVHSMEGDAWgBSm2as7h5kz/+ho\n" + + "+Ithg2zQsrqvvTAdBgNVHQ4EFgQUR/GnpQkrUsCj8jF6/JIE1Rs07zswSQYDVR0R\n" + + "BEIwQIIidmFsaWQucm9vdGNhNC5kZW1vLmFtYXpvbnRydXN0LmNvbYIaZ29vZC5z\n" + + "Y2E0YS5hbWF6b250cnVzdC5jb20wDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQG\n" + + "CCsGAQUFBwMBBggrBgEFBQcDAjA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8vY3Js\n" + + "LmUzbTAyLmFtYXpvbnRydXN0LmNvbS9lM20wMi5jcmwwEwYDVR0gBAwwCjAIBgZn\n" + + "gQwBAgEwdQYIKwYBBQUHAQEEaTBnMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5l\n" + + "M20wMi5hbWF6b250cnVzdC5jb20wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuZTNt\n" + + "MDIuYW1hem9udHJ1c3QuY29tL2UzbTAyLmNlcjAMBgNVHRMBAf8EAjAAMIIBfgYK\n" + + "KwYBBAHWeQIEAgSCAW4EggFqAWgAdgDuzdBk1dsazsVct520zROiModGfLzs3sNR\n" + + "SFlGcR+1mwAAAYgHvZA9AAAEAwBHMEUCIQCmzmQOzunsuAg1GpIcNx0isG6ylbhP\n" + + "y9JP4UFclL2hdwIgBtTM89mE7QJDj7h7xr2eRPio1ehgmeYH1PHXxCqHIGYAdgBI\n" + + "sONr2qZHNA/lagL6nTDrHFIBy1bdLIHZu7+rOdiEcwAAAYgHvZB1AAAEAwBHMEUC\n" + + "IF9hbi82CLU5umfRze4NpX6u4jlT+N8KSaBe6UbhqjBZAiEAi2Y6PTt2+107LxtM\n" + + "oBpHprph7hQvGfjPE+p+rfM/X+EAdgDatr9rP7W2Ip+bwrtca+hwkXFsu1GEhTS9\n" + + "pD0wSNf7qwAAAYgHvZBeAAAEAwBHMEUCIAI+m4mVE3HtZOEMC5VI7m0nEPdPPJUq\n" + + "fxUKPpeIVmk5AiEA0scVJy7g3Fv+2nTVhbcwWCwn/Gvc+0txQrc529juflcwCgYI\n" + + "KoZIzj0EAwMDaAAwZQIxAKV837BpqlNHg35EsCCtrJPoQ6RuY9UoHm1O2CdsCXGR\n" + + "Z3kAnlgIV8A/waI6wQqfsQIwdCqaC+qN60JCnX09YKRD15eQjq1rN3w+llI+lEbS\n" + + "FSMsnoHJcqMZLo9s+4Rf0zS3\n" + "-----END CERTIFICATE-----"; - // Owner: CN=revoked.sca4a.amazontrust.com, O=Amazon Trust Services, L=Seattle, ST=Washington, C=US, \ - // SERIALNUMBER=5846743, OID.2.5.4.15=PrivateOrganization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, \ - // OID.1.3.6.1.4.1.311.60.2.1.3=US - // Issuer: CN=Amazon, OU=Server CA 4A, O=Amazon, C=US - // Serial number: 6f1d79295c384a699d51c2d756bd46213b5b3 - // Valid from: Mon Jan 28 15:41:16 PST 2019 until: Thu Apr 28 16:41:16 PDT 2022 + // Owner: CN=revoked.rootca4.demo.amazontrust.com + // Issuer: CN=Amazon ECDSA 384 M02, O=Amazon, C=US + // Serial number: 4a5d392936b4decb818b7fb106ebbd8 + // Valid from: Tue May 09 17:00:00 PDT 2023 until: Fri Jun 07 16:59:59 PDT 2024 private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + - "MIIDjTCCAxKgAwIBAgITBvHXkpXDhKaZ1RwtdWvUYhO1szAKBggqhkjOPQQDAzBG\n" + - "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2ZXIg\n" + - "Q0EgNEExDzANBgNVBAMTBkFtYXpvbjAeFw0xOTAxMjgyMzQxMTZaFw0yMjA0Mjgy\n" + - "MzQxMTZaMIHcMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQIT\n" + - "CERlbGF3YXJlMRwwGgYDVQQPExNQcml2YXRlT3JnYW5pemF0aW9uMRAwDgYDVQQF\n" + - "Ewc1ODQ2NzQzMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G\n" + - "A1UEBxMHU2VhdHRsZTEeMBwGA1UEChMVQW1hem9uIFRydXN0IFNlcnZpY2VzMSYw\n" + - "JAYDVQQDEx1yZXZva2VkLnNjYTRhLmFtYXpvbnRydXN0LmNvbTB2MBAGByqGSM49\n" + - "AgEGBSuBBAAiA2IABLuNpZTcNU3FElNP3Y/OeXIZcIMXkFTBi/n92fNwHfqUbEhH\n" + - "H+PovJ26eAGvb5a8bGc275MBFcVnWL0rCVgM+j9KAtBDCRJX3f7mo0D2VKcmtZKu\n" + - "jPxwGPy2kuqM505dGqOCASkwggElMA4GA1UdDwEB/wQEAwIHgDAdBgNVHQ4EFgQU\n" + - "zUFIhn+hphzCKA2qgAdLztSBzJgwHwYDVR0jBBgwFoAUpSHN2+tTIZmqytlnQpQl\n" + - "snv0wuMwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMHUGCCsGAQUFBwEB\n" + - "BGkwZzAtBggrBgEFBQcwAYYhaHR0cDovL29jc3Auc2NhNGEuYW1hem9udHJ1c3Qu\n" + - "Y29tMDYGCCsGAQUFBzAChipodHRwOi8vY3J0LnNjYTRhLmFtYXpvbnRydXN0LmNv\n" + - "bS9zY2E0YS5jZXIwKAYDVR0RBCEwH4IdcmV2b2tlZC5zY2E0YS5hbWF6b250cnVz\n" + - "dC5jb20wEwYDVR0gBAwwCjAIBgZngQwBAgEwCgYIKoZIzj0EAwMDaQAwZgIxALDA\n" + - "klY3iKwyzwpwVtLfLxzQEl45xvE2VjBJvfJJ60KhJt7Ud0gt0zxkogh29+mpEQIx\n" + - "ANTG1mk8OJB41DU7ru1Pwc6ju8STw1FdwDp/Eliqhvnm2i0k4/F1bBHLta2mlC2V\n" + - "hg==\n" + + "MIIExjCCBEygAwIBAgIQBKXTkpNrTey4GLf7EG672DAKBggqhkjOPQQDAzA9MQsw\n" + + "CQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMR0wGwYDVQQDExRBbWF6b24gRUNE\n" + + "U0EgMzg0IE0wMjAeFw0yMzA1MTAwMDAwMDBaFw0yNDA2MDcyMzU5NTlaMC8xLTAr\n" + + "BgNVBAMTJHJldm9rZWQucm9vdGNhNC5kZW1vLmFtYXpvbnRydXN0LmNvbTB2MBAG\n" + + "ByqGSM49AgEGBSuBBAAiA2IABFYfMbv5/vgqDunZj4ffJiuELtdwfEPXx9QlZnCm\n" + + "rBP3Z4/GvUVRVmyh5sYdnbCGCEClH/RxU6BC5SKv+TzhsFLEumhezanljnQXRAIL\n" + + "a1OGbP8zLLP6FuAD0cjY3P3adKOCAx0wggMZMB8GA1UdIwQYMBaAFKbZqzuHmTP/\n" + + "6Gj4i2GDbNCyuq+9MB0GA1UdDgQWBBSqnGV5pN/agPCtVdV37CP1z/DUqjBOBgNV\n" + + "HREERzBFgiRyZXZva2VkLnJvb3RjYTQuZGVtby5hbWF6b250cnVzdC5jb22CHXJl\n" + + "dm9rZWQuc2NhNGEuYW1hem9udHJ1c3QuY29tMA4GA1UdDwEB/wQEAwIHgDAdBgNV\n" + + "HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwOwYDVR0fBDQwMjAwoC6gLIYqaHR0\n" + + "cDovL2NybC5lM20wMi5hbWF6b250cnVzdC5jb20vZTNtMDIuY3JsMBMGA1UdIAQM\n" + + "MAowCAYGZ4EMAQIBMHUGCCsGAQUFBwEBBGkwZzAtBggrBgEFBQcwAYYhaHR0cDov\n" + + "L29jc3AuZTNtMDIuYW1hem9udHJ1c3QuY29tMDYGCCsGAQUFBzAChipodHRwOi8v\n" + + "Y3J0LmUzbTAyLmFtYXpvbnRydXN0LmNvbS9lM20wMi5jZXIwDAYDVR0TAQH/BAIw\n" + + "ADCCAX8GCisGAQQB1nkCBAIEggFvBIIBawFpAHYAdv+IPwq2+5VRwmHM9Ye6NLSk\n" + + "zbsp3GhCCp/mZ0xaOnQAAAGIB72QJQAABAMARzBFAiA74zKrlL+y5rYwSLxBL8fs\n" + + "QYRYXF0s0sGoaSEeAg1DkgIhAPu8Z0TLIFoppmyiv+A5z6S+SG+v/kOsAYmQmiUO\n" + + "5scIAHcASLDja9qmRzQP5WoC+p0w6xxSActW3SyB2bu/qznYhHMAAAGIB72QJgAA\n" + + "BAMASDBGAiEAg+x7JBT3oIaZdnfgGN1G6SAiNUL7zR/tBhbWIG9tz94CIQDGwBiV\n" + + "Tslt11+W3ZaNsS7UtUIiB45YHUc4qKm5ry2fTAB2ANq2v2s/tbYin5vCu1xr6HCR\n" + + "cWy7UYSFNL2kPTBI1/urAAABiAe9kAgAAAQDAEcwRQIgPvKfSpMJKRocGk9+GNr3\n" + + "hUj8x8WySB//0X116TNgA0gCIQDhGRqxnEZmEFGEfj5GY9vjEfm0kKwcL0lCuwBu\n" + + "NZG4dzAKBggqhkjOPQQDAwNoADBlAjEA1PLdsrko3tDs50aAeEU9Gn+0CG8QKy7R\n" + + "fQaXBTjGETDgGJk/7zGNpGelKPr/UYV9AjASwdA32S8jIADxA8HrqiMsVYDFMnbU\n" + + "jLLwR6CTLtAcWtwVmoQ2x0usvTvN8YJBPoA=\n" + "-----END CERTIFICATE-----"; - public void runTest(ValidatePathWithParams pathValidator, boolean ocspEnabled) throws Exception { - // EE certificates don't have CRLDP extension - if (!ocspEnabled){ - pathValidator.validate(new String[]{INT}, - ValidatePathWithParams.Status.GOOD, null, System.out); - - return; - } + public void runTest(ValidatePathWithParams pathValidator) throws Exception { // Validate valid pathValidator.validate(new String[]{VALID, INT}, @@ -547,6 +608,6 @@ public void runTest(ValidatePathWithParams pathValidator, boolean ocspEnabled) t // Validate Revoked pathValidator.validate(new String[]{REVOKED, INT}, ValidatePathWithParams.Status.REVOKED, - "Mon Jan 28 15:41:53 PST 2019", System.out); + "Mon May 15 13:42:48 PDT 2023", System.out); } } diff --git a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CertignaCA.java b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CertignaCA.java deleted file mode 100644 index 5e058233370..00000000000 --- a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CertignaCA.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8245654 - * @summary Interoperability tests with Certigna Root CA from Dhimyotis - * @build ValidatePathWithParams - * @run main/othervm -Djava.security.debug=certpath CertignaCA OCSP - * @run main/othervm -Djava.security.debug=certpath CertignaCA CRL - */ - -/* - * Obtain TLS test artifacts for Certigna Root CA from: - * - * Valid TLS Certificates: - * https://valid.servicesca.dhimyotis.com/ - * - * Revoked TLS Certificates: - * https://revoked.servicesca.dhimyotis.com/ - */ -public class CertignaCA { - - // Owner: CN=Certigna Services CA, OID.2.5.4.97=NTRFR-48146308100036, - // OU=0002 48146308100036, O=DHIMYOTIS, C=FR - // Issuer: CN=Certigna, O=Dhimyotis, C=FR - // Serial number: 6f82fa28acd6f784bb5b120ba87367ad - // Valid from: Wed Nov 25 03:33:52 PST 2015 until: Sat Nov 22 03:33:52 PST 2025 - private static final String INT = "-----BEGIN CERTIFICATE-----\n" + - "MIIGFjCCBP6gAwIBAgIQb4L6KKzW94S7WxILqHNnrTANBgkqhkiG9w0BAQsFADA0\n" + - "MQswCQYDVQQGEwJGUjESMBAGA1UECgwJRGhpbXlvdGlzMREwDwYDVQQDDAhDZXJ0\n" + - "aWduYTAeFw0xNTExMjUxMTMzNTJaFw0yNTExMjIxMTMzNTJaMH0xCzAJBgNVBAYT\n" + - "AkZSMRIwEAYDVQQKDAlESElNWU9USVMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgx\n" + - "MDAwMzYxHTAbBgNVBGEMFE5UUkZSLTQ4MTQ2MzA4MTAwMDM2MR0wGwYDVQQDDBRD\n" + - "ZXJ0aWduYSBTZXJ2aWNlcyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC\n" + - "ggIBALPM+7LpWBz9wFcPaTc3xnB+5g0XrnptB0EPPfrR04vO52Ykm4ky1d4ZLd10\n" + - "tbM1fa1RqNSOVWWg93O4pL7zCFKlz6JV74ZZVhHpEAwzBwv2oPnxvVbxtSN67xsS\n" + - "Y66ahUYxjzs8+3FhmsiRxqwnTYvK2u70uglUvRisOKyTL/M6JnrC4y8tlmoz7OSa\n" + - "5BmBMVplJFQtvmON6N9aHLvYMz+EyJPCbXL6pELxeHjFT5QmIaRamsr2DOTaCjtB\n" + - "ZKI1Wnh3X7lnbjM8MESJiV2t7E9tIQNG0Z/HI3tO4aaUMum3KysY5sC8v3vi7rry\n" + - "GidgzHQhrtP0ZXWW5UH/k7umLS/P/XXWnCFpc2Lxa1uDGfc2im7xibRoPP+JNZsz\n" + - "N76euFlls6jyEXAiwnVr14tVVTewLK0OWs5SJHpEKp8PGMZRDj59EmMvokWwzL6Q\n" + - "zNZ6vVAp00oOm05sbspNY9+MFqGKKUsKvhFGEa4XmRNxDe6KswLcjPZB+NKHZ0QW\n" + - "Fd4ip5C5XmEK/8qIPjwVr9dah9+oiHGGO8Wx7gJAMF5DTmkvW7GhqCKj1LmHnabj\n" + - "zc8av6kxWVQZi/C7HCm9i/W4wio+JA2EAFLqNL3GPNbK9kau4yPhQt/c7zxzo0OH\n" + - "nlsV4THCG7oOCd3cfCiyfQcb3FBt6OSpaKRZxjCLBwP00r0fAgMBAAGjggHZMIIB\n" + - "1TASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU\n" + - "rOyGj0s3HLh/FxsZ0K7oTuM0XBIwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF\n" + - "9lo53BGhOKQ2MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAP\n" + - "BgNVBAMMCENlcnRpZ25hggkA/tzjAQ/JSP8wSQYDVR0gBEIwQDA+BgoqgXoBgTEB\n" + - "AAECMDAwLgYIKwYBBQUHAgEWImh0dHBzOi8vd3d3LmNlcnRpZ25hLmZyL2F1dG9y\n" + - "aXRlcy8wfAYIKwYBBQUHAQEEcDBuMDQGCCsGAQUFBzAChihodHRwOi8vYXV0b3Jp\n" + - "dGUuY2VydGlnbmEuZnIvY2VydGlnbmEuZGVyMDYGCCsGAQUFBzAChipodHRwOi8v\n" + - "YXV0b3JpdGUuZGhpbXlvdGlzLmNvbS9jZXJ0aWduYS5kZXIwYQYDVR0fBFowWDAp\n" + - "oCegJYYjaHR0cDovL2NybC5jZXJ0aWduYS5mci9jZXJ0aWduYS5jcmwwK6ApoCeG\n" + - "JWh0dHA6Ly9jcmwuZGhpbXlvdGlzLmNvbS9jZXJ0aWduYS5jcmwwDQYJKoZIhvcN\n" + - "AQELBQADggEBAGLft7gIuGPZVfg0cTM+HT2xAZFPDb/2+siH06x+dH044zMKbBIN\n" + - "bRzhKipwB1A3MW8FQjveE9tyrfyuqZE/X+o2SlGcdNV44ybYkxo4f6kcLEavV/IW\n" + - "+oFEnojZlhpksYcxrvQoEyqkAwshe8IS2KtZHKVACrt+XSs0lwvy7ALGmHaF7A4b\n" + - "y6cZWItA7Lhj8XWp+8tBJDj7HocRbWtxzEODdBuyMgJzFrNjc+97J0vH/K0+3yjm\n" + - "kczpKshMA0tM+MF9XDMN/MuwrPmUWGO/fHiqHgUp8yqeWtl1n44ZxkkK1t9GRwhn\n" + - "DWLv73/xhTmdhWYQ/reo0GbgBoLiltKmIJQ=\n" + - "-----END CERTIFICATE-----"; - - // Owner: SERIALNUMBER=S230100953, CN=valid.servicesca.dhimyotis.com, - // OU=0002 48146308100036, O=DHIMYOTIS, L=VILLENEUVE D'ASCQ, C=FR - // Issuer: CN=Certigna Services CA, OID.2.5.4.97=NTRFR-48146308100036, - // OU=0002 48146308100036, O=DHIMYOTIS, C=FR - // Serial number: 2959798fe2e0e7b43810169ae938bc5f - // Valid from: Sun Mar 13 16:00:00 PDT 2022 until: Mon Mar 13 15:59:59 PDT 2023 - private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + - "MIIIkzCCBnugAwIBAgIQKVl5j+Lg57Q4EBaa6Ti8XzANBgkqhkiG9w0BAQsFADB9\n" + - "MQswCQYDVQQGEwJGUjESMBAGA1UECgwJREhJTVlPVElTMRwwGgYDVQQLDBMwMDAy\n" + - "IDQ4MTQ2MzA4MTAwMDM2MR0wGwYDVQRhDBROVFJGUi00ODE0NjMwODEwMDAzNjEd\n" + - "MBsGA1UEAwwUQ2VydGlnbmEgU2VydmljZXMgQ0EwHhcNMjIwMzEzMjMwMDAwWhcN\n" + - "MjMwMzEzMjI1OTU5WjCBmTELMAkGA1UEBhMCRlIxGjAYBgNVBAcMEVZJTExFTkVV\n" + - "VkUgRCdBU0NRMRIwEAYDVQQKDAlESElNWU9USVMxHDAaBgNVBAsMEzAwMDIgNDgx\n" + - "NDYzMDgxMDAwMzYxJzAlBgNVBAMMHnZhbGlkLnNlcnZpY2VzY2EuZGhpbXlvdGlz\n" + - "LmNvbTETMBEGA1UEBRMKUzIzMDEwMDk1MzCCASIwDQYJKoZIhvcNAQEBBQADggEP\n" + - "ADCCAQoCggEBALpeGHbzRGnv1C0PdJS0nT+Cx98Pw8ctaw51m9Vlk2j8AFGZRu8r\n" + - "lX3noQYX0AIfcbk6KqPAreIvJQV0UgM5jxt3mIQF7iU+55MG4mWmSJgKDDq4b3ck\n" + - "WdBy0KpSBqLmB9sHyTNk9NilNu7VwG03HGIltWA2uQFJGC8CkxwAFpMCQ9RVYw2Z\n" + - "NkL/SsiPgrRLiCJZjesk1oAcLnLp7hbelfUB2Z71VmuDDlom7CsLvdN8eIG+Lj+V\n" + - "wkGmH6AbVGvbFniFDLCNDSJWCQ9AHeO+i0CM/wd2gBRSgm993p2YMxu5mVZjz/rp\n" + - "ELaCYjulvNZKvPIFoNe8qsxlXRWeqWaHuPsCAwEAAaOCA/AwggPsMIHkBggrBgEF\n" + - "BQcBAQSB1zCB1DA4BggrBgEFBQcwAoYsaHR0cDovL2F1dG9yaXRlLmRoaW15b3Rp\n" + - "cy5jb20vc2VydmljZXNjYS5kZXIwNgYIKwYBBQUHMAKGKmh0dHA6Ly9hdXRvcml0\n" + - "ZS5jZXJ0aWduYS5mci9zZXJ2aWNlc2NhLmRlcjAwBggrBgEFBQcwAYYkaHR0cDov\n" + - "L3NlcnZpY2VzY2Eub2NzcC5kaGlteW90aXMuY29tMC4GCCsGAQUFBzABhiJodHRw\n" + - "Oi8vc2VydmljZXNjYS5vY3NwLmNlcnRpZ25hLmZyMB8GA1UdIwQYMBaAFKzsho9L\n" + - "Nxy4fxcbGdCu6E7jNFwSMAkGA1UdEwQCMAAwYQYDVR0gBFowWDAIBgZngQwBAgIw\n" + - "TAYLKoF6AYExAgUBAQEwPTA7BggrBgEFBQcCARYvaHR0cHM6Ly93d3cuY2VydGln\n" + - "bmEuY29tL2F1dG9yaXRlLWNlcnRpZmljYXRpb24wZQYDVR0fBF4wXDAroCmgJ4Yl\n" + - "aHR0cDovL2NybC5jZXJ0aWduYS5mci9zZXJ2aWNlc2NhLmNybDAtoCugKYYnaHR0\n" + - "cDovL2NybC5kaGlteW90aXMuY29tL3NlcnZpY2VzY2EuY3JsMBMGA1UdJQQMMAoG\n" + - "CCsGAQUFBwMBMA4GA1UdDwEB/wQEAwIFoDBIBgNVHREEQTA/gh12YWxpZC5zZXJ2\n" + - "aWNlc2NhLmNlcnRpZ25hLmNvbYIedmFsaWQuc2VydmljZXNjYS5kaGlteW90aXMu\n" + - "Y29tMB0GA1UdDgQWBBSGQwwMIdxiI7P+CFU/Z968XZaSGzCCAX0GCisGAQQB1nkC\n" + - "BAIEggFtBIIBaQFnAHUArfe++nz/EMiLnT2cHj4YarRnKV3PsQwkyoWGNOvcgooA\n" + - "AAF/h9eOGgAABAMARjBEAiBaneK2CTn9lH28CUnL2C2/WklUYkvygMiDrtCIUXfw\n" + - "gQIgJrGxwgGlsYzUdZyZY/oNWSLByO8/Jb5LXbNibdk5SnAAdwDoPtDaPvUGNTLn\n" + - "Vyi8iWvJA9PL0RFr7Otp4Xd9bQa9bgAAAX+H14/NAAAEAwBIMEYCIQCVtuV9p/Ug\n" + - "IhwVoMUjPp1KzGte/FmDaKPx432VjOpD+AIhANKWkDEuVnMzPH8sdJCL+eXoB0Q7\n" + - "0mpe5dHEiFJS8lTBAHUAs3N3B+GEUPhjhtYFqdwRCUp5LbFnDAuH3PADDnk2pZoA\n" + - "AAF/h9eTcQAABAMARjBEAiAjdYhnzPe9lJksk94ngl7PLDRi71tSRN7SslibEyv+\n" + - "XAIgLQ5NKQAaJnF8oA7WnHB8gyJ/8kqZi52d1WFgARDLR30wDQYJKoZIhvcNAQEL\n" + - "BQADggIBAJhLhW5Gh9yOPKsrMhABd7U5juc5ev97c6s7Az70Yr5/EtH6TlgC6a1N\n" + - "i0yzFOeXzAR8Svsq6HzqP9kMJkEFIrdWH8JZdEv871EjYetEzLLnO0m+dNEROJAh\n" + - "fcJ2w2LufPNaQ327tGY/DxDH9jdtgquReO01bPlJ0Yc5J3maz4XapeUm/kQ8dRzS\n" + - "0UBOxfUlEMpDatZzg7wugy7g9vOndW/VbtbN5Iioq2bjuykPJZfZUx4cCAmLUS7w\n" + - "bqPThQ54PnybiPXaF8cH1Gq0Rs/lGB1erzRXRXHgMy61mFY944r13oATnSdTy8Gm\n" + - "QoMsVp9w7WBRo8O4PR606Ke8Ufm9Kg2GJ1sHClf70FNFO/OSFlr3BLDG0vEMdgVW\n" + - "9QLu6UQXa9PhWMoo030k5fmUySzIUljXnstj3rgcD2HE1UrobTqyRHbbQ8JVWaF0\n" + - "PrPR4WDFI9dY0jixVQucKlX6FCqsyNrJF8GWDlZH+Cd8bk+MA9fKUuX/vmoOc2d+\n" + - "bvOCliME7YjAJkyclk6yiFIMnqyh+TD0d8WbjE94YC/293Xqb6WGkRhhsCX9RUrk\n" + - "I6QbS2uicCFGjRsPmjvMkDDxS00MShRl2K/KpsAx68Cv/Gcw3bv31obwNXTB2IBg\n" + - "gI0MfBHnjIp1nmNvCNmVIP52YrGQyC2JE7+GZUWTuwUVeDgBhiEZ\n" + - "-----END CERTIFICATE-----"; - - // Owner: SERIALNUMBER=S230120951, CN=revoked.servicesca.dhimyotis.com, - // OU=0002 48146308100036, O=DHIMYOTIS, L=VILLENEUVE D'ASCQ, C=FR - // Issuer: CN=Certigna Services CA, OID.2.5.4.97=NTRFR-48146308100036, - // OU=0002 48146308100036, O=DHIMYOTIS, C=FR - // Serial number: f88f2566b3dbf73763622db9b2bf9cc - // Valid from: Sun Mar 13 16:00:00 PDT 2022 until: Mon Mar 13 15:59:59 PDT 2023 - private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + - "MIIImTCCBoGgAwIBAgIQD4jyVms9v3N2NiLbmyv5zDANBgkqhkiG9w0BAQsFADB9\n" + - "MQswCQYDVQQGEwJGUjESMBAGA1UECgwJREhJTVlPVElTMRwwGgYDVQQLDBMwMDAy\n" + - "IDQ4MTQ2MzA4MTAwMDM2MR0wGwYDVQRhDBROVFJGUi00ODE0NjMwODEwMDAzNjEd\n" + - "MBsGA1UEAwwUQ2VydGlnbmEgU2VydmljZXMgQ0EwHhcNMjIwMzEzMjMwMDAwWhcN\n" + - "MjMwMzEzMjI1OTU5WjCBmzELMAkGA1UEBhMCRlIxGjAYBgNVBAcMEVZJTExFTkVV\n" + - "VkUgRCdBU0NRMRIwEAYDVQQKDAlESElNWU9USVMxHDAaBgNVBAsMEzAwMDIgNDgx\n" + - "NDYzMDgxMDAwMzYxKTAnBgNVBAMMIHJldm9rZWQuc2VydmljZXNjYS5kaGlteW90\n" + - "aXMuY29tMRMwEQYDVQQFEwpTMjMwMTIwOTUxMIIBIjANBgkqhkiG9w0BAQEFAAOC\n" + - "AQ8AMIIBCgKCAQEAouvIzemKChCjYICW+TzRigLkqaTdMLnaPlGaXyCCoEUS6nkK\n" + - "QnrwTgebf1X9/mwSAuvTo3Ck7CVgE8AMqsPTluSjezCJuED/F3HYy2YsbIhnVK/i\n" + - "uSzKsDGVY3RlVNm2MA2viVTNBbOFhk4kefYqpDCmp3EGvIDOCb7Y5PTuKKQ79s97\n" + - "uDm+0WoBnOdwSuZMUg+hvINBgu2JQFwiWP0g/SxoK6Ci9SVokM3zR4KgECkMVArf\n" + - "cH0dN+5SYvByaGegQJy7TdKqDsf1lIHM19tUXcxOBNRgV3Rf7WMNIlERtLXjRfke\n" + - "IWXf8QtXRVIH/i/PoVTDo2qvQOMnZFY/Eb5dFQIDAQABo4ID9DCCA/AwgeQGCCsG\n" + - "AQUFBwEBBIHXMIHUMDgGCCsGAQUFBzAChixodHRwOi8vYXV0b3JpdGUuZGhpbXlv\n" + - "dGlzLmNvbS9zZXJ2aWNlc2NhLmRlcjA2BggrBgEFBQcwAoYqaHR0cDovL2F1dG9y\n" + - "aXRlLmNlcnRpZ25hLmZyL3NlcnZpY2VzY2EuZGVyMDAGCCsGAQUFBzABhiRodHRw\n" + - "Oi8vc2VydmljZXNjYS5vY3NwLmRoaW15b3Rpcy5jb20wLgYIKwYBBQUHMAGGImh0\n" + - "dHA6Ly9zZXJ2aWNlc2NhLm9jc3AuY2VydGlnbmEuZnIwHwYDVR0jBBgwFoAUrOyG\n" + - "j0s3HLh/FxsZ0K7oTuM0XBIwCQYDVR0TBAIwADBhBgNVHSAEWjBYMAgGBmeBDAEC\n" + - "AjBMBgsqgXoBgTECBQEBATA9MDsGCCsGAQUFBwIBFi9odHRwczovL3d3dy5jZXJ0\n" + - "aWduYS5jb20vYXV0b3JpdGUtY2VydGlmaWNhdGlvbjBlBgNVHR8EXjBcMCugKaAn\n" + - "hiVodHRwOi8vY3JsLmNlcnRpZ25hLmZyL3NlcnZpY2VzY2EuY3JsMC2gK6Aphido\n" + - "dHRwOi8vY3JsLmRoaW15b3Rpcy5jb20vc2VydmljZXNjYS5jcmwwEwYDVR0lBAww\n" + - "CgYIKwYBBQUHAwEwDgYDVR0PAQH/BAQDAgWgMEwGA1UdEQRFMEOCH3Jldm9rZWQu\n" + - "c2VydmljZXNjYS5jZXJ0aWduYS5jb22CIHJldm9rZWQuc2VydmljZXNjYS5kaGlt\n" + - "eW90aXMuY29tMB0GA1UdDgQWBBTGIed1eHBS8Z1H3PdMkItpjyjq2TCCAX0GCisG\n" + - "AQQB1nkCBAIEggFtBIIBaQFnAHcArfe++nz/EMiLnT2cHj4YarRnKV3PsQwkyoWG\n" + - "NOvcgooAAAF/h9g4MAAABAMASDBGAiEAp/1fQB730JrX9YGD3d1Uq7rTAL95tMKe\n" + - "G6kgUP1GEWoCIQCzi6feA3cImTH6tVZALNEmve/n8SVFAvD2AvX8ioCD9QB1AOg+\n" + - "0No+9QY1MudXKLyJa8kD08vREWvs62nhd31tBr1uAAABf4fYNHcAAAQDAEYwRAIg\n" + - "Dnd8oOV7/MuaiyR23qbdRVf1kBSsDxnLp1/vRdD0JTYCIAw7LuZalEVa/0KpuNHs\n" + - "NIdUJgV4Vioa2xkb9fdPIhtkAHUAs3N3B+GEUPhjhtYFqdwRCUp5LbFnDAuH3PAD\n" + - "Dnk2pZoAAAF/h9g7nwAABAMARjBEAiA80M1W3V3iKjm6Dwn+hKkmvGiuXZoM6o3f\n" + - "QJsZ2ZOx0QIgUiS3I83WzoCdD4qO9rlmDQhRD69CeVzCgLtkaTPz3JYwDQYJKoZI\n" + - "hvcNAQELBQADggIBADKub0gNyasTvURoYukQCllqDC+SvWA4TURBcmQMNjdVkreJ\n" + - "B3O91HZhTyhrCBJxybeIG89zuRI6rjTpHCQGFqtP7968NA3eUlxGGnAPpw6VbN47\n" + - "Ake+CRI9XnhxcKmTGm987DjtIBH42BedS59P1T56grZP5ysOog9Hz4eYo2ytbZqt\n" + - "P/DHggivymaaiIaBsqup8C7/XN3vVAa/yo1FeLJ48i1d0M9hjGBUFMajd8Y5+pE7\n" + - "p6Nb5mT1LXbetORYXMyG3MiJQPBAr1dLnRGnOZxc1Kxa1QwoAFQAFIXFpqfBwfHi\n" + - "NaSDdFS/wLbpe7UvtC8FWLq9sgITDEkPqDPCsbu8Vc7OxaMhBJ7HQGaAYMReGADG\n" + - "Elx9ffAc+dFR62zFnqMLouaEznZ7FVNmU3cYbrFVBvnGmoDRe0AKUoYv5DCiawUg\n" + - "qeQS69DgG7DOE5VIDaWX2Cevy81mz7O8EVQsyS15J/MUxzWfQpRaHUqkge6G9FSH\n" + - "hF/Nm48oWgpWop5aIF2O6bA/Bt1VvAWdypUPUr4gtpYIQoOQBzTFgBVWUeOTOImE\n" + - "avvpzSwGQfZkB7t5PcAQ+zYGxWq7fr30/qY3geePcXJCGWS6PXyj8lNn4CaJ2sMF\n" + - "GKxNJGD49/5uoxi3b3TzGUn/3eG2qP2RZoXZ6ZPLAo+moIy3XLwMoZm3Im8r\n" + - "-----END CERTIFICATE-----"; - - public static void main(String[] args) throws Exception { - - ValidatePathWithParams pathValidator; - String[] validChainToValidate; - String[] revChainToValidate; - - if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) { - pathValidator = new ValidatePathWithParams(null); - pathValidator.enableCRLCheck(); - - validChainToValidate = new String[]{VALID, INT}; - revChainToValidate = new String[]{REVOKED, INT}; - } else { - // OCSP check by default - // int certificate doesn't specify OCSP responder - pathValidator = new ValidatePathWithParams(new String[]{INT}); - pathValidator.enableOCSPCheck(); - - validChainToValidate = new String[]{VALID}; - revChainToValidate = new String[]{REVOKED}; - } - - // Validate valid - pathValidator.validate(validChainToValidate, - ValidatePathWithParams.Status.GOOD, null, System.out); - - // Validate Revoked - pathValidator.validate(revChainToValidate, - ValidatePathWithParams.Status.REVOKED, - "Mon Mar 14 03:00:16 PDT 2022", System.out); - } -} - diff --git a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CertignaRoots.java b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CertignaRoots.java new file mode 100644 index 00000000000..92744eac3d0 --- /dev/null +++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CertignaRoots.java @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8245654 8314960 + * @summary Interoperability tests with Certigna Root CAs from Dhimyotis + * @build ValidatePathWithParams + * @run main/othervm -Djava.security.debug=certpath CertignaRoots OCSP + * @run main/othervm -Djava.security.debug=certpath CertignaRoots CRL + */ + +/* + * Obtain TLS test artifacts for Certigna Root CAs from: + * + * Valid TLS Certificates: + * https://valid.servicesca.dhimyotis.com/ + * + * Revoked TLS Certificates: + * https://revoked.servicesca.dhimyotis.com/ + */ +public class CertignaRoots { + + // Owner: CN=Certigna Services CA, OID.2.5.4.97=NTRFR-48146308100036, + // OU=0002 48146308100036, O=DHIMYOTIS, C=FR + // Issuer: CN=Certigna Root CA, OU=0002 48146308100036, O=Dhimyotis, C=FR + // Serial number: fd30cf04344fc38dd90c4e70753d0623 + // Valid from: Wed Nov 25 03:37:21 PST 2015 until: Fri Jun 03 04:37:21 PDT 2033 + private static final String INT_CERTIGNA_ROOT_CA = "-----BEGIN CERTIFICATE-----\n" + + "MIIHETCCBPmgAwIBAgIRAP0wzwQ0T8ON2QxOcHU9BiMwDQYJKoZIhvcNAQELBQAw\n" + + "WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw\n" + + "MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x\n" + + "NTExMjUxMTM3MjFaFw0zMzA2MDMxMTM3MjFaMH0xCzAJBgNVBAYTAkZSMRIwEAYD\n" + + "VQQKDAlESElNWU9USVMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxHTAb\n" + + "BgNVBGEMFE5UUkZSLTQ4MTQ2MzA4MTAwMDM2MR0wGwYDVQQDDBRDZXJ0aWduYSBT\n" + + "ZXJ2aWNlcyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALPM+7Lp\n" + + "WBz9wFcPaTc3xnB+5g0XrnptB0EPPfrR04vO52Ykm4ky1d4ZLd10tbM1fa1RqNSO\n" + + "VWWg93O4pL7zCFKlz6JV74ZZVhHpEAwzBwv2oPnxvVbxtSN67xsSY66ahUYxjzs8\n" + + "+3FhmsiRxqwnTYvK2u70uglUvRisOKyTL/M6JnrC4y8tlmoz7OSa5BmBMVplJFQt\n" + + "vmON6N9aHLvYMz+EyJPCbXL6pELxeHjFT5QmIaRamsr2DOTaCjtBZKI1Wnh3X7ln\n" + + "bjM8MESJiV2t7E9tIQNG0Z/HI3tO4aaUMum3KysY5sC8v3vi7rryGidgzHQhrtP0\n" + + "ZXWW5UH/k7umLS/P/XXWnCFpc2Lxa1uDGfc2im7xibRoPP+JNZszN76euFlls6jy\n" + + "EXAiwnVr14tVVTewLK0OWs5SJHpEKp8PGMZRDj59EmMvokWwzL6QzNZ6vVAp00oO\n" + + "m05sbspNY9+MFqGKKUsKvhFGEa4XmRNxDe6KswLcjPZB+NKHZ0QWFd4ip5C5XmEK\n" + + "/8qIPjwVr9dah9+oiHGGO8Wx7gJAMF5DTmkvW7GhqCKj1LmHnabjzc8av6kxWVQZ\n" + + "i/C7HCm9i/W4wio+JA2EAFLqNL3GPNbK9kau4yPhQt/c7zxzo0OHnlsV4THCG7oO\n" + + "Cd3cfCiyfQcb3FBt6OSpaKRZxjCLBwP00r0fAgMBAAGjggGtMIIBqTASBgNVHRMB\n" + + "Af8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrOyGj0s3HLh/\n" + + "FxsZ0K7oTuM0XBIwHwYDVR0jBBgwFoAUGIdW4G537iQ1PE5zmh/W4eJ5fiswSQYD\n" + + "VR0gBEIwQDA+BgoqgXoBgTECAAEBMDAwLgYIKwYBBQUHAgEWImh0dHBzOi8vd3d3\n" + + "LmNlcnRpZ25hLmZyL2F1dG9yaXRlcy8wgYgGCCsGAQUFBwEBBHwwejA6BggrBgEF\n" + + "BQcwAoYuaHR0cDovL2F1dG9yaXRlLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNh\n" + + "LmRlcjA8BggrBgEFBQcwAoYwaHR0cDovL2F1dG9yaXRlLmRoaW15b3Rpcy5jb20v\n" + + "Y2VydGlnbmFyb290Y2EuZGVyMG0GA1UdHwRmMGQwL6AtoCuGKWh0dHA6Ly9jcmwu\n" + + "Y2VydGlnbmEuZnIvY2VydGlnbmFyb290Y2EuY3JsMDGgL6AthitodHRwOi8vY3Js\n" + + "LmRoaW15b3Rpcy5jb20vY2VydGlnbmFyb290Y2EuY3JsMA0GCSqGSIb3DQEBCwUA\n" + + "A4ICAQCI5QbprXJ93L+JWHYpUTinXAMSvXMx2dmNm4mIiJRAbGnBOoEYx7M61fbL\n" + + "L5EJIYZhw8jLmeYVFuMao5OJLwda+RMmVzE7lyTGsY64IDKdwogByNCqbKzrlhnU\n" + + "8myyMNB0BDs2jgwQe2Dj9v+MddeHr7sDqvs7R1tSS5hoASLtdQhO7oxUzr3m7M8q\n" + + "+lh4jszli+cjfiPUVS2ADFu4ccQIh4OsIX6SWdU+8R+c/fn0FV6ip4SAVbNyCToz\n" + + "0ZbZKO8YTJgORxRmvrop9dPyuLWjaRrZ0LMx4a3EM3sQDPDqmsG0lHtfFj2PiJvq\n" + + "4lEYA+gDiLKODI+3DJMqo559m3QSS52DsShomHX/Txd0lJoZwepCE6X4KkG9FHjV\n" + + "WXyLgYFwCOcn+hkLhdpblms0wtjeSPITGOioSkefzhleJnDgJ9X4M3svd0HLTpJi\n" + + "lC1DmDZgdrXWITVdOoCogr2LFKNiGd0tbpKG533eKpfBALlm+afc6j73p1KhJEAn\n" + + "AfydDZqBRqv6+HHYplNDn/K2I1CZdkwaGrx3HOR/voGUi1sUI+hYbsPAFu8ZxrhD\n" + + "9UiysmLCfEUhqkbojony+L2mKsoLqyd24emQzn7GgMa7emlWX2jQUTwrD4SliZ2u\n" + + "OetVaZX5RLyqJWs4Igo/xye0xtMQN8INJ4hSZvnMQ1qFtuSRcQ==\n" + + "-----END CERTIFICATE-----"; + + // Owner: CN=Certigna Services CA, OID.2.5.4.97=NTRFR-48146308100036, + // OU=0002 48146308100036, O=DHIMYOTIS, C=FR + // Issuer: CN=Certigna, O=Dhimyotis, C=FR + // Serial number: 6f82fa28acd6f784bb5b120ba87367ad + // Valid from: Wed Nov 25 03:33:52 PST 2015 until: Sat Nov 22 03:33:52 PST 2025 + private static final String INT_CERTIGNA = "-----BEGIN CERTIFICATE-----\n" + + "MIIGFjCCBP6gAwIBAgIQb4L6KKzW94S7WxILqHNnrTANBgkqhkiG9w0BAQsFADA0\n" + + "MQswCQYDVQQGEwJGUjESMBAGA1UECgwJRGhpbXlvdGlzMREwDwYDVQQDDAhDZXJ0\n" + + "aWduYTAeFw0xNTExMjUxMTMzNTJaFw0yNTExMjIxMTMzNTJaMH0xCzAJBgNVBAYT\n" + + "AkZSMRIwEAYDVQQKDAlESElNWU9USVMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgx\n" + + "MDAwMzYxHTAbBgNVBGEMFE5UUkZSLTQ4MTQ2MzA4MTAwMDM2MR0wGwYDVQQDDBRD\n" + + "ZXJ0aWduYSBTZXJ2aWNlcyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC\n" + + "ggIBALPM+7LpWBz9wFcPaTc3xnB+5g0XrnptB0EPPfrR04vO52Ykm4ky1d4ZLd10\n" + + "tbM1fa1RqNSOVWWg93O4pL7zCFKlz6JV74ZZVhHpEAwzBwv2oPnxvVbxtSN67xsS\n" + + "Y66ahUYxjzs8+3FhmsiRxqwnTYvK2u70uglUvRisOKyTL/M6JnrC4y8tlmoz7OSa\n" + + "5BmBMVplJFQtvmON6N9aHLvYMz+EyJPCbXL6pELxeHjFT5QmIaRamsr2DOTaCjtB\n" + + "ZKI1Wnh3X7lnbjM8MESJiV2t7E9tIQNG0Z/HI3tO4aaUMum3KysY5sC8v3vi7rry\n" + + "GidgzHQhrtP0ZXWW5UH/k7umLS/P/XXWnCFpc2Lxa1uDGfc2im7xibRoPP+JNZsz\n" + + "N76euFlls6jyEXAiwnVr14tVVTewLK0OWs5SJHpEKp8PGMZRDj59EmMvokWwzL6Q\n" + + "zNZ6vVAp00oOm05sbspNY9+MFqGKKUsKvhFGEa4XmRNxDe6KswLcjPZB+NKHZ0QW\n" + + "Fd4ip5C5XmEK/8qIPjwVr9dah9+oiHGGO8Wx7gJAMF5DTmkvW7GhqCKj1LmHnabj\n" + + "zc8av6kxWVQZi/C7HCm9i/W4wio+JA2EAFLqNL3GPNbK9kau4yPhQt/c7zxzo0OH\n" + + "nlsV4THCG7oOCd3cfCiyfQcb3FBt6OSpaKRZxjCLBwP00r0fAgMBAAGjggHZMIIB\n" + + "1TASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU\n" + + "rOyGj0s3HLh/FxsZ0K7oTuM0XBIwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF\n" + + "9lo53BGhOKQ2MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAP\n" + + "BgNVBAMMCENlcnRpZ25hggkA/tzjAQ/JSP8wSQYDVR0gBEIwQDA+BgoqgXoBgTEB\n" + + "AAECMDAwLgYIKwYBBQUHAgEWImh0dHBzOi8vd3d3LmNlcnRpZ25hLmZyL2F1dG9y\n" + + "aXRlcy8wfAYIKwYBBQUHAQEEcDBuMDQGCCsGAQUFBzAChihodHRwOi8vYXV0b3Jp\n" + + "dGUuY2VydGlnbmEuZnIvY2VydGlnbmEuZGVyMDYGCCsGAQUFBzAChipodHRwOi8v\n" + + "YXV0b3JpdGUuZGhpbXlvdGlzLmNvbS9jZXJ0aWduYS5kZXIwYQYDVR0fBFowWDAp\n" + + "oCegJYYjaHR0cDovL2NybC5jZXJ0aWduYS5mci9jZXJ0aWduYS5jcmwwK6ApoCeG\n" + + "JWh0dHA6Ly9jcmwuZGhpbXlvdGlzLmNvbS9jZXJ0aWduYS5jcmwwDQYJKoZIhvcN\n" + + "AQELBQADggEBAGLft7gIuGPZVfg0cTM+HT2xAZFPDb/2+siH06x+dH044zMKbBIN\n" + + "bRzhKipwB1A3MW8FQjveE9tyrfyuqZE/X+o2SlGcdNV44ybYkxo4f6kcLEavV/IW\n" + + "+oFEnojZlhpksYcxrvQoEyqkAwshe8IS2KtZHKVACrt+XSs0lwvy7ALGmHaF7A4b\n" + + "y6cZWItA7Lhj8XWp+8tBJDj7HocRbWtxzEODdBuyMgJzFrNjc+97J0vH/K0+3yjm\n" + + "kczpKshMA0tM+MF9XDMN/MuwrPmUWGO/fHiqHgUp8yqeWtl1n44ZxkkK1t9GRwhn\n" + + "DWLv73/xhTmdhWYQ/reo0GbgBoLiltKmIJQ=\n" + + "-----END CERTIFICATE-----"; + + // Owner: SERIALNUMBER=S266241169, CN=valid.servicesca.dhimyotis.com, O=DHIMYOTIS, + // L=VILLENEUVE D'ASCQ, C=FR + // Issuer: CN=Certigna Services CA, OID.2.5.4.97=NTRFR-48146308100036, OU=0002 + // 48146308100036, O=DHIMYOTIS, C=FR + // Serial number: c641ef7b0340c21515d8c462e729dc0e + // Valid from: Thu Mar 09 15:00:00 PST 2023 until: Mon Mar 11 15:59:59 PDT 2024 + private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + + "MIIIdzCCBl+gAwIBAgIRAMZB73sDQMIVFdjEYucp3A4wDQYJKoZIhvcNAQELBQAw\n" + + "fTELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURISU1ZT1RJUzEcMBoGA1UECwwTMDAw\n" + + "MiA0ODE0NjMwODEwMDAzNjEdMBsGA1UEYQwUTlRSRlItNDgxNDYzMDgxMDAwMzYx\n" + + "HTAbBgNVBAMMFENlcnRpZ25hIFNlcnZpY2VzIENBMB4XDTIzMDMwOTIzMDAwMFoX\n" + + "DTI0MDMxMTIyNTk1OVowezELMAkGA1UEBhMCRlIxGjAYBgNVBAcMEVZJTExFTkVV\n" + + "VkUgRCdBU0NRMRIwEAYDVQQKDAlESElNWU9USVMxJzAlBgNVBAMMHnZhbGlkLnNl\n" + + "cnZpY2VzY2EuZGhpbXlvdGlzLmNvbTETMBEGA1UEBRMKUzI2NjI0MTE2OTCCASIw\n" + + "DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJDrFpZWEeBJoMUuG37wEmJ7XVeX\n" + + "Jde1bgURpFbLwifRj2TVmMdtfg9hXHL7B7Mh/+I8/e7kJz8mlU9qUYKyH24oAitE\n" + + "myXYHAKTydqTseiM3mp92n4PM+DrgsdbT7bpmiirNM0/sqWFNyGUz7kP6Z5E3uuU\n" + + "HSlzX1LBBj8S0ORNZWvomQho11gjuZJRS72X4XTnSc0DESwnLp2irUfx7pflBNt0\n" + + "sLE8BhpNSSQd91naJVKtCtn0H7df+o4gGBt2ZceCLBwU0NwN8+KXz06KjP8298V4\n" + + "P3+eR2QxAw4QBIanRaG6Gd4AmpdIaT7TpiYHotjrJ/Pbx5C8/cmgxxlmtI0CAwEA\n" + + "AaOCA/IwggPuMIHkBggrBgEFBQcBAQSB1zCB1DA2BggrBgEFBQcwAoYqaHR0cDov\n" + + "L2F1dG9yaXRlLmNlcnRpZ25hLmZyL3NlcnZpY2VzY2EuZGVyMDgGCCsGAQUFBzAC\n" + + "hixodHRwOi8vYXV0b3JpdGUuZGhpbXlvdGlzLmNvbS9zZXJ2aWNlc2NhLmRlcjAu\n" + + "BggrBgEFBQcwAYYiaHR0cDovL3NlcnZpY2VzY2Eub2NzcC5jZXJ0aWduYS5mcjAw\n" + + "BggrBgEFBQcwAYYkaHR0cDovL3NlcnZpY2VzY2Eub2NzcC5kaGlteW90aXMuY29t\n" + + "MB8GA1UdIwQYMBaAFKzsho9LNxy4fxcbGdCu6E7jNFwSMAkGA1UdEwQCMAAwYQYD\n" + + "VR0gBFowWDAIBgZngQwBAgIwTAYLKoF6AYExAgUBAQEwPTA7BggrBgEFBQcCARYv\n" + + "aHR0cHM6Ly93d3cuY2VydGlnbmEuY29tL2F1dG9yaXRlLWNlcnRpZmljYXRpb24w\n" + + "ZQYDVR0fBF4wXDAtoCugKYYnaHR0cDovL2NybC5kaGlteW90aXMuY29tL3NlcnZp\n" + + "Y2VzY2EuY3JsMCugKaAnhiVodHRwOi8vY3JsLmNlcnRpZ25hLmZyL3NlcnZpY2Vz\n" + + "Y2EuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA4GA1UdDwEB/wQEAwIFoDBIBgNV\n" + + "HREEQTA/gh12YWxpZC5zZXJ2aWNlc2NhLmNlcnRpZ25hLmNvbYIedmFsaWQuc2Vy\n" + + "dmljZXNjYS5kaGlteW90aXMuY29tMB0GA1UdDgQWBBSzyYZfPBt65RUDq98+e0AK\n" + + "U8pd/jCCAX8GCisGAQQB1nkCBAIEggFvBIIBawFpAHcA7s3QZNXbGs7FXLedtM0T\n" + + "ojKHRny87N7DUUhZRnEftZsAAAGGy1ZNXwAABAMASDBGAiEAyG838/RfBOpojEI/\n" + + "cx++f0tvuDbc/rVa0WNcd2f9HekCIQDVKV2wI3VkD3wNmO93m022H7kvKD1OBEhw\n" + + "Tn6+0ZLA6QB2AHb/iD8KtvuVUcJhzPWHujS0pM27KdxoQgqf5mdMWjp0AAABhstW\n" + + "TcYAAAQDAEcwRQIhAOuj/r5G1wHNgFOMg3jsr3uWmWzIIkTmwmp4hJqvsJzzAiBf\n" + + "nm/jZCUW8DFY+iC+O/+Hzsk/kVDkKIlBDd6rA3MzJgB2AFWB1MIWkDYBSuoLm1c8\n" + + "U/DA5Dh4cCUIFy+jqh0HE9MMAAABhstWTw4AAAQDAEcwRQIgRbCAqI1/nxc6P4de\n" + + "Fqg/zc1+ldMDWjeamWjhctciGsgCIQDHQ4OKj0AA7hQKFIe1SVp+00BxRefFGmq7\n" + + "ZJ+8q+pRqzANBgkqhkiG9w0BAQsFAAOCAgEAVkzCC9LIHU+iOi+GFeCtWxxa5Fsk\n" + + "5gXnDJmtbdoVe2TJvOhrb+VnNI7/Ak+csBv3vxNl3P3DXIbPryB98aelleX7pkfP\n" + + "PcKhFAlbwzbII2D3L0mjFLERtVwdnoEJXXKcHsb9hJResKipZ//daMPD8FthHvEE\n" + + "HmtOrR0lHLjhbi4ODq0e4xyygbxFXXl5CCjtBw0jBtZaMDQaC3eemK9LkOggLz3h\n" + + "qs/+VQ7RyKfcKCuGC5Wb4GJR+IDKH812hFsUWmXe26MPoyTrzLNq6tfQZHSuY5Hj\n" + + "K0ZwldEkUZ2Hd7PrRlhCiGdVCp/2kS2yefhUkvX7Z5K5wX6n+LylfzOTvWf6ZPwQ\n" + + "1jTI0Js8ig4eHF25GlqgOWrqbyF9j67kLs3f7/c5Kx3FlclJ7/vlL8zEcTmGU7rm\n" + + "ZFOhEMDT/UYkitqAOvrgT60oIm9YJ1XTAVTeDbW0FFAb2nFmeBOrw8N3jaCb+jpO\n" + + "ysBA/lDaGTiQhMlJK44vwgS+TjbeWHxvmAE5srKa7MWU8Mmku2vuX95lupJo4LmD\n" + + "zOsihH00hyhtHFUB1TGXuaf77kFsipE6iycyxpcrpJ1UAWiZrba6PAZ85TbYhEdY\n" + + "FDNm7F7CVPU67HV5gE2kDa3Jprd1SjwO095LsRptWhzxUByhee3JI0jljBTaKowy\n" + + "jPv8oekm7zqCLzY=\n" + + "-----END CERTIFICATE-----"; + + // Owner: SERIALNUMBER=S266251168, CN=revoked.servicesca.certigna.com, O=DHIMYOTIS, + // L=VILLENEUVE D'ASCQ, C=FR + // Issuer: CN=Certigna Services CA, OID.2.5.4.97=NTRFR-48146308100036, OU=0002 + // 48146308100036, O=DHIMYOTIS, C=FR + // Serial number: e863f752a23a735e3ccf958abf18565b + // Valid from: Thu Mar 09 15:00:00 PST 2023 until: Fri Mar 08 14:59:59 PST 2024 + private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + + "MIIIezCCBmOgAwIBAgIRAOhj91KiOnNePM+Vir8YVlswDQYJKoZIhvcNAQELBQAw\n" + + "fTELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURISU1ZT1RJUzEcMBoGA1UECwwTMDAw\n" + + "MiA0ODE0NjMwODEwMDAzNjEdMBsGA1UEYQwUTlRSRlItNDgxNDYzMDgxMDAwMzYx\n" + + "HTAbBgNVBAMMFENlcnRpZ25hIFNlcnZpY2VzIENBMB4XDTIzMDMwOTIzMDAwMFoX\n" + + "DTI0MDMwODIyNTk1OVowfDELMAkGA1UEBhMCRlIxGjAYBgNVBAcMEVZJTExFTkVV\n" + + "VkUgRCdBU0NRMRIwEAYDVQQKDAlESElNWU9USVMxKDAmBgNVBAMMH3Jldm9rZWQu\n" + + "c2VydmljZXNjYS5jZXJ0aWduYS5jb20xEzARBgNVBAUTClMyNjYyNTExNjgwggEi\n" + + "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCBqKNjMkHqJ9EQa3CjuZ6EYMz6\n" + + "mWODrEucRcJDihYMigaV1oRyquGlFQ82ootXaK5bU+EYSMmUwbRpdZ9G/oZUn2+K\n" + + "MKAFDI+MoZoFhQC+2w0AzJycCf/hShUVxcRREKRKdfzv+k5YHj3e8ic16tGlTFXT\n" + + "IF1x3y2Uru7mzZARsZJqnRqaqPPghT/QlBpcA04yLi3iSpgO++mRrJxTUoUHlDw/\n" + + "a1nhqnDgH2yKN7tSfwFTetnXat6/UVt0CJ/6dJF6oY8bGWO1YB03Xdq735eLdJE4\n" + + "t38pV/X8rf5Mc9ZQh8IGrjVW83M8mQmqaX5rbsOl0ZCA/q6RWxRFEF2SwK+dAgMB\n" + + "AAGjggP1MIID8TCB5AYIKwYBBQUHAQEEgdcwgdQwNgYIKwYBBQUHMAKGKmh0dHA6\n" + + "Ly9hdXRvcml0ZS5jZXJ0aWduYS5mci9zZXJ2aWNlc2NhLmRlcjA4BggrBgEFBQcw\n" + + "AoYsaHR0cDovL2F1dG9yaXRlLmRoaW15b3Rpcy5jb20vc2VydmljZXNjYS5kZXIw\n" + + "LgYIKwYBBQUHMAGGImh0dHA6Ly9zZXJ2aWNlc2NhLm9jc3AuY2VydGlnbmEuZnIw\n" + + "MAYIKwYBBQUHMAGGJGh0dHA6Ly9zZXJ2aWNlc2NhLm9jc3AuZGhpbXlvdGlzLmNv\n" + + "bTAfBgNVHSMEGDAWgBSs7IaPSzccuH8XGxnQruhO4zRcEjAJBgNVHRMEAjAAMGEG\n" + + "A1UdIARaMFgwCAYGZ4EMAQICMEwGCyqBegGBMQIFAQEBMD0wOwYIKwYBBQUHAgEW\n" + + "L2h0dHBzOi8vd3d3LmNlcnRpZ25hLmNvbS9hdXRvcml0ZS1jZXJ0aWZpY2F0aW9u\n" + + "MGUGA1UdHwReMFwwLaAroCmGJ2h0dHA6Ly9jcmwuZGhpbXlvdGlzLmNvbS9zZXJ2\n" + + "aWNlc2NhLmNybDAroCmgJ4YlaHR0cDovL2NybC5jZXJ0aWduYS5mci9zZXJ2aWNl\n" + + "c2NhLmNybDATBgNVHSUEDDAKBggrBgEFBQcDATAOBgNVHQ8BAf8EBAMCBaAwTAYD\n" + + "VR0RBEUwQ4IgcmV2b2tlZC5zZXJ2aWNlc2NhLmRoaW15b3Rpcy5jb22CH3Jldm9r\n" + + "ZWQuc2VydmljZXNjYS5jZXJ0aWduYS5jb20wHQYDVR0OBBYEFEQsKyX8x8zVxVC2\n" + + "HEK7+bOBLoMkMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgDuzdBk1dsazsVc\n" + + "t520zROiModGfLzs3sNRSFlGcR+1mwAAAYbLTxPnAAAEAwBHMEUCIQD16IHX+8+4\n" + + "zWnxIME4rzCgQIA4m5OsEqP6ssgRG5iurwIgdBOGFGlF6+DGPSm5FKuk5ShAA8ZC\n" + + "AE+E27CKLkBTnfgAdgB2/4g/Crb7lVHCYcz1h7o0tKTNuyncaEIKn+ZnTFo6dAAA\n" + + "AYbLTxRMAAAEAwBHMEUCIDmW9elysDm3zAeIXsgJwmL33EoMTyVhA3ah2jkvMjzv\n" + + "AiEA6aIZXtwk2DnFt+GA6gLr4UgswUCuK4wxheDVwbpSw/4AdgA7U3d1Pi25gE6L\n" + + "MFsG/kA7Z9hPw/THvQANLXJv4frUFwAAAYbLTxXAAAAEAwBHMEUCIQDGuOg7koEE\n" + + "H9K4VkSHaDD9rAndys2BtswdspfRKUFR3QIgVZ7QUX3H56ECuI8wsAkSjBze4lBO\n" + + "RgfN2xh3l9xQOK0wDQYJKoZIhvcNAQELBQADggIBAFQTTtyQSoV4Zq3QYMnb0yEp\n" + + "u6Hwic/wpYN5L0km+zZoHWuf58vfj8Yg/sfKmftGSZHDdc3NfYSVBlT/0Hl4SDhi\n" + + "zHLLyapoX2GNhbg3esu0Y1fch8E16z2A/wAwrFvxI0XrjHpOyDp4CBDYqDADNPiL\n" + + "vlEkiwP6r7WHjUdWRb7W0t75uAkcajn46XKpFmaHHie5KBch+KDGsUionuH5ZW8Y\n" + + "klh2B34uLWcGZuIR7PeCO9+91mbn/bBNeabGC70qMStaB139lp9P2M+l2WpyREUK\n" + + "l7qHwTsrlMmNb8n44zGtY4wL9NSYWTdTfhcU0FAPdPcLlnjoQubJ1O0vPkzfVYns\n" + + "WQrslxoCBor6CL6AYMQz3jbzQ0soD3Reb11+uTngWGJZtx4DT09RFB3a+1rcYjiS\n" + + "ijCBB+Lqx0xfLQnfBv1A0wjNqUY+gyEe0SpXqB4edqy5uaqawRRKMuNSnb2BVz0/\n" + + "keo1Kif/GSak+JUBpJ8hkJWygtrWCETUNfoseQhqo3gism0EGxJ04tBp+DRvfbrz\n" + + "X4aBgALRro3jSIR1Ibp+e0fxePwShy715SF2H4SfjvplTAKq5bwztZtQUkPR6fJ7\n" + + "5xT0f762c1yytKP1rHFMvzl6k7QWvC6zb2FeG5UqXJw3wFxxWsCuAUu5SPFfXdno\n" + + "5lIHTTV5rpZBN+PzTZsz\n" + + "-----END CERTIFICATE-----"; + + public static void main(String[] args) throws Exception { + // OCSP check by default + boolean ocspEnabled = args.length < 1 || !"CRL".equalsIgnoreCase(args[0]); + + // CN=Certigna + new CertignaCAs().runTest(ocspEnabled, + VALID, + REVOKED, + INT_CERTIGNA); + + // CN=Certigna Root CA + new CertignaCAs().runTest(ocspEnabled, + VALID, + REVOKED, + INT_CERTIGNA_ROOT_CA); + } +} + +class CertignaCAs { + public void runTest(boolean ocspEnabled, + final String VALID, + final String REVOKED, + final String INT_CERT) throws Exception { + + ValidatePathWithParams pathValidator; + String[] validChainToValidate; + String[] revChainToValidate; + + if (!ocspEnabled) { + pathValidator = new ValidatePathWithParams(null); + pathValidator.enableCRLCheck(); + + validChainToValidate = new String[]{VALID, INT_CERT}; + revChainToValidate = new String[]{REVOKED, INT_CERT}; + } else { + // int certificate doesn't specify OCSP responder + pathValidator = new ValidatePathWithParams(new String[]{INT_CERT}); + pathValidator.enableOCSPCheck(); + + validChainToValidate = new String[]{VALID}; + revChainToValidate = new String[]{REVOKED}; + } + + // Validate valid + pathValidator.validate(validChainToValidate, + ValidatePathWithParams.Status.GOOD, null, System.out); + + // Validate Revoked + pathValidator.validate(revChainToValidate, + ValidatePathWithParams.Status.REVOKED, + "Fri Mar 10 03:39:51 PST 2023", System.out); + } +} diff --git a/test/jdk/sun/java2d/loops/SkipConversionIfPossible.java b/test/jdk/sun/java2d/loops/SkipConversionIfPossible.java new file mode 100644 index 00000000000..1b1947b1158 --- /dev/null +++ b/test/jdk/sun/java2d/loops/SkipConversionIfPossible.java @@ -0,0 +1,89 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.AlphaComposite; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.util.Arrays; + +import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR; +import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR; +import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE; +import static java.awt.image.BufferedImage.TYPE_INT_ARGB; +import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE; +import static java.awt.image.BufferedImage.TYPE_INT_BGR; +import static java.awt.image.BufferedImage.TYPE_INT_RGB; + +/** + * @test + * @bug 8297681 + * @summary The blit TYPE_4BYTE_ABGR_PRE to TYPE_INT_ARGB_PRE should be "direct" + */ +public final class SkipConversionIfPossible { + + private static final int SIZE = 256; + + public static void main(String[] args) { + // Initial bug was in the TYPE_4BYTE_ABGR_PRE to TYPE_INT_ARGB_PRE blit. + // But I checked other blits just in case. + test(new int[]{TYPE_INT_ARGB_PRE, TYPE_4BYTE_ABGR_PRE}); + test(new int[]{TYPE_INT_RGB, TYPE_INT_BGR, TYPE_3BYTE_BGR}); + test(new int[]{TYPE_INT_ARGB, TYPE_4BYTE_ABGR}); + } + + private static void test(int[] types) { + for (int src : types) { + for (int dst : types) { + render(src, dst); + } + } + } + + private static void render(int src, int dst) { + BufferedImage from = new BufferedImage(SIZE, SIZE, src); + for (int a = 0; a < SIZE; ++a) { + for (int c = 0; c < SIZE; ++c) { + // The data is intentionally broken for the argb_pre format, but + // it should be stored as is in dst if no conversion was done. + from.getRaster().setPixel(c, a, new int[]{c, c << 24, -c, a}); + } + } + BufferedImage to = new BufferedImage(SIZE, SIZE, dst); + Graphics2D g = to.createGraphics(); + g.setComposite(AlphaComposite.Src); + g.drawImage(from, 0, 0, null); + g.dispose(); + + for (int a = 0; a < SIZE; ++a) { + for (int c = 0; c < SIZE; ++c) { + int[] pixel1 = from.getRaster().getPixel(c, a, (int[]) null); + int[] pixel2 = to.getRaster().getPixel(c, a, (int[]) null); + if (!Arrays.equals(pixel1, pixel2)) { + System.err.println(Arrays.toString(pixel1)); + System.err.println(Arrays.toString(pixel2)); + throw new RuntimeException(); + } + } + } + } +} diff --git a/test/jdk/sun/management/jmxremote/bootstrap/management_ssltest07_ok.properties.in b/test/jdk/sun/management/jmxremote/bootstrap/management_ssltest07_ok.properties.in index 21fa833234c..35b1b1ea3b6 100644 --- a/test/jdk/sun/management/jmxremote/bootstrap/management_ssltest07_ok.properties.in +++ b/test/jdk/sun/management/jmxremote/bootstrap/management_ssltest07_ok.properties.in @@ -1,5 +1,5 @@ -com.sun.management.jmxremote.ssl.enabled.cipher.suites=TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 +com.sun.management.jmxremote.ssl.enabled.cipher.suites=TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA com.sun.management.jmxremote.ssl.enabled.protocols=SSLv2Hello,SSLv3,TLSv1 com.sun.management.jmxremote.ssl.need.client.auth=true com.sun.management.jmxremote.authenticate=false -javax.rmi.ssl.client.enabledCipherSuites=TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 +javax.rmi.ssl.client.enabledCipherSuites=TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA diff --git a/test/jdk/sun/net/ftp/B6427768.java b/test/jdk/sun/net/ftp/B6427768.java index cdadb16fc68..12412cd03d3 100644 --- a/test/jdk/sun/net/ftp/B6427768.java +++ b/test/jdk/sun/net/ftp/B6427768.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -105,13 +105,14 @@ public boolean rename(String from, String to) { } public static void main(String[] args) throws IOException { - FtpServer server = new FtpServer(0); + InetAddress loopback = InetAddress.getLoopbackAddress(); + FtpServer server = new FtpServer(loopback, 0); int port = server.getLocalPort(); server.setFileSystemHandler(new MyFileSystemHandler("/")); server.setAuthHandler(new MyAuthHandler()); server.start(); - URL url = new URL("ftp://user:passwd@localhost:" + port + "/foo.txt"); - URLConnection con = url.openConnection(); + URL url = new URL("ftp://user:passwd@" + server.getAuthority() + "/foo.txt"); + URLConnection con = url.openConnection(Proxy.NO_PROXY); // triggers the connection try { con.getInputStream(); diff --git a/test/jdk/sun/net/ftp/FtpURLConnectionLeak.java b/test/jdk/sun/net/ftp/FtpURLConnectionLeak.java index f6caca9f7dd..3bdaa06856f 100644 --- a/test/jdk/sun/net/ftp/FtpURLConnectionLeak.java +++ b/test/jdk/sun/net/ftp/FtpURLConnectionLeak.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -32,17 +32,19 @@ import java.io.FileNotFoundException; import java.io.InputStream; import java.io.OutputStream; +import java.net.InetAddress; import java.net.URL; public class FtpURLConnectionLeak { public static void main(String[] args) throws Exception { - FtpServer server = new FtpServer(0); + InetAddress loopback = InetAddress.getLoopbackAddress(); + FtpServer server = new FtpServer(loopback, 0); server.setFileSystemHandler(new CustomFileSystemHandler("/")); server.setAuthHandler(new MyAuthHandler()); - int port = server.getLocalPort(); + String authority = server.getAuthority(); server.start(); - URL url = new URL("ftp://localhost:" + port + "/filedoesNotExist.txt"); + URL url = new URL("ftp://" + authority + "/filedoesNotExist.txt"); try (server) { for (int i = 0; i < 3; i++) { try { diff --git a/test/jdk/sun/net/www/AuthHeaderTest.java b/test/jdk/sun/net/www/AuthHeaderTest.java index 62cd443baf8..5ce874ef015 100644 --- a/test/jdk/sun/net/www/AuthHeaderTest.java +++ b/test/jdk/sun/net/www/AuthHeaderTest.java @@ -96,10 +96,11 @@ static void client (String u) throws Exception { public static void main (String[] args) throws Exception { MyAuthenticator auth = new MyAuthenticator (); Authenticator.setDefault (auth); + InetAddress loopback = InetAddress.getLoopbackAddress(); try { - server = new TestHttpServer (new AuthHeaderTest(), 1, 10, 0); - System.out.println ("Server: listening on port: " + server.getLocalPort()); - client ("http://localhost:"+server.getLocalPort()+"/d1/foo.html"); + server = new TestHttpServer (new AuthHeaderTest(), 1, 10, loopback, 0); + System.out.println ("Server: listening on port: " + server.getAuthority()); + client ("http://" + server.getAuthority() + "/d1/foo.html"); } catch (Exception e) { if (server != null) { server.terminate(); diff --git a/test/jdk/sun/net/www/ftptest/FtpCommandHandler.java b/test/jdk/sun/net/www/ftptest/FtpCommandHandler.java index 8a234e82baa..1e491961851 100644 --- a/test/jdk/sun/net/www/ftptest/FtpCommandHandler.java +++ b/test/jdk/sun/net/www/ftptest/FtpCommandHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -238,14 +238,14 @@ private void doPasv() { return; } try { - if (pasv == null) - pasv = new ServerSocket(0); - int port = pasv.getLocalPort(); InetAddress rAddress = cmd.getLocalAddress(); if (rAddress instanceof Inet6Address) { out.println("500 PASV illegal over IPv6 addresses, use EPSV."); return; } + if (pasv == null) + pasv = new ServerSocket(0, 0, rAddress); + int port = pasv.getLocalPort(); byte[] a = rAddress.getAddress(); out.println("227 Entering Passive Mode " + a[0] + "," + a[1] + "," + a[2] + "," + a[3] + "," + (port >> 8) + "," + (port & 0xff) ); @@ -266,7 +266,7 @@ private void doEpsv(String arg) { } try { if (pasv == null) - pasv = new ServerSocket(0); + pasv = new ServerSocket(0, 0, parent.getInetAddress()); int port = pasv.getLocalPort(); out.println("229 Entering Extended Passive Mode (|||" + port + "|)"); } catch (IOException e) { diff --git a/test/jdk/sun/net/www/ftptest/FtpServer.java b/test/jdk/sun/net/www/ftptest/FtpServer.java index 8ea5705fb52..11d007f19c8 100644 --- a/test/jdk/sun/net/www/ftptest/FtpServer.java +++ b/test/jdk/sun/net/www/ftptest/FtpServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -54,6 +54,16 @@ public class FtpServer extends Thread implements AutoCloseable { private boolean done = false; private ArrayList clients = new ArrayList(); + /** + * Creates an instance of an FTP server which will listen for incoming + * connections on the specified port. If the port is set to 0, it will + * automatically select an available ephemeral port. + */ + public FtpServer(InetAddress addr, int port) throws IOException { + listener = new ServerSocket(); + listener.bind(new InetSocketAddress(addr, port)); + } + /** * Creates an instance of an FTP server which will listen for incoming * connections on the specified port. If the port is set to 0, it will @@ -100,6 +110,21 @@ public int getLocalPort() { return listener.getLocalPort(); } + public InetAddress getInetAddress() { + return listener.getInetAddress(); + } + + public String getAuthority() { + InetAddress address = getInetAddress(); + String hostaddr = address.isAnyLocalAddress() + ? "localhost" : address.getHostAddress(); + if (hostaddr.indexOf(':') > -1) { + hostaddr = "[" + hostaddr + "]"; + } + return hostaddr + ":" + getLocalPort(); + } + + void addClient(Socket client) { FtpCommandHandler h = new FtpCommandHandler(client, this); h.setHandlers(fsh, auth); diff --git a/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java b/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java index 1d837841fb4..d2ada718d89 100644 --- a/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java +++ b/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -25,6 +25,7 @@ * @test * @bug 4333920 * @modules jdk.httpserver + * @library /test/lib * @run main ChunkedEncodingTest * @summary ChunkedEncodingTest unit test */ @@ -36,6 +37,7 @@ import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpExchange; import static java.lang.System.out; +import jdk.test.lib.net.URIBuilder; public class ChunkedEncodingTest{ private static MessageDigest serverDigest, clientDigest; @@ -61,7 +63,13 @@ public static void test() { int port = server.getAddress().getPort(); out.println ("Server listening on port: " + port); - client("http://localhost:" + port + "/chunked/"); + String url = URIBuilder.newBuilder() + .scheme("http") + .host(server.getAddress().getAddress()) + .port(port) + .path("/chunked/") + .build().toString(); + client(url); if (!MessageDigest.isEqual(clientMac, serverMac)) { throw new RuntimeException( @@ -83,7 +91,8 @@ public static void main(String[] args) { * Http Server */ static HttpServer startHttpServer() throws IOException { - HttpServer httpServer = HttpServer.create(new InetSocketAddress(0), 0); + InetAddress loopback = InetAddress.getLoopbackAddress(); + HttpServer httpServer = HttpServer.create(new InetSocketAddress(loopback, 0), 0); HttpHandler httpHandler = new SimpleHandler(); httpServer.createContext("/chunked/", httpHandler); httpServer.start(); diff --git a/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java b/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java index 6affe7a767c..38c00e68c87 100644 --- a/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java +++ b/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -27,6 +27,7 @@ * @summary ChunkedEncoding unit test; MeteredStream/ProgressData problem * @modules java.base/sun.net * jdk.httpserver + * @library /test/lib * @run main ChunkedEncodingWithProgressMonitorTest */ diff --git a/test/jdk/sun/net/www/http/ChunkedInputStream/TestAvailable.java b/test/jdk/sun/net/www/http/ChunkedInputStream/TestAvailable.java index a1737d79c23..4ad49b7cc8e 100644 --- a/test/jdk/sun/net/www/http/ChunkedInputStream/TestAvailable.java +++ b/test/jdk/sun/net/www/http/ChunkedInputStream/TestAvailable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -25,6 +25,7 @@ * @test * @bug 6446990 * @modules jdk.httpserver + * @library /test/lib * @run main/othervm TestAvailable * @summary HttpURLConnection#available() reads more and more data into memory */ @@ -35,6 +36,7 @@ import com.sun.net.httpserver.*; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; +import jdk.test.lib.net.URIBuilder; public class TestAvailable { @@ -60,7 +62,13 @@ void doClient() { try { InetSocketAddress address = httpServer.getAddress(); - URL url = new URL("http://localhost:" + address.getPort() + "/testAvailable/"); + URL url = URIBuilder.newBuilder() + .scheme("http") + .host(address.getAddress()) + .port(address.getPort()) + .path("/testAvailable/") + .toURLUnchecked(); + HttpURLConnection uc = (HttpURLConnection)url.openConnection(); uc.setDoOutput(true); @@ -102,7 +110,9 @@ void doClient() { * Http Server */ public void startHttpServer() throws IOException { - httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(0), 0); + InetAddress loopback = InetAddress.getLoopbackAddress(); + InetSocketAddress sockaddr = new InetSocketAddress(loopback, 0); + httpServer = com.sun.net.httpserver.HttpServer.create(sockaddr, 0); // create HttpServer context HttpContext ctx = httpServer.createContext("/testAvailable/", new MyHandler()); diff --git a/test/jdk/sun/net/www/http/HttpClient/MultiThreadTest.java b/test/jdk/sun/net/www/http/HttpClient/MultiThreadTest.java index c4b80809258..cdea76fa4f6 100644 --- a/test/jdk/sun/net/www/http/HttpClient/MultiThreadTest.java +++ b/test/jdk/sun/net/www/http/HttpClient/MultiThreadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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,6 +25,7 @@ * @test * @bug 4636628 * @summary HttpURLConnection duplicates HTTP GET requests when used with multiple threads + * @run main MultiThreadTest */ /* @@ -40,9 +41,14 @@ import java.net.*; import java.io.*; import java.time.Duration; +import java.util.ArrayList; +import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; public class MultiThreadTest extends Thread { @@ -51,8 +57,13 @@ public class MultiThreadTest extends Thread { */ static boolean debug = true; // disable debug once stability proven - static Object threadlock = new Object (); + static final Object threadlock = new Object (); static int threadCounter = 0; + // KEEP_ALIVE sent by the server + static final int KEEP_ALIVE = 1; // seconds + // The sending thread will sleep for this time after sending + // half the number of its requests + static final int SLEEP = KEEP_ALIVE * 1000 + 500; // ms static Object getLock() { return threadlock; } @@ -63,6 +74,9 @@ static void debug(String msg) { static final AtomicInteger reqnum = new AtomicInteger(); + // Set to true after all requests have been sent + static final AtomicBoolean DONE = new AtomicBoolean(); + void doRequest(String uri) throws Exception { URL url = new URL(uri + "?foo="+reqnum.getAndIncrement()); HttpURLConnection http = (HttpURLConnection)url.openConnection(); @@ -79,42 +93,49 @@ void doRequest(String uri) throws Exception { http.disconnect(); } - String uri; - byte[] b; - int requests; - - MultiThreadTest(int port, int requests) throws Exception { - uri = "http://localhost:" + port + "/foo.html"; + final String uri; + final byte[] b; + final int requests; + final CountDownLatch countDown; + MultiThreadTest(String authority, int requests, CountDownLatch latch) throws Exception { + countDown = latch; + uri = "http://" + authority + "/foo.html"; b = new byte [256]; this.requests = requests; - - synchronized (threadlock) { - threadCounter ++; - } } public void run() { long start = System.nanoTime(); - try { for (int i=0; i tests = new ArrayList<>(); + for (int i = 0; i < threads; i++) { + MultiThreadTest t = new MultiThreadTest(svr.getAuthority(), requests, latch); + tests.add(t); + t.start(); } - try { - lock.wait(); - } catch (InterruptedException e) {} - } - // shutdown server - we're done. - svr.shutdown(); - - int cnt = svr.connectionCount(); - MultiThreadTest.debug("Connections = " + cnt); - int reqs = Worker.getRequests (); - MultiThreadTest.debug("Requests = " + reqs); - System.out.println ("Connection count = " + cnt + " Request count = " + reqs); - - // We may have received traffic from something else than - // our client. We should only count those workers for which - // the expected header has been found. - int validConnections = 0; - for (Worker w : svr.workers()) { - if (w.headerFound) validConnections++; - } + latch.await(); + long end = System.nanoTime(); + DONE.compareAndSet(false, true); + for (var test : tests) test.join(); + + MultiThreadTest.debug("DONE at " + at(end) + "ms"); + + // shutdown server - we're done. + svr.shutdown(); + + int cnt = svr.connectionCount(); + MultiThreadTest.debug("Connections = " + cnt); + int reqs = Worker.getRequests(); + MultiThreadTest.debug("Requests = " + reqs); + System.out.println("Connection count = " + cnt + " Request count = " + reqs); + + // We may have received traffic from something else than + // our client. We should only count those workers for which + // the expected header has been found. + int validConnections = 0; + // We detect worker threads that may have timed out, so we don't include them in + // the count to compare with the number of connections. + int becameIdle = 0; + for (Worker w : svr.workers()) { + if (w.headerFound > 0) { + validConnections++; + if (w.mayHaveTimedOut(end)) { + debug("Worker " + w.id + " may have timed out"); + becameIdle++; + } else { + long at0 = at(w.lastReading); + long at1 = at(w.lastReplied); + debug("Worker " + w.id +" has not timed out - last used at " + + Math.max(at0, at1)); + } + } else { + debug("Worker " + w.id + " is not a valid connection"); + } + } - if (validConnections > threads + 1 || validConnections == 0) { // could be less - throw new RuntimeException ("Expected " + threads + " connections: used " + validConnections); - } + if (validConnections > threads) { + if (SLEEP > KEEP_ALIVE) { + debug("INFO: " + validConnections + + " have been used, with " + becameIdle + + " becoming idle for more than " + KEEP_ALIVE + "s" + + " while using " + threads + + " threads to make concurrent connections"); + } else { + debug("WARNING: " + validConnections + + " have been used, with " + becameIdle + + " becoming idle for more than " + KEEP_ALIVE + "s" + + " where only " + threads + + " connections and none idle were expected!"); + } + } - // Sometimes the client drops a connection after a while and - // spawns a new one. Why this is happening is not clear, - // and JDK-8223783 is logged to follow up on this. For the sake - // of test stabilization we don't fail on `threads + 1` connections - // but log a warning instead. - if (validConnections == threads + 1) { - debug("WARNING: " + validConnections - + " have been used, where only " + threads - + " were expected!"); - } + if (validConnections > threads + becameIdle || validConnections == 0) { // could be less + throw new RuntimeException("Expected " + (threads + becameIdle) + " connections: used " + validConnections); + } - if (validConnections != cnt) { - debug("WARNING: got " + (cnt - validConnections) + " unexpected connections!"); - } - if (validConnections == cnt && reqs != threads*requests) { - throw new RuntimeException ("Expected "+ threads*requests+ " requests: got " +reqs); - } + if (validConnections != cnt) { + debug("INFO: got " + (cnt - validConnections) + " unexpected connections"); + } + if (reqs != threads * requests) { + throw new RuntimeException("Expected " + threads * requests + " requests: got " + reqs); + } - for (Thread worker : svr.workers()) { - worker.join(60_000); + } finally { + debug("waiting for worker to shutdown at " + at() +"ms"); + for (Worker worker : svr.workers()) { + // We want to verify that the client will eventually + // close the idle connections. So just join the worker + // and wait... This shouldn't take more than the granularity + // of the keep-alive cache timer - so we're not actually + // going to have to wait for one full minute here. + worker.join(60_000); + } } - debug("main thread end - " + Duration.ofNanos(System.nanoTime() - start)); + debug("main thread end - " + at() + "ms"); } } @@ -209,6 +268,16 @@ class Server extends Thread { this.ss = ss; } + public String getAuthority() { + InetAddress address = ss.getInetAddress(); + String hostaddr = address.isAnyLocalAddress() + ? "localhost" : address.getHostAddress(); + if (hostaddr.indexOf(':') > -1) { + hostaddr = "[" + hostaddr + "]"; + } + return hostaddr + ":" + ss.getLocalPort(); + } + public Queue workers() { return workers; } @@ -219,34 +288,45 @@ public synchronized int connectionCount() { public synchronized void shutdown() { shutdown = true; + try { + ss.close(); + } catch (IOException x) { + } } public void run() { try { - ss.setSoTimeout(2000); + ss.setSoTimeout(6000); + long startServer = System.nanoTime(); for (;;) { Socket s; + long acceptTime; try { MultiThreadTest.debug("server: calling accept."); s = ss.accept(); - MultiThreadTest.debug("server: return accept."); - } catch (SocketTimeoutException te) { + acceptTime = System.nanoTime(); + MultiThreadTest.debug("server: return accept (at " + + MultiThreadTest.at(acceptTime)+ "ms)"); + } catch (IOException te) { MultiThreadTest.debug("server: STE"); synchronized (this) { if (shutdown) { - MultiThreadTest.debug("server: Shuting down."); + MultiThreadTest.debug("server: Shuting down at: " + + MultiThreadTest.at() + "ms"); return; } } - continue; + if (te instanceof SocketTimeoutException) + continue; + throw te; } int id; Worker w; synchronized (this) { id = connectionCount++; - w = new Worker(s, id); + w = new Worker(s, id, acceptTime); workers.add(w); } w.start(); @@ -268,14 +348,39 @@ public void run() { * multiple http requests on same connection. */ class Worker extends Thread { - Socket s; - int id; - volatile boolean headerFound; - - Worker(Socket s, int id) { + final long TIMEOUT = MultiThreadTest.KEEP_ALIVE; // seconds + final long KEEP_ALIVE_NS = Duration.ofSeconds(TIMEOUT).toNanos(); // nanos + final Socket s; + final int id; + + // time at which the connection was accepted (nanos) + final long acceptTime; + + // number of requests that had the expected URI + volatile int headerFound; + // time at which the worker thread exited + volatile long stopTime; + // Time at which the first call to is.read() for the last request + // returned. This includes cases where -1 was returned. + volatile long startReading; + // Lat time at which a byte was read from the stream. + volatile long lastReading; + // number of times that the time between two consecutive received requests + // exceeded the KEEP_ALIVE timeout. + volatile int timeoutExceeded; + // Number of requests handled by this worker + volatile int requestHandled; + // Time at which the last byte of the last reply was sent + volatile long lastReplied; + // Whether the worker was asked to stop + volatile boolean done; + + Worker(Socket s, int id, long acceptTime) { super("Worker-" + id); this.s = s; this.id = id; + // no time can have a value before accepTime + this.acceptTime = lastReading = lastReplied = startReading = acceptTime; } static int requests = 0; @@ -293,12 +398,42 @@ public static void incRequests () { } } + /** + * {@return Whether this worker might have been idle for more + * than the KEEP_ALIVE timeout} + * This will be true if the worker detected that the idle timeout + * was exceeded between two consecutive request, or + * if the time between the last reply and `nanosNow` exceeds + * the keep-alive time. + * @param nanosNow a timestamp in nano seconds + */ + public boolean mayHaveTimedOut(long nanosNow) { + // the minimum time elapsed between nanosNow and: + // - the time the socket was accepted + // - the last time a byte was received + // - the last time a reply was sent. + // We must not use `startReading` here because `startReading` may + // be set if the client asynchronously closes the connection + // after all requests have been sent. We should really only + // take into account `lastReading` and `lastReplied`. + long idle = Math.min(nanosNow - lastReading, nanosNow - lastReplied); + return timeoutExceeded > 0 || idle >= KEEP_ALIVE_NS; + } + int readUntil(InputStream in, StringBuilder headers, char[] seq) throws IOException { int i=0, count=0; + long last; while (true) { int c = in.read(); + last = System.nanoTime(); + if (count == 0) { + // time at which the first byte of the request (or EOF) was received + startReading = last; + } if (c == -1) return -1; + // time at which the last byte of the request was received (excludes EOF) + lastReading = last; headers.append((char)c); count++; if (c == seq[i]) { @@ -315,6 +450,9 @@ int readUntil(InputStream in, StringBuilder headers, char[] seq) throws IOExcept public void run() { long start = System.nanoTime(); + // lastUsed starts when the connection was accepted + long lastUsed = acceptTime; + int expectedReqs = 0; try { int max = 400; byte b[] = new byte[1000]; @@ -325,38 +463,49 @@ public void run() { s.getOutputStream() )); for (;;) { - // read entire request from client - int n=0; + int n; StringBuilder headers = new StringBuilder(); n = readUntil(in, headers, new char[] {'\r','\n', '\r','\n'}); + long idle = startReading - lastUsed; + if (idle >= KEEP_ALIVE_NS) { + if (!MultiThreadTest.DONE.get()) { + // avoid increasing timeoutExceeded after the test is no + // longer sending requests. + timeoutExceeded++; + } + } if (n <= 0) { - MultiThreadTest.debug("worker: " + id + ": Shutdown"); + MultiThreadTest.debug("worker: " + id + ": Shutdown at " + + MultiThreadTest.at() + "ms"); s.close(); return; } if (headers.toString().contains("/foo.html?foo=")) { - headerFound = true; + headerFound = ++expectedReqs; + incRequests(); } else { MultiThreadTest.debug("worker: " + id + ": Unexpected request received: " + headers); + s.close(); + return; } MultiThreadTest.debug("worker " + id + ": Read request from client " + - "(" + n + " bytes)."); + "(" + n + " bytes) at " + MultiThreadTest.at() + "ms"); - incRequests(); out.print("HTTP/1.1 200 OK\r\n"); out.print("Transfer-Encoding: chunked\r\n"); out.print("Content-Type: text/html\r\n"); out.print("Connection: Keep-Alive\r\n"); - out.print("Keep-Alive: timeout=15, max="+max+"\r\n"); + out.print("Keep-Alive: timeout=" + TIMEOUT + ", max="+max+"\r\n"); out.print("\r\n"); out.print("6\r\nHello \r\n"); out.print("5\r\nWorld\r\n"); out.print("0\r\n\r\n"); out.flush(); - + requestHandled++; + lastUsed = lastReplied = System.nanoTime(); if (--max == 0) { s.close(); return; @@ -366,11 +515,19 @@ public void run() { } catch (Exception e) { e.printStackTrace(); } finally { + long end = stopTime = System.nanoTime(); try { s.close(); } catch (Exception e) { } - MultiThreadTest.debug("worker: " + id + " end - " + - Duration.ofNanos(System.nanoTime() - start)); + MultiThreadTest.debug("worker: " + id + " end at " + + MultiThreadTest.at() + "ms, elapsed since worker start: " + + Duration.ofNanos(end - start).toMillis() + "ms, elapsed since accept: " + + Duration.ofNanos(end - acceptTime).toMillis() + + "ms, timeout exceeded: " + timeoutExceeded + + ", successfuly handled " + requestHandled + "/" + + expectedReqs + " genuine requests, " + + ", mayHaveTimedOut: " + mayHaveTimedOut(end)); } } + } diff --git a/test/jdk/sun/net/www/http/HttpClient/RetryPost.java b/test/jdk/sun/net/www/http/HttpClient/RetryPost.java index 8313a648b5a..6b80175135c 100644 --- a/test/jdk/sun/net/www/http/HttpClient/RetryPost.java +++ b/test/jdk/sun/net/www/http/HttpClient/RetryPost.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -25,6 +25,7 @@ * @test * @bug 6427251 6382788 * @modules jdk.httpserver + * @library /test/lib * @run main RetryPost * @run main/othervm -Dsun.net.http.retryPost=false RetryPost noRetry * @summary HttpURLConnection automatically retries non-idempotent method POST @@ -36,12 +37,14 @@ import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.SocketException; import java.net.URL; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; +import jdk.test.lib.net.URIBuilder; public class RetryPost { @@ -66,7 +69,12 @@ public RetryPost() throws Exception { void doClient() throws Exception { try { InetSocketAddress address = httpServer.getAddress(); - URL url = new URL("http://localhost:" + address.getPort() + "/test/"); + URL url = URIBuilder.newBuilder() + .scheme("http") + .host(address.getAddress()) + .port(address.getPort()) + .path("/test/") + .toURLUnchecked(); HttpURLConnection uc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY); uc.setDoOutput(true); uc.setRequestMethod("POST"); @@ -93,7 +101,8 @@ else if (!shouldRetry && httpHandler.getCallCount() != 1) * Http Server */ public void startHttpServer(boolean shouldRetry) throws IOException { - httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(0), 0); + InetAddress loopback = InetAddress.getLoopbackAddress(); + httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(loopback, 0), 0); httpHandler = new MyHandler(shouldRetry); HttpContext ctx = httpServer.createContext("/test/", httpHandler); diff --git a/test/jdk/sun/net/www/http/HttpURLConnection/DigestAuth.java b/test/jdk/sun/net/www/http/HttpURLConnection/DigestAuth.java index 7eaa4f74ed4..597748662c5 100644 --- a/test/jdk/sun/net/www/http/HttpURLConnection/DigestAuth.java +++ b/test/jdk/sun/net/www/http/HttpURLConnection/DigestAuth.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -29,6 +29,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.Authenticator; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.PasswordAuthentication; import java.net.URL; @@ -54,7 +55,6 @@ */ public class DigestAuth { - static final String LOCALHOST = "localhost"; static final String EXPECT_FAILURE = null; static final String EXPECT_DIGEST = "Digest"; static final String REALM = "testrealm@host.com"; @@ -119,8 +119,7 @@ public static void main(String[] args) throws Exception { AuthenticatorImpl auth = new AuthenticatorImpl(); Authenticator.setDefault(auth); - String url = String.format("http://%s:%d/test/", - LOCALHOST, server.getPort()); + String url = String.format("http://%s/test/", server.getAuthority()); boolean success = true; switch (testcase) { @@ -322,6 +321,16 @@ private LocalHttpServer(HttpServer server) { this.server = server; } + public String getAuthority() { + InetAddress address = server.getAddress().getAddress(); + String hostaddr = address.isAnyLocalAddress() + ? "localhost" : address.getHostAddress(); + if (hostaddr.indexOf(':') > -1) { + hostaddr = "[" + hostaddr + "]"; + } + return hostaddr + ":" + getPort(); + } + void setWWWAuthHeader(String wwwAuthHeader) { this.wwwAuthHeader = wwwAuthHeader; } @@ -331,8 +340,9 @@ void setAuthInfoHeader(String authInfoHeader) { } static LocalHttpServer startServer() throws IOException { + InetAddress loopback = InetAddress.getLoopbackAddress(); HttpServer httpServer = HttpServer.create( - new InetSocketAddress(0), 0); + new InetSocketAddress(loopback, 0), 0); LocalHttpServer localHttpServer = new LocalHttpServer(httpServer); localHttpServer.start(); @@ -342,7 +352,7 @@ static LocalHttpServer startServer() throws IOException { void start() { server.createContext("/test", this); server.start(); - System.out.println("HttpServer: started on port " + getPort()); + System.out.println("HttpServer: started on port " + getAuthority()); } void stop() { diff --git a/test/jdk/sun/net/www/http/KeepAliveCache/B8293562.java b/test/jdk/sun/net/www/http/KeepAliveCache/B8293562.java new file mode 100644 index 00000000000..4e0cff8bab4 --- /dev/null +++ b/test/jdk/sun/net/www/http/KeepAliveCache/B8293562.java @@ -0,0 +1,238 @@ +/* + * 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 8293562 + * @library /test/lib + * @run main/othervm -Dhttp.keepAlive.time.server=1 B8293562 + * @summary Http keep-alive thread should close sockets without holding a lock + */ + +import com.sun.net.httpserver.HttpServer; + +import javax.net.ssl.HandshakeCompletedListener; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Socket; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +public class B8293562 { + static HttpServer server; + static CountDownLatch closing = new CountDownLatch(1); + static CountDownLatch secondRequestDone = new CountDownLatch(1); + static CompletableFuture result = new CompletableFuture<>(); + + public static void main(String[] args) throws Exception { + startHttpServer(); + clientHttpCalls(); + } + + public static void startHttpServer() throws Exception { + server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 10); + server.setExecutor(Executors.newCachedThreadPool()); + server.start(); + } + + public static void clientHttpCalls() throws Exception { + try { + System.out.println("http server listen on: " + server.getAddress().getPort()); + String hostAddr = InetAddress.getLoopbackAddress().getHostAddress(); + if (hostAddr.indexOf(':') > -1) hostAddr = "[" + hostAddr + "]"; + String baseURLStr = "https://" + hostAddr + ":" + server.getAddress().getPort() + "/"; + + URL testUrl = new URL (baseURLStr); + + // SlowCloseSocketFactory is not a real SSLSocketFactory; + // it produces regular non-SSL sockets. Effectively, the request + // is made over http. + HttpsURLConnection.setDefaultSSLSocketFactory(new SlowCloseSocketFactory()); + System.out.println("Performing first request"); + HttpsURLConnection uc = (HttpsURLConnection)testUrl.openConnection(Proxy.NO_PROXY); + byte[] buf = new byte[1024]; + try { + uc.getInputStream(); + throw new RuntimeException("Expected 404 here"); + } catch (FileNotFoundException ignored) { } + try (InputStream is = uc.getErrorStream()) { + while (is.read(buf) >= 0) { + } + } + System.out.println("First request completed"); + closing.await(); + // KeepAliveThread is closing the connection now + System.out.println("Performing second request"); + HttpsURLConnection uc2 = (HttpsURLConnection)testUrl.openConnection(Proxy.NO_PROXY); + + try { + uc2.getInputStream(); + throw new RuntimeException("Expected 404 here"); + } catch (FileNotFoundException ignored) { } + try (InputStream is = uc2.getErrorStream()) { + while (is.read(buf) >= 0) { + } + } + System.out.println("Second request completed"); + // let the socket know it can close now + secondRequestDone.countDown(); + result.get(); + System.out.println("Test completed successfully"); + } finally { + server.stop(1); + } + } + + static class SlowCloseSocket extends SSLSocket { + @Override + public synchronized void close() throws IOException { + String threadName = Thread.currentThread().getName(); + System.out.println("Connection closing, thread name: " + threadName); + closing.countDown(); + super.close(); + if (threadName.equals("Keep-Alive-Timer")) { + try { + if (secondRequestDone.await(5, TimeUnit.SECONDS)) { + result.complete(null); + } else { + result.completeExceptionally(new RuntimeException( + "Wait for second request timed out")); + } + } catch (InterruptedException e) { + result.completeExceptionally(new RuntimeException( + "Wait for second request was interrupted")); + } + } else { + result.completeExceptionally(new RuntimeException( + "Close invoked from unexpected thread")); + } + System.out.println("Connection closed"); + } + + // required abstract method overrides + @Override + public String[] getSupportedCipherSuites() { + return new String[0]; + } + @Override + public String[] getEnabledCipherSuites() { + return new String[0]; + } + @Override + public void setEnabledCipherSuites(String[] suites) { } + @Override + public String[] getSupportedProtocols() { + return new String[0]; + } + @Override + public String[] getEnabledProtocols() { + return new String[0]; + } + @Override + public void setEnabledProtocols(String[] protocols) { } + @Override + public SSLSession getSession() { + return null; + } + @Override + public void addHandshakeCompletedListener(HandshakeCompletedListener listener) { } + @Override + public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) { } + @Override + public void startHandshake() throws IOException { } + @Override + public void setUseClientMode(boolean mode) { } + @Override + public boolean getUseClientMode() { + return false; + } + @Override + public void setNeedClientAuth(boolean need) { } + @Override + public boolean getNeedClientAuth() { + return false; + } + @Override + public void setWantClientAuth(boolean want) { } + @Override + public boolean getWantClientAuth() { + return false; + } + @Override + public void setEnableSessionCreation(boolean flag) { } + @Override + public boolean getEnableSessionCreation() { + return false; + } + } + + static class SlowCloseSocketFactory extends SSLSocketFactory { + + @Override + public Socket createSocket() throws IOException { + return new SlowCloseSocket(); + } + // required abstract method overrides + @Override + public Socket createSocket(String host, int port) throws IOException, UnknownHostException { + throw new UnsupportedOperationException(); + } + @Override + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { + throw new UnsupportedOperationException(); + } + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public String[] getDefaultCipherSuites() { + return new String[0]; + } + @Override + public String[] getSupportedCipherSuites() { + return new String[0]; + } + @Override + public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { + throw new UnsupportedOperationException(); + } + } +} + diff --git a/test/jdk/sun/net/www/protocol/http/6550798/test.java b/test/jdk/sun/net/www/protocol/http/6550798/test.java index 2c4527063da..5396c89821f 100644 --- a/test/jdk/sun/net/www/protocol/http/6550798/test.java +++ b/test/jdk/sun/net/www/protocol/http/6550798/test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -43,14 +43,15 @@ public class test { public static void main(String[] args) throws Exception { TestCache.reset(); - HttpServer s = HttpServer.create (new InetSocketAddress(0), 10); - s.createContext ("/", new HttpHandler () { - public void handle (HttpExchange e) { + InetAddress loopback = InetAddress.getLoopbackAddress(); + HttpServer s = HttpServer.create(new InetSocketAddress(loopback, 0), 10); + s.createContext("/", new HttpHandler() { + public void handle(HttpExchange e) { try { byte[] buf = new byte [LEN]; OutputStream o = e.getResponseBody(); e.sendResponseHeaders(200, LEN); - o.write (buf); + o.write(buf); e.close(); } catch (IOException ex) { ex.printStackTrace(); @@ -91,10 +92,10 @@ public void handle (HttpExchange e) { } if (TestCache.fail) { - System.out.println ("TEST FAILED"); - throw new RuntimeException (); + System.out.println("TEST FAILED"); + throw new RuntimeException(); } else { - System.out.println ("TEST OK"); + System.out.println("TEST OK"); } } } diff --git a/test/jdk/sun/net/www/protocol/http/CloseOptionHeader.java b/test/jdk/sun/net/www/protocol/http/CloseOptionHeader.java index e72471a144f..bc1ec86fee4 100644 --- a/test/jdk/sun/net/www/protocol/http/CloseOptionHeader.java +++ b/test/jdk/sun/net/www/protocol/http/CloseOptionHeader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -25,6 +25,7 @@ * @test * @bug 6189206 * @modules java.base/sun.net.www + * @library /test/lib * @run main/othervm -Dhttp.keepAlive=false CloseOptionHeader * @summary HTTP client should set "Connection: close" header in request when keepalive is disabled */ @@ -33,7 +34,7 @@ import java.util.*; import java.io.*; import sun.net.www.MessageHeader; - +import jdk.test.lib.net.URIBuilder; public class CloseOptionHeader implements Runnable { static ServerSocket ss; @@ -79,14 +80,20 @@ public static void main(String args[]) throws Exception { Thread tester = new Thread(new CloseOptionHeader()); /* start the server */ - ss = new ServerSocket(0); + InetAddress loopback = InetAddress.getLoopbackAddress(); + ss = new ServerSocket(); + ss.bind(new InetSocketAddress(loopback, 0)); tester.start(); /* connect to the server just started * server then check the request to see whether * there is a close connection option header in it */ - URL url = new URL("http://localhost:" + ss.getLocalPort()); + URL url = URIBuilder.newBuilder() + .scheme("http") + .host(ss.getInetAddress()) + .port(ss.getLocalPort()) + .toURL(); HttpURLConnection huc = (HttpURLConnection)url.openConnection(); huc.connect(); huc.getResponseCode(); diff --git a/test/jdk/sun/net/www/protocol/https/AbstractCallback.java b/test/jdk/sun/net/www/protocol/https/AbstractCallback.java index 4fc60def96a..e69de29bb2d 100644 --- a/test/jdk/sun/net/www/protocol/https/AbstractCallback.java +++ b/test/jdk/sun/net/www/protocol/https/AbstractCallback.java @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.net.*; -import java.util.*; -import java.io.IOException; - -/** - * This class provides a partial implementation of the HttpCallback - * interface. Use this class if you want to use the requestURI as a means - * of tracking multiple invocations of a request (on the server). - * In this case, you implement the modified request() method, which includes - * an integer count parameter. This parameter indicates the number of times - * (starting at zero) the request URI has been received. - */ - -public abstract class AbstractCallback implements HttpCallback { - - Map requests; - - static class Request { - URI uri; - int count; - - Request (URI u) { - uri = u; - count = 0; - } - } - - AbstractCallback () { - requests = Collections.synchronizedMap (new HashMap()); - } - - /** - * handle the given request and generate an appropriate response. - * @param msg the transaction containing the request from the - * client and used to send the response - */ - public void request (HttpTransaction msg) { - URI uri = msg.getRequestURI(); - Request req = (Request) requests.get (uri); - if (req == null) { - req = new Request (uri); - requests.put (uri, req); - } - request (msg, req.count++); - } - - /** - * Same as HttpCallback interface except that the integer n - * is provided to indicate sequencing of repeated requests using - * the same request URI. n starts at zero and is incremented - * for each successive call. - * - * @param msg the transaction containing the request from the - * client and used to send the response - * @param n value is 0 at first call, and is incremented by 1 for - * each subsequent call using the same request URI. - */ - abstract public void request (HttpTransaction msg, int n); -} diff --git a/test/jdk/sun/net/www/protocol/https/ChunkedOutputStream.java b/test/jdk/sun/net/www/protocol/https/ChunkedOutputStream.java index f9066d02f45..5991c89d4af 100644 --- a/test/jdk/sun/net/www/protocol/https/ChunkedOutputStream.java +++ b/test/jdk/sun/net/www/protocol/https/ChunkedOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2012, 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,8 +24,7 @@ /** * @test * @bug 5026745 - * @modules java.base/sun.net.www - * @build TestHttpsServer HttpCallback + * @library /test/lib * @run main/othervm ChunkedOutputStream * * SunJSSE does not support dynamic system properties, no way to re-use @@ -33,11 +32,35 @@ * @summary Cannot flush output stream when writing to an HttpUrlConnection */ -import java.io.*; -import java.net.*; -import javax.net.ssl.*; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpRetryException; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.SocketException; +import java.net.URL; +import java.nio.charset.Charset; +import java.security.KeyStore; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; -public class ChunkedOutputStream implements HttpCallback { +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManagerFactory; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; + +public class ChunkedOutputStream implements HttpHandler { /* * Where do we find the keystores for ssl? */ @@ -46,6 +69,7 @@ public class ChunkedOutputStream implements HttpCallback { static String trustStoreFile = "truststore"; static String passwd = "passphrase"; static int count = 0; + static final AtomicInteger rogueCount = new AtomicInteger(); static final String str1 = "Helloworld1234567890abcdefghijklmnopqrstuvwxyz"+ "1234567890abcdefkjsdlkjflkjsldkfjlsdkjflkj"+ @@ -54,87 +78,100 @@ public class ChunkedOutputStream implements HttpCallback { static final String str2 = "Helloworld1234567890abcdefghijklmnopqrstuvwxyz"+ "1234567890"; - public void request (HttpTransaction req) { - try { - // this is needed (count++ doesn't work), 'cause we - // are doing concurrent tests - String path = req.getRequestURI().getPath(); - if (path.equals("/d0")) { - count = 0; - } else if (path.equals("/d01")) { - count = 1; - } else if (path.equals("/d3")) { - count = 2; - } else if (path.equals("/d4") || path.equals("/d5")) { - count = 3; - } else if (path.equals("/d6")) { - count = 3; - } else if (path.equals("/d7")) { - count = 4; - } else if (path.equals("/d8")) { - count = 5; - } + private static String getAuthority() { + InetAddress address = server.getAddress().getAddress(); + String hostaddr = address.getHostAddress(); + if (address.isAnyLocalAddress()) hostaddr = "localhost"; + if (hostaddr.indexOf(':') > -1) hostaddr = "[" + hostaddr + "]"; + return hostaddr + ":" + server.getAddress().getPort(); + } + + public void handle(HttpExchange req) throws IOException { + // this is needed (count++ doesn't work), 'cause we + // are doing concurrent tests + System.out.println("Request Received"); + String path = req.getRequestURI().getPath(); + if (path.equals("/d0")) { + count = 0; + } else if (path.equals("/d01")) { + count = 1; + } else if (path.equals("/d3")) { + count = 2; + } else if (path.equals("/d4") || path.equals("/d5")) { + count = 3; + } else if (path.equals("/d6")) { + count = 3; + } else if (path.equals("/d7")) { + count = 4; + } else if (path.equals("/d8")) { + count = 5; + } - switch (count) { + switch (count) { case 0: /* test1 -- keeps conn alive */ case 1: /* test2 -- closes conn */ - String reqbody = req.getRequestEntityBody(); + + String reqbody = ""; + try(InputStream inputStream = req.getRequestBody()) { + reqbody = new String(inputStream.readAllBytes(), Charset.forName("ISO8859_1")); + } if (!reqbody.equals(str1)) { - req.sendResponse (500, "Internal server error"); - req.orderlyClose(); + req.sendResponseHeaders(500, -1); + break; } - String chunk = req.getRequestHeader ("Transfer-encoding"); - if (!"chunked".equals (chunk)) { - req.sendResponse (501, "Internal server error"); - req.orderlyClose(); + String chunk = req.getRequestHeaders().getFirst("Transfer-encoding"); + if (!"chunked".equals(chunk)) { + req.sendResponseHeaders(501, -1); + break; } - req.setResponseEntityBody (reqbody); if (count == 1) { - req.setResponseHeader ("Connection", "close"); + req.getResponseHeaders().set("Connection", "close"); } - req.sendResponse (200, "OK"); - if (count == 1) { - req.orderlyClose(); + req.sendResponseHeaders(200, 0); + try (OutputStream os = req.getResponseBody()) { + os.write(reqbody.getBytes(Charset.forName("ISO8859_1"))); } break; case 2: /* test 3 */ - reqbody = req.getRequestEntityBody(); + reqbody = new String(req.getRequestBody().readAllBytes(), Charset.forName("ISO8859_1")); if (!reqbody.equals(str2)) { - req.sendResponse (500, "Internal server error"); - req.orderlyClose(); + req.sendResponseHeaders(500, -1); + break; } - int clen = Integer.parseInt ( - req.getRequestHeader ("Content-length")); + int clen = Integer.parseInt (req.getRequestHeaders().getFirst("Content-length")); if (clen != str2.length()) { - req.sendResponse (501, "Internal server error"); - req.orderlyClose(); + req.sendResponseHeaders(501, -1); + break; + } + req.getResponseHeaders().set("Connection", "close"); + req.sendResponseHeaders(200, 0); + try (OutputStream os = req.getResponseBody()) { + os.write(reqbody.getBytes(Charset.forName("ISO8859_1"))); } - req.setResponseEntityBody (reqbody); - req.setResponseHeader ("Connection", "close"); - req.sendResponse (200, "OK"); - req.orderlyClose(); break; case 3: /* test 6 */ - req.setResponseHeader ("Location", "https://foo.bar/"); - req.setResponseHeader ("Connection", "close"); - req.sendResponse (307, "Temporary Redirect"); - req.orderlyClose(); + if (path.equals("/d6")) { + reqbody = new String(req.getRequestBody().readAllBytes(), Charset.forName("ISO8859_1")); + } + req.getResponseHeaders().set("Location", "https://foo.bar/"); + req.getResponseHeaders().set("Connection", "close"); + req.sendResponseHeaders(307, -1); break; case 4: /* test 7 */ case 5: /* test 8 */ - reqbody = req.getRequestEntityBody(); - if (reqbody != null && !"".equals (reqbody)) { - req.sendResponse (501, "Internal server error"); - req.orderlyClose(); + reqbody = new String(req.getRequestBody().readAllBytes(), Charset.forName("ISO8859_1")); + if (reqbody != null && !"".equals(reqbody)) { + req.sendResponseHeaders(501, -1); + break; } - req.setResponseHeader ("Connection", "close"); - req.sendResponse (200, "OK"); - req.orderlyClose(); + req.getResponseHeaders().set("Connection", "close"); + req.sendResponseHeaders(200, -1); + break; + default: + req.sendResponseHeaders(404, -1); break; - } - } catch (IOException e) { - e.printStackTrace(); } + req.close(); } static void readAndCompare (InputStream is, String cmp) throws IOException { @@ -152,6 +189,23 @@ static void readAndCompare (InputStream is, String cmp) throws IOException { } } + /* basic smoke test: verify that server drops plain connections */ + static void testPlainText(String authority) throws Exception { + URL url = new URL("http://" + authority + "/Donauschiffsgesellschaftskapitaenskajuete"); + System.out.println("client opening connection to: " + url); + HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY); + int rogue = rogueCount.get(); + try { + int code = urlc.getResponseCode(); + System.out.println("Unexpected response: " + code); + throw new AssertionError("Unexpected response: " + code); + } catch (SocketException x) { + // we expect that the server will drop the connection and + // close the accepted socket, so we should get a SocketException + System.out.println("Got expected exception: " + x); + } + } + /* basic chunked test (runs twice) */ static void test1 (String u) throws Exception { @@ -162,7 +216,7 @@ static void test1 (String u) throws Exception { urlc.setDoOutput(true); urlc.setRequestMethod ("POST"); OutputStream os = urlc.getOutputStream (); - os.write (str1.getBytes()); + os.write(str1.getBytes(Charset.forName("ISO8859_1"))); os.close(); InputStream is = urlc.getInputStream(); readAndCompare (is, str1); @@ -179,7 +233,7 @@ static void test3 (String u) throws Exception { urlc.setDoOutput(true); urlc.setRequestMethod ("POST"); OutputStream os = urlc.getOutputStream (); - os.write (str2.getBytes()); + os.write (str2.getBytes(Charset.forName("ISO8859_1"))); os.close(); InputStream is = urlc.getInputStream(); readAndCompare (is, str2); @@ -196,7 +250,7 @@ static void test4 (String u) throws Exception { urlc.setDoOutput(true); urlc.setRequestMethod ("POST"); OutputStream os = urlc.getOutputStream (); - os.write (str2.getBytes()); + os.write(str2.getBytes(Charset.forName("ISO8859_1"))); try { os.close(); throw new Exception ("should have thrown IOException"); @@ -214,7 +268,7 @@ static void test5 (String u) throws Exception { urlc.setRequestMethod ("POST"); OutputStream os = urlc.getOutputStream (); try { - os.write (str2.getBytes()); + os.write(str2.getBytes(Charset.forName("ISO8859_1"))); throw new Exception ("should have thrown IOException"); } catch (IOException e) {} } @@ -229,7 +283,7 @@ static void test6 (String u) throws Exception { urlc.setDoOutput(true); urlc.setRequestMethod ("POST"); OutputStream os = urlc.getOutputStream (); - os.write (str1.getBytes()); + os.write(str1.getBytes(Charset.forName("ISO8859_1"))); os.close(); try { InputStream is = urlc.getInputStream(); @@ -276,9 +330,10 @@ static void test8 (String u) throws Exception { } } - static TestHttpsServer server; + static HttpsServer server; public static void main (String[] args) throws Exception { + ChunkedOutputStream chunkedOutputStream = new ChunkedOutputStream(); // setup properties to do ssl String keyFilename = System.getProperty("test.src", "./") + "/" + pathToStores + @@ -287,6 +342,8 @@ public static void main (String[] args) throws Exception { System.getProperty("test.src", "./") + "/" + pathToStores + "/" + trustStoreFile; + InetAddress loopback = InetAddress.getLoopbackAddress(); + HostnameVerifier reservedHV = HttpsURLConnection.getDefaultHostnameVerifier(); try { @@ -297,25 +354,48 @@ public static void main (String[] args) throws Exception { HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier()); try { - server = new TestHttpsServer( - new ChunkedOutputStream(), 1, 10, 0); - System.out.println ("Server started: listening on port: " + server.getLocalPort()); + // create and initialize a SSLContext + KeyStore ks = KeyStore.getInstance("JKS"); + KeyStore ts = KeyStore.getInstance("JKS"); + char[] passphrase = "passphrase".toCharArray(); + + ks.load(new FileInputStream(System.getProperty("javax.net.ssl.keyStore")), passphrase); + ts.load(new FileInputStream(System.getProperty("javax.net.ssl.trustStore")), passphrase); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, passphrase); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ts); + + SSLContext sslCtx = SSLContext.getInstance("TLS"); + + sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + server = HttpsServer.create(new InetSocketAddress(loopback, 0), 10); + server.setHttpsConfigurator(new HttpsConfigurator(sslCtx)); + server.createContext("/", chunkedOutputStream); + server.setExecutor(Executors.newSingleThreadExecutor()); + server.start(); + + System.out.println("Server started: listening on: " + getAuthority()); + testPlainText(getAuthority()); // the test server doesn't support keep-alive yet // test1("http://localhost:"+server.getLocalPort()+"/d0"); - test1("https://localhost:"+server.getLocalPort()+"/d01"); - test3("https://localhost:"+server.getLocalPort()+"/d3"); - test4("https://localhost:"+server.getLocalPort()+"/d4"); - test5("https://localhost:"+server.getLocalPort()+"/d5"); - test6("https://localhost:"+server.getLocalPort()+"/d6"); - test7("https://localhost:"+server.getLocalPort()+"/d7"); - test8("https://localhost:"+server.getLocalPort()+"/d8"); + test1("https://" + getAuthority() + "/d01"); + test3("https://" + getAuthority() + "/d3"); + test4("https://" + getAuthority() + "/d4"); + test5("https://" + getAuthority() + "/d5"); + test6("https://" + getAuthority() + "/d6"); + test7("https://" + getAuthority() + "/d7"); + test8("https://" + getAuthority() + "/d8"); } catch (Exception e) { if (server != null) { - server.terminate(); + server.stop(1); } throw e; } - server.terminate(); + server.stop(1); } finally { HttpsURLConnection.setDefaultHostnameVerifier(reservedHV); } @@ -328,7 +408,7 @@ public boolean verify(String hostname, SSLSession session) { } public static void except (String s) { - server.terminate(); + server.stop(1); throw new RuntimeException (s); } } diff --git a/test/jdk/sun/net/www/protocol/https/HttpCallback.java b/test/jdk/sun/net/www/protocol/https/HttpCallback.java index 27af7b7aaf4..e69de29bb2d 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpCallback.java +++ b/test/jdk/sun/net/www/protocol/https/HttpCallback.java @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please 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 interface is implemented by classes that wish to handle incoming HTTP - * requests and generate responses. This could be a general purpose HTTP server - * or a test case that expects specific requests from a client. - *

          - * The incoming request fields can be examined via the {@link HttpTransaction} - * object, and a response can also be generated and sent via the request object. - */ -public interface HttpCallback { - /** - * handle the given request and generate an appropriate response. - * @param msg the transaction containing the request from the - * client and used to send the response - */ - void request (HttpTransaction msg); -} diff --git a/test/jdk/sun/net/www/protocol/https/HttpTransaction.java b/test/jdk/sun/net/www/protocol/https/HttpTransaction.java index ea90c267301..e69de29bb2d 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpTransaction.java +++ b/test/jdk/sun/net/www/protocol/https/HttpTransaction.java @@ -1,330 +0,0 @@ -/* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.*; -import java.nio.*; -import java.nio.channels.*; -import java.net.*; -import sun.net.www.MessageHeader; - -/** - * This class encapsulates a HTTP request received and a response to be - * generated in one transaction. It provides methods for examaining the - * request from the client, and for building and sending a reply. - */ - -public class HttpTransaction { - - String command; - URI requesturi; - TestHttpsServer.ServerWorker server; - MessageHeader reqheaders, reqtrailers; - String reqbody; - byte[] rspbody; - MessageHeader rspheaders, rsptrailers; - SocketChannel ch; - int rspbodylen; - boolean rspchunked; - - HttpTransaction (TestHttpsServer.ServerWorker server, String command, - URI requesturi, MessageHeader headers, - String body, MessageHeader trailers, SocketChannel ch) { - this.command = command; - this.requesturi = requesturi; - this.reqheaders = headers; - this.reqbody = body; - this.reqtrailers = trailers; - this.ch = ch; - this.server = server; - } - - /** - * Get the value of a request header whose name is specified by the - * String argument. - * - * @param key the name of the request header - * @return the value of the header or null if it does not exist - */ - public String getRequestHeader (String key) { - return reqheaders.findValue (key); - } - - /** - * Get the value of a response header whose name is specified by the - * String argument. - * - * @param key the name of the response header - * @return the value of the header or null if it does not exist - */ - public String getResponseHeader (String key) { - return rspheaders.findValue (key); - } - - /** - * Get the request URI - * - * @return the request URI - */ - public URI getRequestURI () { - return requesturi; - } - - public String toString () { - StringBuffer buf = new StringBuffer(); - buf.append ("Request from: ").append (ch.toString()).append("\r\n"); - buf.append ("Command: ").append (command).append("\r\n"); - buf.append ("Request URI: ").append (requesturi).append("\r\n"); - buf.append ("Headers: ").append("\r\n"); - buf.append (reqheaders.toString()).append("\r\n"); - buf.append ("Body: ").append (reqbody).append("\r\n"); - buf.append ("---------Response-------\r\n"); - buf.append ("Headers: ").append("\r\n"); - if (rspheaders != null) { - buf.append (rspheaders.toString()).append("\r\n"); - } - String rbody = rspbody == null? "": new String (rspbody); - buf.append ("Body: ").append (rbody).append("\r\n"); - return new String (buf); - } - - /** - * Get the value of a request trailer whose name is specified by - * the String argument. - * - * @param key the name of the request trailer - * @return the value of the trailer or null if it does not exist - */ - public String getRequestTrailer (String key) { - return reqtrailers.findValue (key); - } - - /** - * Add a response header to the response. Multiple calls with the same - * key value result in multiple header lines with the same key identifier - * @param key the name of the request header to add - * @param val the value of the header - */ - public void addResponseHeader (String key, String val) { - if (rspheaders == null) - rspheaders = new MessageHeader (); - rspheaders.add (key, val); - } - - /** - * Set a response header. Searches for first header with named key - * and replaces its value with val - * @param key the name of the request header to add - * @param val the value of the header - */ - public void setResponseHeader (String key, String val) { - if (rspheaders == null) - rspheaders = new MessageHeader (); - rspheaders.set (key, val); - } - - /** - * Add a response trailer to the response. Multiple calls with the same - * key value result in multiple trailer lines with the same key identifier - * @param key the name of the request trailer to add - * @param val the value of the trailer - */ - public void addResponseTrailer (String key, String val) { - if (rsptrailers == null) - rsptrailers = new MessageHeader (); - rsptrailers.add (key, val); - } - - /** - * Get the request method - * - * @return the request method - */ - public String getRequestMethod (){ - return command; - } - - /** - * Perform an orderly close of the TCP connection associated with this - * request. This method guarantees that any response already sent will - * not be reset (by this end). The implementation does a shutdownOutput() - * of the TCP connection and for a period of time consumes and discards - * data received on the reading side of the connection. This happens - * in the background. After the period has expired the - * connection is completely closed. - */ - - public void orderlyClose () { - try { - server.orderlyCloseChannel (ch); - } catch (IOException e) { - System.out.println (e); - } - } - - /** - * Do an immediate abortive close of the TCP connection associated - * with this request. - */ - public void abortiveClose () { - try { - server.abortiveCloseChannel(ch); - } catch (IOException e) { - System.out.println (e); - } - } - - /** - * Get the SocketChannel associated with this request - * - * @return the socket channel - */ - public SocketChannel channel() { - return ch; - } - - /** - * Get the request entity body associated with this request - * as a single String. - * - * @return the entity body in one String - */ - public String getRequestEntityBody (){ - return reqbody; - } - - /** - * Set the entity response body with the given string - * The content length is set to the length of the string - * @param body the string to send in the response - */ - public void setResponseEntityBody (String body){ - rspbody = body.getBytes(); - rspbodylen = body.length(); - rspchunked = false; - addResponseHeader ("Content-length", Integer.toString (rspbodylen)); - } - /** - * Set the entity response body with the given byte[] - * The content length is set to the gven length - * @param body the string to send in the response - */ - public void setResponseEntityBody (byte[] body, int len){ - rspbody = body; - rspbodylen = len; - rspchunked = false; - addResponseHeader ("Content-length", Integer.toString (rspbodylen)); - } - - - /** - * Set the entity response body by reading the given inputstream - * - * @param is the inputstream from which to read the body - */ - public void setResponseEntityBody (InputStream is) throws IOException { - byte[] buf = new byte [2048]; - byte[] total = new byte [2048]; - int total_len = 2048; - int c, len=0; - while ((c=is.read (buf)) != -1) { - if (len+c > total_len) { - byte[] total1 = new byte [total_len * 2]; - System.arraycopy (total, 0, total1, 0, len); - total = total1; - total_len = total_len * 2; - } - System.arraycopy (buf, 0, total, len, c); - len += c; - } - setResponseEntityBody (total, len); - } - - /* chunked */ - - /** - * Set the entity response body with the given array of strings - * The content encoding is set to "chunked" and each array element - * is sent as one chunk. - * @param body the array of string chunks to send in the response - */ - public void setResponseEntityBody (String[] body) { - StringBuffer buf = new StringBuffer (); - int len = 0; - for (int i=0; i null); } - public static void startHttpServer() throws IOException { + public static void startHttpServer() throws Exception { // Both the https server and the proxy let the // system pick up an ephemeral port. httpTrans = new SimpleHttpTransaction(); - server = new TestHttpsServer(httpTrans, 1, 10, 0); + // create and initialize a SSLContext + KeyStore ks = KeyStore.getInstance("JKS"); + KeyStore ts = KeyStore.getInstance("JKS"); + char[] passphrase = "passphrase".toCharArray(); + + ks.load(new FileInputStream(System.getProperty("javax.net.ssl.keyStore")), passphrase); + ts.load(new FileInputStream(System.getProperty("javax.net.ssl.trustStore")), passphrase); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, passphrase); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ts); + + SSLContext sslCtx = SSLContext.getInstance("TLS"); + + sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + server = HttpsServer.create(new InetSocketAddress(firstNonLoAddress, 0), 10); + server.setHttpsConfigurator(new HttpsConfigurator(sslCtx)); + server.createContext("/", httpTrans); + server.setExecutor(Executors.newSingleThreadExecutor()); + server.start(); proxy = new TunnelProxy(1, 10, 0); } public static void makeHttpCall() throws Exception { - System.out.println("https server listen on: " + server.getLocalPort()); + System.out.println("https server listen on: " + server.getAddress().getPort()); System.out.println("https proxy listen on: " + proxy.getLocalPort()); URL url = new URL("https" , firstNonLoAddress.getHostAddress(), - server.getLocalPort(), "/"); + server.getAddress().getPort(), "/"); HttpURLConnection uc = (HttpURLConnection)url.openConnection(); System.out.println(uc.getResponseCode()); + if(uc.getResponseCode() != 200) { + uc.disconnect(); + throw new RuntimeException("Test failed : bad http request with response code : "+ uc.getResponseCode()); + } uc.disconnect(); } @@ -160,31 +195,21 @@ public boolean verify(String hostname, SSLSession session) { } } -class SimpleHttpTransaction implements HttpCallback { - public boolean hasBadRequest = false; +class SimpleHttpTransaction implements HttpHandler { /* * Our http server which simply redirect first call */ - public void request(HttpTransaction trans) { + public void handle(HttpExchange trans) { try { String path = trans.getRequestURI().getPath(); if (path.equals("/")) { // the first call, redirect it String location = "/redirect"; - trans.addResponseHeader("Location", location); - trans.sendResponse(302, "Moved Temporarily"); + trans.getResponseHeaders().set("Location", location); + trans.sendResponseHeaders(302, -1); } else { - // if the bug exsits, it'll send 2 GET commands - // check 2nd GET here - String duplicatedGet = trans.getRequestHeader(null); - if (duplicatedGet != null && - duplicatedGet.toUpperCase().indexOf("GET") >= 0) { - trans.sendResponse(400, "Bad Request"); - hasBadRequest = true; - } else { - trans.sendResponse(200, "OK"); - } + trans.sendResponseHeaders(200, -1); } } catch (Exception e) { throw new RuntimeException(e); diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java index 82b54dfd08b..389007118fc 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,21 +29,25 @@ * @bug 7129083 * @summary Cookiemanager does not store cookies if url is read * before setting cookiemanager + * @library /test/lib * @run main/othervm CookieHttpsClientTest */ import java.net.CookieHandler; import java.net.CookieManager; import java.net.CookiePolicy; +import java.net.InetAddress; import java.net.URL; import java.io.InputStream; import java.io.IOException; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; +import jdk.test.lib.net.URIBuilder; public class CookieHttpsClientTest { static final int TIMEOUT = 10 * 1000; @@ -91,10 +95,11 @@ public class CookieHttpsClientTest { * to avoid infinite hangs. */ void doServerSide() throws Exception { + InetAddress loopback = InetAddress.getLoopbackAddress(); SSLServerSocketFactory sslssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); SSLServerSocket sslServerSocket = - (SSLServerSocket) sslssf.createServerSocket(serverPort); + (SSLServerSocket) sslssf.createServerSocket(serverPort, 0, loopback); serverPort = sslServerSocket.getLocalPort(); /* @@ -137,10 +142,17 @@ public boolean verify(String hostname, SSLSession session) { return true; }}); - URL url = new URL("https://localhost:" + serverPort +"/"); + URL url = URIBuilder.newBuilder() + .scheme("https") + .loopback() + .port(serverPort) + .path("/") + .toURL(); + + System.out.println("Client ready to connect to: " + url); // Run without a CookieHandler first - InputStream in = url.openConnection().getInputStream(); + InputStream in = url.openConnection(java.net.Proxy.NO_PROXY).getInputStream(); while (in.read() != -1); // read response body so connection can be reused // Set a CookeHandler and retest using the HttpClient from the KAC @@ -183,6 +195,10 @@ static void readOneRequest(InputStream is) throws IOException { volatile Exception serverException = null; volatile Exception clientException = null; + private boolean sslConnectionFailed() { + return clientException instanceof SSLHandshakeException; + } + public static void main(String args[]) throws Exception { String keyFilename = System.getProperty("test.src", ".") + "/" + pathToStores + @@ -229,7 +245,11 @@ public static void main(String args[]) throws Exception { */ if (separateServerThread) { if (serverThread != null) { - serverThread.join(); + // don't join the server thread if the + // client failed to connect + if (!sslConnectionFailed()) { + serverThread.join(); + } } } else { if (clientThread != null) { @@ -259,7 +279,7 @@ public static void main(String args[]) throws Exception { */ if ((local != null) && (remote != null)) { // If both failed, return the curthread's exception. - local.initCause(remote); + local.addSuppressed(remote); exception = local; } else if (local != null) { exception = local; @@ -274,7 +294,7 @@ public static void main(String args[]) throws Exception { * output it. */ if (exception != null) { - if (exception != startException) { + if (exception != startException && startException != null) { exception.addSuppressed(startException); } throw exception; @@ -323,7 +343,7 @@ public void run() { /* * Our client thread just died. */ - System.err.println("Client died..."); + System.err.println("Client died: " + e); clientException = e; } } @@ -333,6 +353,7 @@ public void run() { try { doClientSide(); } catch (Exception e) { + System.err.println("Client died: " + e); clientException = e; } } diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java index cb5136782ab..1b34c3e3460 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -32,12 +32,14 @@ * @summary sun.net.client.defaultConnectTimeout should work with * HttpsURLConnection; HTTP client: Connect and read timeouts; * Https needs to support new tiger features that went into http + * @library /test/lib * @run main/othervm ReadTimeout */ import java.io.*; import java.net.*; import javax.net.ssl.*; +import jdk.test.lib.net.URIBuilder; public class ReadTimeout { @@ -93,10 +95,11 @@ public class ReadTimeout { * to avoid infinite hangs. */ void doServerSide() throws Exception { + InetAddress loopback = InetAddress.getLoopbackAddress(); SSLServerSocketFactory sslssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); SSLServerSocket sslServerSocket = - (SSLServerSocket) sslssf.createServerSocket(serverPort); + (SSLServerSocket) sslssf.createServerSocket(serverPort, 0, loopback); serverPort = sslServerSocket.getLocalPort(); /* @@ -163,7 +166,11 @@ void doClientSide() throws Exception { } HttpsURLConnection http = null; try { - URL url = new URL("https://localhost:" + serverPort); + URL url = URIBuilder.newBuilder() + .scheme("https") + .loopback() + .port(serverPort) + .toURL(); // set read timeout through system property System.setProperty("sun.net.client.defaultReadTimeout", "2000"); @@ -184,7 +191,11 @@ void doClientSide() throws Exception { } try { - URL url = new URL("https://localhost:" + serverPort); + URL url = URIBuilder.newBuilder() + .scheme("https") + .loopback() + .port(serverPort) + .toURL(); HttpsURLConnection.setDefaultHostnameVerifier( new NameVerifier()); @@ -239,6 +250,10 @@ public boolean verify(String hostname, SSLSession session) { volatile Exception serverException = null; volatile Exception clientException = null; + private boolean sslConnectionFailed() { + return clientException instanceof SSLHandshakeException; + } + public static void main(String[] args) throws Exception { String keyFilename = System.getProperty("test.src", "./") + "/" + pathToStores + @@ -282,7 +297,9 @@ public static void main(String[] args) throws Exception { * Wait for other side to close down. */ if (separateServerThread) { - serverThread.join(); + if (!sslConnectionFailed()) { + serverThread.join(); + } } else { clientThread.join(); } diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Redirect.java b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Redirect.java index eacabdd9961..33481203aa0 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Redirect.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Redirect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -26,6 +26,7 @@ * @bug 4423074 * @summary Need to rebase all the duplicated classes from Merlin. * This test will check out http POST + * @library /test/lib * @run main/othervm Redirect * * SunJSSE does not support dynamic system properties, no way to re-use @@ -35,6 +36,7 @@ import java.io.*; import java.net.*; import javax.net.ssl.*; +import jdk.test.lib.net.URIBuilder; public class Redirect { @@ -95,10 +97,11 @@ public class Redirect { * to avoid infinite hangs. */ void doServerSide() throws Exception { + InetAddress loopback = InetAddress.getLoopbackAddress(); SSLServerSocketFactory sslssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); SSLServerSocket sslServerSocket = - (SSLServerSocket) sslssf.createServerSocket(serverPort); + (SSLServerSocket) sslssf.createServerSocket(serverPort, 0, loopback); serverPort = sslServerSocket.getLocalPort(); /* @@ -154,7 +157,11 @@ void doClientSide() throws Exception { } // Send HTTP POST request to server - URL url = new URL("https://localhost:"+serverPort); + URL url = URIBuilder.newBuilder() + .scheme("https") + .loopback() + .port(serverPort) + .toURL(); HttpsURLConnection.setDefaultHostnameVerifier( new NameVerifier()); @@ -190,6 +197,10 @@ public boolean verify(String hostname, SSLSession session) { volatile Exception serverException = null; volatile Exception clientException = null; + private boolean sslConnectionFailed() { + return clientException instanceof SSLHandshakeException; + } + public static void main(String[] args) throws Exception { String keyFilename = System.getProperty("test.src", "./") + "/" + pathToStores + @@ -233,7 +244,9 @@ public static void main(String[] args) throws Exception { * Wait for other side to close down. */ if (separateServerThread) { - serverThread.join(); + if (!sslConnectionFailed()) { + serverThread.join(); + } } else { clientThread.join(); } diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java index 44528ef9e92..a5d5441ee90 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.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 @@ -25,12 +25,27 @@ * */ -import java.net.*; -import java.io.*; -import java.nio.*; -import java.nio.channels.*; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.BufferOverflowException; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Set; + import sun.net.www.MessageHeader; -import java.util.*; public class TunnelProxy { @@ -43,7 +58,6 @@ public class TunnelProxy { * Create a TunnelProxy instance with the specified callback object * for handling requests. One thread is created to handle requests, * and up to ten TCP connections will be handled simultaneously. - * @param cb the callback object which is invoked to handle each * incoming request */ @@ -55,8 +69,6 @@ public TunnelProxy () throws IOException { * Create a TunnelProxy instance with the specified number of * threads and maximum number of connections per thread. This functions * the same as the 4 arg constructor, where the port argument is set to zero. - * @param cb the callback object which is invoked to handle each - * incoming request * @param threads the number of threads to create to handle requests * in parallel * @param cperthread the number of simultaneous TCP connections to @@ -74,8 +86,6 @@ public TunnelProxy (int threads, int cperthread) * the specified port. The specified number of threads are created to * handle incoming requests, and each thread is allowed * to handle a number of simultaneous TCP connections. - * @param cb the callback object which is invoked to handle - * each incoming request * @param threads the number of threads to create to handle * requests in parallel * @param cperthread the number of simultaneous TCP connections @@ -228,7 +238,6 @@ boolean consume (SocketChannel chan) { /* return true if the connection is closed, false otherwise */ private boolean read (SocketChannel chan, SelectionKey key) { - HttpTransaction msg; boolean res; try { InputStream is = new BufferedInputStream (new NioInputStream (chan)); diff --git a/test/jdk/sun/net/www/protocol/https/TestHttpsServer.java b/test/jdk/sun/net/www/protocol/https/TestHttpsServer.java deleted file mode 100644 index 178ec9c7255..00000000000 --- a/test/jdk/sun/net/www/protocol/https/TestHttpsServer.java +++ /dev/null @@ -1,933 +0,0 @@ -/* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.net.*; -import java.io.*; -import java.nio.*; -import java.nio.channels.*; -import sun.net.www.MessageHeader; -import java.util.*; -import javax.net.ssl.*; -import javax.net.ssl.SSLEngineResult.*; -import java.security.*; - -/** - * This class implements a simple HTTPS server. It uses multiple threads to - * handle connections in parallel, and will spin off a new thread to handle - * each request. (this is easier to implement with SSLEngine) - *

          - * It must be instantiated with a {@link HttpCallback} object to which - * requests are given and must be handled. - *

          - * Simple synchronization between the client(s) and server can be done - * using the {@link #waitForCondition(String)}, {@link #setCondition(String)} and - * {@link #rendezvous(String,int)} methods. - * - * NOTE NOTE NOTE NOTE NOTE NOTE NOTE - * - * If you make a change in here, please don't forget to make the - * corresponding change in the J2SE equivalent. - * - * NOTE NOTE NOTE NOTE NOTE NOTE NOTE - */ - -public class TestHttpsServer { - - ServerSocketChannel schan; - int threads; - int cperthread; - HttpCallback cb; - Server[] servers; - - // ssl related fields - static SSLContext sslCtx; - - /** - * Create a TestHttpsServer instance with the specified callback object - * for handling requests. One thread is created to handle requests, - * and up to ten TCP connections will be handled simultaneously. - * @param cb the callback object which is invoked to handle each - * incoming request - */ - - public TestHttpsServer (HttpCallback cb) throws IOException { - this (cb, 1, 10, 0); - } - - /** - * Create a TestHttpsServer instance with the specified number of - * threads and maximum number of connections per thread. This functions - * the same as the 4 arg constructor, where the port argument is set to zero. - * @param cb the callback object which is invoked to handle each - * incoming request - * @param threads the number of threads to create to handle requests - * in parallel - * @param cperthread the number of simultaneous TCP connections to - * handle per thread - */ - - public TestHttpsServer (HttpCallback cb, int threads, int cperthread) - throws IOException { - this (cb, threads, cperthread, 0); - } - - /** - * Create a TestHttpsServer instance with the specified number - * of threads and maximum number of connections per thread and running on - * the specified port. The specified number of threads are created to - * handle incoming requests, and each thread is allowed - * to handle a number of simultaneous TCP connections. - * @param cb the callback object which is invoked to handle - * each incoming request - * @param threads the number of threads to create to handle - * requests in parallel - * @param cperthread the number of simultaneous TCP connections - * to handle per thread - * @param port the port number to bind the server to. Zero - * means choose any free port. - */ - - public TestHttpsServer (HttpCallback cb, int threads, int cperthread, int port) - throws IOException { - schan = ServerSocketChannel.open (); - InetSocketAddress addr = new InetSocketAddress (port); - schan.socket().bind (addr); - this.threads = threads; - this.cb = cb; - this.cperthread = cperthread; - - try { - // create and initialize a SSLContext - KeyStore ks = KeyStore.getInstance("JKS"); - KeyStore ts = KeyStore.getInstance("JKS"); - char[] passphrase = "passphrase".toCharArray(); - - ks.load(new FileInputStream(System.getProperty("javax.net.ssl.keyStore")), passphrase); - ts.load(new FileInputStream(System.getProperty("javax.net.ssl.trustStore")), passphrase); - - KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); - kmf.init(ks, passphrase); - - TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); - tmf.init(ts); - - sslCtx = SSLContext.getInstance("TLS"); - - sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - - servers = new Server [threads]; - for (int i=0; i 0 && ((c=is.read (buf, off, remain))>0)) { - remain -= c; - off += c; - } - return buf; - } - - private void readCRLF(InputStream is) throws IOException { - int cr = is.read(); - int lf = is.read(); - - if (((cr & 0xff) != 0x0d) || - ((lf & 0xff) != 0x0a)) { - throw new IOException( - "Expected : got '" + cr + "/" + lf + "'"); - } - } - - byte[] readChunkedData (InputStream is) throws IOException { - LinkedList l = new LinkedList (); - int total = 0; - for (int len=readChunkLen(is); len!=0; len=readChunkLen(is)) { - l.add (readNormalData(is, len)); - total += len; - readCRLF(is); // CRLF at end of chunk - } - readCRLF(is); // CRLF at end of Chunked Stream. - byte[] buf = new byte [total]; - Iterator i = l.iterator(); - int x = 0; - while (i.hasNext()) { - byte[] b = (byte[])i.next(); - System.arraycopy (b, 0, buf, x, b.length); - x += b.length; - } - return buf; - } - - private int readChunkLen (InputStream is) throws IOException { - int c, len=0; - boolean done=false, readCR=false; - while (!done) { - c = is.read (); - if (c == '\n' && readCR) { - done = true; - } else { - if (c == '\r' && !readCR) { - readCR = true; - } else { - int x=0; - if (c >= 'a' && c <= 'f') { - x = c - 'a' + 10; - } else if (c >= 'A' && c <= 'F') { - x = c - 'A' + 10; - } else if (c >= '0' && c <= '9') { - x = c - '0'; - } - len = len * 16 + x; - } - } - } - return len; - } - - private String readLine (InputStream is) throws IOException { - boolean done=false, readCR=false; - byte[] b = new byte [512]; - int c, l = 0; - - while (!done) { - c = is.read (); - if (c == '\n' && readCR) { - done = true; - } else { - if (c == '\r' && !readCR) { - readCR = true; - } else { - b[l++] = (byte)c; - } - } - } - return new String (b); - } - - /** close the channel associated with the current key by: - * 1. shutdownOutput (send a FIN) - * 2. mark the key so that incoming data is to be consumed and discarded - * 3. After a period, close the socket - */ - - synchronized void orderlyCloseChannel (SocketChannel ch) throws IOException { - ch.socket().shutdownOutput(); - } - - synchronized void abortiveCloseChannel (SocketChannel ch) throws IOException { - Socket s = ch.socket (); - s.setSoLinger (true, 0); - ch.close(); - } - } - - - /** - * Implements blocking reading semantics on top of a non-blocking channel - */ - - static class NioInputStream extends InputStream { - SSLEngine sslEng; - SocketChannel channel; - Selector selector; - ByteBuffer inNetBB; - ByteBuffer inAppBB; - SelectionKey key; - int available; - byte[] one; - boolean closed; - ByteBuffer markBuf; /* reads may be satisifed from this buffer */ - boolean marked; - boolean reset; - int readlimit; - - public NioInputStream (SocketChannel chan, SSLEngine sslEng, ByteBuffer inNetBB, ByteBuffer inAppBB) throws IOException { - this.sslEng = sslEng; - this.channel = chan; - selector = Selector.open(); - this.inNetBB = inNetBB; - this.inAppBB = inAppBB; - key = chan.register (selector, SelectionKey.OP_READ); - available = 0; - one = new byte[1]; - closed = marked = reset = false; - } - - public synchronized int read (byte[] b) throws IOException { - return read (b, 0, b.length); - } - - public synchronized int read () throws IOException { - return read (one, 0, 1); - } - - public synchronized int read (byte[] b, int off, int srclen) throws IOException { - - int canreturn, willreturn; - - if (closed) - return -1; - - if (reset) { /* satisfy from markBuf */ - canreturn = markBuf.remaining (); - willreturn = canreturn>srclen ? srclen : canreturn; - markBuf.get(b, off, willreturn); - if (canreturn == willreturn) { - reset = false; - } - } else { /* satisfy from channel */ - canreturn = available(); - if (canreturn == 0) { - block (); - canreturn = available(); - } - willreturn = canreturn>srclen ? srclen : canreturn; - inAppBB.get(b, off, willreturn); - available -= willreturn; - - if (marked) { /* copy into markBuf */ - try { - markBuf.put (b, off, willreturn); - } catch (BufferOverflowException e) { - marked = false; - } - } - } - return willreturn; - } - - public synchronized int available () throws IOException { - if (closed) - throw new IOException ("Stream is closed"); - - if (reset) - return markBuf.remaining(); - - if (available > 0) - return available; - - inAppBB.clear (); - int bytes = channel.read (inNetBB); - - int needed = sslEng.getSession().getApplicationBufferSize(); - if (needed > inAppBB.remaining()) { - inAppBB = ByteBuffer.allocate(needed); - } - inNetBB.flip(); - SSLEngineResult result = sslEng.unwrap(inNetBB, inAppBB); - inNetBB.compact(); - available = result.bytesProduced(); - - if (available > 0) - inAppBB.flip(); - else if (available == -1) - throw new IOException ("Stream is closed"); - return available; - } - - /** - * block() only called when available==0 and buf is empty - */ - private synchronized void block () throws IOException { - //assert available == 0; - int n = selector.select (); - //assert n == 1; - selector.selectedKeys().clear(); - available (); - } - - public void close () throws IOException { - if (closed) - return; - channel.close (); - closed = true; - } - - public synchronized void mark (int readlimit) { - if (closed) - return; - this.readlimit = readlimit; - markBuf = ByteBuffer.allocate (readlimit); - marked = true; - reset = false; - } - - public synchronized void reset () throws IOException { - if (closed ) - return; - if (!marked) - throw new IOException ("Stream not marked"); - marked = false; - reset = true; - markBuf.flip (); - } - } - - static class NioOutputStream extends OutputStream { - SSLEngine sslEng; - SocketChannel channel; - ByteBuffer outNetBB; - ByteBuffer outAppBB; - SelectionKey key; - Selector selector; - boolean closed; - byte[] one; - - public NioOutputStream (SocketChannel channel, SSLEngine sslEng, ByteBuffer outNetBB, ByteBuffer outAppBB) throws IOException { - this.sslEng = sslEng; - this.channel = channel; - this.outNetBB = outNetBB; - this.outAppBB = outAppBB; - selector = Selector.open (); - key = channel.register (selector, SelectionKey.OP_WRITE); - closed = false; - one = new byte [1]; - } - - public synchronized void write (int b) throws IOException { - one[0] = (byte)b; - write (one, 0, 1); - } - - public synchronized void write (byte[] b) throws IOException { - write (b, 0, b.length); - } - - public synchronized void write (byte[] b, int off, int len) throws IOException { - if (closed) - throw new IOException ("stream is closed"); - - outAppBB = ByteBuffer.allocate (len); - outAppBB.put (b, off, len); - outAppBB.flip (); - int n; - outNetBB.clear(); - int needed = sslEng.getSession().getPacketBufferSize(); - if (outNetBB.capacity() < needed) { - outNetBB = ByteBuffer.allocate(needed); - } - SSLEngineResult ret = sslEng.wrap(outAppBB, outNetBB); - outNetBB.flip(); - int newLen = ret.bytesProduced(); - while ((n = channel.write (outNetBB)) < newLen) { - newLen -= n; - if (newLen == 0) - return; - selector.select (); - selector.selectedKeys().clear (); - } - } - - public void close () throws IOException { - if (closed) - return; - channel.close (); - closed = true; - } - } - - /** - * Utilities for synchronization. A condition is - * identified by a string name, and is initialized - * upon first use (ie. setCondition() or waitForCondition()). Threads - * are blocked until some thread calls (or has called) setCondition() for the same - * condition. - *

          - * A rendezvous built on a condition is also provided for synchronizing - * N threads. - */ - - private static HashMap conditions = new HashMap(); - - /* - * Modifiable boolean object - */ - private static class BValue { - boolean v; - } - - /* - * Modifiable int object - */ - private static class IValue { - int v; - IValue (int i) { - v =i; - } - } - - - private static BValue getCond (String condition) { - synchronized (conditions) { - BValue cond = (BValue) conditions.get (condition); - if (cond == null) { - cond = new BValue(); - conditions.put (condition, cond); - } - return cond; - } - } - - /** - * Set the condition to true. Any threads that are currently blocked - * waiting on the condition, will be unblocked and allowed to continue. - * Threads that subsequently call waitForCondition() will not block. - * If the named condition did not exist prior to the call, then it is created - * first. - */ - - public static void setCondition (String condition) { - BValue cond = getCond (condition); - synchronized (cond) { - if (cond.v) { - return; - } - cond.v = true; - cond.notifyAll(); - } - } - - /** - * If the named condition does not exist, then it is created and initialized - * to false. If the condition exists or has just been created and its value - * is false, then the thread blocks until another thread sets the condition. - * If the condition exists and is already set to true, then this call returns - * immediately without blocking. - */ - - public static void waitForCondition (String condition) { - BValue cond = getCond (condition); - synchronized (cond) { - if (!cond.v) { - try { - cond.wait(); - } catch (InterruptedException e) {} - } - } - } - - /* conditions must be locked when accessing this */ - static HashMap rv = new HashMap(); - - /** - * Force N threads to rendezvous (ie. wait for each other) before proceeding. - * The first thread(s) to call are blocked until the last - * thread makes the call. Then all threads continue. - *

          - * All threads that call with the same condition name, must use the same value - * for N (or the results may be not be as expected). - *

          - * Obviously, if fewer than N threads make the rendezvous then the result - * will be a hang. - */ - - public static void rendezvous (String condition, int N) { - BValue cond; - IValue iv; - String name = "RV_"+condition; - - /* get the condition */ - - synchronized (conditions) { - cond = (BValue)conditions.get (name); - if (cond == null) { - /* we are first caller */ - if (N < 2) { - throw new RuntimeException ("rendezvous must be called with N >= 2"); - } - cond = new BValue (); - conditions.put (name, cond); - iv = new IValue (N-1); - rv.put (name, iv); - } else { - /* already initialised, just decrement the counter */ - iv = (IValue) rv.get (name); - iv.v --; - } - } - - if (iv.v > 0) { - waitForCondition (name); - } else { - setCondition (name); - synchronized (conditions) { - clearCondition (name); - rv.remove (name); - } - } - } - - /** - * If the named condition exists and is set then remove it, so it can - * be re-initialized and used again. If the condition does not exist, or - * exists but is not set, then the call returns without doing anything. - * Note, some higher level synchronization - * may be needed between clear and the other operations. - */ - - public static void clearCondition(String condition) { - BValue cond; - synchronized (conditions) { - cond = (BValue) conditions.get (condition); - if (cond == null) { - return; - } - synchronized (cond) { - if (cond.v) { - conditions.remove (condition); - } - } - } - } -} diff --git a/test/jdk/sun/security/jgss/spnego/NotPreferredMech.java b/test/jdk/sun/security/jgss/spnego/NotPreferredMech.java index d057e95a695..93a3dec8c91 100644 --- a/test/jdk/sun/security/jgss/spnego/NotPreferredMech.java +++ b/test/jdk/sun/security/jgss/spnego/NotPreferredMech.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8048194 + * @bug 8048194 8242151 * @modules java.base/sun.security.util * java.security.jgss/sun.security.jgss * java.security.jgss/sun.security.jgss.spnego:+open @@ -57,7 +57,7 @@ public static void main(String[] argv) throws Exception { mechTypeList.write(DerValue.tag_Sequence, mech); // Generates a NegTokenInit mechToken field for 1.2.3.4 mech - GSSHeader h1 = new GSSHeader(new ObjectIdentifier("1.2.3.4"), 1); + GSSHeader h1 = new GSSHeader(ObjectIdentifier.of("1.2.3.4"), 1); ByteArrayOutputStream bout = new ByteArrayOutputStream(); h1.encode(bout); bout.write(new byte[1]); @@ -78,7 +78,7 @@ public static void main(String[] argv) throws Exception { // and wraps it into a GSSToken GSSHeader h = new GSSHeader( - new ObjectIdentifier(GSSUtil.GSS_SPNEGO_MECH_OID.toString()), + ObjectIdentifier.of(GSSUtil.GSS_SPNEGO_MECH_OID.toString()), spnegoToken.length); bout = new ByteArrayOutputStream(); h.encode(bout); diff --git a/test/jdk/sun/security/krb5/auto/Unavailable.java b/test/jdk/sun/security/krb5/auto/Unavailable.java new file mode 100644 index 00000000000..0c50cd9963d --- /dev/null +++ b/test/jdk/sun/security/krb5/auto/Unavailable.java @@ -0,0 +1,80 @@ +/* + * 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 8274205 + * @summary Handle KDC_ERR_SVC_UNAVAILABLE error code from KDC + * @library /test/lib + * @compile -XDignore.symbol.file Unavailable.java + * @run main jdk.test.lib.FileInstaller TestHosts TestHosts + * @run main/othervm -Djdk.net.hosts.file=TestHosts Unavailable + */ + +import sun.security.krb5.Config; +import sun.security.krb5.PrincipalName; +import sun.security.krb5.internal.KRBError; +import sun.security.krb5.internal.KerberosTime; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Locale; + +public class Unavailable { + + public static void main(String[] args) throws Exception { + + // Good KDC + KDC kdc1 = KDC.create(OneKDC.REALM); + kdc1.addPrincipal(OneKDC.USER, OneKDC.PASS); + kdc1.addPrincipalRandKey("krbtgt/" + OneKDC.REALM); + + // The "not available" KDC + KDC kdc2 = new KDC(OneKDC.REALM, "kdc." + OneKDC.REALM.toLowerCase(Locale.US), 0, true) { + @Override + protected byte[] processAsReq(byte[] in) throws Exception { + KRBError err = new KRBError(null, null, null, + KerberosTime.now(), 0, + 29, // KDC_ERR_SVC_UNAVAILABLE + null, new PrincipalName("krbtgt/" + OneKDC.REALM), + null, null); + return err.asn1Encode(); + } + }; + + Files.write(Path.of(OneKDC.KRB5_CONF), String.format( + "[libdefaults]\n" + + "default_realm = RABBIT.HOLE\n" + + "\n" + + "[realms]\n" + + "RABBIT.HOLE = {\n" + + " kdc = kdc.rabbit.hole:%d\n" + + " kdc = kdc.rabbit.hole:%d\n" + + "}\n", + kdc2.getPort(), kdc1.getPort()).getBytes()); + System.setProperty("java.security.krb5.conf", OneKDC.KRB5_CONF); + Config.refresh(); + + Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); + } +} diff --git a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java index 9d375e5365b..8e22aab9b28 100644 --- a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java +++ b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java @@ -28,7 +28,7 @@ * 8209452 8209506 8210432 8195793 8216577 8222089 8222133 8222137 8222136 * 8223499 8225392 8232019 8234245 8233223 8225068 8225069 8243321 8243320 * 8243559 8225072 8258630 8259312 8256421 8225081 8225082 8225083 8245654 - * 8305975 8304760 8307134 + * 8305975 8304760 8307134 8295894 8314960 * @summary Check root CA entries in cacerts file */ import java.io.ByteArrayInputStream; @@ -52,8 +52,7 @@ public class VerifyCACerts { // SHA-256 of cacerts, can be generated with // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95 private static final String CHECKSUM - = "72:C7:B8:9E:54:94:D2:D9:C0:E5:9F:F7:C3:8C:3B:18:D7:42:23:82:51:F2:AD:A1:14:26:E0:4A:F2:5F:AE:80"; - + = "88:72:92:56:FF:E5:A3:E4:39:98:6D:18:0B:BA:CC:0B:66:CB:1D:6D:52:CE:D7:C8:AD:63:B7:F1:5F:02:24:52"; // map of cert alias to SHA-256 fingerprint @SuppressWarnings("serial") private static final Map FINGERPRINT_MAP = new HashMap<>() { @@ -158,8 +157,6 @@ public class VerifyCACerts { "18:F1:FC:7F:20:5D:F8:AD:DD:EB:7F:E0:07:DD:57:E3:AF:37:5A:9C:4D:8D:73:54:6B:F4:F1:FE:D1:E1:8D:35"); put("quovadisrootca3g3 [jdk]", "88:EF:81:DE:20:2E:B0:18:45:2E:43:F8:64:72:5C:EA:5F:BD:1F:C2:D9:D2:05:73:07:09:C5:D8:B8:69:0F:46"); - put("secomscrootca1 [jdk]", - "E7:5E:72:ED:9F:56:0E:EC:6E:B4:80:00:73:A4:3F:C3:AD:19:19:5A:39:22:82:01:78:95:97:4A:99:02:6B:6C"); put("secomscrootca2 [jdk]", "51:3B:2C:EC:B8:10:D4:CD:E5:DD:85:39:1A:DF:C6:C2:DD:60:D8:7B:B7:36:D2:B5:21:48:4A:A4:7A:0E:BE:F6"); put("swisssigngoldg2ca [jdk]", @@ -252,6 +249,8 @@ public class VerifyCACerts { "34:D8:A7:3E:E2:08:D9:BC:DB:0D:95:65:20:93:4B:4E:40:E6:94:82:59:6E:8B:6F:73:C8:42:6B:01:0A:6F:48"); put("gtsrootecccar4 [jdk]", "34:9D:FA:40:58:C5:E2:63:12:3B:39:8A:E7:95:57:3C:4E:13:13:C8:3F:E6:8F:93:55:6C:D5:E8:03:1B:3C:7D"); + put("certignarootca [jdk]", + "D4:8D:3D:23:EE:DB:50:A4:59:E5:51:97:60:1C:27:77:4B:9D:7B:18:C9:4D:5A:05:95:11:A1:02:50:B9:31:68"); } }; @@ -290,8 +289,8 @@ public static void main(String[] args) throws Exception { String checksum = toHexString(md.digest(data)); if (!checksum.equals(CHECKSUM)) { atLeastOneFailed = true; - System.err.println("ERROR: wrong checksum" + checksum); - System.err.println("Expected checksum" + CHECKSUM); + System.err.println("ERROR: wrong checksum " + checksum); + System.err.println("Expected checksum " + CHECKSUM); } KeyStore ks = KeyStore.getInstance("JKS"); diff --git a/test/jdk/sun/security/pkcs/pkcs10/PKCS10AttrEncoding.java b/test/jdk/sun/security/pkcs/pkcs10/PKCS10AttrEncoding.java index d9ecc2bf435..72457f4a4d9 100644 --- a/test/jdk/sun/security/pkcs/pkcs10/PKCS10AttrEncoding.java +++ b/test/jdk/sun/security/pkcs/pkcs10/PKCS10AttrEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8048357 + * @bug 8048357 8242151 * @summary test DER encoding of PKCS10 attributes * @modules java.base/sun.security.pkcs * java.base/sun.security.pkcs10 @@ -62,7 +62,7 @@ public static void main(String[] args) throws Exception { // initializations int len = ids.length; Object[] values = { - new ObjectIdentifier("1.2.3.4"), + ObjectIdentifier.of("1.2.3.4"), new GregorianCalendar(1970, 1, 25, 8, 56, 7).getTime(), "challenging" }; diff --git a/test/jdk/sun/security/pkcs/pkcs10/PKCS10AttributeReader.java b/test/jdk/sun/security/pkcs/pkcs10/PKCS10AttributeReader.java index aef650c68a5..c4f8c9d0d4b 100644 --- a/test/jdk/sun/security/pkcs/pkcs10/PKCS10AttributeReader.java +++ b/test/jdk/sun/security/pkcs/pkcs10/PKCS10AttributeReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8048357 + * @bug 8048357 8242151 * @summary Read in a file containing a DER encoded PKCS10 certificate request, * flanked with "begin" and "end" lines. * @modules java.base/sun.security.pkcs @@ -86,7 +86,7 @@ public static void main(String[] args) throws Exception { put(PKCS9Attribute.CHALLENGE_PASSWORD_OID, "GuessWhoAmI"); put(PKCS9Attribute.SIGNING_TIME_OID, new Date(861720610000L)); put(PKCS9Attribute.CONTENT_TYPE_OID, - new ObjectIdentifier("1.9.50.51.52")); + ObjectIdentifier.of("1.9.50.51.52")); } }; diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java b/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java index 55806f7723d..413566778f8 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java @@ -30,12 +30,13 @@ * @summary Known Answer Test for AES cipher with GCM mode support in * PKCS11 provider. */ -import java.security.*; -import javax.crypto.*; -import javax.crypto.spec.*; -import java.math.*; - -import java.util.*; +import java.security.GeneralSecurityException; +import java.security.Provider; +import java.util.Arrays; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; public class TestKATForGCM extends PKCS11Test { @@ -307,15 +308,21 @@ public void main(Provider p) throws Exception { System.out.println("Test Passed!"); } } catch (Exception e) { - double ver = getNSSInfo("nss"); - if (ver < 3.251d && p.getName().contains("SunPKCS11-NSS") && - System.getProperty("os.name").equals("SunOS")) { - // buggy behaviour from solaris on 11.2 OS (nss < 3.251) - System.out.println("Skipping: SunPKCS11-NSS: Old NSS: " + ver); - return; // OK - } else { - throw e; + System.out.println("Exception occured using " + p.getName() + " version " + p.getVersionStr()); + + if (isNSS(p)) { + double ver = getNSSInfo("nss"); + String osName = System.getProperty("os.name"); + if (ver < 3.251d && osName.equals("SunOS")) { + // buggy behaviour from solaris on 11.2 OS (nss < 3.251) + System.out.println("Skipping: SunPKCS11-NSS: Old NSS: " + ver); + return; // OK + } else if (ver > 3.139 && ver < 3.15 && osName.equals("Linux")) { + // warn about buggy behaviour on Linux with nss 3.14 + System.out.println("Warning: old NSS " + ver + " might be problematic, consider upgrading it"); + } } + throw e; } } } diff --git a/test/jdk/sun/security/pkcs11/PKCS11Test.java b/test/jdk/sun/security/pkcs11/PKCS11Test.java index 0c74c5bdadc..b14daf6c6d7 100644 --- a/test/jdk/sun/security/pkcs11/PKCS11Test.java +++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java @@ -988,21 +988,21 @@ protected void copyNssCertKeyToClassesDir(Path dbPath) throws IOException { @Artifact( organization = "jpg.tests.jdk.nsslib", name = "nsslib-windows_x64", - revision = "3.41-VS2017", + revision = "3.46-VS2017", extension = "zip") private static class WINDOWS_X64 { } @Artifact( organization = "jpg.tests.jdk.nsslib", name = "nsslib-windows_x86", - revision = "3.41-VS2017", + revision = "3.46-VS2017", extension = "zip") private static class WINDOWS_X86 { } @Artifact( organization = "jpg.tests.jdk.nsslib", name = "nsslib-macosx_x64", - revision = "3.41", + revision = "3.46", extension = "zip") private static class MACOSX_X64 { } diff --git a/test/jdk/sun/security/pkcs11/rsa/TestKeyFactory.java b/test/jdk/sun/security/pkcs11/rsa/TestKeyFactory.java index 2b26a52b0c8..065f22e7181 100644 --- a/test/jdk/sun/security/pkcs11/rsa/TestKeyFactory.java +++ b/test/jdk/sun/security/pkcs11/rsa/TestKeyFactory.java @@ -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 @@ -23,7 +23,7 @@ /* * @test - * @bug 4856966 + * @bug 4856966 8023980 * @summary Test KeyFactory of the new RSA provider * @author Andreas Sterbenz * @library /test/lib .. @@ -42,6 +42,84 @@ public class TestKeyFactory extends PKCS11Test { private static final char[] password = "test12".toCharArray(); + private static final String PKCS1_PRIV_STR = + // the BASE64 string between -----BEGIN RSA PRIVATE KEY----- + // and -----END RSA PRIVATE KEY----- + "MIIEowIBAAKCAQEA0OIArlYES4X1XMTLDordtN/XIWFE1wvhl40RsHWM2n99+Stp" + + "CCJCcUb5FJ2/kefj/XRwB6p5IMpIZrHZqC8XXzlX5fpiFaSu2xnk17oWUKoErW27" + + "Stm098pU2RoUxWPKVl+42a8iVp8tijNElBNFALCGi0zXOhcTxMh0q1Wk0UhMJqam" + + "v5YnCKmT4THwwGYn/KeK3M7Qa+o5MoVBHLbeT9LJgEmSluVzIh44Lh6weX0bw72P" + + "8X2praOhbzg2B343MqS/rMLw6On+0i7ccEgp23vX9G5w85q4A5FSIrk4S/pyv5sO" + + "rwjCQKBW1TS0/2iB9zNkFMj5/+h7l2oqTT7sSQIDAQABAoIBADn6sXOynoiUC1IP" + + "sck8lGOTSjSSujfyrVCSsJlJV6qCfuX9va6rS8QDjjnBu531PtxoSHxoPizy2Pvg" + + "W+kKATPGR/am9DjLuFlKq7GRjoYfWyMEdVtGaKvq9ng4fBF6LHyjHz0VFrPyhQJ6" + + "TovHeXzCguYBkzAlnbAeb/vqzs/kABbOuSHVi7DsaixCoEX9zOptFYQw/l8rh68+" + + "UF2bpNNH3jOC1uN3vZtuSwCupqtN+2Mpkx2h04Rk75vWIhrnPeMgmcd3yP4LNZMR" + + "mfaynb63RRzVkNis7+NVk016SQ1oL79mrBvy5rBg3HeCeArwvqZAmOaWsLSWHzCy" + + "zlVlMTECgYEA6JlnMpC956Qi8HX5ye4Hu2ovBdbNGtH/TMkZmColJz9P7CvNkNIb" + + "Od6mvLMydbPHkhdBUDWD4rhiCKHrf5zKju1i24YqWcvuSGotWj4/KQ3+87mLZM+7" + + "daBsJBmSEVB80sgA9ItqSgOyNoNFpiDgFnlszAfb0n9XXEzB/pwSw1UCgYEA5eXI" + + "d+eKugugP+n6CluQfyxfN6WWCzfqWToCTTxPn2i12AiEssXy+kyLjupJVLWSivdo" + + "83wD5LuxFRGc9P+aKQERPhb0AFaxf1llUCXla65/x2So5xjMvtuzgQ0OktPJqJXq" + + "hYGunctsr5rje33+7vlx4xWkrL2PrQWzJabn7SUCgYEAqw3FesY/Ik7u8u+P1xSZ" + + "0xXvptek1oiAu7NYgzLbR9WjrQc5kbsyEojPDg6qmSyxI5q+iYIRj3YRgk+xpJNl" + + "0154SQCNvKPghJiw6aDFSifkytA01tp9/a8QWCwF433RjiFPsoekjvHQ6Y34dofO" + + "xDhf7lwJKPBFCrfYIqocklECgYAIPI9OHHGP8NKw94UJ0fX/WGug5sHVbQ9sWvOy" + + "KLMBlxLMxqFadlUaOpvVZvdxnX++ktajwpGxJDhX9OWWsYGobm1buB7N1E1Prrg+" + + "gt0RWpMhZa3Xeb/8Jorr2Lfo8sWK0LQyTE8hQCSIthfoWL9FeJJn/GKF/dSj8kxU" + + "0QIGMQKBgG/8U/zZ87DzfXS81P1p+CmH474wmou4KD2/zXp/lDR9+dlIUeijlIbU" + + "P6Y5xJvT33Y40giW9irShgDHjZgw0ap11K3b2HzLImdPEaBiENo735rpLs8WLK9H" + + "+yeRbiP2y9To7sTihm9Jrkctzp6sqFtKyye1+S21X1tMz8NGfXen"; + + private static final String PKCS1_PUB_STR = + // the BASE64 string between -----BEGIN RSA PUBLIC KEY----- + // and -----END RSA PUBLIC KEY----- + "MIIBCgKCAQEA0OIArlYES4X1XMTLDordtN/XIWFE1wvhl40RsHWM2n99+StpCCJC" + + "cUb5FJ2/kefj/XRwB6p5IMpIZrHZqC8XXzlX5fpiFaSu2xnk17oWUKoErW27Stm0" + + "98pU2RoUxWPKVl+42a8iVp8tijNElBNFALCGi0zXOhcTxMh0q1Wk0UhMJqamv5Yn" + + "CKmT4THwwGYn/KeK3M7Qa+o5MoVBHLbeT9LJgEmSluVzIh44Lh6weX0bw72P8X2p" + + "raOhbzg2B343MqS/rMLw6On+0i7ccEgp23vX9G5w85q4A5FSIrk4S/pyv5sOrwjC" + + "QKBW1TS0/2iB9zNkFMj5/+h7l2oqTT7sSQIDAQAB"; + + + private static final PrivateKey CUSTOM_PRIV; + private static final PublicKey CUSTOM_PUB; + + static { + byte[] encodedPriv = Base64.getDecoder().decode(PKCS1_PRIV_STR); + CUSTOM_PRIV = new PrivateKey() { + @Override + public String getAlgorithm() { + return "RSA"; + } + @Override + public String getFormat() { + return "PKCS#1"; + } + @Override + public byte[] getEncoded() { + // skip cloning for testing key. + return encodedPriv; + } + }; + byte[] encodedPub = Base64.getDecoder().decode(PKCS1_PUB_STR); + CUSTOM_PUB = new PublicKey() { + @Override + public String getAlgorithm() { + return "RSA"; + } + @Override + public String getFormat() { + return "PKCS#1"; + } + @Override + public byte[] getEncoded() { + // skip cloning for testing key. + return encodedPub; + } + }; + } + static KeyStore getKeyStore() throws Exception { KeyStore ks; try (InputStream in = new FileInputStream(new File(BASE, "rsakeys.ks"))) { @@ -68,44 +146,64 @@ private static void testKey(Key key1, Key key2) throws Exception { throw new Exception("Format not PKCS#8"); } } - if (key1.equals(key2) == false) { - throw new Exception("Keys not equal"); + // skip equals check when key1 is custom key + if (key1 != CUSTOM_PRIV && key1 != CUSTOM_PUB) { + if (!key1.equals(key2)) { + throw new Exception("Keys not equal"); + } } - if (Arrays.equals(key1.getEncoded(), key2.getEncoded()) == false) { + // only compare encodings if keys are of the same format + if (key1.getFormat().equals(key2.getFormat()) && + !Arrays.equals(key1.getEncoded(), key2.getEncoded())) { throw new Exception("Encodings not equal"); } } - private static void testPublic(KeyFactory kf, PublicKey key) throws Exception { - System.out.println("Testing public key..."); + private static void testPublic(KeyFactory kf, PublicKey key) + throws Exception { + System.out.println("Testing " + (key == CUSTOM_PUB? "PKCS#1" : "") + + " public key..."); PublicKey key2 = (PublicKey)kf.translateKey(key); KeySpec rsaSpec = kf.getKeySpec(key, RSAPublicKeySpec.class); PublicKey key3 = kf.generatePublic(rsaSpec); KeySpec x509Spec = kf.getKeySpec(key, X509EncodedKeySpec.class); PublicKey key4 = kf.generatePublic(x509Spec); - KeySpec x509Spec2 = new X509EncodedKeySpec(key.getEncoded()); - PublicKey key5 = kf.generatePublic(x509Spec2); - testKey(key, key); + if (key != CUSTOM_PUB) { + testKey(key, key); + } testKey(key, key2); testKey(key, key3); testKey(key, key4); - testKey(key, key5); + + if (key.getFormat().equalsIgnoreCase("X.509")) { + KeySpec x509Spec2 = new X509EncodedKeySpec(key.getEncoded()); + PublicKey key5 = kf.generatePublic(x509Spec2); + testKey(key, key5); + } + } - private static void testPrivate(KeyFactory kf, PrivateKey key) throws Exception { - System.out.println("Testing private key..."); + private static void testPrivate(KeyFactory kf, PrivateKey key) + throws Exception { + System.out.println("Testing " + (key == CUSTOM_PRIV? "PKCS#1" : "") + + " private key..."); PrivateKey key2 = (PrivateKey)kf.translateKey(key); KeySpec rsaSpec = kf.getKeySpec(key, RSAPrivateCrtKeySpec.class); PrivateKey key3 = kf.generatePrivate(rsaSpec); KeySpec pkcs8Spec = kf.getKeySpec(key, PKCS8EncodedKeySpec.class); PrivateKey key4 = kf.generatePrivate(pkcs8Spec); - KeySpec pkcs8Spec2 = new PKCS8EncodedKeySpec(key.getEncoded()); - PrivateKey key5 = kf.generatePrivate(pkcs8Spec2); - testKey(key, key); + if (key != CUSTOM_PRIV) { + testKey(key, key); + } testKey(key, key2); testKey(key, key3); testKey(key, key4); - testKey(key, key5); + + if (key.getFormat().equalsIgnoreCase("PKCS#8")) { + KeySpec pkcs8Spec2 = new PKCS8EncodedKeySpec(key.getEncoded()); + PrivateKey key5 = kf.generatePrivate(pkcs8Spec2); + testKey(key, key5); + } // XXX PKCS#11 providers may not support non-CRT keys (e.g. NSS) // KeySpec rsaSpec2 = kf.getKeySpec(key, RSAPrivateKeySpec.class); @@ -145,6 +243,10 @@ public void main(Provider p) throws Exception { test(kf, ks.getCertificate(alias).getPublicKey()); } } + // repeat the test w/ PKCS#1 RSA Private Key + test(kf, CUSTOM_PRIV); + test(kf, CUSTOM_PUB); + long stop = System.currentTimeMillis(); System.out.println("All tests passed (" + (stop - start) + " ms)."); } diff --git a/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java b/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java index d85852d660d..2753904e71e 100644 --- a/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java +++ b/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8076190 8153005 8266182 + * @bug 8076190 8242151 8153005 8266182 * @summary This is java keytool <-> openssl interop test. This test generates * some openssl keystores on the fly, java operates on it and * vice versa. diff --git a/test/jdk/sun/security/pkcs12/PKCS12SameKeyId.java b/test/jdk/sun/security/pkcs12/PKCS12SameKeyId.java index bbdac6c3fc3..de563dc11f8 100644 --- a/test/jdk/sun/security/pkcs12/PKCS12SameKeyId.java +++ b/test/jdk/sun/security/pkcs12/PKCS12SameKeyId.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 6958026 + * @bug 6958026 8242151 * @summary Problem with PKCS12 keystore * @modules java.base/sun.security.pkcs * java.base/sun.security.tools.keytool @@ -75,7 +75,7 @@ public static void main(String[] args) throws Exception { AlgorithmParameters.getInstance("PBEWithSHA1AndDESede"); algParams.init(new PBEParameterSpec("12345678".getBytes(), 1024)); AlgorithmId algid = new AlgorithmId( - new ObjectIdentifier("1.2.840.113549.1.12.1.3"), algParams); + ObjectIdentifier.of("1.2.840.113549.1.12.1.3"), algParams); PBEKeySpec keySpec = new PBEKeySpec(PASSWORD); SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE"); diff --git a/test/jdk/sun/security/pkcs12/ParamsPreferences.java b/test/jdk/sun/security/pkcs12/ParamsPreferences.java index a12a79b5cc3..b790155ad94 100644 --- a/test/jdk/sun/security/pkcs12/ParamsPreferences.java +++ b/test/jdk/sun/security/pkcs12/ParamsPreferences.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -37,7 +37,7 @@ /* * @test - * @bug 8076190 8153005 8266293 + * @bug 8076190 8242151 8153005 8266293 * @library /test/lib * @modules java.base/sun.security.pkcs * java.base/sun.security.x509 diff --git a/test/jdk/sun/security/provider/SecureRandom/SHA1PRNGReseed.java b/test/jdk/sun/security/provider/SecureRandom/SHA1PRNGReseed.java index fdf6911c77a..15caef665f7 100644 --- a/test/jdk/sun/security/provider/SecureRandom/SHA1PRNGReseed.java +++ b/test/jdk/sun/security/provider/SecureRandom/SHA1PRNGReseed.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 @@ -28,14 +28,14 @@ /** * @test - * @bug 8154523 + * @bug 8154523 8247895 * @summary SHA1PRNG output should change after setSeed */ public class SHA1PRNGReseed { public static void main(String[] args) throws Exception { SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); - sr.setSeed(0); + sr.setSeed(1); sr.nextInt(); ByteArrayOutputStream bout = new ByteArrayOutputStream(); @@ -45,7 +45,7 @@ public static void main(String[] args) throws Exception { new ByteArrayInputStream(bout.toByteArray())).readObject(); int i1 = sr.nextInt(); - sr2.setSeed(1); + sr2.setSeed(2); int i2 = sr2.nextInt(); if (i1 == i2) { diff --git a/test/jdk/sun/security/rsa/TestKeyFactory.java b/test/jdk/sun/security/rsa/TestKeyFactory.java index 94a23697ea1..b17806895e5 100644 --- a/test/jdk/sun/security/rsa/TestKeyFactory.java +++ b/test/jdk/sun/security/rsa/TestKeyFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, 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,7 +23,7 @@ /** * @test - * @bug 4853305 8254717 + * @bug 4853305 8023980 8254717 * @summary Test KeyFactory of the new RSA provider * @author Andreas Sterbenz */ @@ -41,6 +41,84 @@ public class TestKeyFactory { private static final char[] password = "test12".toCharArray(); + private static final String PKCS1_PRIV_STR = + // the BASE64 string between -----BEGIN RSA PRIVATE KEY----- + // and -----END RSA PRIVATE KEY----- + "MIIEowIBAAKCAQEA0OIArlYES4X1XMTLDordtN/XIWFE1wvhl40RsHWM2n99+Stp" + + "CCJCcUb5FJ2/kefj/XRwB6p5IMpIZrHZqC8XXzlX5fpiFaSu2xnk17oWUKoErW27" + + "Stm098pU2RoUxWPKVl+42a8iVp8tijNElBNFALCGi0zXOhcTxMh0q1Wk0UhMJqam" + + "v5YnCKmT4THwwGYn/KeK3M7Qa+o5MoVBHLbeT9LJgEmSluVzIh44Lh6weX0bw72P" + + "8X2praOhbzg2B343MqS/rMLw6On+0i7ccEgp23vX9G5w85q4A5FSIrk4S/pyv5sO" + + "rwjCQKBW1TS0/2iB9zNkFMj5/+h7l2oqTT7sSQIDAQABAoIBADn6sXOynoiUC1IP" + + "sck8lGOTSjSSujfyrVCSsJlJV6qCfuX9va6rS8QDjjnBu531PtxoSHxoPizy2Pvg" + + "W+kKATPGR/am9DjLuFlKq7GRjoYfWyMEdVtGaKvq9ng4fBF6LHyjHz0VFrPyhQJ6" + + "TovHeXzCguYBkzAlnbAeb/vqzs/kABbOuSHVi7DsaixCoEX9zOptFYQw/l8rh68+" + + "UF2bpNNH3jOC1uN3vZtuSwCupqtN+2Mpkx2h04Rk75vWIhrnPeMgmcd3yP4LNZMR" + + "mfaynb63RRzVkNis7+NVk016SQ1oL79mrBvy5rBg3HeCeArwvqZAmOaWsLSWHzCy" + + "zlVlMTECgYEA6JlnMpC956Qi8HX5ye4Hu2ovBdbNGtH/TMkZmColJz9P7CvNkNIb" + + "Od6mvLMydbPHkhdBUDWD4rhiCKHrf5zKju1i24YqWcvuSGotWj4/KQ3+87mLZM+7" + + "daBsJBmSEVB80sgA9ItqSgOyNoNFpiDgFnlszAfb0n9XXEzB/pwSw1UCgYEA5eXI" + + "d+eKugugP+n6CluQfyxfN6WWCzfqWToCTTxPn2i12AiEssXy+kyLjupJVLWSivdo" + + "83wD5LuxFRGc9P+aKQERPhb0AFaxf1llUCXla65/x2So5xjMvtuzgQ0OktPJqJXq" + + "hYGunctsr5rje33+7vlx4xWkrL2PrQWzJabn7SUCgYEAqw3FesY/Ik7u8u+P1xSZ" + + "0xXvptek1oiAu7NYgzLbR9WjrQc5kbsyEojPDg6qmSyxI5q+iYIRj3YRgk+xpJNl" + + "0154SQCNvKPghJiw6aDFSifkytA01tp9/a8QWCwF433RjiFPsoekjvHQ6Y34dofO" + + "xDhf7lwJKPBFCrfYIqocklECgYAIPI9OHHGP8NKw94UJ0fX/WGug5sHVbQ9sWvOy" + + "KLMBlxLMxqFadlUaOpvVZvdxnX++ktajwpGxJDhX9OWWsYGobm1buB7N1E1Prrg+" + + "gt0RWpMhZa3Xeb/8Jorr2Lfo8sWK0LQyTE8hQCSIthfoWL9FeJJn/GKF/dSj8kxU" + + "0QIGMQKBgG/8U/zZ87DzfXS81P1p+CmH474wmou4KD2/zXp/lDR9+dlIUeijlIbU" + + "P6Y5xJvT33Y40giW9irShgDHjZgw0ap11K3b2HzLImdPEaBiENo735rpLs8WLK9H" + + "+yeRbiP2y9To7sTihm9Jrkctzp6sqFtKyye1+S21X1tMz8NGfXen"; + + private static final String PKCS1_PUB_STR = + // the BASE64 string between -----BEGIN RSA PUBLIC KEY----- + // and -----END RSA PUBLIC KEY----- + "MIIBCgKCAQEA0OIArlYES4X1XMTLDordtN/XIWFE1wvhl40RsHWM2n99+StpCCJC" + + "cUb5FJ2/kefj/XRwB6p5IMpIZrHZqC8XXzlX5fpiFaSu2xnk17oWUKoErW27Stm0" + + "98pU2RoUxWPKVl+42a8iVp8tijNElBNFALCGi0zXOhcTxMh0q1Wk0UhMJqamv5Yn" + + "CKmT4THwwGYn/KeK3M7Qa+o5MoVBHLbeT9LJgEmSluVzIh44Lh6weX0bw72P8X2p" + + "raOhbzg2B343MqS/rMLw6On+0i7ccEgp23vX9G5w85q4A5FSIrk4S/pyv5sOrwjC" + + "QKBW1TS0/2iB9zNkFMj5/+h7l2oqTT7sSQIDAQAB"; + + + private static final PrivateKey P1_PRIV; + private static final PublicKey P1_PUB; + + static { + byte[] encodedPriv = Base64.getDecoder().decode(PKCS1_PRIV_STR); + P1_PRIV = new PrivateKey() { + @Override + public String getAlgorithm() { + return "RSA"; + } + @Override + public String getFormat() { + return "PKCS#1"; + } + @Override + public byte[] getEncoded() { + // skip cloning for testing key. + return encodedPriv; + } + }; + byte[] encodedPub = Base64.getDecoder().decode(PKCS1_PUB_STR); + P1_PUB = new PublicKey() { + @Override + public String getAlgorithm() { + return "RSA"; + } + @Override + public String getFormat() { + return "PKCS#1"; + } + @Override + public byte[] getEncoded() { + // skip cloning for testing key. + return encodedPub; + } + }; + } + static KeyStore getKeyStore() throws Exception { InputStream in = new FileInputStream(new File(BASE, "rsakeys.ks")); KeyStore ks = KeyStore.getInstance("JKS"); @@ -63,47 +141,67 @@ private static void testKey(Key key1, Key key2) throws Exception { } } else if (key1 instanceof PrivateKey) { if (key2.getFormat().equals("PKCS#8") == false) { - throw new Exception("Format not PKCS#8"); + throw new Exception("Format not PKCS#8: " + key2.getFormat()); } } - if (key1.equals(key2) == false) { - throw new Exception("Keys not equal"); + // skip equals check when key1 is custom key + if (key1 != P1_PRIV && key1 != P1_PUB) { + if (!key1.equals(key2)) { + throw new Exception("Keys not equal"); + } } - if (Arrays.equals(key1.getEncoded(), key2.getEncoded()) == false) { + + // only compare encodings if keys are of the same format + if (key1.getFormat().equals(key2.getFormat()) && + !Arrays.equals(key1.getEncoded(), key2.getEncoded())) { throw new Exception("Encodings not equal"); } } - private static void testPublic(KeyFactory kf, PublicKey key) throws Exception { - System.out.println("Testing public key..."); + private static void testPublic(KeyFactory kf, PublicKey key) + throws Exception { + System.out.println("Testing " + (key == P1_PUB? "PKCS#1" : "") + + " public key..."); + PublicKey key2 = (PublicKey)kf.translateKey(key); KeySpec rsaSpec = kf.getKeySpec(key, RSAPublicKeySpec.class); PublicKey key3 = kf.generatePublic(rsaSpec); KeySpec x509Spec = kf.getKeySpec(key, X509EncodedKeySpec.class); PublicKey key4 = kf.generatePublic(x509Spec); - KeySpec x509Spec2 = new X509EncodedKeySpec(key.getEncoded()); - PublicKey key5 = kf.generatePublic(x509Spec2); - testKey(key, key); + if (key != P1_PUB) { + testKey(key, key); + } testKey(key, key2); testKey(key, key3); testKey(key, key4); - testKey(key, key5); + + if (key.getFormat().equalsIgnoreCase("X.509")) { + KeySpec x509Spec2 = new X509EncodedKeySpec(key.getEncoded()); + PublicKey key5 = kf.generatePublic(x509Spec2); + testKey(key, key5); + } } - private static void testPrivate(KeyFactory kf, PrivateKey key) throws Exception { - System.out.println("Testing private key..."); + private static void testPrivate(KeyFactory kf, PrivateKey key) + throws Exception { + System.out.println("Testing " + (key == P1_PRIV? "PKCS#1" : "") + + " private key..."); PrivateKey key2 = (PrivateKey)kf.translateKey(key); KeySpec rsaSpec = kf.getKeySpec(key, RSAPrivateCrtKeySpec.class); PrivateKey key3 = kf.generatePrivate(rsaSpec); KeySpec pkcs8Spec = kf.getKeySpec(key, PKCS8EncodedKeySpec.class); PrivateKey key4 = kf.generatePrivate(pkcs8Spec); - KeySpec pkcs8Spec2 = new PKCS8EncodedKeySpec(key.getEncoded()); - PrivateKey key5 = kf.generatePrivate(pkcs8Spec2); - testKey(key, key); + if (key != P1_PRIV) { + testKey(key, key); + } testKey(key, key2); testKey(key, key3); testKey(key, key4); - testKey(key, key5); + if (key.getFormat().equalsIgnoreCase("PKCS#8")) { + KeySpec pkcs8Spec2 = new PKCS8EncodedKeySpec(key.getEncoded()); + PrivateKey key5 = kf.generatePrivate(pkcs8Spec2); + testKey(key, key5); + } KeySpec rsaSpec2 = kf.getKeySpec(key, RSAPrivateKeySpec.class); PrivateKey key6 = kf.generatePrivate(rsaSpec2); @@ -141,6 +239,10 @@ public static void main(String[] args) throws Exception { test(kf, ks.getCertificate(alias).getPublicKey()); } } + // repeat the test w/ PKCS#1 RSA Private Key + test(kf, P1_PRIV); + test(kf, P1_PUB); + long stop = System.currentTimeMillis(); System.out.println("All tests passed (" + (stop - start) + " ms)."); } diff --git a/test/jdk/sun/security/rsa/TestRSAOidSupport.java b/test/jdk/sun/security/rsa/TestRSAOidSupport.java new file mode 100644 index 00000000000..2cd06258609 --- /dev/null +++ b/test/jdk/sun/security/rsa/TestRSAOidSupport.java @@ -0,0 +1,78 @@ +/* + * 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. + */ + +/** + * @test + * @bug 8242897 + * @summary Ensure that RSA key factory can parse X.509 encodings containing + * non-standard RSA oid as in older JDK releases before JDK-8146293 + * @run main TestRSAOidSupport + */ + +import java.security.KeyFactory; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.X509EncodedKeySpec; +import java.security.spec.InvalidKeySpecException; + +public class TestRSAOidSupport { + + // SubjectKeyInfo DER encoding w/ Algorithm id 1.3.14.3.2.15 + // which can be used to generate RSA Public Key before PSS + // support is added + private static String DER_BYTES = + "3058300906052b0e03020f0500034b003048024100d7157c65e8f22557d8" + + "a857122cfe85bddfaba3064c21b345e2a7cdd8a6751e519ab861c5109fb8" + + "8cce45d161b9817bc0eccdc30fda69e62cc577775f2c1d66bd0203010001"; + + // utility method for converting hex string to byte array + static byte[] toByteArray(String s) { + byte[] bytes = new byte[s.length() / 2]; + for (int i = 0; i < bytes.length; i++) { + int index = i * 2; + int v = Integer.parseInt(s.substring(index, index + 2), 16); + bytes[i] = (byte) v; + } + return bytes; + } + + public static void main(String[] args) throws Exception { + X509EncodedKeySpec x509Spec = new X509EncodedKeySpec + (toByteArray(DER_BYTES)); + String keyAlgo = "RSA"; + KeyFactory kf = KeyFactory.getInstance(keyAlgo, "SunRsaSign"); + RSAPublicKey rsaKey = (RSAPublicKey) kf.generatePublic(x509Spec); + + if (rsaKey.getAlgorithm() != keyAlgo) { + throw new RuntimeException("Key algo should be " + keyAlgo + + ", but got " + rsaKey.getAlgorithm()); + } + kf = KeyFactory.getInstance("RSASSA-PSS", "SunRsaSign"); + try { + kf.generatePublic(x509Spec); + throw new RuntimeException("Should throw IKSE"); + } catch (InvalidKeySpecException ikse) { + System.out.println("Expected IKSE exception thrown"); + } + } +} + diff --git a/test/jdk/sun/security/ssl/DHKeyExchange/DHEKeySizing.java b/test/jdk/sun/security/ssl/DHKeyExchange/DHEKeySizing.java index 26e30608bdf..b008361273f 100644 --- a/test/jdk/sun/security/ssl/DHKeyExchange/DHEKeySizing.java +++ b/test/jdk/sun/security/ssl/DHKeyExchange/DHEKeySizing.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ /* * @test - * @bug 6956398 + * @bug 6956398 8301700 * @summary make ephemeral DH key match the length of the certificate key * @run main/othervm * DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1643 267 @@ -48,7 +48,7 @@ * DHEKeySizing SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA true 233 75 * * @run main/othervm -Djsse.enableFFDHE=false - * DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1387 139 + * DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1643 267 * @run main/othervm -Djsse.enableFFDHE=false * -Djdk.tls.ephemeralDHKeySize=legacy * DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1323 107 @@ -60,13 +60,13 @@ * DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1387 139 * * @run main/othervm -Djsse.enableFFDHE=false - * DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 361 139 + * DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 617 267 * @run main/othervm -Djsse.enableFFDHE=false * -Djdk.tls.ephemeralDHKeySize=legacy * DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 297 107 * @run main/othervm -Djsse.enableFFDHE=false * -Djdk.tls.ephemeralDHKeySize=matched - * DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 361 139 + * DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 617 267 * @run main/othervm -Djsse.enableFFDHE=false * -Djdk.tls.ephemeralDHKeySize=1024 * DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 361 139 @@ -93,7 +93,7 @@ * } dh_public; * } ClientDiffieHellmanPublic; * - * Fomr above structures, it is clear that if the DH key size increasing 128 + * From the above structures, it is clear that if the DH key size increases 128 * bits (16 bytes), the ServerHello series messages increases 48 bytes * (becuase dh_p, dh_g and dh_Ys each increase 16 bytes) and ClientKeyExchange * increases 16 bytes (because of the size increasing of dh_Yc). @@ -104,7 +104,7 @@ * 512-bit | 1259 bytes | 75 bytes | 233 bytes * 768-bit | 1323 bytes | 107 bytes | 297 bytes * 1024-bit | 1387 bytes | 139 bytes | 361 bytes - * 2048-bit | 1643 bytes | 267 bytes | 361 bytes + * 2048-bit | 1643 bytes | 267 bytes | 617 bytes */ import javax.net.ssl.*; diff --git a/test/jdk/sun/security/ssl/SSLContextImpl/DefaultCipherSuitePreference.java b/test/jdk/sun/security/ssl/SSLContextImpl/DefaultCipherSuitePreference.java new file mode 100644 index 00000000000..247f021f817 --- /dev/null +++ b/test/jdk/sun/security/ssl/SSLContextImpl/DefaultCipherSuitePreference.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 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. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8168261 + * @summary Use server cipher suites preference by default + * @run main/othervm DefaultCipherSuitePreference + */ + +import javax.net.SocketFactory; +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManager; + +public class DefaultCipherSuitePreference { + private static final String[] contextAlgorithms = { + "Default", "SSL", "TLS", "SSLv3", "TLSv1", + "TLSv1.1", "TLSv1.2", "TLSv1.3" + }; + + public static void main(String[] args) throws Exception { + for (String algorithm : contextAlgorithms) { + System.out.println("Checking SSLContext of " + algorithm); + SSLContext sslContext = SSLContext.getInstance(algorithm); + + // Default SSLContext is initialized automatically. + if (!algorithm.equals("Default")) { + // Use default TK, KM and random. + sslContext.init((KeyManager[])null, (TrustManager[])null, null); + } + + // + // Check SSLContext + // + // Check default SSLParameters of SSLContext + checkDefaultCipherSuitePreference( + sslContext.getDefaultSSLParameters(), + "SSLContext.getDefaultSSLParameters()"); + + // Check supported SSLParameters of SSLContext + checkDefaultCipherSuitePreference( + sslContext.getSupportedSSLParameters(), + "SSLContext.getSupportedSSLParameters()"); + + // + // Check SSLEngine + // + // Check SSLParameters of SSLEngine + SSLEngine engine = sslContext.createSSLEngine(); + engine.setUseClientMode(true); + checkDefaultCipherSuitePreference( + engine.getSSLParameters(), + "client mode SSLEngine.getSSLParameters()"); + + engine.setUseClientMode(false); + checkDefaultCipherSuitePreference( + engine.getSSLParameters(), + "server mode SSLEngine.getSSLParameters()"); + + // + // Check SSLSocket + // + // Check SSLParameters of SSLSocket + SocketFactory fac = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket)fac.createSocket(); + checkDefaultCipherSuitePreference( + socket.getSSLParameters(), + "SSLSocket.getSSLParameters()"); + + // + // Check SSLServerSocket + // + // Check SSLParameters of SSLServerSocket + SSLServerSocketFactory sf = sslContext.getServerSocketFactory(); + SSLServerSocket ssocket = (SSLServerSocket)sf.createServerSocket(); + checkDefaultCipherSuitePreference( + ssocket.getSSLParameters(), + "SSLServerSocket.getSSLParameters()"); + } + } + + private static void checkDefaultCipherSuitePreference( + SSLParameters parameters, String context) throws Exception { + if (!parameters.getUseCipherSuitesOrder()) { + throw new Exception( + "The local cipher suite preference is not honored " + + "in the connection populated SSLParameters object (" + + context + ")"); + } + } +} diff --git a/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java b/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java index 0b8eeaecf2b..58c3c4a0d3b 100644 --- a/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java +++ b/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java @@ -126,7 +126,7 @@ public static void main(String args[]) throws Exception { System.out.println("test.java.opts: " + System.getProperty("test.java.opts")); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, + ProcessBuilder pb = ProcessTools.createTestJvm( Utils.addTestJavaOpts("SSLEngineKeyLimit", "p", args[1], args[2])); diff --git a/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java index 0785b2d995a..f87effe9dce 100644 --- a/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java +++ b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java @@ -134,7 +134,7 @@ public static void main(String args[]) throws Exception { System.out.println("test.java.opts: " + System.getProperty("test.java.opts")); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, + ProcessBuilder pb = ProcessTools.createTestJvm( Utils.addTestJavaOpts("SSLSocketKeyLimit", "p", args[1], args[2])); diff --git a/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java b/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java index 8ec9a405c85..f5018fbf6a1 100644 --- a/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java +++ b/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java @@ -35,6 +35,8 @@ * @run main/manual/othervm Compatibility */ +import static java.nio.charset.StandardCharsets.UTF_8; + import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; @@ -43,12 +45,12 @@ import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; -import java.nio.file.Path; import java.nio.file.Files; +import java.nio.file.Path; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.Arrays; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.HashMap; @@ -57,19 +59,18 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; -import java.util.jar.Manifest; import java.util.jar.Attributes.Name; -import java.util.concurrent.TimeUnit; +import java.util.jar.Manifest; import java.util.stream.Collectors; import java.util.stream.IntStream; + import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.util.JarUtils; -import static java.nio.charset.StandardCharsets.UTF_8; - public class Compatibility { private static final String TEST_SRC = System.getProperty("test.src"); @@ -179,7 +180,7 @@ public static void main(String... args) throws Throwable { List signItems = test(jdkInfoList, tsaList, certList, createJars()); - boolean failed = generateReport(tsaList, signItems); + boolean failed = generateReport(jdkInfoList, tsaList, signItems); // Restores the original stdout and stderr. System.setOut(origStdOut); @@ -415,11 +416,15 @@ private static List jdkInfoList() throws Throwable { } List jdkInfoList = new ArrayList<>(); + int index = 0; for (String jdkPath : jdkList) { JdkInfo jdkInfo = "TEST_JDK".equalsIgnoreCase(jdkPath) ? TEST_JDK_INFO : new JdkInfo(jdkPath); // The JDK version must be unique. if (!jdkInfoList.contains(jdkInfo)) { + jdkInfo.index = index++; + jdkInfo.version = String.format( + "%s(%d)", jdkInfo.version, jdkInfo.index); jdkInfoList.add(jdkInfo); } else { System.out.println("The JDK version is duplicate: " + jdkPath); @@ -908,13 +913,22 @@ private static OutputAnalyzer verifyJar(String jarsignerPath, } // Generates the test result report. - private static boolean generateReport(List tsaList, + private static boolean generateReport(List jdkList, List tsaList, List signItems) throws IOException { System.out.println("Report is being generated..."); StringBuilder report = new StringBuilder(); report.append(HtmlHelper.startHtml()); report.append(HtmlHelper.startPre()); + + // Generates JDK list + report.append("JDK list:\n"); + for(JdkInfo jdkInfo : jdkList) { + report.append(String.format("%d=%s%n", + jdkInfo.index, + jdkInfo.runtimeVersion)); + } + // Generates TSA URLs report.append("TSA list:\n"); for(TsaInfo tsaInfo : tsaList) { @@ -1024,9 +1038,11 @@ private static OutputAnalyzer execTool(String toolPath, String... args) private static class JdkInfo { + private int index; private final String jdkPath; private final String jarsignerPath; - private final String version; + private final String runtimeVersion; + private String version; private final int majorVersion; private final boolean supportsTsadigestalg; @@ -1034,14 +1050,15 @@ private static class JdkInfo { private JdkInfo(String jdkPath) throws Throwable { this.jdkPath = jdkPath; - version = execJdkUtils(jdkPath, JdkUtils.M_JAVA_RUNTIME_VERSION); - if (version == null || version.isBlank()) { + jarsignerPath = jarsignerPath(jdkPath); + runtimeVersion = execJdkUtils(jdkPath, JdkUtils.M_JAVA_RUNTIME_VERSION); + if (runtimeVersion == null || runtimeVersion.isBlank()) { throw new RuntimeException( "Cannot determine the JDK version: " + jdkPath); } - majorVersion = Integer.parseInt((version.matches("^1[.].*") ? - version.substring(2) : version).replaceAll("[^0-9].*$", "")); - jarsignerPath = jarsignerPath(jdkPath); + version = execJdkUtils(jdkPath, JdkUtils.M_JAVA_VERSION); + majorVersion = Integer.parseInt((runtimeVersion.matches("^1[.].*") ? + runtimeVersion.substring(2) : runtimeVersion).replaceAll("[^0-9].*$", "")); supportsTsadigestalg = execTool(jarsignerPath, "-help") .getOutput().contains("-tsadigestalg"); } @@ -1073,7 +1090,7 @@ public int hashCode() { final int prime = 31; int result = 1; result = prime * result - + ((version == null) ? 0 : version.hashCode()); + + ((runtimeVersion == null) ? 0 : runtimeVersion.hashCode()); return result; } @@ -1086,17 +1103,17 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; JdkInfo other = (JdkInfo) obj; - if (version == null) { - if (other.version != null) + if (runtimeVersion == null) { + if (other.runtimeVersion != null) return false; - } else if (!version.equals(other.version)) + } else if (!runtimeVersion.equals(other.runtimeVersion)) return false; return true; } @Override public String toString() { - return "JdkInfo[" + version + ", " + jdkPath + "]"; + return "JdkInfo[" + runtimeVersion + ", " + jdkPath + "]"; } } diff --git a/test/jdk/sun/security/tools/jarsigner/compatibility/JdkUtils.java b/test/jdk/sun/security/tools/jarsigner/compatibility/JdkUtils.java index ff48d5b15d0..54818105b08 100644 --- a/test/jdk/sun/security/tools/jarsigner/compatibility/JdkUtils.java +++ b/test/jdk/sun/security/tools/jarsigner/compatibility/JdkUtils.java @@ -36,12 +36,18 @@ private enum Alg { KEY, SIG, DIGEST; } + static final String M_JAVA_VERSION = "javaVersion"; static final String M_JAVA_RUNTIME_VERSION = "javaRuntimeVersion"; static final String M_IS_SUPPORTED_KEYALG = "isSupportedKeyalg"; static final String M_IS_SUPPORTED_SIGALG = "isSupportedSigalg"; static final String M_IS_SUPPORTED_DIGESTALG = "isSupportedDigestalg"; // Returns the JDK build version. + static String javaVersion() { + return System.getProperty("java.version"); + } + + // Returns the JDK build runtime version. static String javaRuntimeVersion() { return System.getProperty("java.runtime.version"); } @@ -63,7 +69,9 @@ static boolean isSupportedAlg(Alg algType, String algName) { } public static void main(String[] args) { - if (M_JAVA_RUNTIME_VERSION.equals(args[0])) { + if (M_JAVA_VERSION.equals(args[0])) { + System.out.print(javaVersion()); + } else if (M_JAVA_RUNTIME_VERSION.equals(args[0])) { System.out.print(javaRuntimeVersion()); } else if (M_IS_SUPPORTED_KEYALG.equals(args[0])) { System.out.print(isSupportedAlg(Alg.KEY, args[1])); diff --git a/test/jdk/sun/security/tools/jarsigner/compatibility/SignTwice.java b/test/jdk/sun/security/tools/jarsigner/compatibility/SignTwice.java index 04b42853de6..e948eb6e8d3 100644 --- a/test/jdk/sun/security/tools/jarsigner/compatibility/SignTwice.java +++ b/test/jdk/sun/security/tools/jarsigner/compatibility/SignTwice.java @@ -36,7 +36,7 @@ * @test * @library /test/lib ../warnings * @compile Compatibility.java - * @run main/othervm/timeout=2500 + * @run main/othervm/timeout=600 * -Djava.security.properties=./java.security * -Duser.language=en * -Duser.country=US @@ -46,8 +46,8 @@ * -DtestComprehensiveJarContents=true * -DtestJarUpdate=true * -Dstrict=true - * -DkeyAlgs=EC;#RSA;#DSA; - * -DdigestAlgs=SHA-512 + * -DkeyAlgs=EC;0 + * -DdigestAlgs=SHA-256 * SignTwice */ public class SignTwice { diff --git a/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java b/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java index a7c895fa2b6..ca5f17e9079 100644 --- a/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java +++ b/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java @@ -27,6 +27,7 @@ import java.security.cert.X509Certificate; import java.util.Date; import java.util.Locale; +import java.util.TimeZone; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.util.JarUtils; @@ -46,6 +47,7 @@ public class NoTimestampTest extends Test { * and checks that proper warnings are shown. */ public static void main(String[] args) throws Throwable { + Locale reservedLocale = Locale.getDefault(); Locale.setDefault(Locale.US); @@ -61,6 +63,9 @@ public static void main(String[] args) throws Throwable { private void start() throws Throwable { String timezone = System.getProperty("user.timezone"); System.out.println(String.format("Timezone = %s", timezone)); + if (timezone != null) { + TimeZone.setDefault(TimeZone.getTimeZone(timezone)); + } // create a jar file that contains one class file Utils.createFiles(FIRST_FILE); @@ -73,10 +78,11 @@ private void start() throws Throwable { "-validity", Integer.toString(VALIDITY)); Date expirationDate = getCertExpirationDate(); + System.out.println("Cert expiration: " + expirationDate); // sign jar file OutputAnalyzer analyzer = jarsigner( - "-J-Duser.timezone=" + timezone, + userTimezoneOpt(timezone), "-keystore", KEYSTORE, "-storepass", PASSWORD, "-keypass", PASSWORD, @@ -90,7 +96,7 @@ private void start() throws Throwable { // verify signed jar analyzer = jarsigner( - "-J-Duser.timezone=" + timezone, + userTimezoneOpt(timezone), "-verify", "-keystore", KEYSTORE, "-storepass", PASSWORD, @@ -103,7 +109,7 @@ private void start() throws Throwable { // verify signed jar in strict mode analyzer = jarsigner( - "-J-Duser.timezone=" + timezone, + userTimezoneOpt(timezone), "-verify", "-strict", "-keystore", KEYSTORE, @@ -117,6 +123,10 @@ private void start() throws Throwable { System.out.println("Test passed"); } + private static String userTimezoneOpt(String timezone) { + return timezone == null ? null : "-J-Duser.timezone=" + timezone; + } + private static Date getCertExpirationDate() throws Exception { KeyStore ks = KeyStore.getInstance("JKS"); try (InputStream in = new FileInputStream(KEYSTORE)) { diff --git a/test/jdk/sun/security/tools/jarsigner/warnings/Test.java b/test/jdk/sun/security/tools/jarsigner/warnings/Test.java index 98ec45cc8b9..414caf22570 100644 --- a/test/jdk/sun/security/tools/jarsigner/warnings/Test.java +++ b/test/jdk/sun/security/tools/jarsigner/warnings/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -21,12 +21,13 @@ * questions. */ -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; /** * Base class. @@ -263,7 +264,9 @@ private OutputAnalyzer tool(String tool, String... args) throws Throwable { cmd.add(tool); cmd.add("-J-Duser.language=en"); cmd.add("-J-Duser.country=US"); - cmd.addAll(Arrays.asList(args)); + cmd.addAll(Arrays.asList(args).stream().filter(arg -> { + return arg != null && !arg.isEmpty(); + }).collect(Collectors.toList())); return ProcessTools.executeCommand(cmd.toArray(new String[cmd.size()])); } } diff --git a/test/jdk/sun/security/tools/keytool/KeyToolTest.java b/test/jdk/sun/security/tools/keytool/KeyToolTest.java index 832da371150..06089962526 100644 --- a/test/jdk/sun/security/tools/keytool/KeyToolTest.java +++ b/test/jdk/sun/security/tools/keytool/KeyToolTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -24,6 +24,7 @@ /* * @test * @author weijun.wang + * @bug 8242151 * @summary Testing keytool * * Run through autotest.sh and manualtest.sh @@ -1599,7 +1600,7 @@ void check(KeyStore ks, String alias, String oid, byte[] value) int pos = 0; System.err.print("x"); Extension ex = ((X509CertImpl)ks.getCertificate(alias)) - .getExtension(new ObjectIdentifier(oid)); + .getExtension(ObjectIdentifier.of(oid)); if (!Arrays.equals(value, ex.getValue())) { throw new RuntimeException("Not same content in " + alias + " for " + oid); @@ -1608,9 +1609,9 @@ void check(KeyStore ks, String alias, String oid, byte[] value) } CheckOid coid = new CheckOid(); assertTrue(((X509CertImpl)ks.getCertificate("oid1")) - .getExtension(new ObjectIdentifier("1.2.3")).isCritical()); + .getExtension(ObjectIdentifier.of("1.2.3")).isCritical()); assertTrue(!((X509CertImpl)ks.getCertificate("oid2")) - .getExtension(new ObjectIdentifier("1.2.3")).isCritical()); + .getExtension(ObjectIdentifier.of("1.2.3")).isCritical()); coid.check(ks, "oid1", "1.2.3", new byte[]{1,2}); coid.check(ks, "oid2", "1.2.3", new byte[]{}); coid.check(ks, "oid12", "1.2.3", new byte[]{}); @@ -1640,14 +1641,14 @@ void check(KeyStore ks, String alias, String oid, byte[] value) assertTrue(a.getAuthorityKeyIdentifierExtension() != null); assertTrue(a.getSubjectKeyIdentifierExtension() != null); assertTrue(a.getKeyUsage() == null); - assertTrue(a.getExtension(new ObjectIdentifier("1.2.3")).isCritical()); - assertTrue(!a.getExtension(new ObjectIdentifier("1.2.4")).isCritical()); - assertTrue(!a.getExtension(new ObjectIdentifier("1.2.5")).isCritical()); + assertTrue(a.getExtension(ObjectIdentifier.of("1.2.3")).isCritical()); + assertTrue(!a.getExtension(ObjectIdentifier.of("1.2.4")).isCritical()); + assertTrue(!a.getExtension(ObjectIdentifier.of("1.2.5")).isCritical()); assertTrue(a.getExtensionValue("1.2.3").length == 3); assertTrue(a.getExtensionValue("1.2.4").length == 4); assertTrue(a.getExtensionValue("1.2.5").length == 5); assertTrue(a.getBasicConstraints() == 2); - assertTrue(!a.getExtension(new ObjectIdentifier("2.3.4")).isCritical()); + assertTrue(!a.getExtension(ObjectIdentifier.of("2.3.4")).isCritical()); assertTrue(a.getExtensionValue("2.3.4").length == 6); // 8073181: keytool -ext honored not working correctly @@ -1657,8 +1658,8 @@ void check(KeyStore ks, String alias, String oid, byte[] value) testOK("", simple+"-importcert -file test2.cert -alias b"); ks = loadStore("x.jks", "changeit", "JKS"); X509CertImpl b = (X509CertImpl)ks.getCertificate("b"); - assertTrue(!b.getExtension(new ObjectIdentifier("1.2.3")).isCritical()); - assertTrue(b.getExtension(new ObjectIdentifier("1.2.4")).isCritical()); + assertTrue(!b.getExtension(ObjectIdentifier.of("1.2.3")).isCritical()); + assertTrue(b.getExtension(ObjectIdentifier.of("1.2.4")).isCritical()); // 8073182: keytool may generate duplicate extensions testOK("", pre+"dup -ext bc=2 -ext 2.5.29.19=30030101FF -ext bc=3"); diff --git a/test/jdk/sun/security/tools/keytool/fakegen/java.base/sun/security/rsa/RSAKeyPairGenerator.java b/test/jdk/sun/security/tools/keytool/fakegen/java.base/sun/security/rsa/RSAKeyPairGenerator.java index 6258f6e7a24..70e977f86c7 100644 --- a/test/jdk/sun/security/tools/keytool/fakegen/java.base/sun/security/rsa/RSAKeyPairGenerator.java +++ b/test/jdk/sun/security/tools/keytool/fakegen/java.base/sun/security/rsa/RSAKeyPairGenerator.java @@ -29,8 +29,7 @@ import java.security.spec.AlgorithmParameterSpec; import java.security.spec.RSAKeyGenParameterSpec; -import sun.security.x509.AlgorithmId; -import static sun.security.rsa.RSAUtil.KeyType; +import sun.security.rsa.RSAUtil.KeyType; /** * A fake RSA keypair generation. @@ -44,7 +43,7 @@ public abstract class RSAKeyPairGenerator extends KeyPairGeneratorSpi { private int keySize; private final KeyType type; - private AlgorithmId rsaId; + private AlgorithmParameterSpec keyParams; RSAKeyPairGenerator(KeyType type, int defKeySize) { this.type = type; @@ -98,7 +97,7 @@ public void initialize(AlgorithmParameterSpec params, SecureRandom random) } try { - this.rsaId = RSAUtil.createAlgorithmId(type, tmpParams); + this.keyParams = RSAUtil.checkParamsAgainstType(type, tmpParams); } catch (ProviderException e) { throw new InvalidAlgorithmParameterException( "Invalid key parameters", e); @@ -536,9 +535,9 @@ public KeyPair generateKeyPair() { BigInteger coeff = q.modInverse(p); try { - PublicKey publicKey = new RSAPublicKeyImpl(rsaId, n, e); + PublicKey publicKey = new RSAPublicKeyImpl(type, keyParams, n, e); PrivateKey privateKey = new RSAPrivateCrtKeyImpl( - rsaId, n, e, d, p, q, pe, qe, coeff); + type, keyParams, n, e, d, p, q, pe, qe, coeff); return new KeyPair(publicKey, privateKey); } catch (InvalidKeyException exc) { // invalid key exception only thrown for keys < 512 bit, diff --git a/test/jdk/sun/security/util/Oid/OidEquals.java b/test/jdk/sun/security/util/Oid/OidEquals.java index 554455b345b..3c408452859 100644 --- a/test/jdk/sun/security/util/Oid/OidEquals.java +++ b/test/jdk/sun/security/util/Oid/OidEquals.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8022444 + * @bug 8022444 8242151 * @summary Test ObjectIdentifier.equals(Object obj) * @modules java.base/sun.security.util */ @@ -32,14 +32,11 @@ public class OidEquals { public static void main(String[] args) throws Exception { - ObjectIdentifier oid1 = new ObjectIdentifier("1.3.6.1.4.1.42.2.17"); - ObjectIdentifier oid2 = - new ObjectIdentifier(new int[]{1, 3, 6, 1, 4, 1, 42, 2, 17}); - ObjectIdentifier oid3 = new ObjectIdentifier("1.2.3.4"); + ObjectIdentifier oid1 = ObjectIdentifier.of("1.3.6.1.4.1.42.2.17"); + ObjectIdentifier oid2 = ObjectIdentifier.of("1.2.3.4"); assertEquals(oid1, oid1); - assertEquals(oid1, oid2); - assertNotEquals(oid1, oid3); + assertNotEquals(oid1, oid2); assertNotEquals(oid1, "1.3.6.1.4.1.42.2.17"); System.out.println("Tests passed."); diff --git a/test/jdk/sun/security/util/Oid/OidFormat.java b/test/jdk/sun/security/util/Oid/OidFormat.java index 48dd2f925bc..975cf9d021d 100644 --- a/test/jdk/sun/security/util/Oid/OidFormat.java +++ b/test/jdk/sun/security/util/Oid/OidFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -24,9 +24,7 @@ /* * @test * @author Weijun Wang - * @bug 6418422 - * @bug 6418425 - * @bug 6418433 + * @bug 6418422 6418425 6418433 8242151 * @summary ObjectIdentifier should reject 1.2.3.-4 and throw IOException on all format errors * @modules java.base/sun.security.util * java.security.jgss @@ -86,57 +84,11 @@ public static void main(String[] args) throws Exception { for (String s: goodOids) { testGood(s); } - - int[][] goodInts = { - {0,0}, {0,1}, {1,0}, {1,2}, - {0,39}, {1,39}, {2,47}, {2,40,3,6}, {2,100,3}, {2,123456,3}, - {1,2,3}, {1,2,3445}, - {1,3,6,1,4,1,42,2,17}, - }; - - for (int[] is: goodInts) { - testGood(is); - } - - int[][] badInts = new int[][] { - {0}, {1}, {2}, - {3,1,1}, {3}, {4}, - {1,40}, {1,111,1}, - {-1,2}, {0,-2}, {1,-2}, {2,-2}, - {1,2,-3,4}, {1,2,3,-4}, - }; - - for (int[] is: badInts) { - testBad(is); - } - - } - - static void testBad(int[] ints) throws Exception { - System.err.println("Trying " + Arrays.toString(ints)); - try { - new ObjectIdentifier(ints); - throw new Exception("should be invalid ObjectIdentifier"); - } catch (IOException ioe) { - System.err.println(ioe); - } - } - - static void testGood(int[] ints) throws Exception { - System.err.println("Trying " + Arrays.toString(ints)); - ObjectIdentifier oid = new ObjectIdentifier(ints); - DerOutputStream os = new DerOutputStream(); - os.putOID(oid); - DerInputStream is = new DerInputStream(os.toByteArray()); - ObjectIdentifier oid2 = is.getOID(); - if (!oid.equals(oid2)) { - throw new Exception("Test DER I/O fails: " + oid + " and " + oid2); - } } static void testGood(String s) throws Exception { System.err.println("Trying " + s); - ObjectIdentifier oid = new ObjectIdentifier(s); + ObjectIdentifier oid = ObjectIdentifier.of(s); if (!oid.toString().equals(s)) { throw new Exception("equal test fail"); } @@ -152,7 +104,7 @@ static void testGood(String s) throws Exception { static void testBad(String s) throws Exception { System.err.println("Trying " + s); try { - new ObjectIdentifier(s); + ObjectIdentifier.of(s); throw new Exception("should be invalid ObjectIdentifier"); } catch (IOException ioe) { System.err.println(ioe); diff --git a/test/jdk/sun/security/util/Oid/S11N.java b/test/jdk/sun/security/util/Oid/S11N.java index b522885d89e..2854b25a15b 100644 --- a/test/jdk/sun/security/util/Oid/S11N.java +++ b/test/jdk/sun/security/util/Oid/S11N.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 4811968 6908628 8006564 8130696 + * @bug 4811968 6908628 8006564 8130696 8242151 * @modules java.base/sun.security.util * @run main S11N check * @summary Serialization compatibility with old versions (and fixes) @@ -118,7 +118,7 @@ private static byte[] out7(String oid) throws Exception { // Gets the serialized form for this java private static byte[] out(String oid) throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputStream(); - new ObjectOutputStream(bout).writeObject(new ObjectIdentifier(oid)); + new ObjectOutputStream(bout).writeObject(ObjectIdentifier.of(oid)); return bout.toByteArray(); } diff --git a/test/jdk/sun/security/util/RegisteredDomain/ParseNames.java b/test/jdk/sun/security/util/RegisteredDomain/ParseNames.java index 69ca9577c68..74045b533c2 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, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8228969 8244087 8255266 + * @bug 8228969 8244087 8255266 8302182 * @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 e4cf659c634..8d8ba34c832 100644 --- a/test/jdk/sun/security/util/RegisteredDomain/tests.dat +++ b/test/jdk/sun/security/util/RegisteredDomain/tests.dat @@ -84,6 +84,10 @@ foo.fj fj foo.fj www.foo.ie ie foo.ie www.foo.gov.ie gov.ie foo.gov.ie +# in +5g.in 5g.in null +www.5g.in 5g.in www.5g.in + # it has a large number of entries www.gr.it gr.it www.gr.it www.blahblahblah.it it blahblahblah.it @@ -153,4 +157,8 @@ w.s.pvt.k12.ma.us pvt.k12.ma.us s.pvt.k12.ma.us foo.السعودية السعودية foo.السعودية w.foo.السعودية السعودية foo.السعودية +# Microsoft +1.azurestaticapps.net 1.azurestaticapps.net null +app.1.azurestaticapps.net 1.azurestaticapps.net app.1.azurestaticapps.net + ## END diff --git a/test/jdk/sun/security/x509/AVA/AVAEqualsHashCode.java b/test/jdk/sun/security/x509/AVA/AVAEqualsHashCode.java index 161cd790403..b0d85f2a11a 100644 --- a/test/jdk/sun/security/x509/AVA/AVAEqualsHashCode.java +++ b/test/jdk/sun/security/x509/AVA/AVAEqualsHashCode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -24,7 +24,7 @@ /* * @test * @author Gary Ellison - * @bug 4170635 + * @bug 4170635 8242151 * @summary Verify equals()/hashCode() contract honored * @modules java.base/sun.security.util * java.base/sun.security.x509 @@ -40,13 +40,11 @@ public class AVAEqualsHashCode { public static void main(String[] args) throws Exception { - int data[] = { 1, 2, 840, 113549, 2, 5 }; - // encode String name = "CN=eve s. dropper"; X500Name dn = new X500Name(name); DerOutputStream deros = new DerOutputStream(); - ObjectIdentifier oid = new ObjectIdentifier(data); + ObjectIdentifier oid = ObjectIdentifier.of("1.2.840.113549.2.5"); dn.encode(deros); byte[] ba = deros.toByteArray(); diff --git a/test/jdk/sun/security/x509/AlgorithmId/ExtensibleAlgorithmId.java b/test/jdk/sun/security/x509/AlgorithmId/ExtensibleAlgorithmId.java index a9322dc2f51..2830caafd7a 100644 --- a/test/jdk/sun/security/x509/AlgorithmId/ExtensibleAlgorithmId.java +++ b/test/jdk/sun/security/x509/AlgorithmId/ExtensibleAlgorithmId.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -23,8 +23,9 @@ /* * @test - * @bug 4162868 8130181 + * @bug 4162868 8130181 8242151 * @modules java.base/sun.security.x509 + * @modules java.base/sun.security.util * @run main/othervm ExtensibleAlgorithmId * @summary Algorithm Name-to-OID mapping needs to be made extensible. */ @@ -39,31 +40,43 @@ public class ExtensibleAlgorithmId { public static void main(String[] args) throws Exception { TestProvider p = new TestProvider(); Security.addProvider(p); - AlgorithmId algid = AlgorithmId.getAlgorithmId("XYZ"); - String alias = "Alg.Alias.Signature.OID." + algid.toString(); + AlgorithmId algid = AlgorithmId.getAlgorithmId(TestProvider.ALG_NAME); + String oid = algid.getOID().toString(); + if (!oid.equals(TestProvider.ALG_OID)) { + throw new Exception("Provider alias oid not used, found " + oid); + } + String name = algid.getName(); + if (!name.equalsIgnoreCase(TestProvider.ALG_NAME)) { + throw new Exception("provider alias name not used, found " + name); + } + String alias = "Alg.Alias.Signature.OID." + oid; String stdAlgName = p.getProperty(alias); - if (stdAlgName == null || !stdAlgName.equalsIgnoreCase("XYZ")) { + if (stdAlgName == null || + !stdAlgName.equalsIgnoreCase(TestProvider.ALG_NAME)) { throw new Exception("Wrong OID"); } } -} -class TestProvider extends Provider { + static class TestProvider extends Provider { - public TestProvider() { + static String ALG_OID = "1.2.3.4.5.6.7.8.9.0"; + static String ALG_NAME = "XYZ"; + + public TestProvider() { super("Dummy", "1.0", "XYZ algorithm"); - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { - put("Signature.XYZ", "test.xyz"); - // preferred OID - put("Alg.Alias.Signature.OID.1.2.3.4.5.6.7.8.9.0", - "XYZ"); - put("Alg.Alias.Signature.9.8.7.6.5.4.3.2.1.0", - "XYZ"); - return null; - } - }); + put("Signature." + ALG_NAME, "test.xyz"); + // preferred OID + put("Alg.Alias.Signature.OID." + ALG_OID, + ALG_NAME); + put("Alg.Alias.Signature.9.8.7.6.5.4.3.2.1.0", + ALG_NAME); + return null; + } + }); + } } } diff --git a/test/jdk/sun/security/x509/X509CertImpl/V3Certificate.java b/test/jdk/sun/security/x509/X509CertImpl/V3Certificate.java index 6fde08c73c9..95741c9f54f 100644 --- a/test/jdk/sun/security/x509/X509CertImpl/V3Certificate.java +++ b/test/jdk/sun/security/x509/X509CertImpl/V3Certificate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8049237 + * @bug 8049237 8242151 * @modules java.base/sun.security.x509 * java.base/sun.security.util * jdk.crypto.ec @@ -153,9 +153,9 @@ public static boolean test(String algorithm, String sigAlg, int keyLength) GeneralNameInterface ipInf = new IPAddressName(address); GeneralName ip = new GeneralName(ipInf); - int[] oidData = new int[]{1, 2, 3, 4}; - GeneralNameInterface oidInf = new OIDName(new ObjectIdentifier(oidData)); + GeneralNameInterface oidInf = + new OIDName(ObjectIdentifier.of("1.2.3.4")); GeneralName oid = new GeneralName(oidInf); SubjectAlternativeNameExtension subjectName diff --git a/test/jdk/sun/security/x509/equalNames/AltNamesEqualsTest.java b/test/jdk/sun/security/x509/equalNames/AltNamesEqualsTest.java index 8ffe02e1cec..b4136506727 100644 --- a/test/jdk/sun/security/x509/equalNames/AltNamesEqualsTest.java +++ b/test/jdk/sun/security/x509/equalNames/AltNamesEqualsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -24,7 +24,7 @@ /* * @test * @summary Make sure names that are equal are treated as such. - * @bug 4273559 + * @bug 4273559 8242151 * @author Yassir Elley * @modules java.base/sun.security.util * java.base/sun.security.x509 @@ -114,7 +114,7 @@ private OIDName stringToOIDName(String name) throws Exception { OIDName oidName = null; - ObjectIdentifier oid = new ObjectIdentifier(name); + ObjectIdentifier oid = ObjectIdentifier.of(name); oidName = new OIDName(oid); return oidName; } diff --git a/test/jdk/tools/jmod/hashes/HashesTest.java b/test/jdk/tools/jmod/hashes/HashesTest.java index cbb7cf0decd..02df7b1ae7a 100644 --- a/test/jdk/tools/jmod/hashes/HashesTest.java +++ b/test/jdk/tools/jmod/hashes/HashesTest.java @@ -368,6 +368,26 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) }); } + @Test + public void upgradeableModule() throws IOException { + Path mpath = Paths.get(System.getProperty("java.home"), "jmods"); + if (!Files.exists(mpath)) { + return; + } + + makeModule("m1"); + makeModule("java.compiler", "m1"); + makeModule("m2", "java.compiler"); + + makeJmod("m1"); + makeJmod("m2"); + makeJmod("java.compiler", + "--module-path", + lib.toString() + File.pathSeparator + mpath, + "--hash-modules", "java\\.(?!se)|^m.*"); + + checkHashes("java.compiler", Set.of("m2")); + } private void makeModule(String mn, String... deps) throws IOException { makeModule(mn, null, deps); diff --git a/test/jdk/tools/launcher/Settings.java b/test/jdk/tools/launcher/Settings.java index 57a1b1b96e0..76e62ffbe57 100644 --- a/test/jdk/tools/launcher/Settings.java +++ b/test/jdk/tools/launcher/Settings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ /* * @test - * @bug 6994753 7123582 + * @bug 6994753 7123582 8305950 * @summary tests -XshowSettings options * @modules jdk.compiler * jdk.zipfs @@ -69,11 +69,13 @@ static void checkNotContains(TestResult tr, String str) { private static final String LOCALE_SETTINGS = "Locale settings:"; private static final String SYSTEM_SETTINGS = "Operating System Metrics:"; private static final String STACKSIZE_SETTINGS = "Stack Size:"; + private static final String TZDATA_SETTINGS = "tzdata version"; static void containsAllOptions(TestResult tr) { checkContains(tr, VM_SETTINGS); checkContains(tr, PROP_SETTINGS); checkContains(tr, LOCALE_SETTINGS); + checkContains(tr, TZDATA_SETTINGS); if (System.getProperty("os.name").contains("Linux")) { checkContains(tr, SYSTEM_SETTINGS); } @@ -139,6 +141,7 @@ static void runTestOptionLocale() throws IOException { checkNotContains(tr, VM_SETTINGS); checkNotContains(tr, PROP_SETTINGS); checkContains(tr, LOCALE_SETTINGS); + checkContains(tr, TZDATA_SETTINGS); } static void runTestOptionSystem() throws IOException { diff --git a/test/jdk/tools/launcher/modules/addexports/AddExportsTest.java b/test/jdk/tools/launcher/modules/addexports/AddExportsTest.java index 92a8a7b238c..610fd7e9305 100644 --- a/test/jdk/tools/launcher/modules/addexports/AddExportsTest.java +++ b/test/jdk/tools/launcher/modules/addexports/AddExportsTest.java @@ -24,7 +24,8 @@ /** * @test * @library /test/lib - * @modules jdk.compiler + * @modules java.compiler + * jdk.compiler * @build AddExportsTest jdk.test.lib.compiler.CompilerUtils * @run testng AddExportsTest * @summary Basic tests for java --add-exports @@ -51,12 +52,15 @@ public class AddExportsTest { private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); private static final Path MODS_DIR = Paths.get("mods"); + private static final Path UPGRADE_MODS_DIRS = Paths.get("upgrademods"); // test module m1 that uses Unsafe private static final String TEST1_MODULE = "m1"; private static final String TEST1_MAIN_CLASS = "jdk.test1.Main"; - + // test module m2 uses java.compiler internals + private static final String TEST2_MODULE = "m2"; + private static final String TEST2_MAIN_CLASS = "jdk.test2.Main"; // test module m3 uses m4 internals private static final String TEST3_MODULE = "m3"; @@ -74,7 +78,19 @@ public void compileTestModules() throws Exception { "--add-exports", "java.base/jdk.internal.misc=m1"); assertTrue(compiled, "module " + TEST1_MODULE + " did not compile"); + // javac -d upgrademods/java.compiler src/java.compiler/** + compiled = CompilerUtils.compile( + SRC_DIR.resolve("java.compiler"), + UPGRADE_MODS_DIRS.resolve("java.compiler")); + assertTrue(compiled, "module java.compiler did not compile"); + // javac --upgrade-module-path upgrademods -d mods/m2 src/m2/** + compiled = CompilerUtils.compile( + SRC_DIR.resolve(TEST2_MODULE), + MODS_DIR.resolve(TEST2_MODULE), + "--upgrade-module-path", UPGRADE_MODS_DIRS.toString(), + "--add-exports", "java.compiler/javax.tools.internal=m2"); + assertTrue(compiled, "module " + TEST2_MODULE + " did not compile"); // javac -d mods/m3 src/m3/** compiled = CompilerUtils.compile( @@ -146,7 +162,25 @@ public void testNamedModule() throws Exception { assertTrue(exitValue == 0); } + /** + * Test --add-exports with upgraded module + */ + public void testWithUpgradedModule() throws Exception { + + // java --add-exports java.compiler/javax.tools.internal=m2 + // --upgrade-module-path upgrademods --module-path mods -m ... + String mid = TEST2_MODULE + "/" + TEST2_MAIN_CLASS; + int exitValue = executeTestJava( + "--add-exports", "java.compiler/javax.tools.internal=m2", + "--upgrade-module-path", UPGRADE_MODS_DIRS.toString(), + "--module-path", MODS_DIR.toString(), + "-m", mid) + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + assertTrue(exitValue == 0); + } /** * Test --add-exports with module that is added to the set of root modules diff --git a/src/jdk.internal.le/windows/classes/module-info.java.extra b/test/jdk/tools/launcher/modules/addexports/src/java.compiler/javax/annotation/processing/Generated.java similarity index 91% rename from src/jdk.internal.le/windows/classes/module-info.java.extra rename to test/jdk/tools/launcher/modules/addexports/src/java.compiler/javax/annotation/processing/Generated.java index 3e791de0b36..2fbd20caaf5 100644 --- a/src/jdk.internal.le/windows/classes/module-info.java.extra +++ b/test/jdk/tools/launcher/modules/addexports/src/java.compiler/javax/annotation/processing/Generated.java @@ -22,6 +22,9 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +package javax.annotation.processing; +public interface Generated { -provides jdk.internal.org.jline.terminal.spi.JnaSupport with jdk.internal.org.jline.terminal.impl.jna.JnaSupportImpl; + +} diff --git a/test/jdk/tools/launcher/modules/addexports/src/java.compiler/javax/tools/ToolsHelper.java b/test/jdk/tools/launcher/modules/addexports/src/java.compiler/javax/tools/ToolsHelper.java new file mode 100644 index 00000000000..29a971851ea --- /dev/null +++ b/test/jdk/tools/launcher/modules/addexports/src/java.compiler/javax/tools/ToolsHelper.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.tools; + +public class ToolsHelper { +} diff --git a/test/jdk/tools/launcher/modules/addexports/src/java.compiler/javax/tools/internal/Helper.java b/test/jdk/tools/launcher/modules/addexports/src/java.compiler/javax/tools/internal/Helper.java new file mode 100644 index 00000000000..3d0f73a9bb3 --- /dev/null +++ b/test/jdk/tools/launcher/modules/addexports/src/java.compiler/javax/tools/internal/Helper.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.tools.internal; + +public class Helper { +} diff --git a/test/jdk/tools/launcher/modules/addexports/src/java.compiler/module-info.java b/test/jdk/tools/launcher/modules/addexports/src/java.compiler/module-info.java new file mode 100644 index 00000000000..11fe1c9db95 --- /dev/null +++ b/test/jdk/tools/launcher/modules/addexports/src/java.compiler/module-info.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module java.compiler { + exports javax.tools; + exports javax.annotation.processing; +} diff --git a/test/jdk/tools/launcher/modules/addexports/src/m2/jdk/test2/Main.java b/test/jdk/tools/launcher/modules/addexports/src/m2/jdk/test2/Main.java new file mode 100644 index 00000000000..b62603a0398 --- /dev/null +++ b/test/jdk/tools/launcher/modules/addexports/src/m2/jdk/test2/Main.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test2; + +import javax.tools.internal.Helper; + +public class Main { + public static void main(String[] args) { + Helper h = new Helper(); + } +} diff --git a/test/jdk/tools/launcher/modules/addexports/src/m2/module-info.java b/test/jdk/tools/launcher/modules/addexports/src/m2/module-info.java new file mode 100644 index 00000000000..a7a3ac95de8 --- /dev/null +++ b/test/jdk/tools/launcher/modules/addexports/src/m2/module-info.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module m2 { + requires java.compiler; +} diff --git a/test/jdk/tools/pack200/UnpackMalformed.java b/test/jdk/tools/pack200/UnpackMalformed.java new file mode 100644 index 00000000000..70a84acdf2e --- /dev/null +++ b/test/jdk/tools/pack200/UnpackMalformed.java @@ -0,0 +1,55 @@ +/* + * 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 8315135 + * @run main/othervm/timeout=300 -Dcom.sun.java.util.jar.pack.disable.native=false -Xmx8m UnpackMalformed + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.jar.JarOutputStream; +import java.util.jar.Pack200; + +@SuppressWarnings("removal") +public class UnpackMalformed { + public static void main(String[] args) { + try { + ByteArrayInputStream in = new ByteArrayInputStream("foobar".getBytes()); + for (int i=0; i < 1_000; i++) { + try { + JarOutputStream out = new JarOutputStream(new ByteArrayOutputStream()); + Pack200.Unpacker unpacker = Pack200.newUnpacker(); + unpacker.unpack(in, out); + } catch (IOException e) { + } + } + } catch (OutOfMemoryError e) { + System.out.println(e); + throw e; + } + } +} diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index c9748ce40fd..3adee21a9d9 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -324,7 +324,7 @@ protected String vmHasSA() { * support. */ protected String vmHasJFR() { - return "" + WB.isJFRIncludedInVmBuild(); + return "" + WB.isJFRIncluded(); } /** @@ -398,7 +398,7 @@ protected String vmAotEnabled() { * @return true if CDS is supported by the VM to be tested. */ protected String vmCDS() { - return "" + WB.isCDSIncludedInVmBuild(); + return "" + WB.isCDSIncluded(); } /** diff --git a/test/langtools/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.java b/test/langtools/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.java index a6b7e479a65..64636fac926 100644 --- a/test/langtools/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.java +++ b/test/langtools/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -49,6 +49,7 @@ public static void main(String... args) throws Exception { void test() { javadoc("-verbose", "-d", "DocTest", + "-sourcepath", System.getProperty("test.src.path"), "-tag", "apiNote:optcm:API Note", "-tag", "implSpec:optcm:Implementation Requirements:", "-tag", "implNote:optcm:Implementation Note:", diff --git a/test/langtools/jdk/javadoc/doclet/lib/JavadocTester.java b/test/langtools/jdk/javadoc/doclet/lib/JavadocTester.java index ec0b042c929..28eaaf7cedb 100644 --- a/test/langtools/jdk/javadoc/doclet/lib/JavadocTester.java +++ b/test/langtools/jdk/javadoc/doclet/lib/JavadocTester.java @@ -112,7 +112,7 @@ * } * * // test methods... - * @Test + * {@literal @}Test * void test() { * javadoc(args); * checkExit(Exit.OK); diff --git a/test/langtools/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java b/test/langtools/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java index b4cf2753233..ca5115788eb 100644 --- a/test/langtools/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java +++ b/test/langtools/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ void test() { + "title=\"class or interface in javax.swing.text\" class=\"externalLink\">Link to AttributeContext innerclass", "Link to external class BigDecimal", - "Link to external member gcd", "Link to external member URI", @@ -90,7 +90,7 @@ void test_warning() { + "title=\"class or interface in javax.swing.text\" class=\"externalLink\">Link to AttributeContext innerclass", "Link to external class BigDecimal", - "Link to external member gcd", "Link to external member URI", diff --git a/test/langtools/jdk/javadoc/doclet/testExternalOverridenMethod/TestExternalOverridenMethod.java b/test/langtools/jdk/javadoc/doclet/testExternalOverridenMethod/TestExternalOverridenMethod.java index 57389873191..30c29e32258 100644 --- a/test/langtools/jdk/javadoc/doclet/testExternalOverridenMethod/TestExternalOverridenMethod.java +++ b/test/langtools/jdk/javadoc/doclet/testExternalOverridenMethod/TestExternalOverridenMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,12 +53,12 @@ void test() { checkOutput("pkg/XReader.html", true, "

          Overrides:
          \n" - + "
          read in class " + "FilterReader
          ", "
          Specified by:
          \n" - + "
          readInt in interface " + "DataInput
          " diff --git a/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java b/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java index a860663482e..3d4a1595a16 100644 --- a/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java +++ b/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ void test() { checkOutput("pkg/C1.html", true, //External link. - "href=\"http://java.sun.com/j2se/1.4/docs/api/java/lang/Object.html?is-external=true#wait(long,int)\"", + "href=\"http://java.sun.com/j2se/1.4/docs/api/java/lang/Object.html?is-external=true#wait-long-int-\"", //Member summary table link. "href=\"#method(int,int,java.util.ArrayList)\"", //Anchor test. diff --git a/test/langtools/jdk/javadoc/doclet/testHrefInDocComment/TestHrefInDocComment.java b/test/langtools/jdk/javadoc/doclet/testHrefInDocComment/TestHrefInDocComment.java index 9b6d8287878..c0794d2addd 100644 --- a/test/langtools/jdk/javadoc/doclet/testHrefInDocComment/TestHrefInDocComment.java +++ b/test/langtools/jdk/javadoc/doclet/testHrefInDocComment/TestHrefInDocComment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 4638015 + * @bug 4638015 8248001 * @summary Determine if Hrefs are processed properly when they * appear in doc comments. * @author jamieh diff --git a/test/langtools/jdk/javadoc/doclet/testHrefInDocComment/pkg/J1.java b/test/langtools/jdk/javadoc/doclet/testHrefInDocComment/pkg/J1.java new file mode 100644 index 00000000000..9be939f37b1 --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testHrefInDocComment/pkg/J1.java @@ -0,0 +1,75 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 pkg; + +/** + *This class has various functions, + * see FTP Site, + * file service for further information + *various functions + *
            + *
          • function1
          • + *
          • function2
          • + *
          • function3
          • + *
          + *special methods + *
            + *
          • method1
          • + *
          • method2
          • + *
          • method3
          • + *
          + */ +public class J1 { + /** + *fields. + */ + protected Object field1; + + /** + *Creates an instance which has various functions. + */ + public J1(){ + } + + /** + *This is aspecial method. + *@param p1 arg1 + */ + public void method1(int p1){ + } + + /** + *See FTP Site for more information. + *@param p1 arg1 + */ + public void method2(int p1){ + } + + /** + *See file service for more information. + *@param p1 arg1 + */ + public void method3(int p1){ + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java index 42f983cd1a4..18fd1e535c3 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,7 +85,7 @@ void test() { checkOutput("pkg/B.html", true, "
          A method with html tag the method " - + "getSystemClassLoader()" + " as the parent class loader.
          ", "
          is equivalent to invoking " diff --git a/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java b/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java index 62eac6bd32f..36f96644961 100644 --- a/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java +++ b/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java @@ -27,6 +27,7 @@ * @summary Control Char check for pty * @modules jdk.internal.le/jdk.internal.org.jline.terminal * jdk.internal.le/jdk.internal.org.jline.terminal.impl + * jdk.internal.le/jdk.internal.org.jline.terminal.spi * @requires (os.family == "linux") | (os.family == "aix") */ @@ -35,10 +36,11 @@ import jdk.internal.org.jline.terminal.Attributes.ControlChar; import jdk.internal.org.jline.terminal.Attributes.LocalFlag; import jdk.internal.org.jline.terminal.impl.ExecPty; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; public class ExecPtyGetFlagsToSetTest extends ExecPty { - public ExecPtyGetFlagsToSetTest(String name, boolean system) { - super(name, system); + public ExecPtyGetFlagsToSetTest(String name, TerminalProvider.Stream stream) { + super(name, stream); } @Override @@ -48,7 +50,7 @@ protected List getFlagsToSet(Attributes attr, Attributes current) { public static void main(String[] args) { ExecPtyGetFlagsToSetTest testPty = - new ExecPtyGetFlagsToSetTest("stty", true); + new ExecPtyGetFlagsToSetTest("stty", TerminalProvider.Stream.Output); Attributes attr = new Attributes(); Attributes current = new Attributes(); diff --git a/test/langtools/tools/javac/Paths/Util.sh b/test/langtools/tools/javac/Paths/Util.sh index 473fa32558b..fa96732fea1 100644 --- a/test/langtools/tools/javac/Paths/Util.sh +++ b/test/langtools/tools/javac/Paths/Util.sh @@ -24,10 +24,10 @@ # Utilities for shell tests : ${TESTSRC=.} ${TESTCLASSES=.} - java="${TESTJAVA+${TESTJAVA}/bin/}java" - javac="${TESTJAVA+${TESTJAVA}/bin/}javac" - jar="${TESTJAVA+${TESTJAVA}/bin/}jar" -jimage="${TESTJAVA+${TESTJAVA}/bin/}jimage" + java="${TESTJAVA+${TESTJAVA}/bin/}java${EXE_SUFFIX}" + javac="${TESTJAVA+${TESTJAVA}/bin/}javac${EXE_SUFFIX}" + jar="${TESTJAVA+${TESTJAVA}/bin/}jar${EXE_SUFFIX}" +jimage="${TESTJAVA+${TESTJAVA}/bin/}jimage${EXE_SUFFIX}" case `uname -s` in Windows*|CYGWIN*|MSYS*|MINGW*) diff --git a/test/lib/jdk/test/lib/Utils.java b/test/lib/jdk/test/lib/Utils.java index 93b0777e1f3..201fcab8c8a 100644 --- a/test/lib/jdk/test/lib/Utils.java +++ b/test/lib/jdk/test/lib/Utils.java @@ -193,6 +193,18 @@ public static String[] addTestJavaOpts(String... userArgs) { return opts.toArray(new String[0]); } + /** + * Combines given arguments with default JTReg arguments for a jvm running a test. + * This is the combination of JTReg arguments test.vm.opts and test.java.opts + * @return The combination of JTReg test java options and user args. + */ + public static String[] prependTestJavaOpts(String... userArgs) { + List opts = new ArrayList(); + Collections.addAll(opts, getTestJavaOpts()); + Collections.addAll(opts, userArgs); + return opts.toArray(new String[0]); + } + /** * Removes any options specifying which GC to use, for example "-XX:+UseG1GC". * Removes any options matching: -XX:(+/-)Use*GC diff --git a/test/lib/jdk/test/lib/cds/CDSTestUtils.java b/test/lib/jdk/test/lib/cds/CDSTestUtils.java index de930a09a2d..7b28faa82b4 100644 --- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java +++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java @@ -264,7 +264,7 @@ public static OutputAnalyzer createArchive(CDSOptions opts) for (String s : opts.suffix) cmd.add(s); String[] cmdLine = cmd.toArray(new String[cmd.size()]); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine); + ProcessBuilder pb = ProcessTools.createTestJvm(cmdLine); return executeAndLog(pb, "dump"); } @@ -412,7 +412,7 @@ public static OutputAnalyzer runWithArchive(CDSOptions opts) for (String s : opts.suffix) cmd.add(s); String[] cmdLine = cmd.toArray(new String[cmd.size()]); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine); + ProcessBuilder pb = ProcessTools.createTestJvm(cmdLine); return executeAndLog(pb, "exec"); } diff --git a/test/lib/jdk/test/lib/containers/cgroup/CgroupMetricsTester.java b/test/lib/jdk/test/lib/containers/cgroup/CgroupMetricsTester.java index 768a6c04e30..689934882c6 100644 --- a/test/lib/jdk/test/lib/containers/cgroup/CgroupMetricsTester.java +++ b/test/lib/jdk/test/lib/containers/cgroup/CgroupMetricsTester.java @@ -31,7 +31,7 @@ interface CgroupMetricsTester { - public static final double ERROR_MARGIN = 0.1; + public static final double ERROR_MARGIN = 0.25; public static final String EMPTY_STR = ""; public void testMemorySubsystem(); diff --git a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java index 7c3be30c50f..5d642aa11c4 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java @@ -27,6 +27,7 @@ import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.Paths; @@ -36,6 +37,7 @@ import java.util.Arrays; import java.util.ArrayList; import java.util.Collections; +import java.util.EnumSet; import java.util.List; import jdk.test.lib.Container; import jdk.test.lib.Utils; @@ -164,7 +166,7 @@ public static void buildJdkContainerImage(String imageName, String dockerfileCon Path jdkSrcDir = Paths.get(JDK_UNDER_TEST); Path jdkDstDir = buildDir.resolve("jdk"); Files.createDirectories(jdkDstDir); - Files.walkFileTree(jdkSrcDir, new CopyFileVisitor(jdkSrcDir, jdkDstDir)); + Files.walkFileTree(jdkSrcDir, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, new CopyFileVisitor(jdkSrcDir, jdkDstDir)); buildImage(imageName, buildDir); } diff --git a/test/lib/jdk/test/lib/jfr/AppExecutorHelper.java b/test/lib/jdk/test/lib/jfr/AppExecutorHelper.java index 239a0f7f9e3..6768f4ed8f9 100644 --- a/test/lib/jdk/test/lib/jfr/AppExecutorHelper.java +++ b/test/lib/jdk/test/lib/jfr/AppExecutorHelper.java @@ -74,7 +74,7 @@ public static OutputAnalyzer executeAndRecord(String settings, String jfrFilenam Collections.addAll(arguments, classArguments); } - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, arguments.toArray(new String[0])); + ProcessBuilder pb = ProcessTools.createTestJvm(arguments); return ProcessTools.executeProcess(pb); } } diff --git a/test/lib/jdk/test/lib/process/ProcessTools.java b/test/lib/jdk/test/lib/process/ProcessTools.java index 8560f8db467..331f3d9b7cb 100644 --- a/test/lib/jdk/test/lib/process/ProcessTools.java +++ b/test/lib/jdk/test/lib/process/ProcessTools.java @@ -277,19 +277,7 @@ public static long getProcessId() throws Exception { * @return The ProcessBuilder instance representing the java command. */ public static ProcessBuilder createJavaProcessBuilder(List command) { - return createJavaProcessBuilder(false, command); - } - - /** - * Create ProcessBuilder using the java launcher from the jdk to be tested. - *

          - * @param addTestVmAndJavaOptions If true, adds test.vm.opts and test.java.opts - * to the java arguments. - * @param command Arguments to pass to the java command. - * @return The ProcessBuilder instance representing the java command. - */ - public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOptions, List command) { - return createJavaProcessBuilder(addTestVmAndJavaOptions, command.toArray(String[]::new)); + return createJavaProcessBuilder(command.toArray(String[]::new)); } /** @@ -299,18 +287,6 @@ public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOp * @return The ProcessBuilder instance representing the java command. */ public static ProcessBuilder createJavaProcessBuilder(String... command) { - return createJavaProcessBuilder(false, command); - } - - /** - * Create ProcessBuilder using the java launcher from the jdk to be tested. - * - * @param addTestVmAndJavaOptions If true, adds test.vm.opts and test.java.opts - * to the java arguments. - * @param command Arguments to pass to the java command. - * @return The ProcessBuilder instance representing the java command. - */ - public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOptions, String... command) { String javapath = JDKToolFinder.getJDKTool("java"); ArrayList args = new ArrayList<>(); @@ -319,10 +295,6 @@ public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOp args.add("-cp"); args.add(System.getProperty("java.class.path")); - if (addTestVmAndJavaOptions) { - Collections.addAll(args, Utils.getTestJavaOpts()); - } - Collections.addAll(args, command); // Reporting @@ -344,6 +316,36 @@ private static void printStack(Thread t, StackTraceElement[] stack) { } } + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested. + * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added. + * + * The command line will be like: + * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds + * Create ProcessBuilder using the java launcher from the jdk to be tested. + * + * @param command Arguments to pass to the java command. + * @return The ProcessBuilder instance representing the java command. + */ + public static ProcessBuilder createTestJvm(List command) { + return createTestJvm(command.toArray(String[]::new)); + } + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested. + * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added. + * + * The command line will be like: + * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds + * Create ProcessBuilder using the java launcher from the jdk to be tested. + * + * @param command Arguments to pass to the java command. + * @return The ProcessBuilder instance representing the java command. + */ + public static ProcessBuilder createTestJvm(String... command) { + return createJavaProcessBuilder(Utils.prependTestJavaOpts(command)); + } + /** * Executes a test jvm process, waits for it to finish and returns the process output. * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added. @@ -375,7 +377,7 @@ public static OutputAnalyzer executeTestJvm(List cmds) throws Exception * @return The output from the process. */ public static OutputAnalyzer executeTestJvm(String... cmds) throws Exception { - ProcessBuilder pb = createJavaProcessBuilder(true, cmds); + ProcessBuilder pb = createTestJvm(cmds); return executeProcess(pb); } diff --git a/test/lib/jdk/test/lib/security/DerUtils.java b/test/lib/jdk/test/lib/security/DerUtils.java index 20fc4936ddd..067eadd36b5 100644 --- a/test/lib/jdk/test/lib/security/DerUtils.java +++ b/test/lib/jdk/test/lib/security/DerUtils.java @@ -101,9 +101,9 @@ public static void checkAlg(byte[] der, String location, if (expected instanceof ObjectIdentifier) { oid = (ObjectIdentifier)expected; } else if (expected instanceof KnownOIDs) { - oid = new ObjectIdentifier(((KnownOIDs) expected).value()); + oid = ObjectIdentifier.of(((KnownOIDs) expected).value()); } else if (expected instanceof String) { - oid = new ObjectIdentifier(KnownOIDs.findMatch((String)expected).value()); + oid = ObjectIdentifier.of(KnownOIDs.findMatch((String)expected).value()); } else { throw new IllegalArgumentException(expected.toString()); } diff --git a/test/lib/jdk/test/lib/security/TestCertificate.java b/test/lib/jdk/test/lib/security/TestCertificate.java index 098cd2f1197..cc2c7c8fe19 100644 --- a/test/lib/jdk/test/lib/security/TestCertificate.java +++ b/test/lib/jdk/test/lib/security/TestCertificate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 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 @@ -24,16 +24,21 @@ package jdk.test.lib.security; import java.io.ByteArrayInputStream; -import java.security.cert.CertPath; -import java.security.cert.CertPathValidator; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.PKIXParameters; -import java.security.cert.TrustAnchor; -import java.security.cert.X509Certificate; -import java.util.Collections; -import java.util.Date; -import java.util.List; +import java.io.IOException; +import java.io.SequenceInputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.*; +import java.security.cert.*; +import java.security.cert.Certificate; +import java.util.*; + +import sun.security.tools.keytool.CertAndKeyGen; +import sun.security.x509.X500Name; + +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.SecurityTools; +import jdk.test.lib.process.OutputAnalyzer; // Certificates taken from old ValWithAnchorByName testcase *** public enum TestCertificate { @@ -122,6 +127,8 @@ public enum TestCertificate { "J2GyCaJINsyaI/I2\n" + "-----END CERTIFICATE-----"); + private static final CertificateFactory CERTIFICATE_FACTORY = getCertificateFactory(); + public String serialNumber; public String algorithm; public String subject; @@ -143,22 +150,80 @@ public enum TestCertificate { this.keyLength = 2048; } - public X509Certificate generate(CertificateFactory cf) throws CertificateException { + private static CertificateFactory getCertificateFactory() { + try { + return CertificateFactory.getInstance("X.509"); + } catch (CertificateException e) { + throw new RuntimeException(e); + } + } + + public X509Certificate certificate() throws CertificateException { ByteArrayInputStream is = new ByteArrayInputStream(encoded.getBytes()); - return (X509Certificate) cf.generateCertificate(is); + return (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(is); + } + + public static Collection certificates() throws CertificateException { + ByteArrayInputStream is1 = new ByteArrayInputStream((TestCertificate.ONE.encoded + "\n").getBytes()); + ByteArrayInputStream is2 = new ByteArrayInputStream(TestCertificate.TWO.encoded.getBytes()); + return CERTIFICATE_FACTORY.generateCertificates(new SequenceInputStream(is1, is2)); + } + + public static void certPath() throws CertificateException { + CertPath cp = CERTIFICATE_FACTORY.generateCertPath(List.of(TestCertificate.ONE.certificate(), + TestCertificate.TWO.certificate())); + + // Get the encoded form of the CertPath we made + byte[] encoded = cp.getEncoded("PKCS7"); + CERTIFICATE_FACTORY.generateCertPath(new ByteArrayInputStream(encoded), "PKCS7"); + } + + public static void keyToolTest() throws Exception { + String config = + "\n" + + "\n" + + " \n" + + " true\n" + + " true\n" + + " \n" + + ""; + Files.writeString(Path.of("config.jfc"), config); + + SecurityTools.keytool("-J-XX:StartFlightRecording=filename=keytool.jfr,settings=config.jfc", + "-genkeypair", "-alias", "testkey", "-keyalg", "RSA", "-keysize", "2048", "-dname", + "CN=8292033.oracle.com,OU=JPG,C=US", "-keypass", "changeit", + "-validity", "365", "-keystore", "keystore.pkcs12", "-storepass", "changeit") + .shouldHaveExitValue(0); + // The keytool command will load the keystore and call CertificateFactory.generateCertificate + jfrTool("keytool.jfr") + .shouldContain("8292033.oracle.com") // should record our new cert + .shouldNotContain("algorithm = N/A") // shouldn't record cert under construction + .shouldHaveExitValue(0); } - public static void generateChain(boolean selfSignedTest) throws Exception { + private static OutputAnalyzer jfrTool(String jfrFile) throws Exception { + ProcessBuilder pb = new ProcessBuilder(); + pb.command(new String[] { JDKToolFinder.getJDKTool("jfr"), "print", "--events", + "jdk.X509Certificate", jfrFile}); + return new OutputAnalyzer(pb.start()); + } + + public static void generateChain(boolean selfSignedTest, boolean trustAnchorCert) throws Exception { // Do path validation as if it is always Tue, 06 Sep 2016 22:12:21 GMT // This value is within the lifetimes of all certificates. Date testDate = new Date(1473199941000L); CertificateFactory cf = CertificateFactory.getInstance("X.509"); - X509Certificate c1 = TestCertificate.ONE.generate(cf); - X509Certificate c2 = TestCertificate.TWO.generate(cf); - X509Certificate ca = TestCertificate.ROOT_CA.generate(cf); + X509Certificate c1 = TestCertificate.ONE.certificate(); + X509Certificate c2 = TestCertificate.TWO.certificate(); + X509Certificate ca = TestCertificate.ROOT_CA.certificate(); - TrustAnchor ta = new TrustAnchor(ca, null); + TrustAnchor ta; + if (trustAnchorCert) { + ta = new TrustAnchor(ca, null); + } else { + ta = new TrustAnchor(ca.getIssuerX500Principal(), ca.getPublicKey(), null); + } CertPathValidator validator = CertPathValidator.getInstance("PKIX"); PKIXParameters params = new PKIXParameters(Collections.singleton(ta)); @@ -172,4 +237,4 @@ public static void generateChain(boolean selfSignedTest) throws Exception { validator.validate(path, params); } } -} \ No newline at end of file +} diff --git a/test/lib/jdk/test/lib/security/timestamp/TsaSigner.java b/test/lib/jdk/test/lib/security/timestamp/TsaSigner.java index 7eb7458a88c..564d88fe5f3 100644 --- a/test/lib/jdk/test/lib/security/timestamp/TsaSigner.java +++ b/test/lib/jdk/test/lib/security/timestamp/TsaSigner.java @@ -170,7 +170,7 @@ private byte[] createResponse(TsaParam requestParam) throws Exception { String policyId = respParam.policyId(); print("policyId", policyId); - tstInfoOut.putOID(new ObjectIdentifier(policyId)); + tstInfoOut.putOID(ObjectIdentifier.of(policyId)); String digestAlgo = respParam.digestAlgo(); print("digestAlgo", digestAlgo); @@ -204,7 +204,7 @@ private byte[] createResponse(TsaParam requestParam) throws Exception { eContentOut.putOctetString(tstInfoSeqData); ContentInfo eContentInfo = new ContentInfo( - new ObjectIdentifier("1.2.840.113549.1.9.16.1.4"), + ObjectIdentifier.of("1.2.840.113549.1.9.16.1.4"), new DerValue(eContentOut.toByteArray())); String defaultSigAlgo = AlgorithmId.getDefaultSigAlgForKey( diff --git a/test/lib/jdk/test/lib/util/FileUtils.java b/test/lib/jdk/test/lib/util/FileUtils.java index 7125955feb9..016e76b6bae 100644 --- a/test/lib/jdk/test/lib/util/FileUtils.java +++ b/test/lib/jdk/test/lib/util/FileUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -23,6 +23,8 @@ package jdk.test.lib.util; +import java.io.BufferedReader; +import java.io.InputStreamReader; import java.io.IOException; import java.io.PrintStream; import java.io.UncheckedIOException; @@ -41,6 +43,8 @@ import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.TimeUnit; import jdk.test.lib.Platform; @@ -238,6 +242,93 @@ public static boolean areFileSystemsAccessible() throws IOException { return areFileSystemsAccessible; } + /** + * Checks whether all file systems are accessible. This is performed + * by checking free disk space on all mounted file systems via a + * separate, spawned process. File systems are considered to be + * accessible if this process completes successfully before a given + * fixed duration has elapsed. + * + * @implNote On Unix this executes the {@code df} command in a separate + * process and on Windows always returns {@code true}. + * + * @return whether file systems appear to be accessible + * + * @throws RuntimeException if there are duplicate mount points or some + * other execution problem occurs + */ + public static boolean areAllMountPointsAccessible() { + final AtomicBoolean areMountPointsOK = new AtomicBoolean(true); + if (!IS_WINDOWS) { + Thread thr = new Thread(() -> { + try { + Process proc = new ProcessBuilder("df").start(); + BufferedReader reader = new BufferedReader + (new InputStreamReader(proc.getInputStream())); + // Skip the first line as it is the "df" output header. + if (reader.readLine() != null ) { + String prevMountPoint = null, mountPoint = null; + while ((mountPoint = reader.readLine()) != null) { + if (prevMountPoint != null && + mountPoint.equals(prevMountPoint)) { + throw new RuntimeException + ("System configuration error: " + + "duplicate mount point " + mountPoint + + " detected"); + } + prevMountPoint = mountPoint; + } + } + + try { + proc.waitFor(90, TimeUnit.SECONDS); + } catch (InterruptedException ignored) { + } + try { + int exitValue = proc.exitValue(); + if (exitValue != 0) { + System.err.printf("df process exited with %d != 0%n", + exitValue); + areMountPointsOK.set(false); + } + } catch (IllegalThreadStateException ignored) { + System.err.println("df command apparently hung"); + areMountPointsOK.set(false); + } + } catch (IOException ioe) { + throw new RuntimeException(ioe); + }; + }); + + final AtomicReference throwableReference = + new AtomicReference(); + thr.setUncaughtExceptionHandler( + new Thread.UncaughtExceptionHandler() { + public void uncaughtException(Thread t, Throwable e) { + throwableReference.set(e); + } + }); + + thr.start(); + try { + thr.join(120*1000L); + } catch (InterruptedException ie) { + throw new RuntimeException(ie); + } + + Throwable uncaughtException = (Throwable)throwableReference.get(); + if (uncaughtException != null) { + throw new RuntimeException(uncaughtException); + } + + if (thr.isAlive()) { + throw new RuntimeException("df thread did not join in time"); + } + } + + return areMountPointsOK.get(); + } + /** * List the open file descriptors (if supported by the 'lsof' command). * @param ps a printStream to send the output to diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java index 47569303546..802614f0ef1 100644 --- a/test/lib/sun/hotspot/WhiteBox.java +++ b/test/lib/sun/hotspot/WhiteBox.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -520,8 +520,8 @@ public Object getMethodOption(Executable method, String name) { public native boolean isShared(Object o); public native boolean isSharedClass(Class c); public native boolean areSharedStringsIgnored(); - public native boolean isCDSIncludedInVmBuild(); - public native boolean isJFRIncludedInVmBuild(); + public native boolean isCDSIncluded(); + public native boolean isJFRIncluded(); public native boolean isJavaHeapArchiveSupported(); public native Object getResolvedReferences(Class c); public native boolean areOpenArchiveHeapObjectsMapped(); @@ -542,6 +542,8 @@ public native int validateCgroup(String procCgroups, String procSelfCgroup, String procSelfMountinfo); public native void printOsInfo(); + public native long hostPhysicalMemory(); + public native long hostPhysicalSwap(); // Decoder public native void disableElfSectionCache(); diff --git a/test/lib/sun/hotspot/code/Compiler.java b/test/lib/sun/hotspot/code/Compiler.java index 3c566111da9..ef7921b36a6 100644 --- a/test/lib/sun/hotspot/code/Compiler.java +++ b/test/lib/sun/hotspot/code/Compiler.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