diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 525f6d27f69..5b84779abab 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 ' ')" 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/closed/custom/copy/Copy-java.base.gmk b/closed/custom/copy/Copy-java.base.gmk index f03f580f1cf..0ae7ba7f69b 100644 --- a/closed/custom/copy/Copy-java.base.gmk +++ b/closed/custom/copy/Copy-java.base.gmk @@ -200,7 +200,7 @@ ifneq ($(OPENSSL_BUNDLE_LIB_PATH), ) # OpenSSL 1.1.1 on AIX has switched to use archive library files (natural way) # instead of 'libcrypto.so' files. # See https://github.com/openssl/openssl/pull/6487. - LIBCRYPTO_NAMES := libcrypto.so.3 libcrypto.so.1.1 libcrypto.so.1.0.0 libcrypto.a + LIBCRYPTO_NAMES := libcrypto64.so.3 libcrypto.so.3 libcrypto.so.1.1 libcrypto.so.1.0.0 else LIBCRYPTO_NAMES := libcrypto.so endif diff --git a/closed/openjdk-tag.gmk b/closed/openjdk-tag.gmk index 06bac66d77e..5f373278995 100644 --- a/closed/openjdk-tag.gmk +++ b/closed/openjdk-tag.gmk @@ -1 +1 @@ -OPENJDK_TAG := jdk-11.0.20+8 +OPENJDK_TAG := jdk-11.0.21+1 diff --git a/closed/src/java.base/aix/native/libjncrypto/NativeCrypto_md.c b/closed/src/java.base/aix/native/libjncrypto/NativeCrypto_md.c index 1f6e9b5f5db..2d29cc3c518 100644 --- a/closed/src/java.base/aix/native/libjncrypto/NativeCrypto_md.c +++ b/closed/src/java.base/aix/native/libjncrypto/NativeCrypto_md.c @@ -1,6 +1,6 @@ /* * =========================================================================== - * (c) Copyright IBM Corp. 2019, 2022 All Rights Reserved + * (c) Copyright IBM Corp. 2019, 2023 All Rights Reserved * =========================================================================== * * This code is free software; you can redistribute it and/or modify it @@ -32,18 +32,34 @@ /* Load the crypto library (return NULL on error) */ void * load_crypto_library(jboolean traceEnabled) { void * result = NULL; + const char *libname3_a_64 = "libcrypto.a(libcrypto64.so.3)"; + const char *libname3_64 = "libcrypto64.so.3"; + const char *libname3_a = "libcrypto.a(libcrypto.so.3)"; + const char *libname3 = "libcrypto.so.3"; const char *libname111 = "libcrypto.a(libcrypto64.so.1.1)"; const char *libname110 = "libcrypto.so.1.1"; const char *libname102 = "libcrypto.so.1.0.0"; const char *symlink = "libcrypto.a(libcrypto64.so)"; - result = dlopen (libname111, RTLD_NOW | RTLD_MEMBER); + result = dlopen (libname3_a_64, RTLD_NOW | RTLD_MEMBER); if (result == NULL) { - result = dlopen (libname110, RTLD_NOW); + result = dlopen (libname3_64, RTLD_NOW); if (result == NULL) { - result = dlopen (libname102, RTLD_NOW); + result = dlopen (libname3_a, RTLD_NOW | RTLD_MEMBER); if (result == NULL) { - result = dlopen (symlink, RTLD_NOW | RTLD_MEMBER); + result = dlopen (libname3, RTLD_NOW); + if (result == NULL) { + result = dlopen (libname111, RTLD_NOW | RTLD_MEMBER); + if (result == NULL) { + result = dlopen (libname110, RTLD_NOW); + if (result == NULL) { + result = dlopen (libname102, RTLD_NOW); + if (result == NULL) { + result = dlopen (symlink, RTLD_NOW | RTLD_MEMBER); + } + } + } + } } } } diff --git a/closed/src/java.base/macosx/native/libjncrypto/NativeCrypto_md.c b/closed/src/java.base/macosx/native/libjncrypto/NativeCrypto_md.c index cd62ca650b6..4b42a130ed7 100644 --- a/closed/src/java.base/macosx/native/libjncrypto/NativeCrypto_md.c +++ b/closed/src/java.base/macosx/native/libjncrypto/NativeCrypto_md.c @@ -1,6 +1,6 @@ /* * =========================================================================== - * (c) Copyright IBM Corp. 2019, 2022 All Rights Reserved + * (c) Copyright IBM Corp. 2019, 2023 All Rights Reserved * =========================================================================== * * This code is free software; you can redistribute it and/or modify it @@ -32,16 +32,20 @@ /* Load the crypto library (return NULL on error) */ void * load_crypto_library(jboolean traceEnabled) { void * result = NULL; - + + const char *libname3 = "libcrypto.3.dylib"; const char *libname = "libcrypto.1.1.dylib"; const char *oldname = "libcrypto.1.0.0.dylib"; const char *symlink = "libcrypto.dylib"; - result = dlopen (libname, RTLD_NOW); + result = dlopen (libname3, RTLD_NOW); if (result == NULL) { - result = dlopen (oldname, RTLD_NOW); + result = dlopen (libname, RTLD_NOW); if (result == NULL) { - result = dlopen (symlink, RTLD_NOW); + result = dlopen (oldname, RTLD_NOW); + if (result == NULL) { + result = dlopen (symlink, RTLD_NOW); + } } } diff --git a/closed/src/java.base/windows/native/libjncrypto/NativeCrypto_md.c b/closed/src/java.base/windows/native/libjncrypto/NativeCrypto_md.c index 3255121c870..26b47d4c870 100644 --- a/closed/src/java.base/windows/native/libjncrypto/NativeCrypto_md.c +++ b/closed/src/java.base/windows/native/libjncrypto/NativeCrypto_md.c @@ -1,6 +1,6 @@ /* * =========================================================================== - * (c) Copyright IBM Corp. 2019, 2022 All Rights Reserved + * (c) Copyright IBM Corp. 2019, 2023 All Rights Reserved * =========================================================================== * * This code is free software; you can redistribute it and/or modify it @@ -29,13 +29,16 @@ /* Load the crypto library (return NULL on error) */ void * load_crypto_library(jboolean traceEnabled) { void * result = NULL; + const char *libname3 = "libcrypto-3-x64.dll"; const char *libname = "libcrypto-1_1-x64.dll"; const char *oldname = "libeay32.dll"; - result = LoadLibrary(libname); - + result = LoadLibrary(libname3); if (result == NULL) { - result = LoadLibrary(oldname); + result = LoadLibrary(libname); + if (result == NULL) { + result = LoadLibrary(oldname); + } } return result; diff --git a/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECUtil.java b/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECUtil.java index 2aefe4ac39f..6769100f525 100644 --- a/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECUtil.java +++ b/closed/src/jdk.crypto.ec/share/classes/sun/security/ec/NativeECUtil.java @@ -107,7 +107,7 @@ static String getCurveName(ECParameterSpec params) { String curveName; if (params instanceof NamedCurve) { NamedCurve namedCurve = (NamedCurve) params; - curveName = namedCurve.getName(); + curveName = namedCurve.getNameAndAliases()[0]; } else { /* use the OID */ try { diff --git a/make/autoconf/hotspot.m4 b/make/autoconf/hotspot.m4 index a3e1e00b2c9..9bb34363e5c 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..a9b6c2ea496 100644 --- a/make/autoconf/version-numbers +++ b/make/autoconf/version-numbers @@ -28,16 +28,16 @@ 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" -DEFAULT_PROMOTED_VERSION_PRE= +DEFAULT_PROMOTED_VERSION_PRE=ea LAUNCHER_NAME=openjdk PRODUCT_NAME=OpenJDK 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/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk index 5146f5a23cb..19ef7ba0410 100644 --- a/make/lib/Awt2dLibraries.gmk +++ b/make/lib/Awt2dLibraries.gmk @@ -559,10 +559,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/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/share/classes/com/sun/crypto/provider/DHPrivateKey.java b/src/java.base/share/classes/com/sun/crypto/provider/DHPrivateKey.java index c87cc1c5d62..a886dc7c31a 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, 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 @@ -71,8 +71,6 @@ final class DHPrivateKey implements PrivateKey, // 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 +217,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); 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..0e8b396bff6 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, 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,9 @@ final class DHPublicKey implements PublicKey, // 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 +204,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(); 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/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/SunJCE.java b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java index 140d39b2164..2c80fd1527e 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 @@ -37,8 +37,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.*; import jdk.crypto.jniprovider.NativeCrypto; import jdk.internal.util.StaticProperty; @@ -113,9 +112,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() { @@ -141,57 +153,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"); @@ -226,8 +187,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); @@ -238,58 +199,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"); @@ -302,157 +263,140 @@ 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"); if (useNativeChaCha20Cipher && (NativeCrypto.getVersionIfAvailable() >= NativeCrypto.OPENSSL_VERSION_1_1_0)) { - ps("Cipher", "ChaCha20", - "com.sun.crypto.provider.NativeChaCha20Cipher$ChaCha20Only", - null, attrs); - ps("Cipher", "ChaCha20-Poly1305", - "com.sun.crypto.provider.NativeChaCha20Cipher$ChaCha20Poly1305", - chachaPolyAliases, attrs); + ps("Cipher", "ChaCha20", + "com.sun.crypto.provider.NativeChaCha20Cipher$ChaCha20Only", + null, attrs); + psA("Cipher", "ChaCha20-Poly1305", + "com.sun.crypto.provider.NativeChaCha20Cipher$ChaCha20Poly1305", + attrs); } else { - ps("Cipher", "ChaCha20", - "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Only", - null, attrs); - ps("Cipher", "ChaCha20-Poly1305", - "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", - chachaPolyAliases, attrs); + ps("Cipher", "ChaCha20", + "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Only", + null, attrs); + psA("Cipher", "ChaCha20-Poly1305", + "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", + 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 @@ -460,142 +404,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 @@ -604,85 +526,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 @@ -690,23 +597,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); @@ -750,8 +654,7 @@ void putEntries() { * KeyStore */ ps("KeyStore", "JCEKS", - "com.sun.crypto.provider.JceKeyStore", - null, null); + "com.sun.crypto.provider.JceKeyStore"); /* * SSL/TLS mechanisms @@ -762,24 +665,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/java/lang/module/ModuleDescriptor.java b/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java index fa359348f6c..f9ebfe1559d 100644 --- a/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java +++ b/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java @@ -333,7 +333,7 @@ public boolean equals(Object ob) { */ @Override public int hashCode() { - int hash = name.hashCode() * 43 + mods.hashCode(); + int hash = name.hashCode() * 43 + modsHashCode(mods); if (compiledVersion != null) hash = hash * 43 + compiledVersion.hashCode(); if (rawCompiledVersion != null) @@ -514,7 +514,7 @@ public int compareTo(Exports that) { */ @Override public int hashCode() { - int hash = mods.hashCode(); + int hash = modsHashCode(mods); hash = hash * 43 + source.hashCode(); return hash * 43 + targets.hashCode(); } @@ -721,7 +721,7 @@ public int compareTo(Opens that) { */ @Override public int hashCode() { - int hash = mods.hashCode(); + int hash = modsHashCode(mods); hash = hash * 43 + source.hashCode(); return hash * 43 + targets.hashCode(); } @@ -2283,7 +2283,7 @@ public int hashCode() { int hc = hash; if (hc == 0) { hc = name.hashCode(); - hc = hc * 43 + Objects.hashCode(modifiers); + hc = hc * 43 + modsHashCode(modifiers); hc = hc * 43 + requires.hashCode(); hc = hc * 43 + Objects.hashCode(packages); hc = hc * 43 + exports.hashCode(); @@ -2568,6 +2568,18 @@ private static String toString(Set mods, String what) { .collect(Collectors.joining(" ")); } + /** + * Generates and returns a hashcode for the enum instances. The returned hashcode + * is a value based on the {@link Enum#name() name} of each enum instance. + */ + private static int modsHashCode(Iterable> enums) { + int h = 0; + for (Enum e : enums) { + h += e.name().hashCode(); + } + return h; + } + private static > int compare(T obj1, T obj2) { if (obj1 != null) { 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/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 51a938f5b57..f09fae47b56 100644 --- a/src/java.base/share/classes/java/security/Security.java +++ b/src/java.base/share/classes/java/security/Security.java @@ -60,6 +60,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 */ @@ -97,115 +100,26 @@ 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); } - - if (overrideAll) { - props = new Properties(); - if (sdebug != null) { - sdebug.println - ("overriding other security properties files!"); - } - } - - // 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) { - 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"); - } - } - } - } - } - } - - if (!loadedProps) { - initializeStatic(); - if (sdebug != null) { - sdebug.println("unable to load security properties " + - "-- using defaults"); - } + loadProps(null, extraPropFile, overrideAll); } /*[IF CRIU_SUPPORT]*/ @@ -223,17 +137,60 @@ private static void initialize() { } } - /* - * 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"); + 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); + } + + is = propURL.openStream(); + if (overrideAll) { + props = new Properties(); + if (sdebug != null) { + sdebug.println + ("overriding other security properties files!"); + } + } + } else { + // unexpected + return false; + } + props.load(is); + if (sdebug != null) { + // 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"); + } + } + } + } } /** 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..2db9cc255dd 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, 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 @@ -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,7 +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}); + ObjectIdentifier.of(KnownOIDs.anyExtendedKeyUsage); static { CertPathHelperImpl.initialize(); @@ -506,7 +502,7 @@ public void setSubjectPublicKeyAlgID(String oid) throws IOException { if (oid == null) { subjectPublicKeyAlgID = null; } else { - subjectPublicKeyAlgID = new ObjectIdentifier(oid); + subjectPublicKeyAlgID = ObjectIdentifier.of(oid); } } @@ -622,7 +618,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 +1101,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; 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 61465e8cbdb..fcb143d80fd 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -2865,22 +2865,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); } } @@ -3300,6 +3298,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/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/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/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/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/SunEntries.java b/src/java.base/share/classes/sun/security/provider/SunEntries.java index bf423e3a388..74897757e54 100644 --- a/src/java.base/share/classes/sun/security/provider/SunEntries.java +++ b/src/java.base/share/classes/sun/security/provider/SunEntries.java @@ -39,6 +39,8 @@ import jdk.crypto.jniprovider.NativeCrypto; 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. @@ -92,18 +94,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); @@ -118,22 +108,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 @@ -146,37 +134,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 @@ -185,31 +164,28 @@ 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 @@ -237,56 +213,45 @@ public static List createAliasesWithOid(String ... oids) { providerSHA512 = "sun.security.provider.SHA5$SHA512"; } - add(p, "MessageDigest", "MD2", "sun.security.provider.MD2", null, attrs); - add(p, "MessageDigest", "MD5", "sun.security.provider.MD5", null, attrs); - add(p, "MessageDigest", "SHA", providerSHA, - 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", providerSHA224, - createAliasesWithOid(sha2BaseOid + ".4"), attrs); - add(p, "MessageDigest", "SHA-256", providerSHA256, - createAliasesWithOid(sha2BaseOid + ".1"), attrs); - add(p, "MessageDigest", "SHA-384", providerSHA384, - createAliasesWithOid(sha2BaseOid + ".2"), attrs); - add(p, "MessageDigest", "SHA-512", providerSHA512, - 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", providerSHA, + attrs); + + addWithAlias(p, "MessageDigest", "SHA-224", providerSHA224, attrs); + addWithAlias(p, "MessageDigest", "SHA-256", providerSHA256, attrs); + addWithAlias(p, "MessageDigest", "SHA-384", providerSHA384, attrs); + addWithAlias(p, "MessageDigest", "SHA-512", providerSHA512, 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); /* @@ -294,22 +259,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 @@ -320,19 +284,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/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/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 773d80c77e3..40e5dc8e1cf 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, 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 @@ -40,10 +40,9 @@ 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; import jdk.crypto.jniprovider.NativeCrypto; /** @@ -75,29 +74,54 @@ 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; private static NativeCrypto nativeCrypto; /** - * 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); } } @@ -124,14 +148,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); } } @@ -139,7 +162,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"); } @@ -147,8 +170,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); } @@ -158,7 +183,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 { @@ -172,11 +197,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); @@ -199,7 +232,7 @@ public static RSAPrivateKey newKey(KeyType type, // see JCA doc @Override public String getAlgorithm() { - return algid.getName(); + return type.keyAlgo; } // see JCA doc @@ -311,9 +344,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; } /** @@ -321,35 +384,15 @@ 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); } 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..af639a2535c 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, 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 @@ -33,9 +33,10 @@ 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 @@ -57,26 +58,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 +111,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,7 +135,7 @@ 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; } 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 ca70dbcb8f0..4f285278c0b 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, 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 @@ -40,9 +40,8 @@ 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; import jdk.crypto.jniprovider.NativeCrypto; /** @@ -67,49 +66,78 @@ 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; private static NativeCrypto nativeCrypto; /** - * 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); @@ -124,9 +152,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"); } @@ -135,8 +163,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); } @@ -159,7 +189,7 @@ static void checkExponentRange(BigInteger mod, BigInteger exp) // see JCA doc @Override public String getAlgorithm() { - return algid.getName(); + return type.keyAlgo; } // see JCA doc @@ -180,22 +210,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); } @@ -204,7 +242,7 @@ 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; } 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..30bceaf0ae8 100644 --- a/src/java.base/share/classes/sun/security/x509/X509CertImpl.java +++ b/src/java.base/share/classes/sun/security/x509/X509CertImpl.java @@ -42,6 +42,7 @@ import javax.security.auth.x500.X500Principal; +import sun.security.jca.JCAUtil; import sun.security.util.*; import sun.security.provider.X509Factory; @@ -130,14 +131,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 +305,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. * @@ -1425,7 +1425,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 +1528,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); @@ -1698,7 +1699,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 +1763,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; } diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index 30751aa7a9e..e5d19a6bdc5 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.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/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/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/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/libfreetype/src/base/ftcolor.c b/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c
    new file mode 100644
    index 00000000000..0edf379b437
    --- /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-2022 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/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..69a3186e1bb 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-map.hh
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-map.hh
    @@ -78,6 +78,10 @@ struct hb_hashmap_t
                     is_used_ (false), is_tombstone_ (false),
                     value () {}
     
    +    // Needed for https://github.com/harfbuzz/harfbuzz/issues/4138
    +    K& get_key () { return key; }
    +    V& get_value () { return value; }
    +
         bool is_used () const { return is_used_; }
         void set_used (bool is_used) { is_used_ = is_used; }
         bool is_tombstone () const { return is_tombstone_; }
    @@ -317,16 +321,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
        */
    @@ -349,21 +343,23 @@ struct hb_hashmap_t
       auto keys_ref () const HB_AUTO_RETURN
       (
         + iter_items ()
    -    | hb_map (&item_t::key)
    +    | hb_map (&item_t::get_key)
       )
       auto keys () const HB_AUTO_RETURN
       (
    -    + keys_ref ()
    +    + iter_items ()
    +    | hb_map (&item_t::get_key)
         | hb_map (hb_ridentity)
       )
       auto values_ref () const HB_AUTO_RETURN
       (
         + iter_items ()
    -    | hb_map (&item_t::value)
    +    | hb_map (&item_t::get_value)
       )
       auto values () const HB_AUTO_RETURN
       (
    -    + values_ref ()
    +    + iter_items ()
    +    | hb_map (&item_t::get_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..ff591cb259f 100644
    --- a/src/java.desktop/share/native/libharfbuzz/hb-subset.cc
    +++ b/src/java.desktop/share/native/libharfbuzz/hb-subset.cc
    @@ -43,17 +43,14 @@
     #include "OT/Color/sbix/sbix.hh"
     #include "hb-ot-os2-table.hh"
     #include "hb-ot-post-table.hh"
    -
    -#if !defined(AIX)
     #include "hb-ot-post-table-v2subset.hh"
    -#endif
    -
     #include "hb-ot-cff1-table.hh"
     #include "hb-ot-cff2-table.hh"
     #include "hb-ot-vorg-table.hh"
     #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 +479,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 +637,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/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/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 63ca048481f..891a466b075 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
    @@ -99,6 +99,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;
    @@ -145,7 +148,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);
    @@ -246,7 +249,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());
         }
    @@ -412,7 +416,7 @@ static PrivateKey privateKey(Session session, long keyID, String algorithm,
             if (keySensitive && (SunPKCS11.mysunpkcs11 != null) && "RSA".equals(algorithm)) {
                 try {
                     byte[] key = SunPKCS11.mysunpkcs11.exportKey(session.id(), attributes, keyID);
    -                RSAPrivateKey rsaPrivKey = RSAPrivateCrtKeyImpl.newKey(key);
    +                RSAPrivateKey rsaPrivKey = RSAPrivateCrtKeyImpl.newKey(KeyType.RSA, "PKCS#8", key);
                     if (rsaPrivKey instanceof RSAPrivateCrtKeyImpl) {
                         return new P11RSAPrivateKeyFIPS(session, keyID, algorithm, keyLength, attributes, (RSAPrivateCrtKeyImpl)rsaPrivKey);
                     } else {
    @@ -544,7 +548,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 de77baf91f4..864461bd29a 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
    @@ -63,6 +63,7 @@
     import sun.security.util.ECUtil;
     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.*;
     import sun.security.pkcs11.TemplateManager;
    @@ -493,10 +494,6 @@ public int hashCode() {
             return System.identityHashCode(this);
         }
     
    -    private static String[] s(String ...aliases) {
    -        return aliases;
    -    }
    -
         byte[] exportKey(long hSession, CK_ATTRIBUTE[] attributes, long keyId) throws PKCS11Exception {
             // Generating the secret key that will be used for wrapping and unwrapping.
             CK_ATTRIBUTE[] wrapKeyAttributes = token.getAttributes(TemplateManager.O_GENERATE, CKO_SECRET_KEY, CKK_AES, new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY), new CK_ATTRIBUTE(CKA_VALUE_LEN, 256 >> 3) });
    @@ -651,11 +648,11 @@ 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;
    @@ -698,10 +695,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];
    @@ -763,51 +766,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,
    @@ -816,18 +805,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));
    @@ -843,12 +834,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,
    @@ -856,8 +847,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));
     
    @@ -865,24 +855,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));
    @@ -890,7 +879,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));
    @@ -898,7 +887,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,
    @@ -907,47 +897,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,
    @@ -955,56 +938,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));
    @@ -1018,30 +991,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));
    @@ -1056,7 +1020,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",
    @@ -1363,7 +1327,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;
    @@ -1383,17 +1347,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.ec/share/classes/sun/security/ec/SunEC.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java
    index 895567c6656..3506ce7e2f8 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
    @@ -33,11 +33,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.*;
     
     import jdk.crypto.jniprovider.NativeCrypto;
     
    @@ -106,6 +106,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) {
    @@ -113,9 +120,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
    @@ -344,7 +350,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
    @@ -352,7 +358,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();
    @@ -364,10 +369,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(",");
                 }
     
    @@ -378,10 +382,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();
     
    @@ -399,25 +401,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",
    @@ -449,11 +446,11 @@ void putEntries(boolean useFullImplementation) {
             ) {
                 putService(new ProviderService(this, "KeyPairGenerator",
                     "EC", "sun.security.ec.NaticeECKeyPairGenerator",
    -                new String[] { "EllipticCurve" }, ATTRS));
    +                List.of("EllipticCurve"), ATTRS));
             } else {
                 putService(new ProviderService(this, "KeyPairGenerator",
                     "EC", "sun.security.ec.ECKeyPairGenerator",
    -                new String[] { "EllipticCurve" }, ATTRS));
    +                List.of("EllipticCurve"), ATTRS));
             }
     
             /*
    @@ -476,12 +473,12 @@ 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));
     
             if (useNativeXDHKeyGen
                 && (NativeCrypto.getVersionIfAvailable() >= NativeCrypto.OPENSSL_VERSION_1_1_1)
    @@ -489,21 +486,21 @@ private void putXDHEntries() {
             ) {
                 putService(new ProviderService(this, "KeyPairGenerator",
                     "XDH", "sun.security.ec.NativeXDHKeyPairGenerator", null, ATTRS));
    -            putService(new ProviderService(this, "KeyPairGenerator",
    +            putService(new ProviderServiceA(this, "KeyPairGenerator",
                     "X25519", "sun.security.ec.NativeXDHKeyPairGenerator.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.NativeXDHKeyPairGenerator.X448",
    -                new String[]{"1.3.101.111", "OID.1.3.101.111"}, ATTRS));
    +                ATTRS));
             } else {
                 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));
             }
     
             if (useNativeXDHKeyAgreement
    @@ -512,22 +509,21 @@ private void putXDHEntries() {
             ) {
                 putService(new ProviderService(this, "KeyAgreement",
                     "XDH", "sun.security.ec.NativeXDHKeyAgreement", null, ATTRS));
    -            putService(new ProviderService(this, "KeyAgreement",
    +            putService(new ProviderServiceA(this, "KeyAgreement",
                     "X25519", "sun.security.ec.NativeXDHKeyAgreement.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.NativeXDHKeyAgreement.X448",
    -                new String[]{"1.3.101.111", "OID.1.3.101.111"}, ATTRS));
    +                ATTRS));
             } else {
                 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/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/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.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/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/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.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/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt
    index 7416cbfc5ff..b67ccf64e98 100644
    --- a/test/hotspot/jtreg/ProblemList.txt
    +++ b/test/hotspot/jtreg/ProblemList.txt
    @@ -40,9 +40,62 @@
     
     # :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
    @@ -101,6 +154,7 @@ gc/stress/gcold/TestGCOldWithCMS.java 8272195 generic-i586
     
     # :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 67934202149..57531725840 100644
    --- a/test/hotspot/jtreg/runtime/appcds/TestCommon.java
    +++ b/test/hotspot/jtreg/runtime/appcds/TestCommon.java
    @@ -147,7 +147,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");
         }
     
    @@ -197,7 +197,7 @@ public static OutputAnalyzer runWithArchive(AppCDSOptions opts)
                 }
             }
     
    -        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmd);
    +        ProcessBuilder pb = ProcessTools.createTestJvm(cmd);
             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/TestJmapCore.java b/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java
    index b9ac66e23e0..717c0e98a15 100644
    --- a/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java
    +++ b/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java
    @@ -86,7 +86,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 f3b50ab2f92..ee0b7a9a5c5 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -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 @@ -746,7 +741,7 @@ 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 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/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/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/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..9c32a334639 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/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 e41e3ae4225..f9b4cd2bcff 100644 --- a/test/jdk/java/lang/StringBuilder/HugeCapacity.java +++ b/test/jdk/java/lang/StringBuilder/HugeCapacity.java @@ -21,37 +21,38 @@ * questions. */ -/* - * =========================================================================== - * (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved - * =========================================================================== - */ - /** * @test * @bug 8149330 * @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 -XX:+CompactStrings 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/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/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/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/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/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..df578274faa 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 * @summary Check root CA entries in cacerts file */ import java.io.ByteArrayInputStream; @@ -47,13 +47,12 @@ public class VerifyCACerts { + File.separator + "security" + File.separator + "cacerts"; // The numbers of certs now. - private static final int COUNT = 97; + private static final int COUNT = 96; // 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"; - + = "9B:AF:A2:BD:88:C9:74:05:7F:DD:F3:97:85:21:18:4A:52:F0:07:CC:46:FD:2B:90:BA:FB:57:09:18:3B:66:0F"; // 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]", @@ -290,8 +287,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/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/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/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 844e85055b8..6a75f7f229a 100644 --- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java +++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java @@ -261,7 +261,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"); } @@ -409,7 +409,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