[java] Java 객체를 null로 설정하면 더 이상 작업이 수행됩니까?

나는 오래된 책을 찾아 보던 중 Peter Hagger의 “Practical Java”사본을 발견했습니다. 성능 섹션 null에는 더 이상 필요하지 않을 때 개체 참조를 설정하는 권장 사항이 있습니다.

Java에서 null성능 또는 가비지 콜렉션 효율성 을 향상시키기 위해 오브젝트 참조를 설정 합니까? 그렇다면 어떤 경우에 문제가됩니까? 컨테이너 클래스? 개체 구성? 익명의 내부 클래스?

나는 이것을 코드에서 자주 봅니다. 이것은 이제 쓸모없는 프로그래밍 조언입니까, 아니면 여전히 유용합니까?



답변

참조를 무효화하려는시기에 따라 다릅니다.

객체 체인 A-> B-> C가있는 경우 A에 도달 할 수 없으면 A, B 및 C가 모두 가비지 수집 대상이됩니다 (다른 항목이 B 또는 C를 참조하지 않는다고 가정). 예를 들어, 참조 A-> B 또는 B-> C를 명시 적으로 null로 설정할 필요가 없으며 그 어느 때도 필요하지 않았습니다.

그 외에도 실제로는 컬렉션의 개체를 다루기 때문에 대부분의 경우 문제가 실제로 발생하지 않습니다. 일반적으로 적절한 remove () 메서드를 호출하여 목록,지도 등에서 객체를 제거하는 것을 항상 생각해야합니다.

이 케이스 로 사용 널로 설정 레퍼런스에 대한 조언은 구체적으로 하였다 메모리 집약적 오브젝트 범위를 통해 사용 도중에 것을 정지 긴 범위 . 예를 들면 :

{
  BigObject obj = ...
  doSomethingWith(obj);
  obj = null;             <-- explicitly set to null
  doSomethingElse();
}

여기서의 이론적 근거는 obj 가 여전히 범위 내에 있기 때문에 참조를 명시 적으로 무효화하지 않으면 doSomethingElse () 메서드가 완료 될 때까지 가비지 수집 가능 상태가되지 않는다는 것 입니다. 그리고 이것은 아마도 최신 JVM에서 더 이상 유지되지 않는 조언입니다 . JIT 컴파일러가 주어진 로컬 객체 참조가 더 이상 사용되지 않는 지점에서 작업 할 수 있다는 것이 밝혀졌습니다.


답변

아니, 쓸데없는 조언이 아닙니다. 댕글 링 참조는 여전히 문제입니다. 특히 ArrayList사전 할당 된 배열을 사용하여 확장 가능한 배열 컨테이너 ( 또는 이와 유사한 것)를 구현하는 경우에는 더욱 그렇습니다 . 목록의 “논리적”크기를 초과하는 요소는 제거해야합니다. 그렇지 않으면 해제되지 않습니다.

Effective Java 2nd ed, Item 6 : Eliminate Obsolete Object References를 참조하십시오.


답변

인스턴스 필드, 배열 요소

개체에 대한 참조가 있으면 가비지 수집 할 수 없습니다. 특히 해당 객체 (및 그 뒤에있는 전체 그래프)가 크면 가비지 수집을 중지하는 참조가 하나만 있고 해당 참조가 더 이상 필요하지 않은 경우 이는 불행한 상황입니다.

병리학 적 사례는 구성에 사용 된 전체 XML DOM 트리에 대한 비 필수적 인스턴스를 유지하는 객체, 등록 해제되지 않은 MBean 또는 전체 클래스 로더가 언로드되는 것을 방지하는 배포되지 않은 웹 응용 프로그램의 객체에 대한 단일 참조입니다. .

따라서 참조 자체를 보유하는 객체가 어쨌든 (또는 그 후에도) 가비지 수집 될 것이라는 확신이없는 경우 더 이상 필요하지 않은 모든 항목을 무효화해야합니다.

범위 변수 :

범위가 끝나기 전에 지역 변수를 null로 설정하여 가비지 수집기에서 회수하고 “지금부터 사용할 수 없음”으로 표시 할 수 있도록 고려중인 경우 대신 더 제한된 범위에 두는 것을 고려해야합니다. .

{
  BigObject obj = ...
  doSomethingWith(obj);
  obj = null;          //   <-- explicitly set to null
  doSomethingElse();
}

된다

{
  {
     BigObject obj = ...
     doSomethingWith(obj);
  }    //         <-- obj goes out of scope
  doSomethingElse();
}

길고 평평한 범위는 일반적으로 코드의 가독성에도 좋지 않습니다. 그 목적을 위해 사물을 분해하는 사적인 방법을 도입하는 것도 전례가 없습니다.


답변

메모리 제한 환경 (예 : 휴대폰)에서 이것은 유용 할 수 있습니다. null을 설정하면 objetc는 변수가 범위를 벗어나 gc가 될 때까지 기다릴 필요가 없습니다.

그러나 일상적인 프로그래밍에서는 Chris Jester-Young이 인용 한 것과 같은 특별한 경우를 제외하고는 이것이 규칙이되어서는 안됩니다.


답변

첫째, 그것은 당신이 객체를 설정하는 것을 의미하지 않습니다 null. 아래에 설명합니다.

List list1 = new ArrayList();
List list2 = list1;

위의 코드 세그먼트에서 우리는 메모리에 저장된 객체 의 객체 참조 변수 이름 list1을 생성하고 ArrayList있습니다. 그래서 list1그 객체를 언급하는 것은 변수 일뿐입니다. 그리고 코드의 두 번째 줄에 우리의 참조 복사 list1로를 list2. 이제 내가 할 경우 귀하의 질문으로 돌아가십시오.

list1 = null;

즉, list1더 이상 메모리에 저장된 객체를 참조하지 않으므로 참조 할 list2것도 없습니다. 따라서 크기를 확인하면 list2:

list2.size(); //it gives you 0

그래서 여기 에 “객체가 보유한 메모리를 해제하는 것에 대해 걱정할 필요가 없습니다. 프로그램에서 더 이상 사용되지 않고 JVM이 저를 관리 할 것임을 알게되면 그렇게 할 것입니다.” 라는 가비지 수집기의 개념이 도착 합니다.

개념이 명확 해 졌으면합니다.


답변

그렇게하는 이유 중 하나는 사용되지 않는 개체 참조를 제거하기위한 것입니다. 여기 에서 텍스트를 읽을 수 있습니다 .


답변