18. GC가 어떻게 수행되고 있는지 보고 싶다

자바 인스턴스 확인을 위한 jps

jps는 해당 머신에서 운영중인 JVM의 목록을 보여준다.

$ jps [-q] [-mlvV] [-Joption] [<hostid>]

GC 상황을 확인하는 jstat

jstat는 GC가 수행되는 정보를 확인하기 위한 명령이다. jstat를 사용하면 유닉스 장비에서 vmstat나 netstat와 같이 라인 단위로 결과를 보여준다.

$ jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

GC 튜닝할 때 가장 유용한 jstat 옵션은 두 개

jstat 명령에서 GC 튜닝을 위해서 필자가 가장 애용하는 옵션은 -gcutil과 -gccapacity이다. gccapacity 옵션은 각 영역의 크기를 알 수 있기 때문에 어떤 영역의 크기를 좀 더 늘리고 줄여야 할 지를 확인할 수 있다. gcutil 옵션은 힙 영역의 사용량을 %로 보여준다.

원격으로 JVM 상황을 모니터링하기 위한 jstatd

jstatd 명령어로 원격 모니터링에 사용할 수 있다.

$ jstatd [-nr] [-p port] [-n rminame]

verbosegc 옵션을 이용하여 gc 로그 남기기

jvmstat를 사용할 수 없는 상황이라면 어떻게 GC를 분석할 수 있을까? 자바 수행 시에 -verbosegc 옵션을 넣어주면 된다.

어설프게 아는 것이 제일 무섭다.

예를 들어 메모리를 2GB로 지정한 시스템에 초당 1건의 요청이 오는 곳에서 한 번 요청이 올 때 10MB의 메모리가 생성된다고 가정하다. 이 시스템의 Old 영역이 1% 증가하려면 얼마나 기다려야 할까?

한 번 요청 올 때 생성되는 10MB의 메모리는 Eden 영역에 쌓일 것이다. 이 데이터가 Survivor 영역으로 넘어가고 Old 영역으로 넘어갈 확률은 얼마나 될까? 보통의 경우 JVM이 자동으로 지정해주는 Young 영역과 Old 영역의 비율은 1:2 ~ 1:9 정도다. 그러면 2GB에서는 100~300MB 정도가 Young 영역에 할당될 것이다. 그럼 이 시스템의 Old 영역이 1% 증가하려면 얼마나 기다려야 할까? 정답은 없지만 적어도 5분에서 2시간 정도 소요될 것이다. 5분에 1%라면 한시간에 12%, 9시간 정도 되어야 100%에 도달하여 Full GC가 발생하게 될 것이다.

메모리 릭이 발생하는지 확인하는 가장 확실한 방법은 verbosegc를 남겨서 보는 방법이다. 그리고 간단하게 확인할 수 있는 가장 확실한 방법은 Full GC가 일어난 이후에 메모리 사용량을 보는 것이다. 정확하게 이야기해서 Full GC가 수행된 후에 Old 영역의 메모리 사용량을 보자. 만약 사용량이 80% 이상이면 메모리 릭을 의심해야 한다. 그런데 Full GC를 한번도 하지 않은 시스템에 메모리 릭이 있다고 생각할 수 있는가? 어떤 시스템도 Full GC가 한번도 발생하지 않는 상황에서 메모리 릭이 있다고 이야기할 수 없다.