스레드를 잘못 사용하면 다양한 종류의 문제가 발생할 수 있습니다. 활성 스레드가 너무 많으면 스레드 기아 상태(thread starvation)가 발생할 수 있고, 스레드가 서로를 차단하여 애플리케이션의 활성도에 영향을 주거나 잘못된 순서로 락을 획득하여 데드락이 발생할 수 있습니다. 또한 스레드에 대한 정보는 디버깅 목적으로도 중요합니다.
JProfiler에서 스레드 프로파일링은 두 개의 뷰 섹션으로 나뉩니다. "Threads" 섹션은 스레드의 라이프사이클과 스레드 덤프 캡처를 다룹니다. "Monitors & locks" 섹션은 여러 스레드 간의 상호작용을 분석하는 기능을 제공합니다.
스레드 검사
스레드 히스토리 뷰는 각 스레드를 타임라인에 색상이 지정된 행으로 표시하며, 여기서 색상은 기록된 스레드 상태를 나타냅니다. 스레드는 생성 시간순, 이름순 또는 스레드 그룹별로 정렬되며 이름으로 필터링할 수 있습니다. 또한 드래그 앤 드롭으로 스레드 순서를 직접 재정렬할 수도 있습니다. monitor 이벤트가 기록된 경우, "Waiting" 또는 "Blocked" 상태였던 스레드 부분에 마우스를 올려 연관된 스택 트레이스를 확인하고 monitor 히스토리 뷰로 연결되는 링크를 볼 수 있습니다.
모든 스레드의 테이블 뷰는 스레드 monitor 뷰에서 확인할 수 있습니다. 스레드가 생성되는 동안 CPU 기록이 활성화되어 있으면 JProfiler는 생성한 스레드의 이름을 저장하고 테이블에 표시합니다. 하단에는 생성한 스레드의 스택 트레이스가 표시됩니다. 성능상의 이유로 JVM에 실제 스택 트레이스를 요청하지 않고 CPU 기록의 현재 정보를 사용합니다. 즉, 스택 트레이스에는 호출 트리 수집 필터 설정을 충족하는 클래스만 표시됩니다.
프로파일링 설정에서 예상 CPU 시간 기록을 활성화하면 테이블에 CPU time 열이 추가됩니다. CPU 시간은 CPU 데이터를 기록할 때만 측정됩니다.
대부분의 디버거와 마찬가지로 JProfiler도 스레드 덤프를 생성할 수 있습니다. 스레드 덤프의 스택 트레이스는 JVM에서 제공하는 전체 스택 트레이스이며 CPU 기록에 의존하지 않습니다. 두 개의 스레드 덤프를 선택하고 Show Difference 버튼을 클릭하면 diff 뷰어에서 서로 다른 스레드 덤프를 비교할 수 있습니다. 또한 단일 스레드 덤프에서 두 스레드를 선택한 후 컨텍스트 메뉴에서 Show Difference를 선택하여 비교할 수도 있습니다.
스택 트레이스가 동일한 스레드 덤프는 그룹화됩니다. 플랫폼 스레드 덤프의 이러한 노드에 대해 유사한 모든 스레드를 표시하는 컨텍스트 메뉴 액션이 제공됩니다.
Java 21 이상을 프로파일할 때는 스레드 덤프 뷰에서 별도의 "Take Thread Dump With Virtual Threads" 액션을 사용할 수 있습니다. 플랫폼 스레드도 가상 스레드 덤프에 포함됩니다.
스레드 덤프는 "Trigger thread dump" 트리거 액션이나 API를 통해서도 생성할 수 있습니다.
락킹 상황 분석
모든 Java 객체에는 두 가지 동기화 작업에 사용할 수 있는 연관된 monitor가 있습니다. 스레드는 다른 스레드가
알림을 보낼 때까지 monitor에서 대기(wait)하거나, 다른 스레드가 락의 소유권을 양도할 때까지 차단(block)될 수
있는 상태로 monitor에 대한 락을 획득할 수 있습니다. 또한 Java는 고급 락킹 전략을 구현하기 위해
java.util.concurrent.locks 패키지의 클래스를 제공합니다. 해당 패키지의 락은 객체의 monitor를
사용하지 않고 다른 네이티브 구현을 사용합니다.
JProfiler는 위의 두 메커니즘 모두에 대한 락킹 상황을 기록할 수 있습니다. 락킹 상황에는 하나 이상의 스레드,
monitor 또는 java.util.concurrent.locks.Lock 인스턴스, 그리고 일정 시간이 소요되는 대기 또는 차단
작업이 포함됩니다. 이러한 락킹 상황은 monitor 히스토리 뷰에 테이블 형식으로 표시되며, 락킹 히스토리 그래프에
시각적으로 표시됩니다.
락킹 히스토리 그래프는 개별 monitor 이벤트의 지속 시간보다는 관련된 모든 monitor와 스레드의 전체 관계 집합에 초점을 맞춥니다. 락킹 상황에 참여하는 스레드와 monitor는 파란색 및 회색 직사각형으로 표시되며, 데드락의 일부인 경우 빨간색으로 표시됩니다. 검은색 화살표는 monitor의 소유권을 나타내고, 노란색 화살표는 대기 중인 스레드에서 연관된 monitor로 이어지며, 빨간색 점선 화살표는 스레드가 monitor를 획득하려고 시도 중이며 현재 차단되어 있음을 나타냅니다. CPU 데이터가 기록된 경우 차단 또는 대기 화살표 위에 마우스를 올리면 스택 트레이스를 확인할 수 있습니다. 이러한 툴팁에는 monitor 히스토리 뷰의 해당 행으로 이동하는 하이퍼링크가 포함되어 있습니다.
테이블 형식의 monitor 히스토리 뷰는 monitor 이벤트를 보여줍니다. 각 이벤트에는 열로 표시되는 지속 시간이 있으므로 테이블을 정렬하여 가장 중요한 이벤트를 찾을 수 있습니다. 테이블 뷰에서 선택한 행에 대해 Show In Graph 액션을 사용하여 그래프로 이동할 수 있습니다.
각 monitor 이벤트에는 연관된 monitor가 있습니다. Monitor Class 열에는 monitor가 사용되는 인스턴스의 클래스 이름이 표시되거나, monitor에 연결된 Java 객체가 없는 경우 "[raw monitor]"가 표시됩니다. 어떤 경우든 monitor에는 별도의 열에 표시되는 고유 ID가 있으므로 여러 이벤트에 걸쳐 동일한 monitor의 사용을 연관 지을 수 있습니다. 각 monitor 이벤트에는 작업을 수행하는 대기 스레드가 있으며, 선택적으로 작업을 차단하고 있는 소유 스레드가 있을 수 있습니다. 제공되는 경우 해당 스택 트레이스가 뷰의 하단에 표시됩니다.
monitor 인스턴스에 대해 추가 질문이 있는 경우, monitor 히스토리 뷰와 락킹 히스토리 그래프의 Show Selection In Heap Walker 액션을 통해 heap walker로 연결하여 해당 monitor 인스턴스를 새 객체 집합으로 선택할 수 있습니다.
관심 이벤트 제한하기
monitor 이벤트 분석 시 발생하는 한 가지 근본적인 문제는 애플리케이션이 엄청난 속도로 monitor 이벤트를 생성할 수 있다는 점입니다. 그렇기 때문에 JProfiler에는 대기 및 차단 이벤트에 대한 기본 임계값이 있어 이보다 짧은 이벤트는 즉시 폐기됩니다. 이러한 임계값은 뷰 설정에서 정의되며 더 긴 이벤트에 집중하기 위해 늘릴 수 있습니다.
기록된 이벤트에 필터를 추가로 적용할 수도 있습니다. monitor 히스토리 뷰 상단에는 임계값, 이벤트 유형 및 텍스트 필터가 제공됩니다. 락킹 히스토리 그래프를 사용하면 관심 있는 스레드나 monitor를 선택하여 표시된 엔터티가 관련된 락킹 상황만 표시할 수 있습니다. 관심 이벤트는 타임라인에 다른 색상으로 표시되며, 해당 이벤트를 순서대로 탐색할 수 있는 보조 내비게이션 바가 있습니다. 현재 이벤트가 관심 이벤트가 아닌 경우, 양방향으로 현재 이벤트와 다음 관심 이벤트 사이에 몇 개의 이벤트가 있는지 확인할 수 있습니다.
선택한 스레드나 monitor가 존재하는 락킹 상황 외에도, 그래프에서 제거되는 락킹 상황도 표시됩니다. 이는 각 monitor 이벤트가 작업이 시작되는 상황과 종료되는 상황이라는 두 개의 락킹 상황으로 정의되기 때문입니다. 이는 완전히 비어 있는 그래프 역시 JVM에 더 이상 락이 없음을 나타내는 유효한 락킹 상황임을 의미합니다.
주의를 기울여야 하는 이벤트 수를 줄이는 또 다른 전략은 락킹 상황을 누적하는 것입니다. 락킹 히스토리 그래프 하단에는 기록된 모든 이벤트를 보여주는 타임라인이 있습니다. 타임라인을 클릭하고 드래그하면 시간 범위가 선택되고 포함된 모든 이벤트의 데이터가 위의 락킹 그래프에 표시됩니다. 누적된 그래프에서는 각 화살표에 동일한 유형의 이벤트가 여러 개 포함될 수 있습니다. 이 경우 툴팁 창에 이벤트 수와 포함된 모든 이벤트의 총시간이 표시됩니다. 툴팁 창의 드롭다운 목록에는 타임스탬프가 표시되어 여러 이벤트 간을 전환할 수 있습니다.
데드락 감지
"Current locking graph" 및 "Current monitors" 뷰는 JProfiler UI의 액션으로 트리거되는 "monitor 덤프"를 기반으로 작동합니다. monitor 덤프를 사용하면 아직 진행 중인 이벤트를 검사할 수 있습니다. 여기에는 절대 완료되지 않아 히스토리 뷰에 표시될 수 없는 이벤트인 데드락이 포함됩니다.
차단 작업은 대개 수명이 짧지만, 데드락이 발생하면 두 뷰 모두 문제에 대한 영구적인 뷰를 표시합니다. 또한 현재 락킹 그래프는 데드락을 유발하는 스레드와 monitor를 빨간색으로 표시하므로 이러한 문제를 즉시 발견할 수 있습니다.
새 monitor 덤프를 생성하면 두 뷰의 데이터가 모두 대체됩니다. 또한 "Trigger monitor dump" 트리거 액션이나 API를 통해 monitor 덤프를 트리거할 수도 있습니다.
Monitor 사용 통계
더 높은 관점에서 차단 및 대기 작업을 조사하기 위해 monitor 통계 뷰는 monitor 기록 데이터로부터 리포트를 계산합니다. monitor, 스레드 이름 또는 monitor 클래스별로 monitor 이벤트를 그룹화하고 각 행의 누적 횟수 및 지속 시간을 분석할 수 있습니다.























