Java 8 lambda 闭包和 GC

SvS*_*SvS 5 java lambda garbage-collection

我对 java 8 的“闭包”有点困惑。据说它会以高于价值的价格收盘。考虑下面的课程。

public class SomeClassWithLargeMemoryFootprint {
     //some state
     private SomeObject someObj;
     //some more state

     public void doSomething(SomeAsyncHelper helper) {
         helper.doAsync( () -> {
                             //some super slow operation
                             int foo = someObj.whatever();
                             //some more stuff    
                       });
     }
}
Run Code Online (Sandbox Code Playgroud)

//Let's assume SomeAsyncHelper.doAsync takes a VoidRunner that looks like below
interface VoidRunner {
    void apply();
}
Run Code Online (Sandbox Code Playgroud)

问题是,当异步助手仍在工作时,SomeClassWithLargeMemoryFootprint 的实例是否可以被 GC 处理?我很清楚“someObj”不能被 GC,因为 doSomething() 中的 lambda 需要它。该州其他地区怎么样?

另外,请考虑以下变体,我们调用包含类的成员方法:

public class SomeClassWithLargeMemoryFootprint {
     //some state
     private SomeObject someObj;
     //some more state

     public void doSomething(SomeAsyncHelper helper) {
         helper.doAsync( () -> {
                //do something
                memberMethod();
                //do something else
                });
     }

     private void memberMethod() {
         //do something
     }

}
Run Code Online (Sandbox Code Playgroud)

现在怎么办?“helper”如何知道如何执行“memberMethod”?它是否获得对 SomeClassWithLargeMemoryFootprint 实例的引用?GC 序列是什么?

JB *_*zet 3

当异步助手仍在工作时,可以对 SomeClassWithLargeMemoryFootprint 的实例进行 GC 吗?

不会。VoidRunner 实例对其封闭的 SomeClassWithLargeMemoryFootprint 对象具有强引用,并且本身由异步任务执行器以某种方式引用。所以不能GC。

该州其他地区怎么样?

状态的其余部分由 SomeClassWithLargeMemoryFootprint 的实例引用,因此无法进行 GC。

“helper”如何知道如何执行“memberMethod”

someObj它知道如何在第一个示例中访问(即)的方式相同this.someObj:它具有对其封闭的 SomeClassWithLargeMemoryFootprint 对象(即)的引用this

  • @SaivivekhSwaminathan:完全正确;lambda 表达式不仅仅是语法糖。请参阅[Java8 lambda 是否像匿名类一样维护对其封闭实例的引用?](/sf/ask/1991263851/) 和[lambda 表达式每次执行时都会在堆上创建一个对象吗?] (/sf/ask/1926711181/) (2认同)