On Wed, 7 Oct 2026 13:12:32 GMT, Chris Hegarty <[email protected]> wrote:

> Fixes a rare NullPointerException in X500Principal.hashCode() and equals() on 
> aarch64, where thisX500Name is null.
> 
> I made `thisX500Name` final. The field was non-final only because 
> `readObject` sets it, and deserialization doesn't run a constructor. I used 
> `Unsafe.putReference` in `readObject` for that, which is how the JDK handles 
> this elsewhere:
> 
> - [x] I confirm that I make this contribution in accordance with the [OpenJDK 
> Interim AI Policy](https://openjdk.org/legal/ai).

src/java.base/share/classes/javax/security/auth/x500/X500Principal.java line 
553:

> 551:     private static final Unsafe UNSAFE = Unsafe.getUnsafe();
> 552:     private static final long X500NAME_OFFSET =
> 553:         UNSAFE.objectFieldOffset(X500Principal.class, "thisX500Name");

Hello Chris, as far as I can see, the pre-existing implementation in the 
`X500Principal` class is doing the right thing by not marking the field as a 
`final`, since that field does get updated after construction of the 
`X500Principal`. So although this proposed solution would fix the issue, I 
think it feels a bit odd to see the use of `Unsafe` and the "forced" `final` 
field in this class.

The actual issue (as you have explained in the JBS description) arises from the 
implementation in `X500Name` which allows concurrent access to the 
`x500Principal` field without proper concurrency protections. I think it would 
be easier to follow and more natural to do the fix in `X500Name` by introducing 
the necessary synchronization construct for the `x500Principal` field.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/33253#discussion_r4218978483

Reply via email to