문제

우리 프로그램 중 하나는 때때로 얻는 것입니다 OutOfMemory 한 사용자의 컴퓨터에 오류가 있지만 물론 테스트 할 때는 아닙니다. 방금 JPROFILER (이전에 사용한 적이 없기 때문에 10 일 평가 라이센스로)와 코드 접두사를 필터링하면 총 크기와 인스턴스 수의 가장 큰 청크는 특정 간단한 클래스의 8000 개 이상의 인스턴스입니다. .

JPROFILER에서 "Garbage Collect"버튼을 클릭했으며 다른 클래스의 대부분의 인스턴스가 사라졌지만 이러한 특정한 것은 아닙니다. 나는 여전히 같은 인스턴스에서 테스트를 다시 실행했으며, 4000+ 이상의 수업을 만들었지 만 "쓰레기 수집"을 클릭하면 8000+ 오리지널을 남겨 두었습니다.

이 인스턴스는 다양한 단계에서 다양한 컬렉션에 빠지게됩니다. 나는 그들이 수집 된 쓰레기가 아니라는 사실이 컬렉션 중 하나에 대한 참조를 붙잡고 있다는 것을 의미하므로 물체에 대한 참조를 유지하고 있음을 의미합니다.

참조에 무엇이 붙잡고 있는지 알아낼 수있는 제안이 있습니까? 코드에서 무엇을 찾아야하는지에 대한 제안과 JProfiler에서이를 찾는 방법을 찾고 있습니다.

도움이 되었습니까?

해결책

힙을 버리고 검사하십시오.

나는 이것을 할 수있는 방법이 둘 이상 있다고 확신하지만 여기에 간단한 것이 있습니다. 이 설명은 MS Windows를위한 것이지만 다른 운영 체제에서도 비슷한 단계를 수행 할 수 있습니다.

  1. 아직 없으면 JDK를 설치하십시오. 깔끔한 도구가 함께 제공됩니다.
  2. 응용 프로그램을 시작하십시오.
  3. 작업 관리자를 열고 java.exe (또는 사용중인 실행 가능)의 프로세스 ID (PID)를 찾으십시오. PID가 기본적으로 표시되지 않으면보기> 선택 열 ... 추가하여 추가하십시오.
  4. 힙을 사용하여 덤프하십시오 JMAP.
  5. 시작하십시오 jhat 생성 한 파일의 서버 및 브라우저를 http : // localhost : 7000 (기본 포트는 7000입니다). 이제 관심있는 유형과 인스턴스 수, 참조가있는 것 등과 같은 정보를 찾아 볼 수 있습니다.

예는 다음과 같습니다.

C:\dump>jmap -dump:format=b,file=heap.bin 3552

C:\dump>jhat heap.bin
Reading from heap.bin...
Dump file created Tue Sep 30 19:46:23 BST 2008
Snapshot read, resolving...
Resolving 35484 objects...
Chasing references, expect 7 dots.......
Eliminating duplicate references.......
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

이것을 해석하려면 일부를 이해하는 것이 유용합니다. 배열 유형 명칭 Java는 그것을 아는 것처럼 사용합니다 클래스 [ljava.lang.object; 실제로 유형의 대상을 의미합니다 물체[.

다른 팁

일식 메모리 분석기를 사용해보십시오. 각 객체에 대해 GC 루트에 어떻게 연결되어 있는지 보여줍니다.

보다 http://dev.eclipse.org/blogs/memoryanalyzer/2008/05/27/automated-heap-dump-analysy-finding-mory-leaks-with-one-click/ 이클립스 매트의 작동 방식에 대한 자세한 내용.

나는 당신의 수업에서 컬렉션 (특히 정적)을 살펴볼 것입니다 (해시 맵은 시작하기에 좋은 장소입니다). 예를 들어이 코드를 가져옵니다.

Map<String, Object> map = new HashMap<String, Object>(); // 1 Object
String name = "test";             // 2 Objects
Object o = new Object();          // 3 Objects
map.put(name, o);                 // 3 Objects, 2 of which have 2 references to them

o = null;                         // The objects are still being
name = null;                      // referenced by the HashMap and won't be GC'd

System.gc();                      // Nothing is deleted.

Object test = map.get("test");    // Returns o
test = null;

map.remove("test");               // Now we're down to just the HashMap in memory
                                  // o, name and test can all be GC'd

해시 맵이나 다른 컬렉션이 해당 물체에 대한 참조가있는 한 수집되지는 않습니다.

실버 총알이 없으므로 프로파일 러를 사용하여 불필요한 물체를 고정하는 컬렉션을 식별하고 제거 해야하는 코드에서 장소를 찾아야합니다. JESPERE가 말했듯이 정적 컬렉션이 가장 먼저 볼 수있는 곳입니다.

명백한 후보 중 하나는 Finalisers가있는 개체입니다. 최종 방법이 호출되는 동안 그들은 머무를 수 있습니다. 수집 한 다음 결승 (보통 단일 파이널 스레드로)을 완료 한 다음 다시 수집해야합니다.

또한 객체 요청이 생성하기에 충분한 것이지만 GC가 충분한 메모리를 수집하지 못했기 때문에 Oome을 얻을 수 있습니다. 그렇지 않으면 성능이 땅에 갈 것입니다.

정적 용기를 주시하십시오. 정적 컨테이너의 모든 물체는 클래스가로드되는 한 유지됩니다.

편집 : 약점에 대한 잘못된 비고를 제거했습니다.

나는 이것에 대한 기사를 읽었지만 어디서 기억할 수 없어서 죄송합니다. 나는 그것이 "효과적인 Java"라는 책에 있었을 것이라고 생각합니다. 참조를 찾으면 대답을 업데이트하겠습니다.

그것이 설명한 두 가지 중요한 교훈은 다음과 같습니다.

1) 최종 방법은 GC가 객체를 컬링 할 때 무엇을 해야하는지 알려주지 만, 그렇게하도록 요구하지 않으며, 그렇게 할 수있는 방법도 없습니다.

2) 관리되지 않는 메모리 환경에서 "메모리 누출"과 동등한 현대는 잊혀진 참조입니다. 모든 참조를 객체에 대해 설정하지 않으면 없는 당신이 그것을 끝내면, 대상이 될 것입니다 절대 컬링하십시오. 이것은 자신의 종류의 컬렉션을 구현할 때 가장 중요합니다. 또는 컬렉션을 관리하는 자신의 포장지를 구현할 때 가장 중요합니다. 수영장이나 스택 또는 대기열이있는 경우 버킷을 설정하지 않는 경우 없는 컬렉션에서 객체를 "제거"하면 물체가 들어간 버킷은 해당 버킷이 다른 물체를 참조하도록 설정 될 때까지 해당 물체를 살리게합니다.

면책 조항 : 다른 답변이 이것을 언급했지만 더 자세한 내용을 제공하려고합니다.

나는 Yourkit Java Profiler를 사용했습니다 (http://www.yourkit.com) Java 1.5의 성능 최적화. 메모리 누출 작업 방법에 대한 섹션이 있습니다. 유용하다고 생각합니다.

http://www.yourkit.com/docs/75/help/performance_problems/memory_leaks/index.jsp

15 일 평가를받을 수 있습니다. http://www.yourkit.com/download/yjp-7.5.7.exe

Br,
~ a

컬렉션이 이미 언급되었습니다. 찾기 어려운 위치는 여러 클래스 로더를 사용하는 경우 이전 클래스 로더를 모든 참조가 진행될 때까지 쓰레기를 수집 할 수 없기 때문에입니다.

또한 정적을 확인하십시오 - 이것들은 불쾌합니다. 로깅 프레임 워크는 내용 부속사의 참조를 유지할 수있는 물건을 열어 놓을 수 있습니다.

문제를 해결 했습니까?

몇 가지 제안 :

  • 무제한지도, 특히 정적 인 경우 캐시로 사용됩니다
  • 스레드가 일반적으로 죽지 않기 때문에 서버 앱의 ThreadLocals가 있으므로 ThreadLocal이 해제되지 않습니다.
  • Interning Strings (strings.intern ()), Permspace에서 문자열 더미가 생성됩니다.

쓰레기 수집 된 언어로 OOM 오류가 발생하는 경우 일반적으로 수집가에 의해 설명되지 않는 메모리가 있음을 의미합니다. 어쩌면 당신의 객체가 자바가 아닌 자원을 보유할까요? 그렇다면 Java 객체가 곧 수집되지 않더라도 자원이 릴리스되도록하는 일종의 'Close'방법이 있어야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top