使用JProfiler分析程序性能问题

发布时间 2023-08-21 21:17:07作者: Geraltz'Rivia

JProfiler是一个分析运行时JVM的专业工具,根据官网的介绍,应用主要有以下几个功能:

  • 方法调用:通常被称为"CPU分析"。方法调用可以通过不同的方式进行测量和可视化, 分析方法调用可以帮助了解你的应用程序正在做什么,并找到提高其性能的方法。

  • 分配:分析堆上对象的分配、引用链和垃圾回收属于"内存分析"的范畴。 这个功能可以让你解决内存泄漏,总之使用更少的内存,分配更少的临时对象。

  • 线程和锁:线程可以持有锁,例如通过在一个对象上做同步。当多个线程协作时,可能会出现死锁,JProfiler可以为你可视化这种情况。 此外,锁可能被争用,这意味着线程在获得锁之前必须等待。通过JProfiler可以深入了解线程及其各种锁情形。

  • 高层子系统:许多性能问题发生在更高的语义层面。例如,对于JDBC调用,你可能想找出哪条SQL语句是最慢的。 对于这样的子系统,JProfiler提供了"探针",将特定有效载荷附加到调用树。

可以使用这个工具对java应用进行性能分析,找到长耗时方法、内存泄露位置等;

安装与启动

可以从官网上找到安装包,下载安装即可。根据网站上介绍的架构可以看出,jprofiler用了与rasp相同的技术javaagent进行程序分析

在本地安装的时候安装全部内容,如果需要在线上定位jvm性能问题,需要到对应机器上安装Jprofiler Agent。

本地使用时,可以在idea到插件仓库中搜索 jprofiler ,安装插件,插件安装完成后,在应用启动配置的面板会多两个按钮

1 可以自动把 jprofile 的启动参数添加到应用到jvm参数中,2 启动本地的 JProfiler GUI,通过选择连接到jvm即可(此时选择jvm的时候,有绿色的底色提示等待连接)

需要进行远程调试的时候,可以在 启动中心-新会话-新远程集成 根据提示步骤连接。

可以在远程集成的一步安装agent的时候,把agent装到目标机器,然后在启动的命令行手动添加jvm 参数 -agentpath:/opt/jprofile/jprofiler13/bin/linux-x64/libjprofilerti.so=port=8849 ,然后 直接 attach 到远端服务器,指定端口号与IP地址即可。

启动之后会有不同的方法调用记录选项,比如 Instrumentation 和 sampling,Instrumentation 修改了字节码,可以准确追踪各函数的调用,sampling只是定时采样,采样周期内的短耗时函数可能不能被记录;Instrumentation支持的功能更多,但是也有一些影响,比如高频调用的函数性能与耗时会被instrumentation影响,这里使用Instrumentation选项查看。

状态监控

连接上jvm后,有个整体的面板可以对jvm中的信息进行监控,比如内存使用、对象数量、GC、cpu活动等

内存监控与对象引用分析

在菜单实时内存页面可以看到内存上对象的数量以及大概占用的内存大小信息,实时内存监控主要是查看哪些临时对象被频繁的创建,可以使用标记当前来设定一个标记,过一段时间新创建的对象就会被用其他颜色标记出来。

不过深入一点的问题都会涉及到对象之间的引用。例如,在记录的对象、分配树和分配热点视图中显示的大小都是浅层大小, 它们只是包括了类的内存布局,但不包括任何引用的类。要想知道一个类的对象到底有多大,你通常需要知道保留大小, 也就是如果从堆中删除这些对象所释放的内存量。

如果想研究对象之间的引用关系,计算保留大小等,需要对内存中的对象信息进行统计计算,这个计算成本很高,一半都是把内存信息转储之后进行分析,也就是堆遍历器的功能,在堆遍历器可以新建一个快照。

新建一个堆转储后,记录的信息是经过gc后存活下的对象信息:

选择一个类后,可以查看类的引用:

  • 传入引用,可以理解为什么对象引用了该对象

  • 传出引用:该对象引用了其他别的什么对象

  • 合并的传入引用:什么类引用了该对象的类

  • 合并的传出引用:这个对象引用了其他的类

  • 合并的支配引用:当清除支配引用中的对象时,当前对象会被gc

参考

https://www.ej-technologies.com/resources/jprofiler/v/12.0/help_zh_CN/doc/main/introduction.html