Обычно мы используем два инструмента: pmap и jcmd.VM.native_memory
Команда для просмотра использования памяти процессом Java.Поскольку команда pmap немного сложна, а многие карты памяти являются анонимными, здесь мы используем jcmd.VM.native_memory
команда, чтобы увидеть каждую часть памяти JVM.
Native Memory Tracking:
Total: reserved=6308603KB, committed=4822083KB
- Java Heap (reserved=4194304KB, committed=4194304KB)
(mmap: reserved=4194304KB, committed=4194304KB)
- Class (reserved=1161041KB, committed=126673KB)
(classes #21662)
( instance classes #20542, array classes #1120)
(malloc=3921KB #64030)
(mmap: reserved=1157120KB, committed=122752KB)
( Metadata: )
( reserved=108544KB, committed=107520KB)
( used=105411KB)
( free=2109KB)
( waste=0KB =0.00%)
( Class space:)
( reserved=1048576KB, committed=15232KB)
( used=13918KB)
( free=1314KB)
( waste=0KB =0.00%)
- Thread (reserved=355251KB, committed=86023KB)
(thread #673)
(stack: reserved=353372KB, committed=84144KB)
(malloc=1090KB #4039)
(arena=789KB #1344)
- Code (reserved=252395KB, committed=69471KB)
(malloc=4707KB #17917)
(mmap: reserved=247688KB, committed=64764KB)
- GC (reserved=199635KB, committed=199635KB)
(malloc=11079KB #29639)
(mmap: reserved=188556KB, committed=188556KB)
- Compiler (reserved=2605KB, committed=2605KB)
(malloc=2474KB #2357)
(arena=131KB #5)
- Internal (reserved=3643KB, committed=3643KB)
(malloc=3611KB #8683)
(mmap: reserved=32KB, committed=32KB)
- Other (reserved=67891KB, committed=67891KB)
(malloc=67891KB #2859)
- Symbol (reserved=26220KB, committed=26220KB)
(malloc=22664KB #292684)
(arena=3556KB #1)
- Native Memory Tracking (reserved=7616KB, committed=7616KB)
(malloc=585KB #8238)
(tracking overhead=7031KB)
- Arena Chunk (reserved=10911KB, committed=10911KB)
(malloc=10911KB)
- Tracing (reserved=25937KB, committed=25937KB)
(malloc=25937KB #8666)
- Logging (reserved=5KB, committed=5KB)
(malloc=5KB #196)
- Arguments (reserved=18KB, committed=18KB)
(malloc=18KB #486)
- Module (reserved=532KB, committed=532KB)
(malloc=532KB #3579)
- Synchronizer (reserved=591KB, committed=591KB)
(malloc=591KB #4777)
- Safepoint (reserved=8KB, committed=8KB)
(mmap: reserved=8KB, committed=8KB)
здесьmmap,mallocНапример, есть два разных метода выделения памяти:
Internal (reserved=3643KB, committed=3643KB)
(malloc=3611KB #8683)
(mmap: reserved=32KB, committed=32KB)
представлятьInternal
занято всего3643KB
,в3611KB
через метод malloc,32KB
Есть через mmap путь. Арена — это память, выделенная malloc, но она не освобождается после выполнения кода, она будет продолжать использоваться после того, как будет помещена в чанк арены.MallocInternals
Видно, что память процесса Java включает в себя:
-
Java Heap: куча памяти, т.е.
-Xmx
Ограничьте максимальный размер кучи памяти. -
Class: Загруженная информация о классе и методе на самом деле представляет собой метапространство, состоящее из двух частей: одна — это метаданные,
-XX:MaxMetaspaceSize
Ограничение максимального размера, в дополнение к пространству класса, составляет-XX:CompressedClassSpaceSize
ограничить максимальный размер -
Thread: Потоки и стеки потоков занимают память, и на размер каждого стека потоков влияет
-Xss
Ограничение есть, но нет ограничения на общий размер. -
Code: Код после JIT-компиляции точно в срок (оптимизированный компилятором C1 C2) занимает память и подлежит
-XX:ReservedCodeCacheSize
ограничение - GC: Сборка мусора занимает память, например, CardTable, необходимая для сборки мусора, количество меток, запись разделения области, метка GC Root и т. д., все из которых требуют памяти. Это не ограничено и, как правило, не очень велико.
- Compiler: Память, занимаемая кодом и тегами самого компилятора C1 C2, не ограничена и в целом не очень велика.
- Internal: Разбор командной строки, память, используемая JVMTI, это не ограничено и, как правило, не очень большое
-
Symbol: размер, занимаемый пулом констант, пул строковых констант подлежит
-XX:StringTableSize
Количество ограничено, а общий объем памяти не ограничен - Native Memory Tracking:Размер памяти, занимаемый самим набором памяти.Если набор не включен (тогда этого не видно, ха-ха), он не будет занят.Это не ограничено и в целом не очень большое.
- Arena Chunk: Вся память, выделенная ареной, не ограничена, как правило, не очень большая
- Tracing: Память, занятая всеми сборами данных, если JFR включена, это в основном память, занятая JFR. Это не ограничено, как правило, не очень большое
- Логирование, Аргументы, Модуль, Синхронизатор, Сейфпойнт, Другое — обычно нас это не волнует.
В дополнение к использованию памяти, регистрируемому Native Memory Tracking, существует два типа памяти.Отслеживание собственной памяти не регистрируется,Это:
-
Direct Buffer: Прямая память, в основном относится к
java.nio.DirectByteBuffer
Выделяет память во время создания. Зачем использовать память вне кучи? Обычно потому что:- Может использоваться совместно между процессами, что снижает репликацию между виртуальными машинами.
- Улучшения приостановки сборки мусора: если некоторые долгоживущие объекты, существующие в большом количестве приложений, часто вызывают YGC или FullGC, вы можете рассмотреть возможность удаления этих объектов из кучи. Чрезмерно большая куча может повлиять на производительность приложений Java. Если используется память вне кучи, памятью вне кучи управляет непосредственно операционная система (а не виртуальная машина). Результатом этого является сохранение небольшого объема памяти в куче, чтобы уменьшить влияние сборки мусора на приложение.
- В некоторых сценариях производительность программных операций ввода-вывода может быть улучшена. Этап копирования данных из памяти в куче в память вне кучи исключен.
-
MMap Buffer: Память с отображением файлов, хотя Java Memory Mapped Files присутствует в пакете java.nio начиная с JDK 1.4, для многих разработчиков программ это все еще довольно новая концепция. После появления NIO Java IO уже работает достаточно быстро, а файлы с отображением памяти обеспечивают самые быстрые операции ввода-вывода, возможные в Java, поэтому эти высокопроизводительные Java-приложения должны использовать файлы с отображением памяти для сохранения данных. В качестве важной функции NIO метод Mmap предоставляет нам возможность отобразить часть или весь файл в адресное пространство памяти, при этом, когда эта область памяти будет записана в грязную страницу, операционная система будет использовать некоторое количество Алгоритм записывает эти данные в файл, и нашей java-программе не нужно об этом заботиться. Это ключевое преимущество отображаемых в память файлов: даже если ваша программа зависнет сразу после записи в память, операционная система все равно запишет данные из памяти в файловую систему. Другим более заметным преимуществом является общая память.К файлам, отображаемым в память, могут обращаться несколько процессов одновременно, выступая в качестве общей памяти с малой задержкой.