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
