【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题

这篇具有很好参考价值的文章主要介绍了【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Jprofiler简介

  • Jprofilers是针对Java开发的性能分析工具(免费试用10天), 可以对Java程序的内存,CPU,线程,GC,锁等进行监控和分析,

1.安装及IDEA集成Jprofiler

本人IDEA版本是2020.2.2,选择的Jprofiler版本是12.0(早期的版本是纯英文的,12.0支持中文,安装主要考虑是否与IDEA插件兼容即可)

  1. 进入Jprofiler官网下载 -> Jprofiler 版本这边建议选择最新的或者次新的(前提是你的IEDA版本也比较新)

  2. 打开IDEA->File->settings->plugins->marketplace->搜索 Jprofiler
    【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁

  3. 插件安装后, 在IDEA工具栏找到如图所示的两个图标,点击箭头指的那个,进行路径配置,让插件能找到第1步中下载好的Jprofiler:
    【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁

    • 选中后然后同意安装协议, 一路next确认就好了,最后选试用10天激活,如果你有秘钥可以选永久激活,至此就安装好了,然后可以通过该按钮启动应用

      【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁

    1. 启动后就可以获取到启动应用的各种信息了, 也可以连接远程服务器上的java应用,或者通过dump出来的文件分析等:

      【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁

2.如何监控并解决死锁

public static void main(String[] args) {
        Object a = new Object();
        Object b = new Object();
        
       new Thread(()->{
            synchronized (a){
                try {
                    System.out.println("已获取到a锁,尝试获取b锁===>");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (b){
                    System.out.println("尝试获取b锁...");
                }
            }
        }).start();
 
       new Thread(()->{
           synchronized (b){
               try {
                   System.out.println("<===已获取到b锁,尝试获取a锁");
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               synchronized (a){
                   System.out.println("尝试获取a锁...");
               }
           }
        }).start();
    }

通过Jprofiler启动这段代码,然后可以在锁菜单界面直接看到当前锁的状态图:
【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁

然后可以在当前Monitor监视器设置一个观察阈值, 如果项目中的锁比较多, 可以把超过一定时间的锁给筛选出来, 进一步观察是否死锁, 因为有些长时间阻塞的锁`也可能是 饿锁
【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁

然后针对筛选出来的几个可能是死锁的进行深入分析, 首先可以看到这些锁的类型是处于阻塞的, 然后鼠标右键任意一个锁上面 选择在堆遍历器中显式所选内容:
【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁
然后在对堆遍历器中点击图表, 就可以看到这个锁所在的代码位置, 然后 看一看代码就知道到底有没有死锁,还是饿锁了
【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁

通常来说产生死锁的原因主要有:

  1. 没有设置锁的失效时间, 然后代码里可能因为异常没有处理, 锁没有在finaly代码块中释放导致其它线程无法获取锁而陷入等待

  2. 锁互相竞争(类似上图这种) ,线程1持有A锁尝试获取B锁, 线程2持有B锁尝试获取A锁, 谁也不让谁, 互相干等着。 这种情况要注意加锁的顺序, 让线程1是先获得了A锁,再去获取B锁, 然后线程2去尝试获取A锁,再获取B锁, 按这样的顺序就不会产生死锁.

  3. 由线程优先级产生的饿锁,即高优先级线程一直占着资源不放而导致其他线程得不到执行, 饿锁不算死锁,但也要引起重视,否则同样会造成资源浪费, 可以通过JUC提供的公平锁解决.

——>按照上面的思路,去排查对应的代码,基本上死锁都能被解决.

3.如何监控及解决内存泄露(重点)

内存泄漏相对于死锁和OOM会比较难定位,而且对整个应用的危害程度比较大, 一旦发生内存泄漏,可能会导致整个应用不可用.

  • 内存泄漏可以通过JDK自带的jconsole或者jvisovm都可以监控到,这里演示下通过Jprofiler如何监控内存泄漏.

  • 通常情况下,内存泄漏会拖垮整个应用,如果应用突然不可用了, 且网络正常. 可以服务器查看应用日志, 如果看到有OOM,可以初步怀疑有内存泄漏发生, 对于比较明显 或者 比较短的时间内产生的内存泄漏, 可以通过本地IDEA直连Jprofile启动应用的方式进行监控 ,对于在特定场景下才会发生的,可以加上VM参数: -XXHeapdump重启线上应用, 以便在下次内存泄漏OOM时,导出dump日志,然后导入Jprofile进行分析. 这里我以直连本地的方式进行演示(偷个懒)

public class Test {
    private final static ThreadLocal<List<String>> threadLocal = new ThreadLocal<>();
    private final static List<String> list = new ArrayList<>();
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        
        executorService.execute(()->{
            while (true){
                for (int i = 0; i < 1000000; i++) {
                    list.add("oom");
                    if (i%100==0){
                        threadLocal.set(list);
                    }
                }
 
                //让过程慢一点,留点时间去分析,否则OOM之后与Jprofiler的连接就断开了
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

为了尽快的看到内存泄漏又能不中断与jprofiler的连接指定最大堆为1024M(-Xmx1024m ) , 以保证上面程序运行久一点, 不因为OOM中断影响分析
【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁
(上图是程序运行了很久之后)

  • 用IDEA的Jprofiler插件启动Jprofiler, 切换到遥测->内存界面, 内存使用量每增长一段时间后, 手动点击一次运行GC, 观察每次GC后已使用内存部分(下图中蓝色部分), 发现每次GC之后,已使用的内存变得越来越多, 如此积累下去, 直到已使用内存超过最大堆大小,应用就无法再创建对象, 然后疯狂触发GC, 但GC后又没有效果, 最终GC过载, CPU和内存资源被榨干,服务处于不可用状态.

    一句话: 观察前一次GC 和 当前GC后 剩余已用内存 是否处于 不断递增之中,如果是 ,则极有可能发生了内存泄漏.

【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁
【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁
通过线上服务不可用监控到的数据, 几乎可以确认是发生了内存泄漏,下面开始排查,到底是哪里发生了内存泄漏?写了什么禽兽代码让内存泄漏了???

  1. 第一步:通过Jprofiler连接到本地或者远程JVM(考虑到安全问题,可以用远程dump的日志导入Jprofiler)

  2. 第二步:点击实时内存菜单下的所有对象, 然后点击标记当前对象, 然后持续观察实例 计数列,相差列,大小列变化

可以从以下几个线索去缩小范围:

  1. 可能发生内存泄漏的一般有 char[],String,Map,List,Object[] 等数据,可以重点去看看

  2. 占据大量内存空间 或是 实例计数超大的

    一般会导致内存泄漏且影响到服务正常吞吐的, 大小列的值都不会太小,毕竟一个应用的最大堆至少也会指定/默认在256Mb以上,像这种几百kb级别的,即便在持续增长,想要让系统不可用,也得积累很久很久

  3. 多次点击运行GC,观察每次GC后剩余的大小,如果大小列的值增长很快,但GC后仍剩余很大,可以怀疑此处可能有内存泄漏

    比如下图被我框了的地方, GC前有400多Mb, GC后仍有186MB剩余, 整个堆区在GC后剩余的总垃圾也不过189MB, 这玩意就独占鳌头186Mb,回收不掉, 隔一阵子再点GC,GC后这个值比186MB还大,再次印证该类很可能存在内存泄漏)

    【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁

    通过上面3种排查方式,逐步缩小排查范围,目前看下来就只有char[],String,Object[]三种类型的数据可能存在内存泄露

  • 第三步: 选中可疑项,点击鼠标右键,选择在堆遍历器中显式

【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁

在打开的新界面中,点击最大对象, 然后选中保留大小最大的(有的时候有好几个都挺大的,只能一一尝试,因为保留大小偏大的一般都可能导致内存泄漏),然后点击鼠标右键,使用选中对象

【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁
然后选择传入引用,点击确定
【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁
在下图中的界面,可以先展开树形结构的数据看一下,这个Oject[]底下是什么东西, 一般来说如果点开是大公司打头的包名,基本可以直接跳过不用看了,因为一般大公司的产品不大会出现内存泄漏,发布之前他们应该也有测过了.

  • 如果看了下包名,是自己应用的包名,就可以继续排查,点击在图表中显示
    【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁

在弹出的新页面中选中上一步中看到的ArrayList对象,点击显示到GC根的路径:

【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁
【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁
然后可以点开+号,瞅瞅, 基本上到这一步,就能确认到发生内存泄漏的代码所在的包名+类名了, 然后重点去排查这段代码即可
【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题,JVM,Jprofiler,JVM调优,内存泄露,内存异常,死锁
原因 :

  • 因为ThreadLocal持有List<String>,然后ThreadLocal并没有remove(),导致List<String>被强引用,无法被GC,致使内存泄漏.

4.总结

  1. 如果没有Jprofiler这类工具, 在生产环境发生内存泄漏, 去一行一行review所有代码是不现实的, 通过此工具我们可以在较短的时间内定位到导致内存泄漏出现的代码位置, 然后review该位置的代码即可.

  2. 内存泄漏的难的主要是定位, 解决起来一般比较简单, 重启生产环境应用,让服务恢复正常, 然后在把导致内存泄漏的代码优化(该释放的释放,强引用显示置为为null...),改好之后测试并重新发布即可解决.

5.后话

当这些问题出现在生产环境时,一般都会带来严重的损失,而且排查和分析起来难度非常大, 在养成良好编码习惯, 尽量去规避死锁,内存溢出,及内存泄漏, 防患于未然是最好的文章来源地址https://www.toymoban.com/news/detail-825514.html

  • 多学点监控和解决方式, 或许有一天还真能派上用场.像这类低频使用的知识, 最好能总结一遍,留下文档,下次再碰到时,可以快速回忆,

到了这里,关于【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MySQL性能测试及调优中的死锁处理方法

    以下从死锁检测、死锁避免、死锁解决3个方面来探讨如何对MySQL死锁问题进行性能调优。 死锁检测 通过SQL语句查询锁表相关信息: (1)查询表打开情况 1 (2)查询锁情况列表 1 (3)查询锁等待信息,其中blocking_lock_id是当前事务在等待的事务 1 (4)查询死锁日志 SHOW ENGI

    2024年01月17日
    浏览(36)
  • 深入解读Kafka:如何进行运维与监控,实现性能调优和故障排除

    Kafka是由Apache Software Foundation开发的一款分布式流处理平台和消息队列系统 可以处理大规模的实时数据流,具有高吞吐量、低延迟、持久性和可扩展性等优点 常用于数据架构、数据管道、日志聚合、事件驱动等场景,对Kafka的运维和监控十分必要 本文旨在介绍Kafka的运维和监

    2024年02月04日
    浏览(50)
  • 【JVM】性能调优

    性能调优,顾名思义,就是对系统或软件的性能进行优化,以提高其运行效率和响应速度。在计算机科学中,性能调优通常涉及到硬件、操作系统、数据库、网络等多个方面。对于Java开发者来说,JVM(Java虚拟机)的性能调优是非常重要的一环,因为JVM的性能直接影响到Java程

    2024年01月18日
    浏览(47)
  • 06-JVM 性能调优

    在高性能硬件上部署程序,目前主要有两种方式: 通过 64 位 JDK 来使用大内存; 使用若干个 32 位虚拟机建立逻辑集群来利用硬件资源。 堆内存变大后,虽然垃圾收集的频率减少了,但每次垃圾回收的时间变长。 如果堆内存为 14 G,那么每次 Full GC 将长达数十秒。如果 Full

    2024年02月08日
    浏览(38)
  • JVM性能调优

    一、JVM内存模型及垃圾收集算法      1.根据Java虚拟机规范,JVM将内存划分为:   New(年轻代) Tenured(年老代) 永久代(Perm)   其中New和Tenured属于堆内存,堆内存会从JVM启动参数(-Xmx:3G)指定的内存中分配,Perm不属于堆内存,有虚拟机直接分配,但可以通过-XX:PermSize

    2024年02月13日
    浏览(67)
  • JVM 性能调优

    在高性能硬件上部署程序,目前主要有两种方式: 通过 64 位 JDK 来使用大内存; 使用若干个 32 位虚拟机建立逻辑集群来利用硬件资源。 堆内存变大后,虽然垃圾收集的频率减少了,但每次垃圾回收的时间变长。 如果堆内存为 14 G,那么每次 Full GC 将长达数十秒。如果 Full

    2024年02月11日
    浏览(41)
  • JVM性能调优简介

    一、JVM内存模型及垃圾收集算法      1.根据Java虚拟机规范,JVM将内存划分为:   New(年轻代) Tenured(年老代) 永久代(Perm)   其中New和Tenured属于堆内存,堆内存会从JVM启动参数(-Xmx:3G)指定的内存中分配,Perm不属于堆内存,有虚拟机直接分配,但可以通过-XX:PermSize

    2023年04月11日
    浏览(41)
  • 【jvm系列-13】jvm性能调优篇---参数设置以及日志分析

    JVM系列整体栏目 内容 链接地址 【一】初识虚拟机与java虚拟机 https://blog.csdn.net/zhenghuishengq/article/details/129544460 【二】jvm的类加载子系统以及jclasslib的基本使用 https://blog.csdn.net/zhenghuishengq/article/details/129610963 【三】运行时私有区域之虚拟机栈、程序计数器、本地方法栈 https

    2024年02月06日
    浏览(89)
  • 性能测试 —— Tomcat监控与调优:Jconsole监控

    JConsole的图形用户界面是一个符合Java管理扩展(JMX)规范的监测工具,JConsole使用Java虚拟机(Java VM),提供在Java平台上运行的应用程序的性能和资源消耗的信息。在Java平台,标准版(Java SE平台)6,JConsole的已经更新到目前的外观,类似于Windows和GNOME桌面(其他平台,将目前标准的J

    2024年02月07日
    浏览(54)
  • 【Jvm】性能调优(上)线上问题排查工具汇总

    产品闭环 产品闭环是能够让 用户主动迭代促进产品发展的方式 。例如一些内容产品,比如 糗事百科 ,种子用户 产出高质量内容 ,举报与赞起到 筛选内容 ,提高内容质量的作用, 内容质量的提升有助于吸引更多用户 。 这就是产品闭环, 产品给予用户需求解决方法,用户

    2024年02月20日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包