Эта статья в основном учит записывать часто используемые в работеJDK
принести некоторыеJVM
Инструменты настройки и мониторинга производительности, понимая эти инструменты, могут дать нам большую помощь при устранении неисправностей проблем и принести некоторые скрытые вещи на поверхность для анализа.
jps(Java Virtual Machine Process Status Tool)
jps
В основном используется для выводаJVM
Информация о состоянии процессов, запущенных в . Формат синтаксиса следующий:
jps [options] [hostid]
Если не указаноhostid
Поскольку по умолчанию используется текущий хост или сервер, параметры командной строки описываются следующим образом:
-q Не выводить имя класса, имя Jar и параметры, переданные в основной метод
➜ ~ jps -q
42060
-m выводить аргументы, переданные основному методу (та же информация, что возвращается командой jps по умолчанию)
➜ ~ jps -m
42060 TestSofaBootApplication
-l напечатать полное имя основного класса или jar
➜ ~ jps -l
42060 com.glmapper.bridge.boot.TestSofaBootApplication
-v выходные аргументы, переданные в JVM
➜ ~ jps -v
42060 TestSofaBootApplication -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:51645,suspend=y,server=n -XX:TieredStopAtLevel=1 -Xverify:none -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -javaagent:/Users/xxxx/Library/Caches/JetBrains/IntelliJIdea2020.1/captureAgent/debugger-agent.jar -Dfile.encoding=UTF-8
При устранении неполадок мы проходим пройдемjps
Давайте посмотрим на процессы, запущенные на текущей машине, и используем различные параметры, чтобы быстро найти местоположение нашего целевого процесса.pid
, чтобы облегчить нашу последующую серию операций по устранению неполадок.
jstack(Java Stack Trace)
jstackВ основном используется для просмотраJava
Информация о стеке потоков внутри процесса. еслиjava
Программа аварии генерацииcore
документ,jstack
средства можно использовать для полученияcore
документjava stack
иnative stack
информацию, чтобы вы могли легко узнатьjava
Как происходит сбой программы и где возникает проблема в программе. Кроме того,jstack
Инструменты также могут быть прикреплены к запускуjava
В программе я видел его работающим в то время.java
процедурныйjava stack
иnative stack
информация, если в настоящее время работаетjava
Рендеринг программыhung
статус,jstack
очень полезно.
Нижеjstack
Формат синтаксиса:
jstack [option] pid
jstack [option] executable core
jstack [option] [server-id@]remote-hostname-or-ip
Независимо от того, что это за команда, мы должны сначала научиться проверять ее с помощью -h
➜ ~ jstack -h
Usage:
jstack [-l] <pid>
(连接到正在运行的进程)
jstack -F [-m] [-l] <pid>
(连接到挂起的进程)
jstack [-m] [-l] <executable> <core>
(连接到 core 文件)
jstack [-m] [-l] [server_id@]<remote server IP or hostname>
(连接到远程调试服务器)
Options:
-F to force a thread dump. Use when jstack <pid> does not respond (process is hung)
-m to print both java and native frames (mixed mode)
-l long listing. Prints additional information about locks
-h or -help to print this help message
Options
Описание параметра выглядит следующим образом:
опции | эффект |
---|---|
-F | Когда обычный запрос вывода не отвечает, принудительно стек потока вывода |
-m | Если вызов локального метода, то можно отобразить стек C/C++ |
-l | В дополнение к стеку отображается дополнительная информация о блокировке.В случае взаимоблокировки вы можете использовать jstack -l pid для наблюдения за состоянием удержания блокировки. |
Давайте сосредоточимся на разговоре о том,jstack
Как посмотреть информацию.
введение информации о стеке jstack
Нижеjstack
раздел выводаtacer
данные
"main" #1 prio=5 os_prio=31 tid=0x00007fb93b802000 nid=0x2703 waiting on condition [0x0000700005e5d000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.glmapper.bridge.boot.TestJstack.testWaitingOnConditionCondition(TestJstack.java:19)
at com.glmapper.bridge.boot.TestJstack.main(TestJstack.java:10)
С этими данными мы, вероятно,get
Пункты, которые необходимо посетить, в основном включают следующую информацию:
- имя основного потока
- #1 Порядковый номер стека не имеет фактического значения и может быть проигнорирован
- приоритет приоритета потока
- os_prio приоритет на уровне ОС
- идентификатор потока
- идентификатор нид-треда
Введение в состояние потока
Из информации, выводимой jstack выше, вы можете увидеть информацию, относящуюся к статусу потока, такую как
TIMED_WAITING
java.lang.Thread.State: TIMED_WAITING (sleeping)
RUNNABLE
java.lang.Thread.State: RUNNABLE
еще чуть-чуть"GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007fcee9004000 nid=0x1f07 runnable
Информация, это используется jvm для восстановления памяти, не обращайте на это внимание, вот основной видjava.lang.Thread.State
;
public enum State {
/**
* 当线程对象创建时存在的状态,此时线程不可能执行
*/
NEW,
/**
* 当调用thread.start()后,线程变成为 Runnable 状态。只要得到CPU,就可以执行;
*/
RUNNABLE,
/**
* 如果进入同步方法或同步代码块,没有获取到锁,则会进入该状态;
*/
BLOCKED,
/**
* 执行thread.join()或在锁对象调用obj.wait()等情况就会进该状态,表明线程正处于等待某个资源或条件发生来唤醒自己;
*/
WAITING,
/**
* 执行Thread.sleep(long)、thread.join(long)或obj.wait(long)等就会进该状态,与Waiting的区别在于Timed_Waiting的等待有时间限制;
*/
TIMED_WAITING,
/**
* 终止
*/
TERMINATED;
}
Возвращаясь к приведенной выше информации о стеке, можно заметить, что когда состояние TIMED_WAITING, стек появитсяwaiting on condition xxxx
информация, похожая на:
- В ожидании записи монитора: ждет, чтобы приобрести замок, как правило, соответствует заблокированному
- в Object.wait(): после получения блокировки выполните obj.wait(), чтобы отказаться от блокировки, обычно это соответствует ОЖИДАНИЮ
Вот несколько простых примеров таких состояний.
Пример статуса потока и анализ jstack
waiting on condition
1. Выполнить код
/**
* 产生 waiting on condition
*/
private static void testWaitingOnConditionCondition(){
while (true){
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2. Результаты исполнения
"main" #1 prio=5 os_prio=31 tid=0x00007fb93b802000 nid=0x2703 waiting on condition [0x0000700005e5d000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.glmapper.bridge.boot.TestJstack.testWaitingOnConditionCondition(TestJstack.java:19)
at com.glmapper.bridge.boot.TestJstack.main(TestJstack.java:10)
3. Анализ результатов
Здесь очевидно, что основной поток находится в методе сна. Однако скобки после TIMED_WAITING здесь также специально указываютsleeping
, в некоторых сценариях парковка является обычным явлением, см. примеры ниже.
waiting on condition (parking)
1. Выполнить код
private static void testWaitingOnConditionConditionWithParking(){
// 提供一个阻塞对了
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<String>(1);
// 先加一个
blockingQueue.add("test-parking");
try {
//继续加,这里肯定加不进去,所以会阻塞
blockingQueue.put("test-parking-xxx");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
2. Результаты исполнения
"main" #1 prio=5 os_prio=31 tid=0x00007fd6d5008800 nid=0x2803 waiting on condition [0x000070000ffc1000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x000000076af3a938> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.ArrayBlockingQueue.put(ArrayBlockingQueue.java:353)
at com.glmapper.bridge.boot.TestJstack.testWaitingOnConditionConditionWithParking(TestJstack.java:113)
at com.glmapper.bridge.boot.TestJstack.main(TestJstack.java:13)
3. Анализ результатов
Основной поток входит в состояние ожидания в состоянии, ожидая определенного ресурса, вы можете видеть, что он находится в состоянии ожидания.a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObjec
Подождал, заблокировал.
waiting on monitor entry
1. Выполнить код
/**
* 产生 waiting on monitor entry
*/
private static void testWaitingOnMonitorEntry(){
final Object obj = new Object();
final Thread thread = new Thread(){
@Override
public void run() {
// 锁 obj 对象
synchronized (obj){
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
final Thread thread1 = new Thread(){
@Override
public void run() {
// 锁 obj 对象
synchronized (obj){
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread.setName("test-thread");
thread.start();
thread1.setName("test-thread1");
thread1.start();
}
2. Результаты исполнения
"test-thread1" #14 prio=5 os_prio=31 tid=0x00007f9563880800 nid=0x5c03 waiting for monitor entry [0x000070000b029000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.glmapper.bridge.boot.TestJstack$2.run(TestJstack.java:50)
- waiting to lock <0x000000076af261d0> (a java.lang.Object)
"test-thread" #13 prio=5 os_prio=31 tid=0x00007f956387f800 nid=0x5a03 waiting on condition [0x000070000af26000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.glmapper.bridge.boot.TestJstack$1.run(TestJstack.java:38)
- locked <0x000000076af261d0> (a java.lang.Object)
3. Анализ результатов
Тестовый поток получил блокировку объекта obj, поэтому он выполняет операцию ожидания, и состояние TIMED_WAINTING, в то время как тестовый поток1 находится в состоянии BLOCKED, поскольку он не получил блокировку объекта obj.
test-thread1 "ожидает блокировки ", пытаясь заблокировать объект по адресу 0x000000076af261d0, который удерживается потоком test-thread [заблокирован ]. Поток тестового потока «ожидает условия», что указывает на то, что он ожидает срабатывания условия.Согласно jstack, этот поток находится в спящем режиме.
object.wait()
1. Выполнить код
private static void testObjectWait() {
final Thread thread = new Thread() {
@Override
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName());
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread.start();
thread.setName("test-object-wait");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (thread) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.notify();
}
}
2. Результаты исполнения
"test-object-wait" #13 prio=5 os_prio=31 tid=0x00007fd43a809000 nid=0xa803 in Object.wait() [0x0000700010926000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076af26140> (a com.glmapper.bridge.boot.TestJstack$3)
at java.lang.Object.wait(Object.java:502)
at com.glmapper.bridge.boot.TestJstack$3.run(TestJstack.java:73)
- locked <0x000000076af26140> (a com.glmapper.bridge.boot.TestJstack$3)
"main" #1 prio=5 os_prio=31 tid=0x00007fd43b001800 nid=0x2603 waiting on condition [0x000070000f2e4000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.glmapper.bridge.boot.TestJstack.testObjectWait(TestJstack.java:93)
- locked <0x000000076af26140> (a com.glmapper.bridge.boot.TestJstack$3)
at com.glmapper.bridge.boot.TestJstack.main(TestJstack.java:10)
3. Анализ результатов
Поскольку блокировка снимается при вызове метода object.wait(), поэтомуtest-object-wait
Этот поток появляется в состоянии Object.wait(), а состояние потока — ожидание, ожидание пробуждения уведомления. Так как поток mian получаетtest-object-wait
После блокировки потока вызывается метод Thread.sleep, поэтому в это время он входит в состояние ожидания для ожидания определенного ресурса и переходит в состояние time_waiting.
резюме
В общем, когда мы занимаемся устранением неполадок, если система очень медленная, нам нужно обратить особое вниманиеBlocked
,Waiting on condition
эти состояния. Если загрузка ЦП системы относительно высока, вы можете проверить ее с помощью таких идей, как бесконечные циклы.В это время вы должны обратить внимание на следующееRunable
состояние; если в стеке естьDeadlock
, то есть возникает взаимоблокировка.
jstat (инструмент мониторинга статистики JVM)
jstat
Это инструмент статистического мониторинга JVM, и его синтаксис выглядит следующим образом:
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
vmid
даJava
виртуальная машинаID
,существуетLinux/Unix
Система, как правило, является процессомID
.interval
интервал времени выборки;count
это количество образцов. Например, следующий выводGC
Информация, интервал выборки 1000 мс, количество выборок 3:
➜ ~ jstat -gc 58950 1000 3
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
10752.0 10752.0 0.0 0.0 65536.0 6554.0 175104.0 0.0 4480.0 785.7 384.0 75.9 0 0.000 0 0.000 0.000
10752.0 10752.0 0.0 0.0 65536.0 6554.0 175104.0 0.0 4480.0 785.7 384.0 75.9 0 0.000 0 0.000 0.000
10752.0 10752.0 0.0 0.0 65536.0 6554.0 175104.0 0.0 4480.0 785.7 384.0 75.9 0 0.000 0 0.000 0.000
Определение столбца выходной информации:
- S0C, S1C, S0U, S1U: вместимость области Survivor 0/1 (емкость) и использование (использовано)
- EC, EU: Емкость и использование зоны Eden
- OC, OU: старая генерирующая мощность и использование
- ПК, ПУ: постоянная генерирующая мощность и использование
- YGC, YGT: время GC для молодого поколения и время GC
- FGC, FGCT: время полного GC и время полного GC
- GCT: общее время GC
jmap(Memory Map)
jmap
Используется для просмотра использования памяти кучи, обычно в сочетании сjhat
использовать. Синтаксис его использования следующий:
jmap [option] <pid>
jmap [option] <executable <core>
jmap [option] [server_id@]<remote server IP or hostname>
Options
Описание параметра выглядит следующим образом:
опции | эффект |
---|---|
печатать сSolaris pmap та же информация |
|
-heap | Распечататьjava сводка кучи |
-histo[:live] | Вывести гистограмму кучи java-объектов, если указана подопция «живые», учитываются только живые объекты |
-clstats | распечатать статистику загрузчика классов |
-finalizerinfo | Распечатать информацию об объекте, ожидающем завершения |
--dump: : | дамп кучи java в двоичном формате hprof |
-F | Принудительно используйте -dump: или -histo |
-J | Переход непосредственно в систему выполнения |
dump-options также включает следующие параметры:
- live : выгружать только живые объекты; если не указано, будут выгружены все объекты в куче.
- format=b : двоичный формат
- file= : дамп в указанный файл
jmap -heap
указавpid
, вы можете преобразовать текущий процессheap
Информационная печатьconsole
в том числе с использованиемGC
Алгоритм, параметры конфигурации кучи и использование памяти кучи в каждом поколении следующие:
$ jmap -heap 3493
Attaching to process ID 3493, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.172-b245
using parallel threads in the new generation.(eden 区使用的是并发线程)
using thread-local object allocation.(使用线程本地对象分配)
Concurrent Mark-Sweep GC (使用 CMS 垃圾收集器)
# 堆配置信息
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 2147483648 (2048.0MB)
NewSize = 805306368 (768.0MB)
MaxNewSize = 805306368 (768.0MB)
OldSize = 1342177280 (1280.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
# 堆使用情况
Heap Usage:
New Generation (Eden + 1 Survivor Space):
capacity = 724828160 (691.25MB)
used = 35156456 (33.527809143066406MB)
free = 689671704 (657.7221908569336MB)
4.850315970063856% used
Eden Space:
capacity = 644349952 (614.5MB)
used = 19878008 (18.95714569091797MB)
free = 624471944 (595.542854309082MB)
3.084970820328392% used
From Space:
capacity = 80478208 (76.75MB)
used = 15278448 (14.570663452148438MB)
free = 65199760 (62.17933654785156MB)
18.984577787815553% used
To Space:
capacity = 80478208 (76.75MB)
used = 0 (0.0MB)
free = 80478208 (76.75MB)
0.0% used
concurrent mark-sweep generation:
capacity = 1342177280 (1280.0MB)
used = 166885296 (159.1542205810547MB)
free = 1175291984 (1120.8457794189453MB)
12.433923482894897% used
55843 interned Strings occupying 6689024 bytes.
jmap -clstats
Указав pid, статистика загрузчика классов текущего процесса может быть напечатана на консоли, включая имя загрузчика классов, жив ли объект, адрес объекта, родительский загрузчик классов, размер загруженного класса и т. д., как показано ниже:
$ jmap -clstats 3493
Attaching to process ID 3493, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.172-b245
finding class loader instances ..done.
computing per loader stat ..done.
please wait.. computing liveness.......................liveness analysis may be inaccurate ...
class_loader classes bytes parent_loader alive? type
<bootstrap> 3211 5818395 null live <internal>
0x00000000b150ed50 1 1491 0x00000000b0020830 dead sun/reflect/DelegatingClassLoader@0x000000010000a040
0x00000000b8715670 1 900 0x00000000b0020830 dead sun/reflect/DelegatingClassLoader@0x000000010000a040
0x00000000cb417140 1 1503 0x00000000b0020830 dead sun/reflect/DelegatingClassLoader@0x000000010000a040
0x00000000b98b4388 1 1491 null dead sun/reflect/DelegatingClassLoader@0x000000010000a040
0x00000000b5a419a0 1 900 0x00000000b0020830 dead sun/reflect/DelegatingClassLoader@0x000000010000a040
0x00000000b358df50 1 1493 0x00000000b0020830 dead sun/reflect/DelegatingClassLoader@0x000000010000a040
0x00000000b7b277b8 1 1503 0x00000000b0020830 dead sun/reflect/DelegatingClassLoader@0x000000010000a040
0x00000000c2527c58 1 1505 0x00000000b0020830 dead sun/reflect/DelegatingClassLoader@0x000000010000a040
0x00000000b98b4580 1 1491 0x00000000b0026260 dead sun/reflect/DelegatingClassLoader@0x000000010000a040
0x00000000b9b307b8 1 1493 0x00000000b0020830 dead sun/reflect/DelegatingClassLoader@0x000000010000a040
0x00000000e236b038 1 900 0x00000000b0020830 dead sun/reflect/DelegatingClassLoader@0x000000010000a040
0x00000000b0108400 1 1493 0x00000000b0020830 dead sun/reflect/DelegatingClassLoader@0x000000010000a040
0x00000000b010bc00 3 7946 0x00000000b0022f60 live org/jacoco/compass/agent/rt/internal/fastjson/util/ASMClassLoader@0x00000001000eb830
0x00000000b358e148 1 1493 0x00000000b0020830 dead sun/reflect/DelegatingClassLoader@0x000000010000a040
jmap -histo
Используйте jmap -histo pid для просмотра количества объектов в куче памяти, гистограммы статистики размера, как показано ниже:
# jmap -histo:live 1493 带上 live 则只统计存活对象
$ jmap -histo 1493
num #instances #bytes class name
----------------------------------------------
1: 1314509 144436976 [C
2: 1572864 37748736 org.apache.logging.log4j.core.async.AsyncLoggerConfigDisruptor$Log4jEventWrapper
3: 77458 32776608 [B
4: 1061561 25477464 java.lang.String
5: 731623 23411936 java.util.HashMap$Node
6: 32930 22826616 [I
7: 150340 15546784 [Ljava.util.HashMap$Node;
8: 144895 14968208 [Ljava.lang.Object;
9: 377379 12076128 java.util.concurrent.ConcurrentHashMap$Node
10: 230943 11085264 java.util.HashMap
11: 81124 3893952 java.nio.HeapByteBuffer
12: 3396 3869944 [Ljava.util.concurrent.ConcurrentHashMap$Node;
13: 78418 3764064 java.nio.HeapCharBuffer
14: 75784 3031360 java.util.TreeMap$Entry
15: 72865 2914600 java.util.LinkedHashMap$Entry
16: 166213 2659408 java.util.HashSet
17: 18355 2643120 com.mysql.jdbc.Field
18: 18394 2044336 java.lang.Class
19: 19966 1757008 java.lang.reflect.Method
PS: [C [B на приведенном выше рисунке относится к типу объекта класса, а следующее является ссылкой на общие типы
- B byte
- C char
- D double
- F float
- I int
- J long
- Z boolean
- [Массив, например [я для INT []
- [L+имя класса Другие объекты, такие как [Ljava.lang.Object
jmap -dump
В большинстве случаев мы не будем выводить анализ прямо в консоль.Более традиционный подход состоит в том, чтобы сделать дамп в указанный файл, а затем использовать некоторые визуальные инструменты для помощи в анализе, а затем выполнить дамп в файл, следующие команды обычно используются:
jmap -dump:format=b,file=dumpFileName pid # 语法
$ jmap -dump:format=b,file=test-dump.bin 85716 # 举例
Dumping heap to /Users/guolei.sgl/test-dump.bin ...
Heap dump file created
Для анализа файлов дампа вы можете использовать графические инструменты, такие как jprofile, следующим образом.
Вы также можете просмотреть его через jhat, метод работы следующий:
1. Запустите http-сервис
jhat -port 9300 test-dump.bin
Reading from test-dump.bin...
Dump file created Wed Oct 28 17:54:24 CST 2020
Snapshot read, resolving...
Resolving 1151952 objects...
Chasing references, expect 230 dots......................................................................................................................................................................................................................................
Eliminating duplicate references......................................................................................................................................................................................................................................
Snapshot resolved.
Started HTTP server on port 9300
Server is ready.
2. Сводная информация о классе дампа
Посетите localhost: 9300 для просмотра сводной информации свалки
3, детали класса
Нажмите на класс, чтобы просмотреть подробности
резюме
В этой статье представлены некоторые инструменты мониторинга настройки производительности, которые поставляются с JDK. Освоив эти инструменты, мы можем быстро найти и решить некоторые проблемы в фактической разработке или эксплуатации и обслуживании. Наиболее распространенными из них являются OOM, утечки памяти, взаимоблокировки потоков, высокая загрузка ЦП, д.; в сообществе также есть много полезных инструментов, таких какArthas,perfmaЖдать.