java服务宕机的问题排查

java服务宕机的问题排查 - 知乎

java服务是否可用

telnet ip port
ps -ef | grep java

Linux系统杀掉进程

Linux系统在内存不足时,会主动去杀掉一些进程,OOM-Killer机制,默认配置下,日志文件保存在/var/log目录下

cd /var/log
cat messages* | grep java

有一种内核作业(Kernel Job)名为 Out of Memory Killer,它会在可用内存极低的情况下“杀死”(kill)某些进程。OOM Killer 会对所有进程进行打分,
然后将评分较低的进程“杀死”,具体的评分规则可以参考 Surviving the Linux OOM Killer。
不同于其他的 OOM 错误, Killprocessorsacrifice child 错误不是由 JVM 层面触发的,而是由操作系统层面触发的。

JVM自身奔溃

JVM自身故障导致进程没有时,会有一个hs_err_pid_xxx.log的文件生成,该文件的目录,默认是在工作目录下(启动的jar包所在目录),同样也可以通过Java启动参数来设置

-XX:ErrorFile=/var/log/hs_err_pid.log

1、mmap: 将一个文件或者其它对象映射进内存
mmap操作提供了一种机制,让用户程序直接访问设备内存,这种机制,相比较在用户空间和内核空间互相拷贝数据,效率更高。
在要求高性能的应用中比较常用。mmap映射内存必须是页面大小的整数倍(否则先内存对齐),面向流的设备不能进行mmap
2、swap place
SWAP(交换)分区是一种通过在硬盘中预先划分一定的空间,然后将把内存中暂时不常用的数据临时存放到硬盘中,
以便腾出物理内存空间让更活跃的程序服务来使用的技术,其设计目的是为了解决真实物理内存不足的问题。
但由于交换分区毕竟是通过硬盘设备读写数据的,速度肯定要比物理内存慢,所以只有当真实的物理内存耗尽后才会调用交换分区的资源

free

参数解析

free -h
  free [-bkmotV][-s <间隔秒数>]
  -b  以Byte为单位显示内存使用情况。 
  -k  以KB为单位显示内存使用情况。 
  -m  以MB为单位显示内存使用情况。
  -g   以GB为单位显示内存使用情况。
  -h   根据内存大小自动选择合适的单位显示
  -o  不显示缓冲区调节列。 
  -s  持续观察内存使用状况。
  -c   和-s配合使用
  -t  显示内存总和列。 
  -V  显示版本信息

响应值解析

Mem :表示物理内存的缓存统计
Swap:表示硬盘上交换分区的使用情况

total:表示 总计物理内存的大小。
used:表示 已使用多少。
free:表示 可用内存多少。
Shared:表示多个进程共享的内存总额。
Buffers/cached:表示 磁盘缓存的大小
available: 在不计算交换空间的情况下,预计可以被新启动的应用程序所使用的内存空间。与 cache 或者 free 部分不同,
            这一列把页面缓存计算在内,并且不是所有的可回收的 slab 内存都可以真正被回收,因为可能有被占用的部分。
           (等同于 /proc/meminfo 中的 MemAvailable;自内核 3.14 版本可用,自内核 2.6.27 版本开始模拟;
            在其他版本上这个值与 free 这一列相同)

Buffer和Cache解析

Cache:为了调高CPU和内存之间数据交换而设计,Buffer(缓冲)为了提高内存和硬盘(或其他I/O设备的数据交换而设计)
Buffer:主要是针对写操作设计的,更细的说是针对内存和硬盘之间的写操作来设计的,目的是将写的操作集中起来进行,
       减少磁盘碎片和硬盘反复寻址过程,提高性能

top

参数解析

top -c
top [-] [d delay] [q] [c] [S] [s] [i] [n] [b]
d : 改变显示的更新速度,或是在交谈式指令列( interactive command)按 s
q : 没有任何延迟的显示速度,如果使用者是有 superuser 的权限,则 top 将会以最高的优先序执行
c : 切换显示模式,共有两种模式,一是只显示执行档的名称,另一种是显示完整的路径与名称
S : 累积模式,会将己完成或消失的子行程 ( dead child process ) 的 CPU time 累积起来
s : 安全模式,将交谈式指令取消, 避免潜在的危机
i : 不显示任何闲置 (idle) 或无用 (zombie) 的行程
n : 更新的次数,完成后将会退出 top
b : 批次档模式,搭配 "n" 参数一起使用,可以用来将 top 的结果输出到档案内
p : 指定进程

响应值解析

 PID:进程的ID
USER:进程所有者
PR:进程的优先级别,越小越优先被执行
NInice:值
VIRT:进程占用的虚拟内存
RES:进程占用的物理内存
SHR:进程使用的共享内存
S:进程的状态。S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值为负数
%CPU:进程占用CPU的使用率
%MEM:进程使用的物理内存和总内存的百分比
TIME+:该进程启动后占用的总的CPU时间,即占用CPU使用时间的累加值。
COMMAND:进程启动命令名称

jinfo 查看 Java 进程运行的 JVM 参数

jinfo [option] <pid>
  -flag [name]	输出对应名称的参数
  -flag [+ -] [name]	开启或者关闭对应名称的参数
  -flag [name]=[value]	修改指定参数的值
  -flags	查看jvm的非默认的参数值
  -sysprops	输出当前 jvm 进行的全部的系统属性

jstat

参数解析

jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
[options] : 操作参数,一般使用 -gcutil 查看gc情况 
  -class 类加载的行为统计
  -compiler JIT编译器行为统计
  -gc 垃圾回收的行为统计
  -gccapacity 各个垃圾回收代容量和他们相应的空间统计
  -gccause 垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因
  -gcmetacapacity 统计元空间使用情况
  -gcnew 显示新生代统计信息
  -gcnewcapacity 统计新生代及内存使用情况
  -gcold 统计老年代和元空间使用情况
  -gcoldcapacity 统计老年代内存使用情况
  -gcutil 显示各个各代内存使用百分比
  -printcompilation 虚拟机方法编译统计情况
[-h<lines>]:每隔多少行打印头部 -h3
VMID : 本地虚拟机进程ID,即当前运行的java进程号
[interval] : 连续输出的时间间隔,单位为秒或者毫秒 
[count] : 连续输出的次数,如果缺省打印无数次 

-gc响应值解析

jstat -gc 8 1000 10
S0C : 第一个幸存区的总容量(KB) 
S1C : 第二个幸存区的总容量(KB) 
S0U : 第一个幸存区已使用的容量(KB) 
S1U : 第二个幸存区已使用的容量(KB) 
EC : 年轻代中Eden(伊甸园)的总容量(KB) 
EU : 年轻代中Eden(伊甸园)已使用容量(KB) 
OC : 老年区的总容量(KB) 
MC : 元空间的总容量(KB) 
MU : 元空间已使用容量(KB)
CCSC : 压缩类空间总容量(KB) 
CCSU : 压缩类空间已使用总容量(KB) 
YGC : 新生代GC次数 
YGCT :新生代GC总耗费时间
FGC : 老年代GC次数 
FGCT : 老年代GC总耗费时间 
GCT : GC总耗费时间 

-gcutil响应值解析

jstat -gcutil 8 1000 10
S0: 新生代中Survivor space 0区已使用空间的百分比
S1: 新生代中Survivor space 1区已使用空间的百分比
E: 新生代已使用空间的百分比
O: 老年代已使用空间的百分比
M: 元空间
CCS: 压缩类空间利用率为百分比
YGC: 从应用程序启动到当前,发生Yang GC 的次数
YGCT: 从应用程序启动到当前,Yang GC所用的时间【单位秒】
FGC: 从应用程序启动到当前,发生Full GC的次数
FGCT: 从应用程序启动到当前,Full GC所用的时间
GCT: 从应用程序启动到当前,用于垃圾回收的总时间【单位秒】jstat -gcutil 命令使用GCT: 从应用程序启动到当前,用于垃圾回收的总时间【单位秒】

jstack

jstack命令用于生成虚拟机当前时刻的线程快照。
线程快照是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因, 
如线程间死锁、死循环、请求外部资源导致的长时间等待等问题

1、Java语言定义了6种线程池状态:
New:创建后尚未启动的线程处于这种状态,不会出现在Dump中。
RUNNABLE:包括Running和Ready。线程开启start()方法,会进入该状态,在虚拟机内执行的。
Waiting:无限的等待另一个线程的特定操作。
Timed Waiting:有时限的等待另一个线程的特定操作。
阻塞(Blocked):在程序等待进入同步区域的时候,线程将进入这种状态,在等待监视器锁。
结束(Terminated):已终止线程的线程状态,线程已经结束执行。
2、Dump文件的线程状态一般其实就以下3种:
RUNNABLE,线程处于执行中
BLOCKED,线程被阻塞
WAITING,线程正在等待
deadlock,死锁

jstack -l 8 [ > jstack.txt]
-F当正常输出的请求不被响应时,强制输出线程堆栈
-m如果调用到本地方法的话,可以显示C/C++的堆栈
-l除堆栈外,显示关于锁的附加信息,在发生死锁时可以用jstack -l pid来观察锁持有情况

jvm内存模型

jvm内存模型

程序计数器:当前线程所执行的字节码的行号指示器,用于记录正在执行的虚拟机字节指令地址,线程私有。
Java虚拟栈:局部变量表(八大原始类型、对象引用、返回地址)、操作数栈、动态链接、方法出口信息、当前栈帧、栈帧0、栈帧1...
Native方法栈:和虚拟栈相似,只不过它服务于Native方法,线程私有。
Java堆:java内存最大的一块,所有对象实例、数组都存放在java堆,GC回收的地方,线程共享。
方法区:存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码数据等。(即永久带),
        回收目标主要是常量池的回收和类型的卸载,各线程共享

Hotspot中方法区的变化

元空间的本质和永久代类似,都是对JVM规范中方法区的实现,最大的区别在于:元数据空间并不在虚拟机中,而是使用本地内存。

堆区比例

查看默认比例

java -XX:+PrintFlagsFinal -version | grep -E 'NewRatio|InitialSurvivorRatio'

1、新生代与老年代比例
默认 -XX:NewRatio=2
表示老年代时新生代的2倍空间,新生代、老年代默认空间1/3、2/3
2、Eden和survior的比例
默认 -XX:+UseAdaptiveSizePolicy=8
标识eden占新生代的8成,剩下的2成平均分为两个幸存区

查看堆区空间配置

java -XX:+PrintFlagsFinal -version | grep -E 'InitialHeapSize|MaxHeapSize'

手动配置
-Xms3550m: 设置初始堆大小为3550m。
-Xmx3550m: 设置初始堆最大为3550m。

猜你喜欢

转载自blog.csdn.net/gao_yuwushengchu/article/details/126098335
今日推荐