Java 8 lambda闭包和GC

时间:2017-10-31 20:24:40

标签: 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    
                       });
     }
}

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

问题是,当异步帮助程序仍在工作时,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
     }

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

1 个答案:

答案 0 :(得分:2)

  

当异步帮助程序仍在工作时,SomeClassWithLargeMemoryFootprint的实例是否可以GC?

没有。 VoidRunner实例对其封闭的SomeClassWithLargeMemoryFootprint对象有强引用,并且它本身由异步任务执行程序引用。所以它不能被GCed。

  

其他州呢?

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

  

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

它在第一个示例中知道如何访问this.someObj(即this)的方式相同:它包含对其封闭的SomeClassWithLargeMemoryFootprint对象的引用(即let routes = [] app._router.stack.forEach(function (middleware) { if(middleware.route) { routes.push(Object.keys(middleware.route.methods) + " -> " + middleware.route.path); } }); console.log(JSON.stringify(routes, null, 4)); )。