2016-06-16 6 views
4

기사를 오래 읽었으므로 찾을 수 없습니다. 범위 안에있는 객체가 아직 지워지지 않을 수도있는 아래의 행동을 설명했다. 어떤 경우에는 당신이 아래 내가 인쇄 문 Afinalize을 넣었을 때 OutOfMemoryError범위에서 개체를 지우지 않는 GC

public static void main(String[] args) { 
    List<A> collect = null; 
    int i=0; 
    while(true){ 
     System.out.println(i++); 
     collect = IntStream.range(0, 10_00_000).mapToObj(x -> new A(x + "")).collect(Collectors.toList()); 
    } 
} 

class A{ 
    String temp; 
    A(String a){ 
     this.temp = a; 
    } 
} 

로 끝나는 이유에 대해 설명하는 데 도움 주시기 바랍니다 수 있습니다, 그것은 인쇄되지 않습니다. 그리고 몇 번의 반복 작업 후에 인스턴스는 OOME으로 끝납니다. 이전에 생성 된 gc이 지워지지 않는 이유는 무엇입니까? collect. 그리고 반복 횟수뿐만 아니라이 3 심지어 100 범위, 일정하지 않지만 궁극적으로 두 번째로 재미를 위해 -Xmx500m

실패, 나는 JIT 장애인 -Djava.compiler=NONE와 위의 프로그램을 실행했습니다. 그리고 예상대로 영원히 돌아갑니다. JIT는 어떻게 영향을 줍니까?

추신 : 내 while 절에 System.gc();을 포함하면 예상대로 실행됩니다.

+0

System.out 다음에 버퍼를 플러시하십시오. –

+0

@MarshallTigerus 그다지 영향을 미치지 않습니다. 그건 그렇고, 그것은 defaul에 의해 홍조가된다. t – Jatin

+0

주요한 이슈는 모든 반복에서 새로운 1m elems리스트를 생성하고 오래된리스트를 무시한다는 것이다. 어쩌면'collect.clear()'와'collect.addAll()'을 대신 호출하면 – everton

답변

8

-Xmx500m으로 결과를 재현 할 수 없지만 -Xmx200m으로 결과를 재현 할 수 없습니다. 일관되게이 프로그램은 finalize() 메서드를 추가 할 때 종료자가 최종적으로 원인 인이 문제의입니다. 그러나 이고 일부는 "finalized" 메시지가 내 시스템에 인쇄되어 있습니다. finalize() 메서드가 없다면, 그것은 영원히 완벽하게 실행됩니다 (실제로, 죽일 때까지).

일반 객체의 공간을 되 찾는 데는 문제가 없지만, 중요하지 않은 객체 인 finalize() 메소드를 추가하면 객체가 범위에서 벗어나는 것을 적극적으로 방지합니다. 이제는 객체를 최종 대기열에 넣어야합니다.

OutOfMemoryError을 던지기 전에 JVM이 항상 가비지 수집을 수행하고 사용하지 않는 모든 객체를 비우는 동안 최종 객체 대기열에 걸려있는 객체에 대한 보장은 없습니다. JIT를 사용하지 않도록 설정하여 주 작업을 느리게 진행하면 최종 작업을 통해 더 많은 요소를 처리 할 수 ​​있습니다. 두 가지 모두를 가짐으로써 주 작업과 System.out에 인쇄하는 마무리 방법은 처리의 타이밍을 중요하게 만들 수있는 동기화 효과가 있음을 명심하십시오.

결과에 영향을 줄 수있는 몇 가지 환경 측면입니다. 어떤 스레드가 파이널 라이저를 실행할 것인지에 대한 보장이 없으므로 파이널 라이즈는 사용되지 않는 모든 CPU 코어를 사용할 수 있습니다 (메인 스레드는 하나만 사용합니다). 또한 실제 가비지 수집 알고리즘 (JVM이 여러 알고리즘 중 하나를 선택할 수 있음)이 영향을 미칠 수 있습니다.