Hi,

On 07/16/2018 02:10 PM, Alan Bateman wrote:
On 11/07/2018 14:27, Adam Farley8 wrote:
Hi All,

-- Summary:

When calling "ResourceBundle.getBundle(String, Locale, ClassLoader)" on
JDK8, the ClassLoader can get GC'd before we're finished with it.

This can result in us getting the wrong result back, like if we asked for "Stuff" with the locale "fr, CA" and got back "Stuff_fr.class" instead of
"Stuff_fr_CA.class".

-- Likely Cause:

Inside the CacheKey object in the getBundleImpl method, we use a soft
reference that can result in the ClassLoader object getting GC'd before
we're done with it.

-- Example Fix:

One fix proven to work is to create a static, volatile Object with global
scope in ResourceBundle, and compare it ("==" style) to the loader right
before it gets returned from getBundleImpl.

The result of the compare can be something direct like "throw new
Error("Unexpected error.")", as this compare should never return true.

-- Only seen on...

This defect is only seen on JDK8, on ppcle and zLinux, and hasn't yet been
seen using the Hotspot VM (defect found using OpenJ9 VM).

ResourceBundle has changed significantly since JDK 8 so I'm curious if you have studied the implementation in the mainline (jdk/jdk) to see if the issue is possible there. If it's still a bug then I assume we would want to fix it in jdk/jdk first before thinking about a back port.

-Alan

Checking the differences shows that instead of WeakReference<ClassLoader>, CacheKey uses two WeakReference<Module> instead in JDK 9+. One is the caller module and the other is the module of the bundle (unnamed module if ClassLoader is used to search for the bundle). The caller module is guaranteed to stay reachable for the entire call (as it holds the calling code), but the Module of the bundle could go out of scope during the call, so I think there is a theoretical possibility that the lookup CacheKey becomes non-equal to a key in the cache before the cache lookup is executed.

Placing Reference.reachabilityFence(module) at the right place(s) should help eliminate the possibility. The fix for JDK 8 can not use Reference.reachabilityFence(module) as it is JDK 9+ API, but as we learned, an empty static method taking an Object parameter is equivalent to Reference.reachabilityFence() at least in the HotSpot VM. That might not be true for J9 VM though...

Regards, Peter


Reply via email to