当前位置:   article > 正文

jvm5--线上问题排查_tomcat 内存溢出 自动打dump

tomcat 内存溢出 自动打dump

问题

1、OOM

- java.lang.StackOverflowError

栈空间溢出 ,递归调用卡死

- java.lang.OutOfMemoryError:Java heap space

内存溢出 , 对象过大

- java.lang.OutOfMemoryError:GC overhead limit exceeded

GC回收时间过长

过长的定义是超过98%的时间用来做GC并且回收了而不倒2%的堆内存

连续多次GC,都回收了不到2%的极端情况下才会抛出

如果不抛出,那就是GC清理的一点内存很快会被再次填满,迫使GC再次执行,这样就恶性循环,

cpu使用率一直是100%,二GC却没有任何成果

int i = 0;
List<String> list = new ArrayList<>();
try{
    while(true){
        list.add(String.valueOf(++i).intern());
    }
}catch(Throwable e){
    System.out.println("********");
    e.printStackTrace();
    throw e;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

- java.lang.OutOfMemoryError:Direct buffer memory

执行内存挂了

写NIO程序经常使用ByteBuffer来读取或写入数据,这是一种基于通道(Channel)与缓存区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作,这样能在一些场景中显著提高性能,因为避免了在java堆和native堆中来回复制数据

ByteBuffer.allocate(capability) 第一种方式是分配JVM堆内存,属于GC管辖,由于需要拷贝所以速度较慢

ByteBuffer.alloctedDirect(capability)分配os本地内存,不属于GC管辖,不需要拷贝,速度较快

但如果不断分配本地内存,堆内存很少使用,那么jvm就不需要执行GC,DirectByteBuffer对象们就不会被回收,这时候堆内存充足,但本地内存可能已经使用光了,再次尝试分配本地内存救护i出现oom,程序崩溃

- java.lang.OutOfMemoryError:unable to create new native thread

  • 应用创建了太多线程,一个应用进程创建了多个线程,超过系统承载极限
  • 你的服务器并不允许你的应用程序创建这么多线程,linux系统默认允许单个进程可以创建的线程数是1024,超过这个数量,就会报错

解决办法

1)降低应用程序创建线程的数量,分析应用给是否针对需要这么多线程,如果不是,减到最低
2)修改linux服务器配置

- java.lang.OutOfMemoryError:Metaspace

元空间主要存放了虚拟机加载的类的信息、常量池、静态变量、即时编译后的代码

2、CPU或内存飙升

  • 内存溢出造成频繁fullgc
  • 某个线程执行阻塞(资源未释放、sql慢查询、死锁等)

一、内存溢出dump文件(jstat、jmap)

1、步骤

0)根据ps|top命令查看进程pid
1 )jstat -gcutil [进程id] 1000 JVM统计监测工具
2) jmap -histo [进程id] > jmap.txt 看堆内存中的对象数目如果带上live则只统计活对象
jmap -dump:format=b,file=aa.bin [进程id] dump到文件中,再用jhat分析查看
或者 MAT、JVisualVM、jprofiler 工具

2、tomcat内存溢出自动生成dump文件

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=D:\oom.hprof

二、cpu爆满分析堆栈(jstack)

1、top找到cpu高的进程
2、 找出该进程内最耗费CPU的线程 top -Hp pid  
或者 - ps -mp 进程编号 -o Thread,tid,time定位到具体线程

 -m :显示所有的线程
 -p pid 进程使用cpu的时间
 -o:该参数后是用户自定义格式
  • 1
  • 2
  • 3

3)将该线程转为16进制
TIME列就是各个Java线程耗费的CPU时间,CPU时间最长的是线程ID为21742的线程,用

`printf` `"%x\n"` `21742`
  • 1

4) jstack 21711 | grep 54ee(16进制pid)

`root@ubuntu:/``# jstack 21711 | grep 54ee``"PollIntervalRetrySchedulerThread"` `prio=10 tid=0x00007f950043e000 nid=0x54ee ``in` `Object.wait() [0x00007f94c6eda000]`
  • 1

可以看到CPU消耗在PollIntervalRetrySchedulerThread这个类的Object.wait(),找到业务代码进行排查

5)注意:
jstack [进程ID] > jstack_01(内容太多)
jstack主要用来查看某个Java进程内的线程堆栈信息。
可以看到状态不对的线程,以及是否有死锁

三、可视化工具

1、JProfiler

JProfiler 是由 ej-technologies 公司开发的一款 Java 应用性能诊断工具。它聚焦于四个重要主题上。

方法调用 - 对方法调用的分析可以帮助您了解应用程序正在做什么,并找到提高其性能的方法。
内存分配 - 通过分析堆上对象、引用链和垃圾收集能帮您修复内存泄漏问题,优化内存使用。
线程和锁 - JProfiler 提供多种针对线程和锁的分析视图助您发现多线程问题。
高级子系统 - 许多性能问题都发生在更高的语义级别上。例如,对于JDBC调用,您可能希望找出执行最慢的 SQL 语句。JProfiler 支持对这些子系统进行集成分析。

2、JVisualvm

2.1 本地监控或者分析dump
JVisualvm 是 JDK 内置的可视化性能诊断工具,它通过 JMX、jstatd、Attach API 等方式获取目标 JVM 的分析数据,包括 CPU 使用率、内存使用量、线程堆栈信息等。
直观地展示 Java 堆中各对象的数量和大小;
各 Java 方法的调用次数和执行时间。
分析dump文件,比较两个dump文件内存对象差异
https://mp.weixin.qq.com/s/Q1NJ5bQmu8c6y0g9XXWwrwJProfiler

2.2监控远程JVM
1)概述:该JVM进程的主类,参数和详细的jvm参数等

2)监视:包含CPU,堆(内存),类的加载和启动的线程等信息
在这里插入图片描述

3)线程:线程相关的信息
在这里插入图片描述

4)抽样:可对CPU、内存进行抽样
在这里插入图片描述

5)Visual GC
在这里插入图片描述

四、 生产环境服务器变慢诊断思路

1. 整机:top 系统性能

2. CPU:vmstat

  • 查看CPU

    vmstat -n 2 3 第一个参数是采样的时间间隔数单位s,第二个参数是采样的次数

    - procs

    r:运行和等待CPU时间片的进程数,原则上1核CPu的运行队列不要超过2,真个系统的运行队列不能超过总核数的2倍,否则表示系统压力过大

    b:等待资源的进程数,比如正在等待磁盘I/O,网络I/O等

    - cpu

    us:用户进程消耗cpu时间百分比,us高,用户进程消耗cpu时间多,如果长期大于50%,优化程序

    sy:内核进程消耗的cpu时间百分比

    us+sy:参考值为80%,如果大于80,说明可能存在cpu不足

    id:处于空闲的cpu百分比

    wa:系统等待IO的cpu时间百分比

    st:来自于一个虚拟机偷取的cpu时间的百分比

  • 查看额外

    • 查看所有cpu核信息 mpstat -P ALL 2
    • 每个进程使用cpu的用量分解信息 pidstat -u 1 -p 进程编号

3. 内存:free

   查看内存   free -m   free -g

   pidstat -p 进程编号 -r 采样间隔秒数
  • 1
  • 2
  • 3

4. 硬盘:df

   查看磁盘剩余空间  df -h
  • 1

5. 磁盘IO:iostat

 iostat -hdk 2 3

 - rkB/s每秒读取数据kb;
 - wkB/s每秒读写数据量kb
 - svctm I/O请求的平均服务时间,单位毫秒;
 - await I/O请求的平均等待时间,单位毫秒;值越小,性能越好;
 - ==util== 一秒中又百分几的时间用于I/O操作,接近100%时,表示磁盘带宽跑满,需要优化程序或加磁盘
 - rkB/s,wkB/s根据系统该应用不同回有不同的值,担忧规律遵循:长期、超大数据读写,肯定不正常,需要优化程序读取。
 - svctm的值与await的值很接近,表示几乎没有I/O等待,磁盘性能好,如果await的值远高于svctm的值,则表示I/O队列等待太长,需要优化程序或更换更快磁盘
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

6. 网络IO:ifstat

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/255124
推荐阅读
  

闽ICP备14008679号