2009-03-13 2 views
40

내 응용 프로그램에 너무 많은 정적 변수 또는 메서드가있는 경우 정의에 따라 힙에 저장됩니다. 내가 틀렸다면 나를 바로 잡으시오.너무 많은 정적 변수를 사용하면 Java에서 메모리 누수가 발생할 수 있습니까?

1) 응용 프로그램을 닫을 때까지 이러한 변수가 힙에 있습니까?
2) 언제든지 GC에 사용할 수 있습니까? 그렇지 않다면 메모리 누수라고 말할 수 있습니까?

답변

76

정적 메서드는 힙에 저장되지 않고 그냥 "this"매개 변수를 사용하지 않는 메서드입니다.

정적 변수는 GC의 "루트"역할을합니다. 결과적으로 명시 적으로 null로 설정하지 않으면 프로그램이 살아있는 한 계속 살 것이며 모든 것이 도달 할 수 있습니다.

메모리가 비어 있고 사용 가능하지 않은 경우 상황은 메모리 누수로 간주됩니다. 정적 변수가 시간의 일부분에 대한 객체에 대한 참조를 포함하려는 경우 해당 객체를 완료하면 null로 설정하는 것을 잊어 버리면 누수가 발생할 가능성이 높습니다. 그러나 정적 변수에 넣고 프로그램이 실행되는 동안 거기에 있도록하려는 경우 가장 확실한 누수가 아니며 "영구 싱글 톤"일 가능성이 큽니다. 개체가 여전히 존재하기를 원하는 동안 개체가 재생 된 경우 매우 위험합니다.

힙에 대한 질문 : Java의 모든 개체는 힙이나 스택에 존재합니다. 새 연산자로 힙에 오브젝트가 작성됩니다. 그런 다음 참조가 첨부됩니다. 참조가 null이거나 범위를 벗어나는 경우 (예 : 블록 종료) GC는 해당 객체에 다시 도달하여이를 회수 할 방법이 없다는 것을 인식합니다. 참조가 정적 변수에 있으면 범위를 벗어나지 않지만 여전히 null 또는 다른 객체로 설정할 수 있습니다.

+0

IIRC 정적 필드는 선언 된 클래스가 GCed 되 자마자 GC됩니다.클래스의 엘라스틱 인스턴스가 사라지면 클래스 선언과 정적 필드가 함께 표시됩니다. – ordnungswidrig

+1

@ o11rig가 완전히 정확한지 확실하지 않지만 GC가 특정 상황에서 멤버가없는 클래스에 대한 통계를 수집 할 수 있다고 믿습니다. 몇 가지 소식을 들었지만 정확한 설명을 듣지 못했습니다. –

+0

약간의 오류 : 모든 Java * 객체 *가 힙에 있습니다. Object * references *와 프리미티브는 현재 실행중인 메소드의 locals 인 경우 스택에 저장 될 수 있으며, 그렇지 않으면 힙에 저장됩니다. (JIT가있는 현대의 JVM을 제외하고 JIT의 옵티마이 저가 원하는 곳에 객체를 놓을 수 있습니다. 객체가 힙에있는 것처럼 동작하는 한). 그리고 정적 메소드 - 또는 , 적어도 그것들을 구현하는 자바 바이트 코드는 정의 된 클래스를 나타내는 Class 객체의 일부로 힙에도 존재합니다. –

1

코드의 어딘가에서 이러한 변수를 참조 할 수있는 한 GCed는 응용 프로그램이 끝날 때까지 이러한 변수를 참조 할 수 없습니다.

메모리 누수라고 부를 수 있습니까? 보통 메모리 누수가 아닙니다. 일반적으로 메모리 누수는 일반적으로 복구가 예상되지만 결코 수행하지 않는 메모리이거나 일부만 복구하는 메모리입니다. 또한 메모리 누수는 대개 시간이 갈수록 악화됩니다 (예 : 메서드를 호출 할 때마다 더 많은 메모리가 "누수 됨"). 그러나이 경우 해당 변수의 메모리 사용량은 (일종의) 정적입니다.

그것은이 경우 예

Class A{ 

static B foo; 

... 

static void makeFoo(){ 
    foo = new B(); 
    foo = new B(); 
} 

들어 ... 고전 C 센스 메모리 누수가 발생하지 않습니다

+0

코드에서 정적 변수를 참조 할 필요가 없습니다. 클래스 로더가 참조를 영구적으로 보유하므로 GC가 실행되지 않습니다. – ReneS

1

는 makeFoo()의 호출은 같은 메모리 누수 발생되지 첫 번째 인스턴스는 가비지 수집 될 수 있습니다.

2

정적으로 직접 또는 간접적으로 참조되는 객체는 적절한 클래스 로더가 수집 될 때까지 힙에 남아 있습니다. 다른 객체가 클래스 로더를 간접적으로 참조하여 그것이 수집되지 않은 채로 남아있는 경우 (ThreadLocal, 예를 들어)가 있습니다.

정적 목록이 있고 그것에 대한 참조를 동적으로 추가하면 "개체 수명 충돌 문제"로 끝날 수 있습니다. 여러 가지 이유로 가변적 인 통계를 피하십시오.

3

정적 해시 맵이 있고 여기에 데이터를 추가하면 ... 더 이상 데이터가 필요하지 않을 경우 데이터가 사라지지 않고 누출이 생깁니다. 데이터가 필요하다면, 누수가 아니라 거대한 메모리 더미가 있습니다.

+0

정적 해시 맵에 많은 객체가 있다고 가정합니다. 그리고 내가 포함 된 모든 객체가 아닌 null에 대한 맵 참조를 만들었습니까? 메모리 누출인가요? "클래스 로더가 정적 참조를 영구적으로 보유하므로 GC가 실행되지 않습니다." –

+0

정적 참조를 null로 설정하고 다른 곳에서 해당 맵을 참조하지 않으면 메모리가 해제됩니다. 매핑 된 객체는 참조 된 객체가 다른 객체에 의해 참조되지 않으면 해제됩니다. – ReneS

관련 문제