RFR: 8223260: NamingManager should cache InitialContextFactory

Seán Coffey sean.coffey at oracle.com
Fri Jan 31 13:16:10 UTC 2020


Thanks for the review Peter. All good points! My latest patch contains 
adjustments based on feedback from you and others to date.

* Incorporate use of ClassLoaderValue -
  -- I'd appreciate feedback on whether I'm using it correctly.
* Use of ServiceLoader.stream()
* adjusted test for both the ServiceLoader and legacy classpath load 
approach
* insert use of sleep which testing GC.

http://cr.openjdk.java.net/~coffeys/webrev.8223260.v2/webrev/

regards,
Sean.

On 30/01/2020 07:59, Peter Levart wrote:
> Hi Seán,
>
> WeakHashMap is not safe to be called concurrently. Even get() method, 
> although it may seem read-only, can modify internal state (expunging 
> stale Weak entries), so holding a READ lock while accessing 
> WeakHashMap it is wrong.
>
> getInitialContext() static method is called with an env Hashtable 
> which means it can be called with different keys/values for the same 
> TCCL. So caching of InitialContextFactory is just performed for the 
> 1st call for a particular TCCL. Subsequent calls for the same TCCL and 
> different class names are not cached. Is this the behavior you are 
> pursuing? You could cache the factory using (TCCL, class name) as a 
> compound key.
>
> Also, by caching in a WeakHashMap<ClassLoader, InitialContextFactory>, 
> you make a strong reference to InitialContextFactory from class loader 
> of the NamingManager.class and such InitialContextFactory may 
> indirectly reference the ClassLoader key of the same entry, so it will 
> never go away because NamingManager class is never going away. You 
> should at least use a WeakHashMap<ClassLoader, 
> WeakReference<InitialContextFactory>> for that.
>
> Shameless plug: there is a JDK internal class 
> jdk.internal.loader.ClassLoaderValue which you might be able to use 
> for caching if a part of your key is a ClassLoader. From the javadoc:
>
>  * ClassLoaderValue allows associating a
>  * {@link #computeIfAbsent(ClassLoader, BiFunction) computed} non-null 
> value with
>  * a {@code (ClassLoader, keys...)} tuple. The associated value, as 
> well as the
>  * keys are strongly reachable from the associated ClassLoader so care 
> should be
>  * taken to use such keys and values that only reference types 
> resolvable from
>  * the associated ClassLoader. Failing that, ClassLoader leaks are 
> inevitable.
>
> So if you know that the InitialContextFactory instance is always 
> resolvable (by class name) from the ClassLoader you are using for the 
> caching key (the TCCL), then this utility might be just right for your 
> purpose.
>
> Regards, Peter
>
>
> On 1/29/20 6:22 PM, Seán Coffey wrote:
>> Thanks for the reviews. I found an issue with the new test also -
>>
>> it's loading the custom factory class via the non-serviceloader 
>> approach. I was hoping to exercise ServiceLoader here. I'll address 
>> this and the comments raised and revert with a new patch shortly.
>>
>> Regards,
>> Sean.
>>
>> On 29/01/20 16:27, Alan Bateman wrote:
>>> On 29/01/2020 15:55, Daniel Fuchs wrote:
>>>> Hi Seán,
>>>>
>>>>> http://cr.openjdk.java.net/~coffeys/webrev.8223260.v1/webrev/
>>>>> A WeakHashKey with the TCCL as the key should be okay here.
>>>>
>>>> If the TCCL is the key then there are good chances that the
>>>> concrete factory class is expected to be loaded by the TCCL.
>>>>
>>>> If that happens then the value will reference the key and
>>>> nothing will ever get garbage collected.
>>> I don't know how much JNDI is used much beyond LDAP these days but 
>>> you are right that a factory with a strong ref to the TCCL would 
>>> prevent it from being GC'ed.  The internal WeakPairMap might be 
>>> useful here.
>>>
>>> -Alan
>>
>


More information about the core-libs-dev mailing list