Java8Lambda闭包和GC
我对Java8的“闭包”有点困惑。它被认为是价值观的终结。 考虑下面的类。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( () ->
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
}
}