Jvm理论与实战-定位线上OOM、CPU100%、死锁等问题

绝地灬酷狼 2023-07-05 13:12 163阅读 0赞
  1. 前沿
    本文为jvm专栏文章,本专栏从jvm的内存模型、gc算法和收集器(包含gc日志分析)、jvm线上问题OOM和CPU100%定位和解决、性能调优和指令实战,本文是线上OOM和CPU100%问题定位和解决。
  2. 线上问题示例-死锁代码(不常见)
    模拟死锁的代码

    @PostMapping(“/deadLock”)

    1. public JsonResult deadLock() {
    2. Object a = new Object();
    3. Object b = new Object();
    4. new Thread(() -> {
    5. synchronized (a) {
    6. System.out.println(Thread.currentThread().getName() + "锁第一个对象");
    7. synchronized (b) {
    8. System.out.println(Thread.currentThread().getName() + "第二把锁");
    9. }
    10. }
    11. }).start();
    12. new Thread(() -> {
    13. synchronized (b) {
    14. System.out.println(Thread.currentThread().getName() + "第一把锁");
    15. synchronized (a) {
    16. System.out.println(Thread.currentThread().getName() + "第二把锁");
    17. }
    18. }
    19. }).start();
    20. return JsonResult.success("请求成功");
    21. }

使用jvisualvm后台管理工具查看示例图 ,检查到死锁 ,如图死锁线程图
打印线程dump ,命令 jstack 12598 > 12598.txt (12598为java进程id)中也检测出死锁:线程dump线程死锁不会造成应用崩溃,还是可以访问,但是会浪费线程资源,线程资源是有限的

  1. 线上问题示例-OOM(内存溢出)(线上较常见)

OOM原因
有可能是内存分配确实过小,而正常业务使用了大量内存
某一个对象被频繁申请,却没有释放,内存不断泄漏,导致内存耗尽
某一个资源被频繁申请,系统资源耗尽,例如:不断创建线程,不断发起网络连接

模拟OOM代码

  1. @PostMapping("/testOOM")
  2. public JsonResult testOOM() {
  3. List<Object> list = new ArrayList<>();
  4. while (true) {
  5. list.add(new Object());
  6. }
  7. }

首先设置jvm参数,让内存空间较小,容易引起内存溢出
-Xms80M -Xmx80M
-XX:+PrintGCDetails
-XX:+PrintHeapAtGC
-XX:+HeapDumpOnOutOfMemoryError

jvm参数设置
结果真的溢出了,发起请求,fullGC失败,内存溢出 ,控制台打印如图:内存溢出 ,fullGC失败
解决方案:
查看gc的统计情况:
jstat -gcutil [pid] 1000
在这里插入图片描述#查看堆分配情况,然后合理分配内存空间
jmap -heap [pid]
#分析哪个最占资源,幸运的话可以追踪到自己写的哪行代码哪个对象没有被回收
jmap -histo:live [pid]

  1. 线上问题示例-cpu100%问题(较常见)
    原因:
    1 程序中有死循环存在,空耗cpu资源,让cpu负载一直处于高位
    2 请求一直访问不了,java的垃圾回收把CPU的资源耗尽了,所有线程被gc线程打满,进程处于假死状态,应用线程一直工作不了,这时查看看gc一直处理高频回收的原因,是否有回收不了的对象,看是否有oom的情况。

解决方案:
查看cpu占用情况:
top命令查看进程,如图查看示例 ,进程15634(死循环的main进程)的cpu在100%左右
在这里插入图片描述
top -H -p [pid] 查看某个进程的线程tid(十进制)
使用printf “%x\n” tid 命令 转换为十六进制
使用 jstack [pid] > [pid].txt 查看线程dump ,定位查询上述tid占用请求状况

发表评论

表情:
评论列表 (有 0 条评论,163人围观)

还没有评论,来说两句吧...

相关阅读

    相关 线实例定位

    既然可以上锁,那么假如有2个线程,一个线程想先锁对象1,再锁对象2,恰好另外有一个线程先锁对象2,再锁对象1。在这个过程中,当线程1把对象1锁好以后,就想去锁对象2,但是不巧,