On Tue, 27 Jan 2026 18:09:57 GMT, Phil Race <[email protected]> wrote:
>> src/java.desktop/share/classes/javax/swing/UIManager.java line 247:
>>
>>> 245: */
>>> 246: private static LAFState getLAFState() {
>>> 247: return LAF_STATE;
>>
>> I think you still have to use `synchronized (classLock)`, otherwise
>> `LAF_STATE.initialized` in `isLafStateInitialized` could return a stale
>> value.
>
> The existing code only used that when creating the instance, not when
> retrieving an already created instance, so I don't see why we'd need to
> extend the lock to the retrieval.
Indeed, the existing code use the lock only when creating the instance.
Yet there are quite a few places where `synchronized (classLock)` is used. In
particular, `maybeInitialize` method.
https://github.com/openjdk/jdk/blob/eb6e74b1fa794bf16f572d5dbce157d1cae4c505/src/java.desktop/share/classes/javax/swing/UIManager.java#L1461-L1468
The logic in `maybeInitialize` will remain thread-safe, yet
`SwingAccessor.isLafStateInitialized` can return a stale value of `false`.
Thus, `SwingAccessor.getLAFStateAccessor().lafStateIsInitialized()` in
`DefaultMetalTheme` can return `false` even after `UIManager` was initialised.
I guess this problem existed in the original code, too.
To ensure thread-safe access to the `initialized` flag, the method
`UIManager.isLafStateInitialized` has to access the flag inside the
`synchronized (classLock)` block.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/29437#discussion_r2733775328