On Wed, 10 May 2023 10:03:46 GMT, Sergey Chernyshev <d...@openjdk.org> wrote:

>> Hi all,
>> 
>> I would like to propose a patch for an issue discussed in [1][2] that fixes 
>> an OOME in the current code base. The issue appears when a SunJCE provider 
>> object reference is stored in a non-static variable, which eventually leads 
>> to a Java heap OOME.
>> 
>> The solution proposed earlier [1] raised a concern that the identity of 
>> provider objects may be somehow broken when using `WeakHashMap<Class<? 
>> extends Provider>, Object>` instead of `IdentityHashMap<Provider, Object>`. 
>> The solution hasn't been integrated that time. Later in 2019 a performance 
>> improvement was introduced with [3][4] that changed `IdentityHashMap` to 
>> `ConcurrentHashMap` of `IdentityWrapper<Provider> `objects that maintained 
>> the object identity while improved performance.
>> 
>> The solution being proposed keeps up with performance improvement in [3], 
>> further narrowing the synchronization down to the hash table node, avoids 
>> lambdas that may cause startup time regressions and maintains providers 
>> identity using `WeakIdentityWrapper` that extends `WeakReference<Object>` 
>> while avoiding depletion of Java heap by using weak pointers as the mapping 
>> key. Once a provider object becomes weakly reachable it is queued along with 
>> its reference object to the `ReferenceQueue` (a new static member in 
>> `JceSecurity`). The `equals()` method of the `WeakIdentityWrapper` will 
>> never match a new wrapper object to anything inside the hash table after the 
>> corresponding element's `WeakReference.get()` returned null. This leads to 
>> accumulating "empty" elements in the hash table. The new static function 
>> `expungeStaleWrappers()` drops the "empty" elements queued by GC each time 
>> the `getVerificationResult()` method is called.
>> 
>> `ConcurrentHashMap`'s `computeIfAbsent()` does (partially) detect recursive 
>> updates for keys that are being added to empty bins. For such keys an 
>> `IllegalStateException` is thrown prior to recursive execution of the 
>> `mappingFunction`. For nodes that are added to existing TreeBins or linked 
>> lists, in which case no recursion detection is done prior to calling 
>> `mappingFunction`, the recursion detection relies on old method with 
>> `IdentityMap` of Providers.
>> 
>> I include a test that runs under memory constrained conditions (128M) that 
>> hits the heap limit in current VMs where it is impossible to reclaim 
>> providers' memory (unless they've been cached under weak references). The 
>> updated jdk versions pass the test.
>> 
>> Testing: jtreg + JCK on a downport of the patch to JDK 17 with no 
>> regressio...
>
> Sergey Chernyshev has updated the pull request incrementally with one 
> additional commit since the last revision:
> 
>   addressed review comment

Marked as reviewed by valeriep (Reviewer).

-------------

PR Review: https://git.openjdk.org/jdk/pull/13658#pullrequestreview-1425046189

Reply via email to