사용자 도구

사이트 도구


java:memory

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판 이전 판
다음 판
이전 판
java:memory [2015/07/02 18:00]
kwon37xi [jmap]
java:memory [2022/01/26 14:47] (현재)
kwon37xi [Default 값]
줄 2: 줄 2:
   * [[java:debug|Java Debug]]   * [[java:debug|Java Debug]]
   * [[java:gc|Java Garbage Collection]]   * [[java:gc|Java Garbage Collection]]
 +  * [[java:memory:mat|Java Memory Analyzer(MAT)]]
 +  * [[java:memory:heaphero|HeapHero]]
 +  * [[java:memory:jxray|JXRay]]
   * [[http://blog.naver.com/salsu0/30000025219|Java Heap 영역 설명]]   * [[http://blog.naver.com/salsu0/30000025219|Java Heap 영역 설명]]
 +
 +===== 기본 Heap 메모리 설정 =====
 +  * https://www.elastic.co/guide/en/elasticsearch/guide/current/heap-sizing.html 참조.
 +  * 장비 메모리에서 OS와 다른 애플리케이션이 사용하는 것을 제외하고 설정할 수 있다.(보통 2GB정도 남겨두고 나머지를 설정하면 될듯)
 +  * 하지만 Lucene의 경우 off heap 메모리를 사용하기 때문에 ElasticSearch는 장비 메모리의 50%만 heap으로 설정함. off heap 사용시에 관련 사항 주의.
 +  * 운영체제 메모리가 아무리 많아도 heap은 32GB를 넘기지는 않게 한다. 31GB 정도 추천
 +  * Linux 운영체제 swap 일어나는 것을 방지하기 위해 **swappiness=1** 로 조정한다. [[linux:performance|Linux Performance]]
 +
 +===== Default 값 =====
 +  * 운영체제에 따라 Java 버전에 따라 또한 현재 실행하고 있는 시스템의 메모리 상황에 따라 기본 메모리 설정이 다를 수 있다. 아래 명령으로 확인 가능하다.
 +<code sh>
 +# 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}
 +</code>
 +  * 혹은 Java 애플리케이션에서 확인도 가능하다.
 +<code java>
 +System.out.println(Runtime.getRuntime().maxMemory());
 +</code>
 +  * [[https://sarc.io/index.php/java/1092-jvm-default-heap-size|JVM의 default Heap Size가 궁금하세요?]]
 +  * [[https://mkyong.com/java/find-out-your-java-heap-memory-size|Find out your Java heap memory size - Mkyong.com]]
 +  * [[https://docs.oracle.com/en/java/javase/11/gctuning/ergonomics.html#GUID-DA88B6A6-AF89-4423-95A6-BBCBD9FAE781|Ergonomics]]
 +  * 기본 규칙(Java 11)
 +    * Min : 물리 메모리의 1/64
 +    * Max : 물리 메모리의 1/4
 +===== 64Bit 운영체제에서 포인터 크기 =====
 +  * 64Bit 운영체제에서라도 64bit long이 아니라 기본적으로 32bit 포인터를 사용한다.
 +  * 그러나 Heap 사이즈가 **대략 32GB**가 넘어가면 그때부터 64bit 포인터로 바뀐다. 이렇게 되면 포인터 자체가 차지하는 메모리가 너무 커서 낭비적이 될 수 있다.
 +  * 일반적으로 Heap Size가 31GB 정도일 때 32bit 압축 포인터가 거의 확실하게 사용된다. 그 이상일 때는 운영체제 환경, JDK 종류/버전 등에 따라 64bit가 사용될 가능성도 있다.
 +  * [[java:options|Oracle(SUN) JVM Options]]에서 ''UseCompressedOops=true'' 일 때 참조.
  
 ===== Heap Dump on OutOfMemoryError ===== ===== Heap Dump on OutOfMemoryError =====
줄 9: 줄 46:
 </code> </code>
   * ''-XX:HeapDumpPath''를 생략하면 JVM 시작 디렉토리에 ''java_pid<pid>.hprof''형태로 생성된다.   * ''-XX:HeapDumpPath''를 생략하면 JVM 시작 디렉토리에 ''java_pid<pid>.hprof''형태로 생성된다.
 +  * ''-XX:+PrintClassHistogramAfterFullGC'', ''-XX:+PrintClassHistogramBeforeFullGC'' 등의 옵션으로 Full GC 전/후의 메모리 상태를 간략히 덤프할 수 있다. [[java:gc|Java Garbage Collection]] 참조.
  
 ===== jmap ===== ===== jmap =====
줄 36: 줄 74:
 ===== jhat ===== ===== jhat =====
   * 힙 덤프를 분석한다.   * 힙 덤프를 분석한다.
-  * ''jhap -J-mx2048m 파일명.bin'' 실행후 http://localhost:7000/ 에서 살펴볼 수 있다.+  * ''jhat -J-mx2048m 파일명.bin'' 실행후 http://localhost:7000/ 에서 살펴볼 수 있다.
     * 힘 덤프 파일의 크기가 클 경우 OOM 에러가 발생할 수 있으므로 ''-J-mx2048m'' 지정     * 힘 덤프 파일의 크기가 클 경우 OOM 에러가 발생할 수 있으므로 ''-J-mx2048m'' 지정
   * 메모리를 너무 많이 먹어서 실제로 제대로 실행하기 힘듬.   * 메모리를 너무 많이 먹어서 실제로 제대로 실행하기 힘듬.
줄 80: 줄 118:
 | gcutil | GC 통계 데이터의 개요| | gcutil | GC 통계 데이터의 개요|
 | printcompilation |HotSpot 컴파일 방법의 통계 데이터| | printcompilation |HotSpot 컴파일 방법의 통계 데이터|
 +
 +===== SSH로 특정 서버의 GC 상태보기 =====
 +서버가 여러대일 경우 특정 서버에 자동 접속하여 해당 서버의 Tomcat 인스턴스를 찾아서 gcutil 실행
 +<code sh>
 +ssh myhostname 'bash -s' <<'ENDSSH'
 +jstat -gcutil `jps | grep Bootstrap | awk '{print $1}'` 1s
 +ENDSSH
 +</code>
 +
 +===== Code로 heap dump 뜨기 =====
 +  * [[https://blogs.oracle.com/sundararajan/programmatically-dumping-heap-from-java-applications|Programmatically dumping heap from Java applications]]
 +<code java>
 +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);
 +    }
 +}
 +</code>
  
java/memory.1435827643.txt.gz · 마지막으로 수정됨: 2015/07/02 18:00 저자 kwon37xi