2017-10-31 3 views
2

자바 8의 '클로저'와 약간 혼동 스럽습니다. 그것은 가치 이상으로 추정된다. 다음 클래스를 고려하십시오.Java 8 람다 클로저와 GC

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'd 될 수있다? "someObj"는 doSomething()의 람다에서 필요하므로 GC로 지정할 수 없습니다. 나머지 국가는 어떨까요? 지금

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 시퀀스는 무엇입니까?

+0

내가 아는 한 Java의 GC는 Java에서 참조 카운팅과 람다를 사용하여 인라인 클래스의 구문 론적 설탕에 지나지 않습니다. 긴 이야기 짧게 :이 모든 것을 인라인 클래스로 구현하는 것처럼 작동합니다. 인라인 클래스는 프라이빗 클래스이기 때문에 언제든지 주변 개체와 그 속성 및 메소드에 액세스 할 수 있습니다. 참조 카운팅은 객체의 나머지와 올바른 릴리스를 처리합니다 (람다가 실행 된 후에 일명). – Turing85

+0

** 실제로는 중복되었지만 다른 질문이 있습니다. [Java8 람다가 익명 클래스와 같은 해당 인스턴스에 대한 참조를 유지합니까?] (https://stackoverflow.com/a/28447015/581205). ** See https://stackoverflow.com/a/23991339/581205. – maaartinus

답변

1

비동기 도우미가 여전히 작동 중일 때 SomeClassWithLargeMemoryFootprint의 인스턴스를 GC 할 수 있습니까?

아니오 VoidRunner 인스턴스는 바깥 SomeClassWithLargeMemoryFootprint 개체에 대한 강한 참조가, 그 자체는 비동기 작업 실행에 의해 어떻게 든 참조됩니다. 그래서 GCed 할 수 없습니다.

나머지 주는 어떨까요?

나머지 상태는 SomeClassWithLargeMemoryFootprint의 인스턴스에서 참조되므로 GCed 할 수 없습니다.

는 '도우미'

는 첫 번째 예에서 someObj (즉 this.someObj)에 액세스하는 방법을 알고 같은 방법을 "memberMethod"를 실행하는 방법을 알고 않는 방법 : 그것의 바깥 쪽에 대한 참조가 LargeMemoryFootprint 개체 (예 : this)가있는 SomeClass.

+0

쿨 .. 고마워! 익명의 클래스가 그 클래스를 둘러싸는 클래스를 참조하고 있다는 사실은 분명합니다. –

+0

후속 질문 : 람다에 포함 된 클래스의 멤버에 액세스하지 않을 때 엔 클로징 클래스에 대한 강력한 참조를 끊는 방법이 있습니까? 이것에 의해, 나는 람다를 사용함에있어서의 편파성이 너무 깔끔하지 않은 깔끔한 방법을 의미합니다. 람다 인터페이스를 구현하는 구체적인 클래스가 아닙니다. –

+0

나는 람다와 인터페이스의 정적 최종 인스턴스를 생성하고 주위에 전달할 수있을 것 ... –