Heap Dump 를 생성하고 보기 위해 VisualVM 을 사용하는 과정을 정리한 글입니다.
Object 의 생성과 Garbage Collection(GC) 으로 인해 heap 에서 Object 가 제거되는 것을
VisualVM 을 통해 눈으로 확인해보겠습니다.
VisualVM 은 다양한 기능을 제공하지만
이 글에서는 Heap Dump 에 초점을 맞추었습니다.
그리고 macOS 기준으로 작성한 글이라 다른 OS환경과는 다르게 보일 수 있습니다.
1. 설치 및 실행
VisualVM홈페이지 에서 자신의 OS환경에 맞는 설치파일로 VisualVM 을 설치하실 수 있습니다.
처음 실행하면 아래 그림처럼 현재 자신의 로컬 환경에 실행 중인 JVM 어플리케이션들을 볼 수 있습니다.
이 어플리케이션들 중 하나를 예시로 사용법을 확인해보겠습니다.
특정 어플리케이션을 우클릭하여 Open 을 누르면 우측에 이 프로세스에 대한 정보를 보거나 상태를 모니터링 할 수 있습니다.
하지만 하고자 하는 것은 Heap Dump 를 생성하고 확인하는 것입니다.
왼쪽 탭에서 우클릭한 메뉴를 보면 Open 외에 Heap Dump 라는 메뉴가 있습니다.
이 Heap Dump 메뉴를 클릭하면 다음과 같이 진행됩니다.
왼쪽 탭에서 Heap Dump 가 생성된 것을 볼 수 있고 이에 대한 정보가 오른쪽에 나타납니다.
여기에서 생성된 Object 들에 대한 정보를 보려면 Summary 로 선택된 드랍다운을 Objects 로 선택하면 됩니다.
그러면 이 어플리케이션에서 생성되어 살아있는 Object 들에 대한 정보를 볼 수 있습니다.
2. 로컬에서 자바 코드를 실행하고 VisualVM 으로 확인하기
위에서 Heap Dump 를 생성하고 생성된 Object 들에 대한 정보를 확인하는 법을 알아보았으니
작은 자바 코드를 실행하고 Heap Dump 를 생성하여 이 코드에서 생성한 Object 를 VisualVM 을 통해 확인해보겠습니다.
실행할 코드는 다음과 같습니다.
import java.io.IOException;
class Main {
public static void main(String[] args) throws IOException {
MyHeapDump myHeapDump = new MyHeapDump();
System.in.read(); // 프로그램이 종료되지 않게 하기 위함
}
static class MyHeapDump {
}
}
이 코드를 실행하고 VisualVM 을 확인해보면 아래 이미지처럼 이 프로세스가 인식된 것을 볼 수 있습니다.
위에서 Heap Dump 를 생성했던 것처럼 이 항목을 우클릭하여 Heap Dump 를 누르면 Heap Dump 를 생성할 수 있습니다.
※ 여기서 잠깐!
이 단계에서 VisualVM 이 아래 이미지처럼 아무 응답이 없을 수 있습니다.(잘 되면 넘어가시면 됩니다)
이 경우엔 실행 시 아래 옵션을 추가해주면 됩니다.
-Djava.rmi.server.hostname=localhost
- command line 으로 실행할 경우
// 현재 디렉토리에 Main.java 가 있음
javac Main.java
java -Djava.rmi.server.hostname=localhost Main
- intellij 로 실행할 경우
위 옵션을 추가하고 실행하면 이상 없이 실행이 될 것입니다.
다시 본론으로 돌아와서 위에서 본 것처럼 VisualVM 에서 Heap Dump 를 생성하고 생성된 Object 를 보는 곳으로 가면
코드에서 생성한 MyHeapDump 클래스의 Object 가 생성된 것을 확인할 수 있습니다.
3. Heap Dump 생성 시 알아둬야 할 사항
위의 방법처럼 VisualVM 에서 Heap Dump 를 생성하면 GC 를 한번 실행한 후 Heap Dump 를 생성합니다.
아래 명령어처럼 GC 로그를 켜고 코드를 실행한 뒤 VisualVM 에서 Heap Dump 를 생성하면 GC 가 실행되는 것을 볼 수 있습니다.
// 현재 디렉토리에 Main.java 가 있음
javac Main.java
java -Djava.rmi.server.hostname=localhost -Xlog:gc Main
그래서 현재 힙 메모리 상태 그대로 Heap Dump 를 생성하고 싶다면 VisualVM 의 plugin 을 사용하거나 jmap 을 사용하면 됩니다.
[VisualVM 의 plugin 사용 방법]
VisualVM 의 plugin 을 사용하여 Heap Dump 를 GC 없이 생성하고 그것을 Load 하는 방법을 보여드리겠습니다.
상단의 Tool 탭에서 plugin 메뉴를 볼 수 있습니다.
Plugins 메뉴를 클릭하면 아래 화면이 나오고 VisualVM-MBeans 를 체크하여 install 버튼을 눌러 설치합니다.
plugin 설치가 완료된 후 다시 자바 프로그램을 실행해서 다음과 같은 절차를 따릅니다.
1. VisualVM 에서 새로 실행한 자바 프로세스를 우클릭하여 open.
2. 우측에 MBeans 라는 메뉴가 새로 생긴 것을 확인하고 클릭
3. 클릭하면 나오는 창의 왼쪽 탭에 com.sun.management 라는 메뉴를 누르면 HotSpotDiagnostic 을 볼 수 있음. 클릭
4. 오른쪽에 나오는 탭의 Operations 탭에 가서 p0의 우측칸에는 String 을 지우고 Heap Dump 파일이 생성될 디렉토리 + 파일명을 입력(ex. /Users/MyHeapDump.hprof). Heap Dump 확장자는 hprof 로 해야 함. p1 에는 false 를 입력.
5. dumpHeap 버튼을 누르면 p0 파라미터로 넘긴 디렉토리 + 파일명으로 HeapDump 가 GC 없이 생성됩니다.
예시
위 절차를 통해 생성한 Heap Dump 파일을 VisualVM 으로 Load 해서 사용해야 합니다.
맨 윗 탭에 보면 Load 메뉴가 있습니다.
해당 메뉴를 통해 위에서 생성한 Heap Dump 파일을 로드하면 Heap Dump 내용을 볼 수 있습니다.
[ jmap 을 사용한 방식 ]
jmap 은 jdk 에 포함된 툴 이어서 jdk 를 설치하였다면 바로 실행할 수 있습니다.
이번 방법은 jps + jmap 2개의 툴을 사용할 예정입니다.
과정은 다음과 같습니다.
1. 자바 코드를 실행시킨다.
java -Djava.rmi.server.hostname=localhost -Xlog:gc Main
2. 새로운 터미널을 열어서 jps 명령어를 통해 1번에서 실행한 프로세스 번호를 알아낸다.
3. jmap 명령어를 통해 Heap Dump 를 생성한다.
> jps
87824 Jps
86887 Main
75865
25802
84090 Launcher
> jmap -dump:format=b,file=test.hprof 86887
이렇게 jmap 을 통해 Heap Dump 를 생성하면 GC 없이 Heap Dump 를 생성할 수 있습니다.
이렇게 생성한 Heap Dump 파일을 VisualVM 에서 Load 하면 Heap Dump 를 볼 수 있습니다.
4. 코드에서 GC 를 실행하고 Heap Dump 확인
이제 다음과 같은 시나리오로 코드를 작성하고 VisualVM 을 통해 눈으로 Heap 메모리의 변화를 확인해보겠습니다.
1. Object 3개를 생성하는데 2개는 (GC 될 수 있게) 생성만 하고 변수에 담지 않는다.
2. 1번 상태로 Heap Dump를 생성하여 VisualVM 에서 3개의 Object 가 생성된 것을 확인한다.
3. System.gc 를 통해 GC 가 수행되게 한다.
4. 다시 Heap Dump 를 생성하고 VisualVM 으로 Object 2개가 heap 에서 제거된 것을 확인한다.
실행할 코드
import java.io.IOException;
class Main {
public static void main(String[] args) throws IOException {
new MyHeapDump();
new MyHeapDump();
MyHeapDump myHeapDump = new MyHeapDump();
System.in.read(); // 실행을 잠시 멈추고 Heap Dump 를 생성하기 위함
System.gc();
System.in.read(); // 실행을 잠시 멈추고 Heap Dump 를 생성하기 위함
}
static class MyHeapDump {
}
}
이 자바 코드를 실행시켜서 코드의 주석에 나와 있는 것처럼 2개의 지점에서 Heap Dump 를 생성해서
GC 가 일어나기 전 과 후를 확인해보겠습니다.
[코드 실행]
> javac Main.java
> java -Djava.rmi.server.hostname=localhost -Xlog:gc Main
[Heap Dump 생성]
jmap 를 사용하여 Heap Dump 를 생성하였습니다.
Heap Dump 를 VisualVM 으로 확인해보면 3개의 인스턴스가 생성된 것을 볼 수 있습니다.
[GC 실행]
엔터를 쳐서(입력을 넣어서) 코드를 진행시키고 GC 를 발생시킵니다.
자바 코드를 실행할 때 GC 로그를 켜놔서 GC 로그가 찍히는 것을 볼 수 있습니다.
[Heap Dump 생성]
GC 가 된 후를 확인해보겠습니다.
원했던 대로 Object 가 3개에서 1개로 줄어든 것을 볼 수 있습니다.
정리
- 자바 코드를 실행할 때 -Xlog:gc 옵션을 주면 GC 로그를 볼 수 있습니다.
- VisualVM 에서 그냥 Heap Dump 를 생성하면 GC 가 발생한 후의 Heap Dump 를 생성합니다.
- Heap Dump 를 GC 없이 생성하는 방법은 VisualVM 의 플러그인을 사용하는 것 또는 jmap 이 있습니다.
'개발' 카테고리의 다른 글
자바 HashMap의 capacity 는 왜 항상 2의 n승일까? (0) | 2023.02.26 |
---|---|
자바 ArrayList 의 default size 는 10 맞을까? (0) | 2023.02.19 |
알면 유용한 Java 8, 9 에서 추가, 변경된 Collection 관련 내용 (0) | 2023.02.11 |
자바 8 stream 의 lazy (0) | 2023.02.05 |
자바 8 람다는 익명 클래스와 같을까? (0) | 2023.01.30 |