2013-10-29 1 views
0

최근 프로젝트에서 이상한 메모리 누수 문제가 있습니다. 나는 '핸들러'코드에 메시지를 보내는 'main'코드를 가지고있다. 전달되면 핸들러 코드는 고정 된 작업을 수행하고 그 결과를 디스크에 쓴 다음 종료합니다. 고정 작업은 다른 클래스의 특정 함수를 호출하여 수행됩니다.Java : 스레드 종료 후 힙이 회수되지 않습니다.

이 함수를 실행하는 동안 힙 크기가 증가합니다 (예상대로). 그러나 코드가 완료되면 결과 자체가 많은 공간을 차지해서는 안됩니다. 핸들러 호출이 완료되어 메모리 사용량이 적을 것으로 예상됩니다. 그러나 'top'은 핸들러가 여전히 많은 양의 메모리 (RES)를 소비 함을 보여줍니다.

스레드가 종료 할 때 스레드가 소비 한 힙을 회수해야합니까? System.gc() 호출을 함수의 실행을 게시하려고했지만 가비지 수집을 강제로 수행하지 않습니다.

답변

4

핫스팟 JVM의 가비지 수집기는 "마지 못해"운영 체제에 메모리를 다시 제공합니다. 응용 프로그램은 교정 된 공간에 더 많은 개체를 만들 것이라고 가정합니다. GC가 메모리를 다시 돌려 준다면, 다시 요청할 필요가 있고, churn은 여분의 시스템 호출 등을 초래할 것이다.

그러나 JVM이 힙이 불필요하게 크다는 것을 알게되면 힙 크기가 줄어들어 결국 JVM이 일부 메모리를 반환하게됩니다. 크기 조정 메커니즘은 Oracle Heap Tuning Parameters 페이지에 설명되어 있습니다.


스레드의 스택은 Java 힙 내에 할당되지 않습니다. 오히려 스레드가 시작될 때 OS에서 일반적으로 요청되는 힙이 아닌 메모리 세그먼트에 있으며 스레드가 종료 될 때 해제됩니다.

+0

+1 전혀 아닐 경우. 이 메모리는 JVM의 다른 부분에서 사용할 수 있지만 대부분 OS로 반환하지는 않습니다. – Gray

2

스레드가 종료 할 때 스레드가 소비 한 힙을 회수해야합니까? System.gc() 호출을 함수의 실행을 게시하려고했지만 가비지 수집을 강제로 수행하지 않습니다. 재생되는 사실,

-verbose:gc 
-XX:+PrintGCTimeStamps 
-XX:+PrintGCDetails 

나는 당신이 그 공간이 나타납니다 상상 : 일부 JVM 플래그를 추가

시도는 GC 작업을 기록합니다. top에 의해보고되는 메모리 사용 공간에는 오브젝트를 할당하는 데 사용되었는지 여부에 관계없이 Java 힙용으로 예약 된 공간이 포함됩니다. 이 숫자를 안정적으로 GC 활동을 모니터링하는 데 사용할 수는 없습니다.

스레드 종료는 반드시 가비지 수집을 트리거하지 않습니다. 또한 가비지 수집시 프로세스의 공간이 줄어들지도 않을 것입니다. JVM은 필요에 따라 관리되는 힙의 크기를 늘릴 것이지만, 처음 기회 (또는 아마도)로 축소 할 필요는 없습니다. 프로그램의 메모리 사용량이 한 번 수준에 도달하면 JVM이 다시 발생하지 않을 것이라고 믿을 이유가 없으므로 시스템 메모리가 매우 높지 않으면 JVM이 해당 메모리를 즉시 OS로 되돌릴 수 없습니다 (if 이제까지).