On Tue, 25 Apr 2023 21:16:41 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 regressions
> 
> [1] https://mail.openjdk.org/pipermail/security-dev/2016-October/015024.html
> [2] https://bugs.openjdk.org/browse/JDK-8168469
> [3] https://bugs.openjdk.org/browse/JDK-7107615
> [4] 
> https://github.com/openjdk/jdk/commit/74d45e481d1ad6aa5d7c6315ea86681e1a978ce0

@valeriepeng Could you please take a look at this change?

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

PR Comment: https://git.openjdk.org/jdk/pull/13658#issuecomment-1534961823

Reply via email to