null
Java에서 사용되지 않는 객체 참조를 할당하면 가비지 수집 프로세스가 측정 가능한 방식으로 개선됩니까?
Java (및 C #)에 대한 경험을 통해 가상 머신 또는 JIT 컴파일러를 시도하고 능가하는 것이 직관적이지 않은 경우가 많지만 동료가이 방법을 사용하는 것을 보았고 이것이 좋은 방법인지 궁금합니다. 아니면 부두 프로그래밍 미신 중 하나?
답변
일반적으로 아닙니다.
그러나 모든 것들이 그렇듯이 상황에 따라 다릅니다. 요즘 Java의 GC는 매우 훌륭하며 더 이상 도달 할 수없는 즉시 모든 것을 정리해야합니다. 이것은 지역 변수에 대한 메서드를 떠난 직후와 클래스 인스턴스가 더 이상 필드에 대해 참조되지 않을 때입니다.
그렇지 않으면 참조 된 상태로 유지된다는 것을 알고있는 경우에만 명시 적으로 null이 필요합니다. 예를 들어 주변에 보관되는 배열입니다. 더 이상 필요하지 않은 경우 배열의 개별 요소를 null로 지정할 수 있습니다.
예를 들어 ArrayList의 다음 코드는 다음과 같습니다.
public E remove(int index) {
RangeCheck(index);
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
return oldValue;
}
또한 객체를 명시 적으로 null로 설정해도 참조가 남아 있지 않는 한 자연스럽게 범위를 벗어나는 것보다 더 빨리 객체가 수집되지 않습니다.
양자 모두:
void foo() {
Object o = new Object();
/// do stuff with o
}
과:
void foo() {
Object o = new Object();
/// do stuff with o
o = null;
}
기능적으로 동일합니다.
답변
내 경험상, 사람들은 종종 필요가 아니라 편집증 때문에 참고 문헌을 무효화합니다. 다음은 빠른 지침입니다.
-
객체 A를 참조가 B 객체 경우 와 더 이상이 참조를 필요로하지 와 객체 A가 가비지 컬렉션에 적합하지 않습니다 당신은 명시 적으로 필드를 null로해야한다. 둘러싸고있는 객체가 어쨌든 가비지 수집을받는 경우 필드를 null로 만들 필요가 없습니다. dispose () 메서드에서 필드를 제거하는 것은 거의 항상 쓸모가 없습니다.
-
메서드에서 생성 된 개체 참조를 null 아웃 할 필요가 없습니다. 메소드가 종료되면 자동으로 지워집니다. 이 규칙의 예외는 매우 긴 메서드 또는 대규모 루프에서 실행 중이고 메서드가 끝나기 전에 일부 참조를 지워야하는 경우입니다. 다시 말하지만, 이러한 경우는 극히 드뭅니다.
대부분의 경우 참조를 무효화 할 필요가 없습니다. 가비지 수집기를 능가하는 것은 쓸모가 없습니다. 비효율적이고 읽을 수없는 코드로 끝날 것입니다.
답변
좋은 기사는 오늘의 코딩 공포 입니다.
GC의 작업 방식은 포인터가없는 객체를 찾는 것입니다. 검색 영역은 힙 / 스택 및 기타 공간입니다. 따라서 변수를 null로 설정하면 실제 개체는 이제 누구도 가리 키지 않으므로 GC가 될 수 있습니다.
그러나 GC가 정확한 순간에 실행되지 않을 수 있으므로 실제로는 아무것도 구매하지 않을 수 있습니다. 그러나 방법이 상당히 길다면 (실행 시간 측면에서) GC가 해당 객체를 수집 할 가능성이 높아 지므로 그만한 가치가 있습니다.
이 문제는 코드 최적화로도 복잡 할 수 있습니다. 변수를 null로 설정 한 후 변수를 사용하지 않는 경우 값을 null로 설정하는 줄을 제거하는 것이 안전한 최적화입니다 (실행할 명령이 하나 적음). 따라서 실제로 개선되지 않을 수도 있습니다.
요약하면 도움이 될 수 있지만 결정적이지는 않습니다 .
답변
적어도 자바에서는 부두 프로그래밍이 아닙니다. 다음과 같은 것을 사용하여 Java에서 객체를 만들 때
Foo bar = new Foo();
두 가지 작업을 수행합니다. 첫째, 객체에 대한 참조를 생성하고 둘째, Foo 객체 자체를 생성합니다. 해당 참조 또는 다른 참조가 존재하는 한 특정 객체는 gc’d 될 수 없습니다. 그러나 해당 참조에 null을 할당하면 …
bar = null ;
다른 객체에 대한 참조가 없다고 가정하면 다음 번 가비지 수집기가 지나갈 때 gc에서 해제되고 사용할 수 있습니다.
답변
때에 따라 다르지.
일반적으로 개체에 대한 참조를 짧게 유지하면 수집 속도가 빨라집니다.
메서드를 실행하는 데 2 초가 걸리고 메서드 실행 1 초 후에 더 이상 개체가 필요하지 않은 경우 해당 참조를 지우는 것이 좋습니다. GC가 1 초 후에도 객체를 참조하면 다음 번에 1 분 정도 후에 확인할 수 있습니다.
어쨌든, 기본적으로 모든 참조를 null로 설정하는 것은 저에게 조기 최적화이며 메모리 소모를 현저하게 감소시키는 특정 드문 경우가 아니면 아무도 수행해서는 안됩니다.
답변
변수가 범위를 벗어나도록하는 대신 명시 적으로 null에 대한 참조를 설정하는 것은 보유한 개체가 매우 크지 않는 한 가비지 수집기에 도움이되지 않습니다. 작업을 마치는 즉시 null로 설정하는 것이 좋습니다.
일반적으로 참조를 null로 설정하는 것은이 개체가 완전히 완료되었으며 더 이상 염려하지 않아야하는 코드의 READER를 의미합니다.
추가 중괄호 세트를 넣어 더 좁은 범위를 도입하여 유사한 효과를 얻을 수 있습니다.
{
int l;
{ // <- here
String bigThing = ....;
l = bigThing.length();
} // <- and here
}
이렇게하면 중첩 된 중괄호를 떠난 직후에 bigThing이 가비지 수집 될 수 있습니다.
답변
public class JavaMemory {
private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6);
public void f() {
{
byte[] data = new byte[dataSize];
//data = null;
}
byte[] data2 = new byte[dataSize];
}
public static void main(String[] args) {
JavaMemory jmp = new JavaMemory();
jmp.f();
}
}
위의 프로그램은 OutOfMemoryError
. 주석을 제거 data = null;
하면 OutOfMemoryError
문제가 해결됩니다. 항상 사용하지 않는 변수를 null로 설정하는 것이 좋습니다.