Разбор и настройка параметров JVM

Java JVM

Разбор и настройка параметров JVM

Raymon 2017-06-28   Java

Полное название JVM — виртуальная машина Java. Файл .class, сгенерированный после компиляции программы Java, передается JVM для выполнения. JVM переводит содержимое файла .class на машинный язык, распознаваемый системой. Вот почему Java можно скомпилировать один раз и запускать везде.

О конфигурации JVM и настройки JVM является обязательным для Java-программистов для мастера. Отличный программист Java может установить параметры JVM в соответствии с запущенной средой, чтобы добиться оптимальной конфигурации, привести разумное и полное использование системных ресурсов и избежать некоторых вхождений В качестве OOM в производственной среде. Исключение или резьбовые тупики, Java Process CPU Расход CPU слишком высок и так далее.

Инструменты отладки JVM

jps (JVM Process Status Tool)

--- Вывести информацию о состоянии процесса Java, запущенного jvm

Формат команды:

jps [options] [hostId]

Значением hostId по умолчанию является текущий хост Команды включают:

 -q 不输出类名、Jar名和传入main方法的参数
 -m 输出传入main方法的参数
 -l 输出main类或Jar的全限名
 -v 输出传入JVM的参数

Используйте следующим образом:

[root@localhost ~]#
[root@localhost ~]# jps -m -l
28353 uyun.bat.monitor.impl.Startup
22852 uyun.bat.datastore.Startup
25799 uyun.bat.event.impl.Startup
19976 /opt/uyun/platform/jetty/start.jar
29320 uyun.bat.report.Startup

jstack

--- Вывести конкретную информацию о стеке внутрипроцессного потока Java

jstask должен быть широко используемым инструментом отладки JVM Формат команды:

jstack [option] [pid]

Командные инструкции:

-l long listings 打印线程锁信息,发生死锁时可以使用该参数调试
-m mixed mode 不仅输出java堆栈信息,还会输出C/C++堆栈信息

Пример практического применения: просмотр информации о стеке потоков процесса, занимающего больше всего ресурсов ЦП.

  1. ps -ef | grep Найдите соответствующий процесс или используйте команду top, чтобы просмотреть информацию об использовании системы и найти процесс, который потребляет больше всего. Здесь я использую команду top:
top - 07:38:01 up 3 days,  6:20,  5 users,  load average: 15.72, 15.02, 14.14
Tasks: 148 total,   7 running, 141 sleeping,   0 stopped,   0 zombie
%Cpu(s): 71.2 us, 26.1 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  2.7 si,  0.0 st
KiB Mem:  20397888 total, 20124388 used,   273500 free,        0 buffers
KiB Swap:  1081340 total,  1081340 used,        0 free.  2163376 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
24152 es        20   0 3323892 492160  28496 S 35.7  2.4   1613:51 java
 3247 mysql     20   0 1152924 297932   5836 S  9.9  1.5 418:51.47 mysqld
20009 root      20   0 3688420 1.563g  13132 S  7.9  8.0 653:51.83 java
22852 root      20   0 3450392 546480  12828 S  7.6  2.7 322:33.85 java
 5779 root      20   0 3652656 1.114g   4976 S  4.3  5.7 109:57.89 java
28353 root      20   0 3624988 337680  12824 S  3.3  1.7 125:49.11 java
  268 root       0 -20       0      0      0 S  2.3  0.0  43:33.35 kworker/0:1H
11539 root      20   0  369916  14108   4020 R  2.0  0.1   0:00.06 python
25799 root      20   0 3356336 475416  12832 S  1.7  2.3  64:56.00 java
 1544 root      20   0  247448  27916   1144 S  1.3  0.1  56:24.67 redis-server
11540 root      20   0  131528   5048   3880 S  1.3  0.0   0:00.04 sshd
21497 root      20   0 3306144 313020  12712 S  1.0  1.5  20:59.73 java
    1 root      20   0  133816   6772   2084 S  0.7  0.0  40:38.49 systemd

После того, как команда top для поиска наиболее интенсивно использующей ЦП Java является процессом, идентификатор процесса равен 24152, потребление памяти достигло 35,7%, после представления ps -ef | grep pid этот процесс является процессом ElasticSearch.

  1. Вторые шаги нам нужно найти самую дорогостоящую тему процессора в процессе, вы можете использовать PS -LFP PID, PS -MP PID -O TOTE, TOP -HP PID, здесь мы используем третью команду, топ-HP 24152
top - 07:44:20 up 3 days,  6:27,  5 users,  load average: 19.72, 15.50, 14.42
Threads:  40 total,   1 running,  39 sleeping,   0 stopped,   0 zombie
%Cpu(s): 64.3 us, 32.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  3.7 si,  0.0 st
KiB Mem:  20397888 total, 19894260 used,   503628 free,        0 buffers
KiB Swap:  1081340 total,  1081340 used,        0 free.  1994824 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
24937 es        20   0 3319268 485312  21512 R 23.0  2.4 748:12.71 java
24953 es        20   0 3319268 485312  21512 S  4.3  2.4 151:27.67 java
24157 es        20   0 3319268 485312  21512 S  3.0  2.4 142:46.82 java
24459 es        20   0 3319268 485312  21512 S  0.3  2.4   1:58.92 java
24876 es        20   0 3319268 485312  21512 S  0.3  2.4  16:58.66 java
24152 es        20   0 3319268 485312  21512 S  0.0  2.4   0:00.00 java
24154 es        20   0 3319268 485312  21512 S  0.0  2.4   0:02.02 java
24155 es        20   0 3319268 485312  21512 S  0.0  2.4   0:00.00 java
24156 es        20   0 3319268 485312  21512 S  0.0  2.4  42:25.76 java
24158 es        20   0 3319268 485312  21512 S  0.0  2.4   0:31.47 java

Здесь мы видим, что pid самого дорогого потока равен 24937.

  1. Третий шаг — получить шестнадцатеричное значение идентификатора потока 24937.
[root@localhost ~]# printf "%x\n" 24937
6169

Затем используйте jstack для вывода информации о стеке с идентификатором потока 24937, grep в соответствии с шестнадцатеричным значением идентификатора потока.

jstack 24152 | grep 6169

Вот у меня проблема, после выполнения команды jstack система не возвращает информацию о jvm, а выдает ошибку:

Unable to open socket file: target process not responding or HotSpot VM not loaded

Сообщается о причине, по которой эта ошибка не может найти файл.Прежде всего, мы должны знать, что каталог hsperfdata_$user будет создан при запуске jvm.По умолчанию /tmp под Linux.Мы также можем настроить параметр запуска jvm -Djava.io.tmpdir Чтобы указать место хранения временного файла информации о номере процесса, после проверки подтвердите наличие сгенерированного каталога hsperfdata_es в /tmp

[root@localhost hsperfdata_es]# pwd
/tmp/hsperfdata_es
[root@localhost hsperfdata_es]# ls
24152
[root@localhost hsperfdata_es]#

Причина, по которой jstack сообщит об ошибке, что файл не может быть найден, заключается в том, что процесс ElasticSearch запущен с пользователем es, а мы вошли в систему с учетной записью root, поэтому мы не можем получить доступ к этому файлу.После переключения пользователя на es, используйте jstack для повторной печати информации о стеке потока:

[root@localhost hsperfdata_es]# su es
[es@localhost hsperfdata_es]$ jstack 24152 | grep 6169
"elasticsearch[Grenade][bulk][T#1]" #49 daemon prio=5 os_prio=0 tid=0x00007f78440b2000 nid=0x6169 runnable [0x00007f7840fa1000]
[es@localhost hsperfdata_es]$

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

jmap jhat

--- jmap выводит использование памяти кучи --- jhat инструмент для анализа кучи памяти Java

jmap и jhat часто используются вместе.

jmap -hap pid

Используется для просмотра использования процессов использования памяти, включая параметры конфигурации кучи и использование кучи памяти в каждом поколе, например:

whale.server01:/root# jmap -heap 17047
Attaching to process ID 17047, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.77-b03

using thread-local object allocation.
Parallel GC with 4 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 1073741824 (1024.0MB)
   NewSize                  = 175112192 (167.0MB)
   MaxNewSize               = 357564416 (341.0MB)
   OldSize                  = 351272960 (335.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 134217728 (128.0MB)
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 70254592 (67.0MB)
   used     = 22570248 (21.52466583251953MB)
   free     = 47684344 (45.47533416748047MB)
   32.126366914208255% used
From Space:
   capacity = 9961472 (9.5MB)
   used     = 6859688 (6.541908264160156MB)
   free     = 3101784 (2.9580917358398438MB)
   68.86219225431743% used
To Space:
   capacity = 10485760 (10.0MB)
   used     = 0 (0.0MB)
   free     = 10485760 (10.0MB)
   0.0% used
PS Old Generation
   capacity = 184025088 (175.5MB)
   used     = 99082056 (94.49201202392578MB)
   free     = 84943032 (81.00798797607422MB)
   53.841602292835205% used

24334 interned Strings occupying 2508568 bytes.

Используйте jmap -histo[:live] pid для просмотра количества объектов в памяти кучи, гистограммы статистики размера, если вы приводите живые объекты, будут учитываться только живые объекты, следующим образом:

whale.server01:/root# jmap -histo:live 17047 | more

 num     #instances         #bytes  class name
----------------------------------------------
   1:         77521        8038136  [C
   2:          1056        2890752  [J
   3:          6362        2595656  [B
   4:          5812        1968312  [I
   5:         76614        1838736  java.lang.String
   6:         19709        1734392  java.lang.reflect.Method
   7:         18318        1268024  [Ljava.lang.Object;
   8:         10179        1136280  java.lang.Class
   9:         33025        1056800  java.util.concurrent.ConcurrentHashMap$Node
  10:         12388         594624  org.aspectj.weaver.reflect.ShadowMatchImpl
  11:         16901         540832  java.util.HashMap$Node
  12:         12304         492160  java.util.LinkedHashMap$Entry
  13:         12388         396416  org.aspectj.weaver.patterns.ExposedState
  14:          2633         352464  [Ljava.util.HashMap$Node;
  15:         11008         352256  java.util.Hashtable$Entry
  16:           436         330440  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  17:         13383         321192  java.util.ArrayList
  18:          9319         298208  java.lang.ref.WeakReference
  19:           741         278616  java.lang.Thread
  20:         17352         277632  java.lang.Object
  21:          5707         228280  java.lang.ref.SoftReference
  22:          3612         173376  java.util.HashMap
  23:           302         164288  rx.internal.util.unsafe.SpscArrayQueue
  24:          5104         163328  java.util.concurrent.locks.ReentrantLock$NonfairSync
  25:          2872         160832  java.util.LinkedHashMap
  26:          4784         153088  java.lang.ThreadLocal$ThreadLocalMap$Entry
  27:          1828         146240  java.lang.reflect.Constructor
  28:          1473         139856  [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;
  29:          5152         123648  java.beans.MethodRef
  30:          3831         119752  [Z
  31:          5550         118632  [Ljava.lang.Class;
  32:          2003         112168  java.security.Provider$Service
  33:           464         107616  [Ljava.util.Hashtable$Entry;

С описанием объекта класса:

B  byte
C  char
D  double
F  float
I  int
J  long
Z  boolean
[  数组,如[I表示int[]
[L+类名 其他对象

Другой сценарий — выгрузить использование памяти процесса с помощью jmap, а затем проанализировать его с помощью jhat. Команда выглядит следующим образом:

whale.server01:/root# jmap -dump:format=b,file=/tmp/dump.dat 17047
Dumping heap to /tmp/dump.dat ...
Heap dump file created

Используйте jhat для просмотра:

jhat -port 9998 /tmp/dump.dat

После выполнения откройте http://ip:9998 в браузере для просмотра результатов


jstat

--- вывод использования памяти jvm

Система мониторинга общего использования ресурсов jstat, использующая синтаксис:

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

Сцена jstat чаще используется для просмотра статистики сборки мусора в реальном времени, обычно команда выглядит следующим образом:

[root@localhost hsperfdata_root]# jstat -gc 19560 5000

То есть статус GC процесса 19560 будет отображаться каждые 5 секунд:

 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
17472.0 17472.0 275.9   0.0   139968.0  2271.9   349568.0   21151.3   55808.0 53992.8 6400.0 6044.1   5554   30.602   4      0.809   31.411
17472.0 17472.0 275.9   0.0   139968.0 58303.5   349568.0   21151.3   55808.0 53992.8 6400.0 6044.1   5554   30.602   4      0.809   31.411
17472.0 17472.0 275.9   0.0   139968.0 102692.6  349568.0   21151.3   55808.0 53992.8 6400.0 6044.1   5554   30.602   4      0.809   31.411
17472.0 17472.0 275.9   0.0   139968.0 103396.5  349568.0   21151.3   55808.0 53992.8 6400.0 6044.1   5554   30.602   4      0.809   31.411
17472.0 17472.0 275.9   0.0   139968.0 136708.8  349568.0   21151.3   55808.0 53992.8 6400.0 6044.1   5554   30.602   4      0.809   31.411
17472.0 17472.0  0.0   273.1  139968.0 31730.4   349568.0   21151.3   55808.0 53992.8 6400.0 6044.1   5555   30.605   4      0.809   31.414
17472.0 17472.0  0.0   273.1  139968.0 64034.4   349568.0   21151.3   55808.0 53992.8 6400.0 6044.1   5555   30.605   4      0.809   31.414

Можно видеть, что при печати GC в шестой раз в приведенном выше примере выполняется YGC, и пространство памяти EU (использование eden) и S0U (использование Survivor0) очищается один раз.

Прикрепите описание каждого столбца:

S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

параметры JVM

Куча памяти JVM

Весь размер кучи = молодое поколение + старое поколение + пермская область памяти кучи JVM используется для объектов и массивов, созданных с помощью new, а стековая память используется для размещения переменных базового типа и ссылок на объекты, когда программа выходит за рамки, ссылки в стеке будет освобождено, а объекты в куче памяти, потерявшие адрес ссылки, станут мусором, а память будет высвобождена и освобождена сборщиком мусора в неизвестное время;

Диаграмма состава памяти кучи:堆内存

  • -Xms начальный размер кучи по умолчанию физической памяти 1/64 (менее 1 ГБ), когда размер свободной кучи меньше 40%, JVM будет увеличивать кучу до максимального предела -Xmx

  • -Xmx максимальный размер кучи Когда свободный размер кучи, равный 1/4 физической памяти по умолчанию (менее 1 ГБ), превышает 70 %, JVM уменьшит размер кучи до минимального предела -Xms.

Мы можем получить динамическую память фиксированного размера, установив одинаковый размер для "-Xms" и "-Xmx". -Xms и -Xmx на самом деле являются сокращением для -XX:InitialHeapSize и -XX:MaxHeapSize. Мы также можем использовать эти два параметра напрямую, они имеют тот же эффект.

  • -Xmn размер молодого поколения

  • -XX:NewSize Установить начальный размер молодого поколения

  • -XX: MaxNewSize молодого поколения максимального значения

  • -Xx: Permsize Настройки для начального значения продолжительности

  • -XX:MaxPermSize установить максимальное постоянное поколение

  • -Xss Размер стека каждого потока После JDK5.0 размер стека каждого потока составляет 1 М. Раньше размер стека каждого потока составлял 256 КБ. Этот параметр оказывает большое влияние и требует корректировки после строгого тестирования.

  • -XX:NewRatio Отношение молодого поколения (включая Эдем и две области Survivor) к старому поколению (исключая постоянное поколение) -XX:NewRatio=4 означает, что отношение молодого поколения к старому составляет 1:4 , а на молодое поколение приходится 1/5 всего стека, при задании Xms=Xmx и Xmn этот параметр задавать не нужно.

  • -XX:SurvivorRatio Соотношение размера области Эдема к области Выживших устанавливается равным 8, тогда соотношение двух областей Выживших к одной области Эдема составляет 2:8, и на одну область Выживших приходится 1/10 всего молодого поколения

  • -XX:+HeapDumpOnOutOfMemoryError и -XX:HeapDumpPath Когда мы не можем установить подходящий размер для -Xmx (максимальной памяти кучи), мы можем столкнуться с риском переполнения памяти (OutOfMemoryError), с которым можно столкнуться при использовании JVM. коренная причина одного из самых ужасных зверей переполнения памяти требует тщательной локализации. Вообще говоря, анализ моментального снимка памяти кучи (Heap Dump) является хорошим средством определения того, не создается ли моментальный снимок памяти при переполнении памяти, особенно для того типа JVM, который потерпел крах или ошибка возникает только после плавной работы для несколько часов или даже несколько дней.Сегодня будет сложно анализировать сбои в производственной системе.

幸运的是,我们可以通过设置 -XX:+HeapDumpOnOutOfMemoryError 让JVM在发生内存溢出时自动的生成堆内存快照。有了这个参数,当我们不得不面对内存溢出异常的时候会节约大量的时间。默认情况下,堆内存快照会保存在JVM的启动目录下名为java_pid.hprof 的文件里(在这里就是JVM进程的进程号)。也可以通过设置-XX:HeapDumpPath=来改变默认的堆内存快照生成路径, Может быть относительным или абсолютным путем.

Цитировать:Настройка памяти параметров утилиты JVM Инструмент мониторинга настройки производительности JVM использование команды jstat

Гиталк загружается...