jps [pid] 查看java进程
jstat -gc -t -h30 9895 1s 300
-t:显示系统运行的时间
-h30:间隔30行数据,输出一次表头
9895:Java进程ID
1s:时间间隔
300:本次输出的数据行数```
## 堆内信息统计-jmap
jmap工具实际使用方式:jmap -heap [pid]或jmap -dump:live,format=b,file=Dump.phrof [pid]等。
堆快照导出命令解析:
live:导出堆中存活对象快照;format:指定输出格式;file:指定输出的文件名及其格式(.dat、.phrof等格式)。```
jstack工具主要用于捕捉JVM当前时刻的线程快照,线程快照是JVM中每条线程正在执行的方法堆栈集合。在线上情况时,生成线程快照文件可以用于定位线程出现长时间停顿的原因,如线程死锁、死循环、请求外部资源无响应等等原因导致的线程停顿。
当线程出现停顿时,可以通过jstack工具生成线程快照,从快照信息中能查看到Java程序内部每条线程的调用堆栈情况,从调用堆栈信息中就可以清晰明了的看出:发生停顿的线程目前在干什么,在等待什么资源等。
jstack -l [pid]
OOM异常大致分为两种,一种是内存溢出,而另一种是内存泄漏
内存溢出的出现的场景
1. 短时间内并发量突然增大
2. 一次读取过大的对象到内存中,比如报表、excel等大型文件
3. 一次性从外部将体积过于庞大的数据载入内存,如DB读表、读本地报表文件等。
4. 程序中使用容器(Map/List/Set等)后未及时清理,内存紧张而GC无法回收。
5. 程序逻辑中存在死循环或大量循环,或单个循环中产生大量重复的对象实例。
6. 程序中引入的第三方依赖中存在BUG问题,因此导致内存出现故障问题。
7. 程序中存在内存溢出问题,一直在蚕食可用内存,GC无法回收导致内存溢出。
8. 第三方依赖加载大量类库,元空间无法载入所有类元数据,因而诱发OOM。
问题排查
获取dump文件至本地,用mat来分析,定位问题位置
出现场景
排查手段同上
排查手段 jps+jstack
D:\> jps
19552 Jps
2892 DeadLock
jstack -l 2892
可以从dump日志中明显看出,jstack工具从该进程中检测到了一个死锁问题,是由线程名为T1、T2的线程引起的,而死锁问题的诱发原因可能是DeadLock.java:41、DeadLock.java:25行代码引起的。而到这一步之后其实就已经确定了死锁发生的位置,我们就可以跟进代码继续去排查程序中的问题,优化代码之后就可以确保死锁不再发生。
[root@localhost ~]# top
top - 14:09:20 up 2 days, 16 min, 3 users, load average: 0.45, 0.15, 0.11
Tasks: 98 total, 1 running, 97 sleeping, 0 stopped, 0 zombie
%Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 997956 total, 286560 free, 126120 used, 585276 buff/cache
KiB Swap: 2097148 total, 2096372 free, 776 used. 626532 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
77915 root 20 0 2249432 25708 11592 S 99.9 2.6 0:28.32 java
636 root 20 0 298936 6188 4836 S 0.3 0.6 3:39.52 vmtoolsd
1 root 20 0 46032 5956 3492 S 0.0 0.6 0:04.27 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.07 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:04.21 ksoftirqd/0
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
7 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh
9 root 20 0 0 0 0 S 0.0 0.0 0:11.97 rcu_sched
.......
[root@localhost ~]# top -Hp 77915
.....省略系统资源相关的信息......
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
77935 root 20 0 2249432 26496 11560 R 99.9 2.7 3:43.95 java
77915 root 20 0 2249432 26496 11560 S 0.0 2.7 0:00.00 java
77916 root 20 0 2249432 26496 11560 S 0.0 2.7 0:00.08 java
77917 root 20 0 2249432 26496 11560 S 0.0 2.7 0:00.00 java
77918 root 20 0 2249432 26496 11560 S 0.0 2.7 0:00.00 java
77919 root 20 0 2249432 26496 11560 S 0.0 2.7 0:00.00 java
77920 root 20 0 2249432 26496 11560 S 0.0 2.7 0:00.00 java
77921 root 20 0 2249432 26496 11560 S 0.0 2.7 0:00.01 java
.......
[root@localhost ~]# jstack 77915 > java_log/thread_stack.log
[root@localhost ~]# vi java_log/thread_stack.log
-------------然后再按/,输入线程ID:1306f-------------
"ActiveThread-Hot" #18 prio=5 os_prio=0 tid=0x00007f7444107800
nid=0x1306f runnable [0x00007f7432ade000]
java.lang.Thread.State: RUNNABLE
at CpuOverload.lambda$main$1(CpuOverload.java:18)
at CpuOverload$$Lambda$2/531885035.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
当项目执行后,多次手动执行Full GC,查看每次Full GC中老年代剩余对象大小,将堆大小设置为其的3-4倍
JIT会对我们当前方法的局部变量进行分析,若它作用域不超过该方法,则对其进行栈上分配的优化,这样它就不会加载到堆中,有利于减少gc次数
注意:栈上分配并不是在栈上分配对象,而是对该对象的属性进行标量替换