# java 7 이하 java -XX:+PrintFlagsFinal -version 2>&1 | grep -i -E 'heapsize|permsize|version' # java 8 이상 java -XX:+PrintFlagsFinal -version 2>&1 | grep -i -E 'heapsize|metaspace|version' uintx InitialHeapSize := 522190848 {product} uintx MaxHeapSize := 8355053568 {product}
System.out.println(Runtime.getRuntime().maxMemory());
UseCompressedOops=true
일 때 참조.OutOfMemoryError
로 인한 JVM에 종료시 Heap Dump를 생성해준다.-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=jvm.hprof
-XX:HeapDumpPath
를 생략하면 JVM 시작 디렉토리에 java_pid<pid>.hprof
형태로 생성된다.-XX:+PrintClassHistogramAfterFullGC
, -XX:+PrintClassHistogramBeforeFullGC
등의 옵션으로 Full GC 전/후의 메모리 상태를 간략히 덤프할 수 있다. Java Garbage Collection 참조.live
옵션을 주면 live 객체만 덤프를 받는다. 이 옵션이 없으면 Heap 상의 모든 객체를 덤프 받는다.# jmap 사용 jps # Java PID 확인 jmap -dump:live,format=b,file=파일명.bin <PID> # jmap 잘 안될때 force. live 허용 안됨. jmap -F -dump:format=b,file=파일명.bin <PID> # gcore 사용 gcore -o 파일명.core <PID> # 파일명.core.<PID> 파일생성 jmap -dump:format=b,file=파일명.bin /usr/java/defaults/bin/java 파일명.core
jps -v | grep "원하는검색어" | awk '{print $1}' | xargs jmap -dump:live,format=b,file=jdump.hprof
jmap -histo:live <PID>
jhat -J-mx2048m 파일명.bin
실행후 http://localhost:7000/ 에서 살펴볼 수 있다.-J-mx2048m
지정-Xmx2048m
형태로 메모리 옵션을 줘야 한다.현재 JVM의 메모리 상태를 확인해 볼 수 있다.
jps # PID확인 jstat -gc <PID> 1000 # 1초마다 gc 확인
옵션명 | 내용 |
---|---|
class | 클래스 로더의 동작에 관한 통계 데이터 |
compiler | HotSpot Just-in-Time 컴파일러의 동작에 관한 통계 데이터 |
gc | GC된 heap의 동작에 관한 통계 데이터 |
gccapactiy | 세대마다의 용량과 대응하는 영역에 관한 통계 데이터 |
gccause | GC 통계 데이터의 개요(-gcutil 와 같다)와 직전 및 현재 (적용 가능한 경우)의 GC이벤트의 원인 |
gcnew | New 세대의 동작에 관한 통계 데이터 |
gcnewcapacity | New 세대의 사이즈와 대응하는 영역에 관한 통계 데이터 |
gcold | Old 세대 및 Permanent 세대의 동작에 관한 통계 데이터 |
gcoldcapacity | Old 세대의 사이즈에 관한 통계 데이터 |
gcpermcapacity | Permanent 세대의 사이즈에 관한 통계 데이터 |
gcutil | GC 통계 데이터의 개요 |
printcompilation | HotSpot 컴파일 방법의 통계 데이터 |
서버가 여러대일 경우 특정 서버에 자동 접속하여 해당 서버의 Tomcat 인스턴스를 찾아서 gcutil 실행
ssh myhostname 'bash -s' <<'ENDSSH' jstat -gcutil `jps | grep Bootstrap | awk '{print $1}'` 1s ENDSSH
import javax.management.MBeanServer; import java.lang.management.ManagementFactory; import com.sun.management.HotSpotDiagnosticMXBean; /** * 현재 Java Application의 Heap Dump를 뜨는 함수 * @see <a href="https://blogs.oracle.com/sundararajan/programmatically-dumping-heap-from-java-applications">Programmatically dumping heap from Java applications</a> */ public class HeapDumper { // This is the name of the HotSpot Diagnostic MBean private static final String HOTSPOT_BEAN_NAME = "com.sun.management:type=HotSpotDiagnostic"; // field to store the hotspot diagnostic MBean private static volatile HotSpotDiagnosticMXBean hotspotMBean; /** * Call this method from your application whenever you * want to dump the heap snapshot into a file. * * @param fileName name of the heap dump file * @param live flag that tells whether to dump * only the live objects */ public static void dumpHeap(String fileName, boolean live) { // initialize hotspot diagnostic MBean initHotspotMBean(); try { hotspotMBean.dumpHeap(fileName, live); } catch (RuntimeException re) { throw re; } catch (Exception exp) { throw new RuntimeException(exp); } } // initialize the hotspot diagnostic MBean field private static void initHotspotMBean() { if (hotspotMBean == null) { synchronized (HeapDumper.class) { if (hotspotMBean == null) { hotspotMBean = getHotspotMBean(); } } } } // get the hotspot diagnostic MBean from the // platform MBean server private static HotSpotDiagnosticMXBean getHotspotMBean() { try { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); HotSpotDiagnosticMXBean bean = ManagementFactory.newPlatformMXBeanProxy(server, HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class); return bean; } catch (RuntimeException re) { throw re; } catch (Exception exp) { throw new RuntimeException(exp); } } public static void main(String[] args) { // default heap dump file name String fileName = "heap.hprof"; // by default dump only the live objects boolean live = true; // simple command line options switch (args.length) { case 2: live = args[1].equals("true"); case 1: fileName = args[0]; } // dump the heap dumpHeap(fileName, live); } }