HPROF 출력 파일에 대한 설명

파일의 첫 번째 섹션에는 옵션, 저작권 및 면책사항 설명과 같은 일반 헤더 정보가 포함되어 있습니다. 그 다음으로 각 스레드에 대한 요약이 나옵니다.

아래 표시된 것처럼 단순 프로그램과 함께 HPROF를 사용하면 출력을 볼 수 있습니다. 이 테스트 프로그램에서는 짧은 시간 동안 두 개의 스레드를 작성하여 실행합니다. 출력에서 applesoranges(이)라는 두 스레드가 시스템 생성 main 스레드 뒤에 작성되었음을 확인할 수 있습니다. 두 스레드 모두 main 스레드 이전에 종료됩니다. 각 스레드에 대한 주소, ID, 이름 및 스레드 그룹 이름이 표시됩니다. 스레드가 시작되고 완료되는 순서를 확인할 수 있습니다.

THREAD START (obj=11199050, id = 1, name="Signal dispatcher", group="system")
THREAD START (obj=111a2120, id = 2, name="Reference Handler", group="system")
THREAD START (obj=111ad910, id = 3, name="Finalizer", group="system")
THREAD START (obj=8b87a0, id = 4, name="main", group="main")
THREAD END (id = 4)
THREAD START (obj=11262d18, id = 5, name="Thread-0", group="main")
THREAD START (obj=112e9250, id = 6, name="apples", group="main")
THREAD START (obj=112e9998, id = 7, name="oranges", group="main")
THREAD END (id = 6)
THREAD END (id = 7)
THREAD END (id = 5)

추적 출력 섹션에는 일반 스택 추적 정보가 있습니다. 각 추적의 수준을 설정할 수 있으며 각 추적에는 고유 ID가 있습니다.

TRACE 5:
	java/util/Locale.toLowerCase(Locale.java:1188)
	java/util/Locale.convertOldISOCodes(Locale.java:1226)
	java/util/Locale.<init>(Locale.java:273)
	java/util/Locale.<clinit>(Locale.java:200)

추적에는 여러 프레임이 포함되어 있으며 각 프레임에는 클래스 이름, 메소드 이름, 파일 이름 및 행 번호가 포함되어 있습니다. 이전 예에서 Locale.java의 행 번호 1188이(toLowerCase 메소드에 있음) 동일한 클래스의 convertOldISOCodes() 함수에서 호출되었음을 확인할 수 있습니다. 프로그램의 실행 경로 다음에 나오는 이러한 추적은 유용합니다. 모니터 옵션을 설정하는 경우 다음 예와 같은 모니터 덤프가 만들어집니다.

MONITOR DUMP BEGIN
    THREAD 8, trace 1, status: R
    THREAD 4, trace 5, status: CW
    THREAD 2, trace 6, status: CW
    THREAD 1, trace 1, status: R
    MONITOR java/lang/ref/Reference$Lock(811bd50) unowned
	waiting to be notified: thread 2
    MONITOR java/lang/ref/ReferenceQueue$Lock(8134710) unowned
	waiting to be notified: thread 4
    RAW MONITOR "_hprof_dump_lock"(0x806d7d0)
	owner: thread 8, entry count: 1
    RAW MONITOR "Monitor Cache lock"(0x8058c50)
	owner: thread 8, entry count: 1
    RAW MONITOR "Monitor Registry lock"(0x8058d10)
	owner: thread 8, entry count: 1
    RAW MONITOR "Thread queue lock"(0x8058bc8)
	owner: thread 8, entry count: 1
MONITOR DUMP END
MONITOR TIME BEGIN (total = 0 ms) Thu Aug 29 16:41:59 2002
MONITOR TIME END
모니터 덤프의 첫 번째 파트에는 스레드 목록이 있으며, 스레드가 실행한 코드를 식별하는 추적 항목이 목록에 포함되어 있습니다. 각 스레드의 스레드 상태도 다음과 같이 표시되어 있습니다.
  • R — Runnable(기회가 주어지면 스레드를 실행할 수 있습니다.)
  • S - Suspended(스레드가 다른 스레드에 의해 일시중단되었습니다.)
  • CW - Condition Wait(스레드가 대기 중입니다.)
  • MW - Monitor Wait(모니터가 대기 중입니다.)
다음에는 해당 소유자 및 대기 중인 스레드가 있는지 여부에 대한 표시가 포함된 모니터 목록입니다.

다음 섹션은 힙 덤프입니다. 이 정보는 다양한 메모리 영역 목록을 포함하고 있으며 이러한 영역이 할당되는 방법을 보여줍니다.

CLS 1123edb0 (name=java/lang/StringBuffer, trace=1318)
	super		111504e8
	constant[25]	8abd48
	constant[32]	1123edb0
	constant[33]	111504e8
	constant[34]	8aad38
	constant[115]	1118cdc8
CLS 111ecff8 (name=java/util/Locale, trace=1130)
	super		111504e8
	constant[2]	1117a5b0
	constant[17]	1124d600
	constant[24]	111fc338
	constant[26]	8abd48
	constant[30]	111fc2d0
	constant[34]	111fc3a0
	constant[59]	111ecff8
	constant[74]	111504e8
	constant[102]	1124d668
	...
CLS 111504e8 (name=java/lang/Object, trace=1)
	constant[18]	111504e8

CLS를 통해 메모리가 클래스에 할당되고 있음을 알 수 있습니다. 뒤에 나오는 16진수는 해당 메모리가 할당된 주소입니다.

다음에는 클래스 이름이, 그 뒤에는 추적 참조가 나옵니다. 이 정보를 사용하여 추적 출력을 상호 참조하고 클래스 호출 시기를 확인하십시오. 특정 추적을 참조하면 이 오브젝트를 작성하도록 지시한 명령어의 행 번호를 가져올 수 있습니다. 이 클래스에 있는 상수의 주소도 표시되며 이전 예에서는 수퍼클래스에 대한 클래스 정의 주소입니다. 두 클래스 모두 동일한 수퍼클래스의 하위입니다(주소는 11504e8임). 출력에서 더 찾아보면 이 클래스의 정의 및 이름을 확인할 수 있습니다. 해당 클래스는 오브젝트 클래스(모든 클래스가 상속하는 클래스)입니다. JVM이 전체 수퍼클래스 계층 구조를 로드해야 서브클래스를 사용할 수 있습니다. 따라서 모든 수퍼클래스에 대한 클래스 정의가 항상 있습니다. 오브젝트(OBJ) 및 배열 (ARR)에 대한 항목도 있습니다.

OBJ 111a9e78 (sz=60, trace=1, class=java/lang/Thread@8b0c38)
	name		111afbf8
	group		111af978
	contextClassLoader	1128fa50
	inheritedAccessControlContext	111aa2f0
	threadLocals	111bea08
	inheritableThreadLocals	111bea08
ARR 8bb978 (sz=4, trace=2, nelems=0, elem type=java/io/ObjectStreamField@8bac80)

heap 옵션을 sites 또는 all로 설정하는 경우 코드에 의해 할당된 각 스토리지 영역의 목록도 가져옵니다. all 매개변수는 dumpsites를 결합합니다. 이 목록은 메모리가 가장 많이 할당된 사이트가 맨 위에 오도록 정렬되어 있습니다.

SITES BEGIN (ordered by live bytes) Tue Feb 06 10:54:46 2007
          percent          live          alloc'ed  stack class
 rank   self  accum     bytes objs     bytes  objs trace name
    1 20.36% 20.36%    190060   16    190060    16 300000 byte[]
    2 14.92% 35.28%    139260 1059    139260  1059 300000 char[]
    3  5.27% 40.56%     49192   15     49192    15 300055 byte[]
    4  5.26% 45.82%     49112   14     49112    14 300066 byte[]
    5  4.32% 50.14%     40308 1226     40308  1226 300000 java.lang.String
    6  1.62% 51.75%     15092  438     15092   438 300000 java.util.HashMap$Entry
    7  0.79% 52.55%      7392   14      7392    14 300065 byte[]
    8  0.47% 53.01%      4360   16      4360    16 300016 char[]
    9  0.47% 53.48%      4352   34      4352    34 300032 char[]
   10  0.43% 53.90%      3968   32      3968    32 300028 char[]
   11  0.40% 54.30%      3716    8      3716     8 300000 java.util.HashMap$Entry[]
   12  0.40% 54.70%      3708   11      3708    11 300000 int[]
   13  0.31% 55.01%      2860   16      2860    16 300000 java.lang.Object[]
   14  0.28% 55.29%      2644   65      2644    65 300000 java.util.Hashtable$Entry
   15  0.28% 55.57%      2640   15      2640    15 300069 char[]
   16  0.27% 55.84%      2476   17      2476    17 300000 java.util.Hashtable$Entry[]
   17  0.25% 56.08%      2312   16      2312    16 300013 char[]
   18  0.25% 56.33%      2312   16      2312    16 300015 char[]
   19  0.24% 56.57%      2224   10      2224    10 300000 java.lang.Class

이 예에서는 추적 300055가 할당된 전체 메모리의 5.27%를 할당했습니다. 이 백분율은 49192바이트로 계산됩니다.

cpu 옵션은 프로세서에 대한 프로파일링 정보를 제공합니다. cpu가 샘플로 설정되어 있는 경우 코드 실행 도중 가져온 주기적 샘플의 결과가 출력에 포함됩니다. 각 샘플에서 처리 중인 코드 경로가 기록되며 다음과 같은 보고서가 생성됩니다.

CPU SAMPLES BEGIN (total = 714) Fri Aug 30 15:37:16 2002
rank   self  accum   count trace method
1 76.28% 76.28% 501 77 MyThread2.bigMethod
2 6.92% 83.20% 47 75 MyThread2.smallMethod
...
CPU SAMPLES END

bigMethod()는 프로세서 실행 시간의 76.28%를 차지하며 714개의 샘플 중 501번 실행되었음을 확인할 수 있습니다. 추적 ID를 사용하는 경우 이 메소드가 호출되는 정확한 경로를 확인할 수 있습니다.