Диаграммы по управлению памятью в Java процессе

    В интернете огромное количество статей и диаграмм на эту тему, однако, по моему мнению, ни одна из них не позволяет сформировать общее представление об использовании памяти в Java процессе. А без общего представления довольно сложно находить решения конкретных проблем с памятью в сложных системах. В результате, я решил выложить свои диаграммы.

    Упрощенная диаграмма использования памяти Java процесса:

    Упрощенная диаграмма использования памяти Java процесса
    Упрощенная диаграмма использования памяти Java процесса

    Детализированная диаграмма использования памяти Java процесса некоторыми параметрами:

    Детализированная диаграмма использования памяти Java процесса некоторыми параметрами
    Детализированная диаграмма использования памяти Java процесса некоторыми параметрами
    Список параметров JVM для Copy Paste

    -XX:+UnlockDiagnosticVMOptions 
    -XX:+PrintFlagsFinal 
    -XX:+PrintGCDetails
    -Xlog:gc+heap
    -XX:+HeapDumpOnOutOfMemoryError

    -XX:+UseSerialGC
    -XX:+UseParallelGC
    -XX:+UseConcMarkSweepGC
    -XX:+UseParNewGC 
    -XX:+UseG1GC
    -XX:+UseShenandoahGC
    -XX:+UseZGC
    -XX:+UseEpsilonGC 

    -XX:MinRAMPercentage
    -XX:MaxRAMPercentage-Xms
    -Xmx
    -XX:-AdaptiveSizePolicy

    -XX:MetaspaceSize
    -XX:MaxMetaspaceSize
    -XX:MinMetaspaceFreeRatio
    -XX:MaxMetaspaceFreeRatio

    -n jvmJavaOSStackSize
    -Xss
    -XX:VmThreadStackSize
    -XX:CompilerThreadStackSize

    -XX:+PrintGCDetails 
    -XX:+TraceClassUnloading 
    -XX:+TraceClassLoading
    -XX:CompressedClassSpaceSize
    -XX:-UseCompressedClassPointers

    -XX:+PrintStringTableStatistics
    -XX:StringTableSize
    -XX:+UseStringDeduplication

    -XX:+PrintCodeCache
    -XX:InitialCodeCacheSize
    -XX:ReservedCodeCacheSize 
    -XX:CodeCacheExpansionSize 

    -n jvmNativeStackSize 

    -XX:MaxDirectMemorySize

    -XX:NativeMemoryTracking=off | summary | detail  
    -XX:+PrintNMTStatistics 
    -XX:-AutoShutdownNMT

    -XX:+PrintCompilation

    -XX:+UnlockDiagnosticVMOptions 
    -XX:+LogCompilation
    -XX:+PrintFlagsFinal

    -XX:CICompilerCount
    -XX:CompileThresholdn
    -XX:-TieredCompilation

    -Dcom.sun.management.jmxremote 
    -Dcom.sun.management.jmxremote.authenticate=false 
    -Dcom.sun.management.jmxremote.ssl=false 
    -Dcom.sun.management.jmxremote.port=9099 
    -Dcom.sun.management.jmxremote.rmi.port=9099 
    -Dcom.sun.management.jmxremote.local.only=false 
    -Djava.rmi.server.hostname=0.0.0.0 
    -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000

    Краткий список инструментов для диагностики

    JProfiler
    VisualVM
    JConsole
    Java Flight Recorder
    async-profiler
    JDK Mission Control
    jstack
    jmap

    Данные диаграммы не имеют цели дать полные знания, но они могут стать отправной точкой в изучении темы глубже, восполнении пробелов в знаниях, тюнингу JVM и поиску проблемы в текущей системе.

    Комментарии 8

      +5

      Что кроме кучи есть стек, нативные буферы и прочее — для кого-то, может, и окажется новостью (или полезным напоминанием).
      Но причём тут Docker? Что изменится, если применить эту диаграмму к хостовой системе с ограниченными ресурсами?

        –3
        Вот тут поясняется, в чем проблема и «что изменится»: developers.redhat.com/blog/2017/03/14/java-inside-docker TL;DR: JVM «видит» объём памяти хостовой машины и не обращает внимания на limit указанный контейнеру, получаются интересные эффекты. Этим отличается запуск JVM на машине с ограниченными ресурсами и в контейнере с «ограниченными ресурсами».
          +3
          Закопайте назад эту статью! Эта проблема уже давно пофикшена (с 8u131 экспериментально и с 8u191 окончательно). Даже в приведенной вами статье добавлена сноска про фикс.
          Данная статья вообще не про это, а вообще непонятно про что про типы памяти JVM, и что нативный не-Java код (сюрприз! сюрприз!) не обращает внимания ни на Xmx с Xms и прочими параметры памяти, назначенные JVM, ни вообще на количество доступной памяти, а тем более cgroups, если его разработчик отдельно об этом не подумал.
            0
            Спасибо за комментарий. Заголовок и содержание поправил, чтобы не вносить путаницу с Docker'ом, и показать, что статья — справочная диаграмма использования памяти Java процесса.
          0
          Спасибо за комментарий. Согласен, информация про Docker полезной нагрузки статье не добавляет и заголовок вводит в заблуждение. Исправил. OS также имеет возможность убить процесс, из-за потребления памяти и результат будет аналогичен моей истории с Docker.
          0
          нижняя диаграмма более-менее читабельна в масштабе страницы 150%
            0
            Увеличил шрифты, загрузил картинку большего размера, но Хабр не дает возможность увеличить ее в интерфейсе. Рекомендую загрузить эту картинку и увеличивать вручную. Она достаточно хорошего качества.
            0
            Почему Direct ByteBuffers не часть «memory footprint» Java-процесса?

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

            Самое читаемое