diff --git a/src/java.base/share/classes/java/security/PKCS12Attribute.java b/src/java.base/share/classes/java/security/PKCS12Attribute.java index 114660c06f8..fd844dc7f4d 100644 --- a/src/java.base/share/classes/java/security/PKCS12Attribute.java +++ b/src/java.base/share/classes/java/security/PKCS12Attribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ import java.io.IOException; import java.math.BigInteger; import java.util.Arrays; import java.util.regex.Pattern; + +import jdk.internal.vm.annotation.Stable; import sun.security.util.*; /** @@ -45,7 +47,9 @@ public final class PKCS12Attribute implements KeyStore.Entry.Attribute { private String name; private String value; private final byte[] encoded; - private int hashValue = -1; + + @Stable + private int hashValue; /** * Constructs a PKCS12 attribute from its name and value. @@ -207,7 +211,7 @@ public final class PKCS12Attribute implements KeyStore.Entry.Attribute { @Override public int hashCode() { int h = hashValue; - if (h == -1) { + if (h == 0) { hashValue = h = Arrays.hashCode(encoded); } return h; diff --git a/src/java.base/share/classes/java/security/cert/URICertStoreParameters.java b/src/java.base/share/classes/java/security/cert/URICertStoreParameters.java index b73383cf3d5..0080bb7bc28 100644 --- a/src/java.base/share/classes/java/security/cert/URICertStoreParameters.java +++ b/src/java.base/share/classes/java/security/cert/URICertStoreParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package java.security.cert; +import jdk.internal.vm.annotation.Stable; + import java.net.URI; /** @@ -57,7 +59,8 @@ public final class URICertStoreParameters implements CertStoreParameters { /* * Hash code for this parameters object. */ - private int myhash = -1; + @Stable + private int myhash; /** * Creates an instance of {@code URICertStoreParameters} with the @@ -105,10 +108,11 @@ public final class URICertStoreParameters implements CertStoreParameters { */ @Override public int hashCode() { - if (myhash == -1) { - myhash = uri.hashCode()*7; + int h = myhash; + if (h == 0) { + myhash = h = uri.hashCode()*7; } - return myhash; + return h; } /** diff --git a/test/jdk/java/security/PKCS12Attribute/HashCode.java b/test/jdk/java/security/PKCS12Attribute/HashCode.java index 21d2fd1f7f2..58217214321 100644 --- a/test/jdk/java/security/PKCS12Attribute/HashCode.java +++ b/test/jdk/java/security/PKCS12Attribute/HashCode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,18 +23,98 @@ /* * @test - * @bug 8200792 - * @summary PKCS12Attribute#hashCode is always constant -1 + * @bug 8200792 8355379 + * @summary Tests PKCS12Attribute#hashCode correctness, stability, and caching after Stable annotation fix */ - import java.security.PKCS12Attribute; +import java.util.HashSet; +import java.util.Set; public class HashCode { public static void main(String[] args) throws Exception { int h1 = new PKCS12Attribute("1.2.3.4", "AA").hashCode(); int h2 = new PKCS12Attribute("2.3.4.5", "BB,CC").hashCode(); if (h1 == -1 || h2 == -1 || h1 == h2) { - throw new Exception("I see " + h1 + " and " + h2); + throw new Exception("Unexpected hashCodes: " + h1 + " and " + h2); + } + + PKCS12Attribute attr1 = new PKCS12Attribute("1.2.3.4", "AA"); + + // Equality and hash code consistency + testHashCode(attr1); + + // Inequality and hash code difference + testInequality(new PKCS12Attribute("1.2.3.4", "AA"), + new PKCS12Attribute("1.2.3.4", "BB")); + testInequality(new PKCS12Attribute("1.2.3.4", "AA"), + new PKCS12Attribute("2.3.4.5", "AA")); + + // Repeated hashCode consistency + testRepeatHashCode(attr1); + + // Hash code uniqueness stress test + testHashCodeUniqueness(); + } + + private static void testHashCode(PKCS12Attribute attr) throws Exception { + int originalHash = attr.hashCode(); + + PKCS12Attribute reconstructed = new PKCS12Attribute(attr.getName(), attr.getValue()); + + if (!attr.equals(reconstructed)) { + throw new Exception("Equality failed for: name=" + attr.getName() + + ", value=" + attr.getValue()); + } + + int newHash = reconstructed.hashCode(); + if (originalHash != newHash) { + throw new Exception("Hash code mismatch for: name=" + attr.getName() + + ", original=" + originalHash + ", new=" + newHash); + } + + System.out.println("Pass: name=" + attr.getName() + ", value=" + attr.getValue() + + ", hashCode=" + originalHash); + } + + private static void testInequality(PKCS12Attribute a1, PKCS12Attribute a2) throws Exception { + if (a1.equals(a2)) { + throw new Exception("Unexpected equality: name=" + a1.getName() + + ", values=" + a1.getValue() + " vs " + a2.getValue()); + } + + if (a1.hashCode() == a2.hashCode()) { + System.out.println("Warning: Different attributes share hashCode: " + a1.hashCode()); + } else { + System.out.println("Pass: name=" + a1.getName() + + ", values differ and hashCodes differ"); } } + + private static void testRepeatHashCode(PKCS12Attribute attr) throws Exception { + int h1 = attr.hashCode(); + int h2 = attr.hashCode(); + + if (h1 != h2) { + throw new Exception("Inconsistent hashCode for: name=" + attr.getName() + + ", value=" + attr.getValue()); + } + + System.out.println("Pass: repeat hashCode consistency for name=" + attr.getName()); + } + + private static void testHashCodeUniqueness() { + Set seen = new HashSet<>(); + int collisions = 0; + + for (int i = 0; i < 1000; i++) { + PKCS12Attribute attr = new PKCS12Attribute("1.2.3." + i, "V" + i); + if (!seen.add(attr.hashCode())) { + System.out.println("Hash collision: name=" + attr.getName() + + ", value=" + attr.getValue()); + collisions++; + } + } + + System.out.println("Hash uniqueness test complete. Collisions: " + collisions); + } } diff --git a/test/jdk/java/security/cert/URICertStoreParameters/TestBasic.java b/test/jdk/java/security/cert/URICertStoreParameters/TestBasic.java index ed96d32a5c7..e62c1d469bd 100644 --- a/test/jdk/java/security/cert/URICertStoreParameters/TestBasic.java +++ b/test/jdk/java/security/cert/URICertStoreParameters/TestBasic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,10 +24,12 @@ import java.security.cert.CertStore; import java.security.cert.URICertStoreParameters; import java.net.URI; +import java.util.HashSet; +import java.util.Set; /* * @test - * @bug 8038084 + * @bug 8038084 8355379 * @summary Basic testing for URICertStoreParameters * @run main TestBasic */ @@ -37,6 +39,7 @@ public class TestBasic { String str1 = "ldap://myownhost:5000/"; String str2 = "ldap://myownhost:5000/cn=foo"; test(str1, str2); + testRepeatedHashCode(str1); System.out.println("Test passed"); } @@ -68,4 +71,15 @@ public class TestBasic { throw new Exception("Error: p1/p1Too should NOT equal p2"); } } + + private static void testRepeatedHashCode(String str) throws Exception { + System.out.println("Testing repeated hashCode consistency"); + URICertStoreParameters p = new URICertStoreParameters(new URI(str)); + int h1 = p.hashCode(); + int h2 = p.hashCode(); + if (h1 != h2) { + throw new Exception("hashCode inconsistent across calls"); + } + System.out.println("hashCode consistency verified"); + } }