2010-05-19 1 views
9

간혹 2 일에 한 번에서 2 주에 한 번 사이에 응용 프로그램이 임의의 위치에서 코드 : java.lang.OutOfMemoryError: GC overhead limit exceeded과 같이 충돌하는 경우가 있습니다. 내 응용 프로그램이 분명히 가비지 컬렉션의 전체 시간의 98 %를 지출 하더군요"java.lang.OutOfMemoryError : GC 오버 헤드 한도 초과"의 과도한 GC 시간 지속

The parallel collector will throw an OutOfMemoryError if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, an OutOfMemoryError will be thrown. This feature is designed to prevent applications from running for an extended period of time while making little or no progress because the heap is too small. If necessary, this feature can be disabled by adding the option -XX:-UseGCOverheadLimit to the command line.

가의 2 %를 회복 :이 오류를 구글하면 나는 this SO question에 와서 그 expains this piece of sun documentation에 저를 이끌어 더미.

몇시에 98 %? 응용 프로그램이 실행되는 전체 2 주 중 98 % 마지막 밀리 초의 98 %?

나는 단지 -XX:-UseGCOverheadLimit을 사용하는 것보다는이 문제를 실제로 해결하는 최선의 방법을 결정하려고 노력하고 있지만, 나는 해결해야 할 문제를 더 잘 이해할 필요가 있다고 생각한다.

+3

문서에서 보면 2 주 전체의 98 % 인 것으로 보입니다. GC 로그에 -verbose : gc -XX : + PrintGCDetails XX : + PrintGCTimeStamps -Xloggc : PATH_FROM_ROOT/gclog.log 플래그를 설정 했습니까? 앱 실행 시간과 GC로 인해 중단 된 시간을 확인하는 것이 좋습니다. – JoseK

+0

GC 로깅은 좋은 제안입니다. 2 주 중 98 %는 불가능할 것 같지만 당신이 맞습니다. 그것이 바로 문서가 의미하는 것입니다. 나는 그것이 부정확 한 글을 쓰기를 희망한다. –

+0

98 %의 의미를 알았습니까? 내 생각에 GC는 2 주 동안 예외가 발생한 바로 그 순간에 애플리케이션 사용량의 98 %를 차지하는 것이 바쁠 것입니다. –

답변

6

I'm trying to determine a best approach to actually solving this issue rather than just using -XX:-UseGCOverheadLimit but I feel a need to better understand the issue I'm solving.

글쎄, 너무 많은 메모리를 사용하고 있습니다. 소리가 나면서 느린 메모리 누수가 원인 일 수 있습니다.

-Xmx으로 힙 크기를 늘리면 메모리 누수가 아니라 앱에 실제로 많은 힙이 필요하고 현재 가지고있는 설정이 약간 낮다는 신호가되는 데 도움이됩니다. 메모리 누수가 발생하면 피할 수없는 것을 연기 할 것입니다.

메모리 누수인지 조사하려면 -XX:+HeapDumpOnOutOfMemoryError 스위치를 사용하여 OOM에 힙을 덤프하고 힙 덤프를 분석하여 더 많은 종류의 개체가 있는지 확인하십시오. http://blogs.oracle.com/alanb/entry/heap_dumps_are_back_with은 시작하기에 꽤 좋은 곳입니다.


편집 : 운명을 것, 나는이 질문이 배치 스타일 앱에 물었다 후 하루 만이 문제로 자신을 실행 일어났다. 이것은 메모리 누수로 인한 것이 아니며 증가하는 힙 크기는 도움이되지 않았습니다. 내가 실제로 한 것은 힙 크기 (1GB에서 256MB까지)로 전체 GC를 더 빠르게 만들었지 만 (다소 자주 발생 함). YMMV,하지만 그럴 가치가있어.

편집 2 : 작은 힙으로 해결 된 모든 문제가있는 것은 아닙니다. 다음 단계는 CMS보다 나은 작업 인 것처럼 보이는 G1 garbage collector을 활성화하는 것입니다.

+0

프로파일 링을 시도하고 있는데, 그 중 하나를 시도해 보겠습니다. 감사. –

+0

나는 당신이했던 것과 비슷한 경로를 매개 변수를 가지고 실험했다. 궁극적으로 힙 크기를 늘리고 내 코드를 약간 수정하면 (메모리 누수가 발견되지 않음) 내 문제가 해결 된 것으로 보입니다. –

+0

배치 스타일 앱에서 CMS 또는 G1을 사용하는 이유는 무엇입니까? 처리량 수집기가 더 좋지 않습니까? – endless

1

> 98 %는 2 % 미만의 메모리가 회수되는 동일한 기간에 대해 측정됩니다.

일정 기간이 없어도 가능합니다. 예를 들어, OOM 검사가 매 1,000,000 건의 객체 라이브 검사 후에 수행되는 경우입니다. 소요되는 시간은 기계에 따라 다릅니다.

-XX:-UseGCOverheadLimit을 추가하면 문제를 "해결할"수 없습니다. 가장 큰 결과는 응용 프로그램이 크롤링 속도가 느려지고 더 많은 메모리를 사용하며 GC가 단순히 임의의 메모리를 복구하지 못하는 지점에 도달한다는 것입니다. 대신 메모리 누수를 수정 한 다음 (필요한 경우) 힙 크기를 늘리십시오.

1

But 98% of what time? 98% of the entire two weeks the application has been running? 98% of the last millisecond?

간단히 대답하면 지정되어 있지 않습니다. 그러나 실제로는 경험적으로 "작동"하기 때문에 사용자가 제시 한 두 가지 극단적 인 해석 중 하나 일 수 없습니다.

이 실제로 인 경우 측정 간격을 알려면 OpenJDK 6 또는 7 소스 코드를 항상 읽을 수 있습니다. 하지만 문제를 해결하는 데 도움이되지 않을 것이므로 걱정하지 않아도됩니다.

"최선의"방법은 튜닝 (Oracle/Sun 페이지 시작)에서 약간의 독서를하고 조심스럽게 "튜닝 노브를 돌리십시오"입니다. 그다지 과학적이지는 않지만 문제 공간 (정확히 응용 프로그램 + GC 성능 예측)은 현재 사용할 수있는 도구를 고려할 때 "너무 어렵습니다".