On Thu, 9 Feb 2023 18:11:18 GMT, Volker Simonis <simo...@openjdk.org> wrote:

>> Prior to 
>> [JDK-8239384](https://bugs.openjdk.org/browse/JDK-8239384)/[JDK-8238358](https://bugs.openjdk.org/browse/JDK-8238358)
>>  LambdaMetaFactory has created VM-anonymous classes which could easily be 
>> unloaded once they were not referenced any more. Starting with JDK 15 and 
>> the new "hidden class" based implementation, this is not the case any more, 
>> because the hidden classes will be strongly tied to their defining class 
>> loader. If this is the default application class loader, these hidden 
>> classes can never be unloaded which can easily lead to Metaspace exhaustion 
>> (see the [test case in the JBS 
>> issue](https://bugs.openjdk.org/secure/attachment/102601/LambdaClassLeak.java)).
>>  This is a regression compared to previous JDK versions which some of our 
>> applications have been affected from when migrating to JDK 17.
>> 
>> The reason why the newly created hidden classes are strongly linked to their 
>> defining class loader is not clear to me. JDK-8239384 mentions it as an 
>> "implementation detail":
>> 
>>> *4. the lambda proxy class has the strong relationship with the class 
>>> loader (that will share the VM metaspace for its defining loader - 
>>> implementation details)*
>> 
>> From my current understanding the strong link between a hidden class created 
>> by `LambdaMetaFactory` and its defining class loader is not strictly 
>> required. In order to prevent potential OOMs and fix the regression compared 
>> the JDK 14 and earlier I propose to create these hidden classes without the 
>> `STRONG` option.
>> 
>> I'll be happy to add the test case as JTreg test to this PR if you think 
>> that would be useful.
>
> Volker Simonis has updated the pull request incrementally with two additional 
> commits since the last revision:
> 
>  - Remove assertions which insist on Lambda proxy classes being strongly 
> linked to their class loader
>  - Removed unused import of STRONG und updated copyright year

Even in JDK 11, a lambda proxy classes that's referenced by the cpCache (i.e., 
from a resolved invokedynamic instruction associated with a lamda expression) 
is always kept alive. See test below.

So if I understand correctly, this patch will not affect lamda expressions in 
Java source code. It affects only direct calls to 
`LambdaMetafactory.metafactory()`. Is this correct?


public class LambdaGC {
    public static void main(String[] args) throws Throwable  {
      System.out.println("Entering LambdaGC");
      doit(() -> {
          Thread.dumpStack();
      });
      for (int i = 0; i < 10; i++) {
            System.gc();
      }
      System.out.println("Finish LambdaGC");
    }
    static void doit(Runnable r) {
        r.run();
    }
}

$ java11 -cp . -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames 
-Xlog:class+load -Xlog:class+unload LambdaGC | grep LambdaGC
[0.022s][info][class,load] LambdaGC source: file:/jdk3/tmp/
Entering LambdaGC
[0.024s][info][class,load] LambdaGC$$Lambda$1/0x0000000840060840 source: 
LambdaGC
java.lang.Exception: Stack trace
        at java.base/java.lang.Thread.dumpStack(Thread.java:1387)
        at LambdaGC.lambda$main$0(LambdaGC.java:5)
        at LambdaGC$$Lambda$1/0x0000000840060840.run(<Unknown>:1000000)
        at LambdaGC.doit(LambdaGC.java:13)
        at LambdaGC.main(LambdaGC.java:4)
Finish LambdaGC

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

PR: https://git.openjdk.org/jdk/pull/12493

Reply via email to