Java8Lambda闭包和GC

Java8Lambda闭包和GC,java,lambda,garbage-collection,Java,Lambda,Garbage Collection,我对Java8的“闭包”有点困惑。它被认为是价值观的终结。 考虑下面的类。 public class SomeClassWithLargeMemoryFootprint { //some state private SomeObject someObj; //some more state public void doSomething(SomeAsyncHelper helper) { helper.doAsync( () ->

我对Java8的“闭包”有点困惑。它被认为是价值观的终结。 考虑下面的类。

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    
                       });
     }
}

问题是,当异步助手仍在工作时,是否可以对具有大内存足迹的某个类的实例进行GC? 我很清楚,“someObj”不能是GC'd,因为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
     }

}
现在怎么办?“助手”如何知道如何执行“memberMethod”?它是否获得对某个具有较大内存足迹的类的实例的引用?GC序列是什么

当异步助手仍在工作时,是否可以对具有较大内存足迹的某个类的实例进行GC

否。VoidRunner实例对其封闭的SomeClassWithLargeMemoryFootprint对象具有强引用,并且异步任务执行器以某种方式引用了它本身。所以它不可能是普通教育

州里其他地方呢

该状态的其余部分由某个具有较大内存足迹的类的实例引用,因此无法对其进行GCed

“助手”如何知道如何执行“memberMethod”


在第一个示例中,它知道如何访问
someObj
(即
this.someObj
)的方法是一样的:它有一个对其封闭的SomeClassWithLargeMemoryFootprint对象的引用(即
this
)。

据我所知,Java中的GCs使用引用计数,Java中的lambdas只是内联类的一些语法糖。长话短说:它的工作原理就像您要用一个内联类实现所有这些一样。由于内联类是私有类,因此始终可以访问周围的对象(及其属性和方法)。引用计数负责对象的其余部分和正确释放(也就是在lambda被执行之后)。这确实是一个重复,但有一个不同的问题:。另见,酷。。谢谢匿名类持有对封闭类的引用这一事实清楚地表明了这一点。接下来的问题是:当我不访问lambda中封闭类的任何成员时,有没有办法打破对封闭类的强引用?我的意思是一种简洁的方式,与使用lambda的方便性没有太大的区别。不是一个实现lambda接口的具体类。我想我可以创建一个带有lambda的接口的静态最终实例,并将其传递给周围的人…@Saiviekh Swaminathan:当您不访问周围实例的成员时,lambda表达式将不会捕获对周围实例的引用。在这种情况下,没有必要“打破强引用”。在第一个变体中,您仅在
someObj
上调用一个方法,通过首先将目标对象读入局部变量
SomeObject localVar=this.someObj,可以避免捕获
this
,并仅使用lambda中的局部变量:
helper.doAsync(()->{…int foo=localVar.whatever();…})
仅通过
localVar
@saiviekhswaminathan捕获
SomeObject
实例:准确;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
     }

}