자바 프로그램을 추적하는 방법?


25

sysadmin으로서 때때로 오류가 전혀 발생하지 않거나 넌센스 오류 메시지를 생성하는 동안 프로그램이 비정상적으로 작동하는 상황에 직면합니다.

과거에는 자바가 들어 오기 전에 두 가지 대책이있었습니다.

  1. 아무것도 도움이되지 않으면-RTFM ;-)
  2. 1.조차도 도움이되지 않는 경우-시스템 호출을 추적하고 무슨 일이 일어나고 있는지 확인하십시오

나는 보통 strace -fLinux 에서이 작업에 사용 합니다 (다른 OS는 비슷한 추적 도구가 있습니다). 이제 이것은 일반적으로 구식 프로그램에서 잘 작동하지만 Java 프로세스 에서 동일한 작업을 수행하면 추적이 매우 흐려집니다. 실제 작업과 관련이없는 것처럼 보이는 시스템 호출이 너무 많으므로 그러한 덤프를 통해 검색하는 것이 끔찍합니다.

더 좋은 방법이 있습니까 (소스 코드를 사용할 수없는 경우)?

답변:


16

ckhan이 언급했듯이 jstackJVM에서 모든 활성 스레드의 전체 스택 추적을 제공하기 때문에 훌륭합니다. SIGQUIT를 사용하여 JVM의 stderr에서도 동일하게 얻을 수 있습니다.

또 다른 유용한 도구는 jmap프로세스의 PID를 사용하여 JVM 프로세스에서 힙 덤프를 가져올 수 있습니다.

jmap -dump:file=/tmp/heap.hprof $PID

이 힙 덤프는 visualvm(이제 jvisualvm이라는 표준 Oracle Java SDK 설치의 일부 임) 와 같은 도구로로드 할 수 있습니다 . 또한 VisualVM은 실행중인 JVM에 연결하여 내부 CPU 사용량, 스레드 수 및 힙 사용량 그래프 표시를 포함하여 JVM에 대한 정보를 표시 할 수 있습니다. 이는 누수를 추적하는 데 유용합니다.

다른 도구 jstat( vmstat 3) 는 숫자 인수 (예 :)를 사용하여 실행하는 경우 vmstat와 같은 기간 동안 JVM에 대한 가비지 콜렉션 통계를 수집 할 수 있습니다 .

마지막으로, Java 에이전트를 사용하여로드시 모든 오브젝트의 모든 메소드에 대한 계측을 푸시 할 수 있습니다. 라이브러리 javassist는이 작업을 매우 쉽게 수행 할 수 있도록 도와줍니다. 따라서 자신의 추적을 추가하는 것이 가능합니다. 어려운 점은 추적 출력을 원할 때만 추적 출력을 얻는 방법을 찾는 것이지, 항상 JVM을 크롤링하는 속도를 늦출 수 있습니다. dtrace이와 같은 방식으로 작동 하는 프로그램 이 있습니다. 나는 그것을 시도했지만 성공하지 못했습니다. 에이전트를 계측하기 전에 JVM 부트 스트랩에 필요한 클래스가로드 된 후 에이전트가 모든 클래스를 계측 할 수 없으며, 해당 클래스에 계측을 추가하기에는 너무 늦습니다.

내 제안 -VisualVM으로 시작하여 JVM에 대한 현재 스레드 및 중요한 통계를 표시 할 수 있기 때문에 알아야 할 사항이 있는지 확인하십시오.


그건 그렇고, 이것은 멋진 질문입니다. 더 많은 사람들이 다른 아이디어로 답변을 추가하기를 바랍니다. 수년간 Java를 사용하는 사람들에게 추적에 대해 물었을 때, 그들은 나에게 공허한 응시를 주었다. 아마도 그들은 strace의 굉장함을 알지 못합니다.
ash

10

Linux 시스템에서 잘못된 프로그램을 디버깅 할 때도 비슷한 도구를 사용하여 시스템에서 실행중인 JVM을 디버깅 할 수 있습니다.

도구 # 1-jvmtop

와 마찬가지로 jvmtoptop사용 하여 시스템에서 실행중인 JVM 내에서 어떤 클래스가 사용 되는지 확인할 수 있습니다 . 설치되면 다음과 같이 호출하십시오.

$ jvmtop.sh

결과는 도구처럼 보이도록 비슷한 스타일로되어 있습니다 top.

 JvmTop 0.8.0 alpha   amd64  8 cpus, Linux 2.6.32-27, load avg 0.12
 http://code.google.com/p/jvmtop

  PID MAIN-CLASS      HPCUR HPMAX NHCUR NHMAX    CPU     GC    VM USERNAME   #T DL
 3370 rapperSimpleApp  165m  455m  109m  176m  0.12%  0.00% S6U37 web        21
11272 ver.resin.Resin [ERROR: Could not attach to VM]
27338 WatchdogManager   11m   28m   23m  130m  0.00%  0.00% S6U37 web        31
19187 m.jvmtop.JvmTop   20m 3544m   13m  130m  0.93%  0.47% S6U37 web        20
16733 artup.Bootstrap  159m  455m  166m  304m  0.12%  0.00% S6U37 web        46

도구 # 2-jvmmonitor

또 다른 대안은 jvmmonitor 를 사용하는 입니다. JVM 모니터는 Java 애플리케이션의 CPU, 스레드 및 메모리 사용량을 모니터하기 위해 Eclipse와 통합 된 Java 프로파일 러입니다. 이를 사용하여 로컬 호스트에서 실행중인 JVM을 자동으로 찾거나 port @ host를 사용하여 원격 JVM에 연결할 수 있습니다.

jvmmonitor의 ss

도구 # 3-visualvm

visualvm 은 아마도 JVM 관련 문제를 디버깅 할 때 도달 할 수있는 "도구"일 것입니다. 기능 세트는 매우 깊으며 내부를 매우 깊이 볼 수 있습니다.

애플리케이션 성능 프로파일 링 또는 메모리 할당 분석 :

visualvm # 2의 ss

스레드 덤프를 가져 와서 표시하십시오.

visualvm # 3의 ss

참고 문헌


4

고려하십시오 jstack. 에 대한 일치 stracepstack아니지만 더 많은- 아날로그가 있지만 적어도 스냅 샷의 사진을 제 시간에 제공합니다. 필요한 경우 조잡한 흔적을 얻기 위해 함께 묶을 수 있습니다.

이 SO 기사의 제안도 참조하십시오 : https : //.com/questions/1025681/call-trace-in-java


2

RHEL OpenJDK를 사용하는 경우 (또는 비슷한 점은 Oracle의 JDK가 아님) SystemTap 을 사용할 수 있습니다 .

일부 프로브는 자바 명령 행 옵션을 사용하여 사용할 수 있습니다 -XX:+DTraceMethodProbes, -XX:+DTraceAllocProbes, -XX:+DTraceMonitorProbes. 이러한 프로브를 활성화하면 프로그램 성능에 상당한 영향을 미칩니다.

SystemTap 스크립트의 예는 다음과 같습니다.

#!/usr/bin/stap

probe hotspot.class_loaded {
    printf("%12s [???] %s\n", name, class);
}

probe hotspot.method_entry, 
      hotspot.method_return {
    printf("%12s [%3d] %s.%s\n", name, thread_id, class, method);
}

probe hotspot.thread_start, 
      hotspot.thread_stop {
    printf("%12s [%3d] %s\n", name, id, thread_name);
}

probe hotspot.monitor_contended_enter, 
      hotspot.monitor_contended_exit {
    printf("%12s [%3d] %s\n", name, thread_id, class);
}

jstack()프로세스의 Java 스택을 가져 오는 데 사용할 수도 있지만 JVM 전에 SystemTap을 시작한 경우에만 작동합니다 .


SystemTap은 모든 메소드 를 추적 합니다 . 또한 메소드의 인수를 얻을 수 없습니다. 다른 옵션은 JVMTI라고하는 JVM 고유의 추적 기능을 사용하는 것입니다. 가장 유명한 JVMTI 구현 중 하나는 BTrace 입니다.


0

코드 변경이나 재배치없이 메소드 입력 및 종료를 추적 할 수있는 JVM 추적 도구 인 Jackplay 를 시도하는 것이 좋습니다 .


실행중인 JVM에 첨부 할 수 없습니다. 그 외에도 흥미로운 도구
Nils
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.