2011-08-30 2 views
15

Java 응용 프로그램이 SIGSEGV 및 스택 데이터 덤프 및 텍스트 파일의 정보로드로 정기적으로 충돌하기 시작했습니다.코드를 실행할 때 JVM에서 발생하는 Segfaults를 어떻게 디버깅합니까?

gdb에서 C 프로그램을 디버깅했으며 IDE에서 Java 코드를 디버깅했습니다. 실행중인 Java 프로그램에서 C와 유사한 충돌에 접근하는 방법을 잘 모르겠습니다.

여기서 JVM 버그를보고 있지 않다고 가정합니다. 다른 Java 프로그램도 정상적으로 작동하며 Sun의 JVM은 내 코드보다 안정적입니다. 그러나 Java 코드로 segfaults를 발생시킬 수도 있습니다. 사용할 수있는 메모리가 충분하고 프로필러를 마지막으로 체크인했을 때 힙 사용량은 약 50 %였으며 때로는 스파이크가 약 80 % 정도였습니다. 조사 할 수있는 시작 매개 변수가 있습니까? 이와 같은 버그에 접근 할 때 좋은 체크리스트는 무엇입니까?

이벤트를 신뢰할 수있게 재현 할 수는 없지만 무작위로 발생하는 것으로 보이지는 않으므로 테스트가 완전히 불가능하지는 않습니다.

ETA :. 실제 문제는 매우 구체적으로 수 있으므로

(나는 일반적인 접근 방법을 찾고 있어요 피투성이의 세부 사항 중 일부는 아직도이 이미 수집 된 몇 가지 정보입니다 그것은이 될 수 있습니다 얼마 전, 나는 내 CI 서버 (자세한 내용은 here 참조) 업그레이드 한 후 유사한 보이는 문제가 있었다

일부 값입니다.)하지만,() -XX:MaxPermSize 설정이 수정이 시간이 도움이되지 않았다.

추가 조사에 따르면 "현재 스레드"로 표시된 스레드는 절대로 내 스레드 중 하나가 아니며 "VMThread"또는 "GCTaskThread"중 하나라고합니다. 후자이므로 추가로 "(종료됨)"주석이 표시된 경우, 이전의 경우 GCTaskThread가 목록에 없습니다. 이 문제는 GC 작업이 끝날 무렵에 발생할 수 있다고 생각합니다.

+0

스택 추적을 얻을 수 있습니까? 같은 장소에서 SEGV입니까? 우리는 더 많은 정보를 얻을 수 있을까요? –

+0

응용 프로그램에 원시 코드가 있습니까? JVM이 바이트 코드의 수집을 허용한다면, 바이트 코드가 얼마나 버그가 있더라도 segfault를 유발할 수 있습니다. 사실, JVM (또는 JRE) 버그를 확인하고 있습니다. –

+0

@Ed - 스택 트레이스는 많이 있지만 텍스트의 거대한 벽입니다. 어떤 부분을 게시하는 것이 가장 유용할까요? 저는이 문제 유형에 접근하는 일반적인 방법을 주로 찾고 있습니다. 그러므로 여기에 매우 구체적인 정보를 쏟아 부어 주저합니다. –

답변

22

여기서 JVM 버그를보고 있지 않다고 가정합니다. 다른 Java 프로그램 은 정상적으로 실행되며 Sun의 JVM은 내 코드보다 안정적입니다.

나는 그 가정을해야한다고 생각하지 않습니다. JNI을 사용하지 않으면 SIGSEGV를 발생시키는 Java 코드를 작성할 수 없습니다. 내 요점은, 그것이 발생하면 JVM의 버그 (예기치 않은)이거나 일부 JNI 코드의 버그입니다. 자신의 코드에 JNI가 없다면 그것이 라이브러리를 사용하고 있지 않다는 것을 의미하지는 않습니다. 이전에 이런 종류의 문제를봤을 때 이미지 조작 라이브러리에있었습니다. 범인이 자신의 JNI 코드에없는 경우에는 버그를 '고칠 수 없지만 여전히 해결할 수 있습니다.

먼저 동일한 플랫폼에서 대체 JVM을 가져 와서 재현 해보십시오. one of these alternatives을 사용해보십시오.

재현 할 수없는 경우 JVM 버그 일 가능성이 큽니다. 그런 다음 특정 JVM 또는 search the bug database을 위임하는 방법에 대해 알고있는 것을 사용하여 제안 된 해결 방법을 얻을 수 있습니다. (당신이 그것을 재현 할 수없는 경우에도, 많은 JVM 구현은 오라클의 핫스팟 구현에 불과 비틀기가있다, 그래서 여전히 JVM 버그 수 있습니다.)

당신이 다른 JVM으로 재현 할 수있는 경우, 것을 할 수있는 오류 JNI 버그가 있습니다. 어떤 라이브러리를 사용하고 있으며 어떤 기본 호출을하고 있는지 살펴보십시오. 때로는 동일한 라이브러리 또는 대체 라이브러리에 대해 거의 동일한 것을 수행하는 대체 "순수 Java"구성 또는 jar 파일이 있습니다.

행운을 빈다.

+4

+1 "당신은 아마 버그를 고칠 수 없을 것입니다"포스터의 질문에 대한 답은 "코드를 실행할 때 JVM에서 Segfaults를 어떻게 디버깅합니까?"입니다. "* 너는 하지마." – Raedwald

9

네이티브 코드가 없으면 다음은 거의 쓸모가 없을 것입니다. 그러나 여기에 간다.

  1. java 디버거에서 Java 프로그램을 시작하고 가능한 sigsegv보다 먼저 중단 점을 사용하십시오.
  2. ps 명령을 사용하여 java의 processid를 가져옵니다.
  3. GDB는/usr/lib 디렉토리/JVM/태양 java6/빈/자바는
  4. 은 GDB '핸들'명령이
  5. 중단 점에서 자바 디버거에서 계속 SIGSEGV에 중지로 설정되어 있는지 확인 PROCESSID.
  6. 폭발 대기. 당신이 정말로 JVM은 자신의 네이티브 코드없이 SIGSEGV을 만들기 위해 관리 한 경우

을 조사하기

  • 사용 GDB는, 당신은 당신이 다음에 표시되는 내용의 이해가 매우 가능성이 있으며, 당신이 할 수있는 최선의 방법은 테스트 케이스를 버그 리포트에 푸시하는 것입니다.

  • +1

    JVM의 특별 버전이 필요합니까? C에서, 나는 gdb를 사용할 때 디버그 기호로 재 컴파일해야하는 데 익숙하다. –

    +0

    내 경험에 비추어 볼 때 JVM에는 항상 역 추적을위한 충분한 기호가 있습니다. 당신이 정말로 세부적으로 그것을 디버깅하고자한다면, openJDK와 디버그 빌드를 해제하십시오. – bmargulies

    2

    http://www.oracle.com/technetwork/java/javase/crashes-137240.html에서 좋은 목록을 발견했습니다. GC 동안 충돌이 발생하므로 가비지 수집기를 전환 해 봅니다.

    직렬 및 병렬 GC (64 비트 Linux 서버의 기본값 인 후자)간에 전환을 시도했지만 이에 따라 오류 메시지가 변경되었습니다.

    프로파일 러에서 새로 분석 한 후 최대 힙 크기를 16G에서 10G로 줄이면 (힙 사용이 8G로 ​​줄어들 었음) 상당히 "가상 메모리"풋 프린트 (16G 대신 60G)가 발생했습니다. 하지만 그게 무슨 뜻인지조차 모르겠다. 그리고 인터넷은 중요하지 않다.

    현재 JVM은 -client 시작 옵션을 사용하여 기본값 인 -server을 덮어 쓰는 클라이언트 모드에서 실행됩니다. 지금까지 충돌은 없지만 성능에 미치는 영향은 다소 커 보인다.

    0

    Java crash.use valgrind를 일으킨 C 프로그램 carsh가 유효하지 않음을 알 수 있는지 확인하고 스택 크기를 교차 확인하십시오.

    관련 문제