RFR: 8161203: ResourceBundle.getBundle performance regression

Peter Levart peter.levart at gmail.com
Thu Jul 21 19:59:28 UTC 2016


Hi Claes and Masayoshi again,

Ah sorry, I totally missed the part that skips looking up of the 
providers for unnamed module. Here's that part included:

http://cr.openjdk.java.net/~plevart/jdk9-dev/ResourceBundle.cleanup/webrev.03/

Regards, Peter


On 07/21/2016 09:49 PM, Peter Levart wrote:
> Hi Claes and Masayoshi,
>
> On 07/21/2016 06:54 PM, Claes Redestad wrote:
>> Doesn't this fail to address part of the regression, i.e., we 
>> shouldn't go into various privileged actions at all if the module is 
>> unnamed?
>>
>> /Claes
>
> Right, it addresses the part that lazily looks up providers via 
> service loader instead of in CacheKey constructor, but it introduces a 
> regression where previously the privileged action was not executed if 
> the lookup for providers failed (couldn't load the provider type or 
> ServiceLoader threw ServiceConfigurationError) as opposed to when the 
> lookup was successful but didn't find any providers in which case the 
> privileged action was executed and returned null, but it also set 
> cacheKey.callerHasProvider = Boolean.FALSE if it was null. A slight 
> semantical difference. I wonder if it was intended.
>
> Anyway, here's how the old behavior can be restored:
>
> http://cr.openjdk.java.net/~plevart/jdk9-dev/ResourceBundle.cleanup/webrev.02/
>
> Regards, Peter
>
>
>>
>> On 2016-07-21 18:16, Peter Levart wrote:
>>> Hi Masayoshi,
>>>
>>> The whole story about InterruptedException (in my previous message) 
>>> is moot. I have checked all the places where the 'cause' is reported 
>>> into the CacheKey and there's nowhere a possibility that an 
>>> InterruptedException would get set. So the cloning of cacheKey (in 
>>> line 1766) and checking for InterruptedException in the clone can 
>>> all be just removed from the code.
>>>
>>> Code around providers can be simplified too. Without the need for a 
>>> boolean flag, you just have to change the signature of 'providers' 
>>> field from ServiceLoader<ResourceBundleProvider> to 
>>> Iterable<ResourceBundleProvider> and assign a 
>>> Collections.emptyList() to it in clone().
>>>
>>> getServiceLoader() method(s) can similarly just return 
>>> Collections.emptyList() instead of null after changing their 
>>> signature(s). CacheKey does not need a hasProviders() method and any 
>>> checking for null can get away.
>>>
>>> I also found a race in putBundleInCache() method. It tries hard to 
>>> return the bundle that gets installed into cache 1st, but it doesn't 
>>> try hard enough. If there is an expired entry already in the cache, 
>>> it just overwrites it with new bundle, but doesn't take into account 
>>> the possibility that two or more threads can do the same thing - 
>>> just overwrite each other's entry and each return its own instance 
>>> to the caller.
>>>
>>> The effort that the code takes in this method to prevent the newly 
>>> allocated BundleReference from being enqueued into the 
>>> ReferenceQueue is also moot. The reference will only get discovered 
>>> and enqueued if it remains reachable. If if doesn't get installed 
>>> into the cache it will be GCed and not enqueued.
>>>
>>> All of the above can be fixed in the following way:
>>>
>>> http://cr.openjdk.java.net/~plevart/jdk9-dev/ResourceBundle.cleanup/webrev.01/ 
>>>
>>>
>>>
>>> Take whatever you want from it. The rest can be included in some new 
>>> cleanup task if you like it.
>>>
>>> Regards, Peter
>>>
>>>
>>> On 07/21/2016 03:13 PM, Peter Levart wrote:
>>>> Hi Masayoshi,
>>>>
>>>> Previously the CacheKey::clone() method cleared a reference to 
>>>> 'providers' in the clone making the provides unreachable from the 
>>>> clone and making the clone unable to obtain providers. Now you also 
>>>> reset the 'providersChecked' flag which makes the clone be able to 
>>>> re-obtain the providers. This is dangerous as the clone is used as 
>>>> a key in the cache and is strongly reachable from the cache. A 
>>>> slight future modification of code could unintentionally produce a 
>>>> class loader leak. To prevent that, I would somehow mark the clone 
>>>> so that any attempt to invoke getProviders() on the clone would 
>>>> throw IllegalStateException.
>>>>
>>>> Regards, Peter
>>>>
>>>> On 07/21/2016 06:14 AM, Masayoshi Okutsu wrote:
>>>>> Hi,
>>>>>
>>>>> Please review the fix for JDK-8161203. The fix is to lazily load 
>>>>> ResourceBundleProviders. It's not necessary to load providers 
>>>>> before cache look-up.
>>>>>
>>>>> Issue:
>>>>> https://bugs.openjdk.java.net/browse/JDK-8161203
>>>>>
>>>>> Webrev:
>>>>> http://cr.openjdk.java.net/~okutsu/9/8161203/webrev.01
>>>>>
>>>>> Thanks,
>>>>> Masayoshi
>>>>>
>>>>
>>>
>>
>



More information about the jigsaw-dev mailing list