JVM监控及诊断工具-GUI篇

news2024/11/17 9:50:39

文章目录

  • JVM监控及诊断工具-GUI篇
    • 工具概述
    • JConsole
    • Visual VM
    • 再谈内存泄漏
    • Java中内存泄漏的8种情况
    • Arthas(阿尔萨斯)

JVM监控及诊断工具-GUI篇

工具概述

使用上一章命令行工具或组合能获取目标Java应用性能相关的基础信息,但它们存在下列局限:

  1. 无法获取方法级别的分析数据,如方法间的调用关系、各方法的调用次数和调用时间等(这对定位应用性能瓶颈至关重要)。
  2. 要求用户登录到目标Java应用所在的宿主机上,使用起来不是很方便。
  3. 分析数据通过终端数据,结果展示不够直观。

为此,JDK提供了一些内存泄漏的分析工具,如jconsole,jvisualvm等,用于辅助开发人员定位问题,但是这些工具很多时候并不满足快速定位的需求。所以这里我们介绍的工具相对多一些、丰富一些。

图形化综合诊断工具
1)JDK自带工具

  • jconsole:JDK自带的可视化监控工具。查看Java应用程序的运行概况、监控堆信息、永久代(或元空间)使用情况、类加载情况等。位置:jdk\bin\jconsole.exe
  • Visual VM:Visual VM是一个工具,它提供了一个可视见面,用于查看Java虚拟机上运行的基于Java技术的应用程序的详细信息。位置:jdk\bin\jvisualvm.exe
  • Java Mission Control,内置Java Flight Recorder。能够以极低的性能开销收集Java虚拟机的性能数据。

2)第三方工具

  • MAT:MAT(Memory Analyzer Tool) 是基于Eclipse的内存分析工具,是一个快速、功能丰富的Java heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。
  • JProfiler:商业软件,需要付费。功能强大。
  • Arthas:Alibaba开源的Java诊断空间。深受开发者喜爱。
  • Btrace:Java运行时追踪工具。可以在不停机的情况下,跟踪指定的方法调用、构造函数调用和系统内存等信息。

JConsole

基本概述
从Java5开始,在JDK中自带的Java监控和管理控制台。用于对JVM中内存、线程和类等的监控,是一个基于JMX(Java management extensions)的GUI性能监控工具。
官方教程:https://docs.oracle.com/javase/7/docs/technotes/guides/management/jconsole.html

启动

  • jdk/bin目录下,启动jconsole.exe命令即可。
  • 打开DOS窗口,直接输入jconsole就可以了。

三种连接方式
1)Local
使用JConsole连接一个正在本地系统运行的JVM,并且执行程序的和运行JConsole的需要是同一个用户。JConsole使用文件系统的授权通过RMI连接起链接到平台的MBean的服务器上。这种从本地连接的监控能力只有Sun的JDK具有。

2)Remote
使用下面的URL通过RMI连接器连接到一个JMX代理,service:jmx:rmi:///jndi/rmi://hostName:portNum/jmxrmi。JConsole为建立连接,需要在环境变量中设置mx.remote.credentials来指定用户名和密码,从而进行授权。

3)Advanced
使用一个特殊的URL连接JMX代理。一般情况使用自己定制的连接器而不是RMI提供的连接器来连接JMX代理,或者是一个使用JDK1.4的实现了JMX和JMX Rmote的应用。

看一下我们这里的Local本地连接,首先启动idea中的一个项目,如下图:
在这里插入图片描述
然后点击jdk\bin\jconsole.exe,如下图:
在这里插入图片描述
连接上之后如下图:
在这里插入图片描述
看一下怎么使用JConsole.exe工具去检测死锁,我们有一个如下的程序,如下:

/**
 * @author xuan
 * @create 2023/10/8
 */
public class ScannerTest {
    static Object A = new Object();
    static Object B = new Object();

    public static void main(String[] args) {
        Runnable task = new Runnable() {
            @Override
            public void run() {
                synchronized (A) {
                    try {
                        Thread.sleep(1000);
                        synchronized (B) {
                            System.out.println();
                        }
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        Thread thread = new Thread(task);
        thread.start();

        synchronized (B) {
            try {
                Thread.sleep(1000);
                synchronized (A) {
                    System.out.println();
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }
}

然后去JConsole工具的线程菜单栏查看,如下图:
在这里插入图片描述
点击检测死锁之后如下图:
在这里插入图片描述

Visual VM

jvisualvm和visual vm的区别
没什么区别,只是visual vm是单独下载的,jvisualvm是JDK自带的

基本概述

  • Visual VM是一个功能强大的多合一故障诊断和性能监控的可视化工具。
  • 它集成了多个JDk命令行工具,使用Visual VM可用于显示虚拟机进程以及进程的配置和环境信息(jps,jinfo),监控应用程序的CPU、GC、堆、方法区及线程的信息(jstat、jstack)等,甚至代替JConsole。
  • 在JDK 6 Update 7以后,Visual VM便作为JDK的一部分发布(VisualVM 在JDK/bin目录下)
  • 此外,Visual VM也可以作为独立的软件安装:

首页:https://visualvm.github.io/index.html

jdk中自带的有VisualVM,如下图:
在这里插入图片描述
点击打开之后的界面,如下图:
在这里插入图片描述
如下图:
在这里插入图片描述
在这里插入图片描述
我们这里是写了一个while循环,无限循环创造对象,所以这里一直会进行垃圾回收,如果后续遇到了垃圾回收比较频繁的情况,那肯定是那个地方出问题了。

如果我们发现我们的程序出现卡顿了,那说明可能有些方法执行时间比较长,我们可以在抽样器里面去查看,如下图:
在这里插入图片描述
在抽样器里面,点击CPU可以去查看每个方法运行所占用的时间,它会把那些占用时间比较长的方法统计出来,我们后面可以单独分析分析,为什么这个方法的运行时间会比较长?比如说上面Server服里面的printNoticeCount方法的运行时间就比较长。

再谈内存泄漏

何为内存泄漏?
在这里插入图片描述
可达性分析算法来判断对象是否是不再使用的对象,本质都是判断一个对象是否还被引用。那么对于这种情况下,由于代码的实现不同就会出现很多种内存泄漏问题(让JVM误以为此对象还在引用中,无法回收,造成内存泄漏)。

内存泄漏(memory leak)的理解
严格来说,只有对象不会再被程序用到,但是GC又不能回收他们的情况,才叫内存泄漏。
但实际情况很多时候一些不太好的时间(或疏忽)会导致对象的生命周期变得很长甚至导致OOM,也可以叫做宽泛意义上的“内存泄漏”。
在这里插入图片描述
对象X引用对象Y,X的生命周期比Y的生命周期长;

​ 那么当Y生命周期结束的时候,X依然引用着Y,这个时候,垃圾回收器是不会回收对象Y的;

​ 如果对象X还引用着生命周期比较短的A、B、C,对象A又引用着对象a、b、c,这样就可能造成大量无用的对象不能被回收,进而占据了内存资源,造成内存内存泄漏,直到内存溢出。

内存泄漏与内存溢出的关系
(1)内存泄漏(memory leak)
申请了内存用完了不释放,比如一共有1024M的内存,分配了512M的内存一直不回收,那么可以用的内存只有521M了,仿佛泄漏了一部分;
(2)内存溢出(out of memory)
申请内存时,没有足够的内存可以使用;
可见,内存泄漏和内存溢出的关系:内存泄漏的增多,最终会导致内存溢出。

内存泄漏的分类
(1)经常发生:发生内存泄漏的代码会被多次执行,每次执行,泄漏一块内存;
(2)偶然发生:在某些特定情况下才会发生;
(3)一次性:发生内存泄漏的方法只会执行一次;
(4)隐式泄漏:一直占着内存不释放,直到执行结束;严格的说这个不算内存泄漏,因为最终释放掉了。

Java中内存泄漏的8种情况

1.静态集合类
静态集合类,如HashMap、LinkedList等等。如果这些容器为静态的,那么它们的生命周期与JVM程序一样,则容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏。简单而言,长生命周期的对象持有短生命周期对象的引用,尽管短生命周期的对象不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收。

2、单例模式
​ 单例模式,和静态集合导致内存泄漏的原因类似,因为单例的静态特性,它的生命周期和JVM的生命周期一样长,所以如果单例对象如果持有外部对象的引用,那么这个外部对象也不会被会回收,那么就会造成内存泄漏。

3、内部类持有外部类
内部类持有外部类,如果一个外部类的实例对象的方法返回了一个内部类的实例对象。

​ 这个内存类对象被长期引用了,即使那个外部实例对象不再被使用,但由于内部类持有外部类的实例对象,这个外部类对象将不会被垃圾回收,这也会造成内存泄漏。

4、各种连接,如数据库连接、网络连接和IO连接等
在对数据库进行操作的过程中,首先需要建立与数据库的连接,当不再使用时,需要调用close方法来释放与数据库的连接。只有连接被关闭后,垃圾回收器才会回收对应的对象。
​ 否则,如果在访问数据库的过程中,对Connection、Statement或ResultSet不显性地关闭,将会造成大量的对象无法被回收,从而引起内存泄漏。

5、变量不合理的作用域
一般而言,一个变量的定义的作用范围大于其使用范围,很有可能会造成内存泄漏。另一方面,如果没有及时地把对象设置为null,很有可能导致内存泄漏的发生。

6、改变哈希值
改变哈希值,当一个对象被存储进HashSet集合以后,就不能修改这个对象中那些参与计算哈希值的字段了。
​ 否则,对象修改后哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,及时在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也就会导致无法从HashSet集合中单独删除当前对象,造成内存泄漏。
​ 这也是String为什么被设置了不可变类型,我们可以放心地把String存入HashSet,或者把String当做HashMap的key值;

7、缓存泄漏
内存泄漏的另一个常见来源是缓存,一旦把对象引用放入到缓存中,他就很容易遗忘。比如:之前项目在一次上线的时候,应用启动奇慢无比,就是因为代码中会加载一个表的数据到缓存(内存)中,测试环境只有几百条数据,但是生产环境有几百万的数据。
​ 对于这个问题,可以使用WeakHashMap代表缓存,此种Map的特点是,当除了自身有对Key的引用外,此key没有其他引用那么此map会自动丢次此值。

在读这条信息的时候,不知道怎么就突然想到如果一个方法A里面我们有条语句Student stu = new Student();那么这个方法执行完毕之后,当后面堆里面的新生代的伊甸园区里面进行GC垃圾回收的时候,会把我们创建在堆上的Student对象给回收掉吗?会的。因为当我们的A方法执行的时候它会变成栈帧入栈,一个方法相当于是一个栈帧,然后栈帧里面的局部变量表里面有个stu变量,它的地址就是引用堆区里面的Student对象,而当我们A方法执行完毕之后,A方法对应的栈帧就从栈里面出栈了,这个时候stu这个变量就消失了,因此就不会再有对Studnet对象的引用了,这个对象也就变成了一个垃圾对象,当伊甸园区的对象满了之后Java进行GC垃圾回收的时候,会自动的把Student这个对象给回收掉。这就是java的GC垃圾回收,现在懂了之后感觉java的设计非常的神奇。

8、监听器和回调
内存泄漏第三个常见来源是监听器和其他回调,如果客户端在你实现的API中注册回调,却没有显示的取消,那么就会积聚。
​ 需要确保回调立即被当作垃圾回收的最佳方法是只保存它的弱引用,例如将他们保存称为WeakHashMap中的键。

Arthas(阿尔萨斯)

背景
Jvisualvm和Jprofile这两款工具在业界知名度也比较高,他们的优点是可以图形界面上看到各维度的性能数据,使用这根据这些数据进行综合分析,然后判断哪里出现了性能问题。

​ 但是这两款工具也有缺点,都必须在服务端项目进程中配置相关的监控参数。然后工具通过远程连接到项目进程,获取相关的的数据。这样就会带来一些不便,比如线上环境的网络是隔离的,本地的监控工具根本连不上线上环境。并且类似于JProfiler这样的商业工具,是需要付费的。

​ 那么有没有一款工具不需要远程连接,也不需要配置监控参数,同时也提供了丰富的性能监控数据呢?

​ 答案就是阿里巴巴开源的性能分析神器Arthas(阿尔萨斯)

概述
Artha(阿尔萨斯)是Alibaba开源的Java诊断工具,深受开发者喜爱。在线排查问题,无需重启;动态跟踪Java代码:实时监控JVM状态。

Arthas 支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

当你遇到一下类似问题而束手无策,Arthas可以帮助解决:

  • 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
  • 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
  • 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
  • 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
  • 是否有一个全局视角来查看系统的运行状况?
  • 有什么办法可以监控到 JVM 的实时运行状态?
  • 怎么快速定位应用的热点,生成火焰图?
  • 怎样直接从 JVM 内查找某个类的实例?

官方地址:https://arthas.aliyun.com/

Arthas阿尔萨斯概述https://www.cnblogs.com/qiaoyihang/p/10533672.htmlwindows下安装Arthas 首先需要下载arthas-boot.jar,然后用java -jar的方式启动,下载命令:
curl -0 https://alibaba.github.io/arthas/arthas-boot.jar --output arthas-boot.jar java -jar arthas-boot.jar
在这里插入图片描述
在运行第二句代码之前一定要启动一个java进程,否则会发生错误,因为阿尔萨斯检测不到你本地的java进程,如下图:
在这里插入图片描述
我们可以启动idea,因为idea就是一个java进程,启动完idea之后,再执行上面的命令,如下图:
在这里插入图片描述
执行成功。这时Arthas会发现我们本地是没有Arthas的安装包的,这时会提示我们选择,这里我们选择2,1是我们在本地运行的Java进程。 选择2就会从网上去下载Arthas,从maven仓库中下载。如下图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
快速入门:使用Arthas追踪线程 首先,arthas为我们提供了一个测试jar包,如下图:
在这里插入图片描述
接着,运行这个jar包,如下图:
在这里插入图片描述
然后另外开一个cmd命令行窗口,运行arthas-boot.jar包,如下图:
在这里插入图片描述
端口号已经被占用了,我们可以可以使用命令java -jar arthas-boot.jar --telnet-port 9998 --http-port -1换一个端口号进行运行,如下图:
在这里插入图片描述
在Idea里面安装Arthas插件 因为Arthas的命令实在是太多了,我们不能一一记住,因此idea里面为我们集成了一个arthas插件,去idea插件库里搜索arthas即可发现。这个插件可以让我们拿到各种命令,如下图:
在这里插入图片描述
使用Arthas监听我们方法参数 比如我们游戏中的人物可以行走,它行走的时候调用的方法,在线运行的时候的输入参数是什么呢?我们可以通过Arthas进行分析,找到对应的方法,拿到对应的arthas命令,如下图:
在这里插入图片描述
开启arthas监听,如下图:
在这里插入图片描述
在这里插入图片描述
客户端移动游戏人物之后,我们就可以在cmd命令行窗口中监听到方法的输入参数,如下图:
在这里插入图片描述
使用Arthas监听我们目标方法的调用堆栈信息 可以在idea中获取相关的Arthas命令,如下图:
在这里插入图片描述
然后在cmd命令行窗口使用arthas监听方法的调用堆栈如下图:
方法调用的堆栈信息
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1073304.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript入门——基础知识(4)

一、for语句 1.1 for语句的基本使用 1.1.1 for循环语法 作用&#xff1a;重复执行代码 好处&#xff1a;把声明起始值、循环条件、变化值写到一起&#xff0c;让人一目了然&#xff0c;它是最常使用的循环形式 for(变量起始值;终止条件;变量变化量){// 循环体 } <script&g…

gici-open示例数据运行(ground_truth坐标的转换)

1. 坐标系转换说明 涉及的两个坐标转换&#xff1a; nmea_pose_to_pose &#xff1a;激光IMU中心到数据集IMU中心&#xff0c;主要是杆臂误差&#xff0c;转换关系为&#xff1a; //坐标转换的主要步骤(若发现有错误的地方&#xff0c;请评论指出) //定义激光IMU和数据集IMU之…

springboot项目做成公共项目

一&#xff1a;引言 最近碰到个需求&#xff0c;就是把我项目做成一个公共的提供jar包给别人使用&#xff0c;我也是捣鼓了一段时间去研究这个问题&#xff0c;这个东西其实就是A 项目提供jar包给B项目&#xff0c;B项目只要引入A项目的jar包就可以使用A项目的功能。 问题一&…

Jumpserver安全一窥:Sep系列漏洞深度解析

Jumpserver是中国国内公司开发的一个开源项目&#xff0c;在开源堡垒机领域一家独大。在2023年9月官方集中修复了一系列安全问题&#xff0c;其中涉及到如下安全漏洞&#xff1a; JumpServer 重置密码验证码可被计算推演的漏洞&#xff0c;CVE编号为CVE-2023-42820JumpServer 重…

untitle

实用的科研图形美化处理教程分享 ​ 显微照片排版标记 除了统计图表之外&#xff0c;显微照片也是文章中必不可少的实验结果呈现方式。除了常规实验的各种组织切片照片&#xff0c;在空间转录组文章中显微照片更是常见。显微照片的呈现方式也是有讲究的&#xff0c;比如对照片…

硬核!一个基于SpringBoot+Vue前后端分离低代码项目

一、项目介绍 这是一款基于SpringBootVue的前后端分离的项目&#xff0c;麻雀虽小&#xff0c;五脏俱全&#xff0c;开箱即用&#xff01; JNPF开发平台的前端采用Vue.js&#xff0c;这是一种流行的前端JavaScript框架&#xff0c;用于构建用户界面。Vue.js具有轻量级、可扩展性…

网络电视机顶盒怎么样?数码粉私藏网络机顶盒排行榜

对于新手来说&#xff0c;选购网络机顶盒十分困难&#xff0c;不少低价网络机顶盒虚标配置&#xff0c;偷工减料&#xff0c;售后也没有保障&#xff0c;不知道网络机顶盒什么牌子好很容易踩雷&#xff0c;近来某知名数码媒体发布了最新的网络机顶盒排名&#xff0c;入围的是哪…

swift界面初体验

1.添加视图 lazy var contentView: UIView {let a UIView()self.view.addSubview(a)return a}()2.添加文本 lazy var tipsLabel: UILabel {let a UILabel()a.font UIFont.regular13a.textColor UIColor.withHex(hexString:"#58C65C")a.text R.string.locali…

延时中间继电器 JZS-7/125 DC220V 0.02-9.99S 带一延时一瞬动辅助接点

JZS-7/125可调延时中间继电器系列型号&#xff1a; JZS-7/125静态可调延时中间继电器&#xff1b; JZS-7/145静态可调延时中间继电器&#xff1b; JZS-7/127静态可调延时中间继电器&#xff1b; JZS-7147静态可调延时中间继电器&#xff1b; 1 用途 JZS-7系列静态可调延时中间…

QT5 WebCapture 页面定时截图工具

QT5 WebCapture 网页定时截图工具 1.设置启动时间&#xff0c;程序会到启动时间后开始对网页依次进行截图 2.根据所需截图的页面加载速度&#xff0c;设置页面等待时间&#xff0c;尽量达到等页面加载完成后&#xff0c;再执行截图 3.根据需求&#xff0c;设置截图周期 4.程序…

基于多线程的Reactor模式的 回声服务器 EchoServer

记录下 一个线程专门用来接受accept获取客户端的fd 获取fd之后 从剩余的执行线程中 找到一个连接客户端数量最少的线程 然后将客户端的fd加入到这个线程中并通过EPOLL监听这个fd 线程之间通过eventfd来通信 将客户端的fd传到 对应的线程中 参考了MediaServer 引入…

[java基础学习]之DOS命令

#java基础学习 1.常用的DOS命令&#xff1a; dir:列出当前目录下的文件以及文件夹 md: 创建目录 rd:删除目录cd:进入指定目录 cd.. :退回到上级目录 cd\ : 退回到根目录 del:删除文件 exit:退出dos命令行 1.dir:列出当前目录下的文件以及文件夹 2.md: 创建目录 …

解决Adobe Premiere Pro CC 2018打开无反应,并出现.crash的文件问题

一 问题描述 Adobe Premiere Pro CC 2018软件安装完成后&#xff0c;打开该软件没反应&#xff0c;且打开时桌面会出现Crash文件&#xff01; 二 解决方法 如果Adobe Premiere Pro CC 2018在打开时无反应&#xff0c;并出现.crash文件的问题&#xff0c;可以尝试以下解决方法…

KekeBlog项目实战(更新中)

一、前言 1. 项目简介 本项目是前后端分离项目&#xff0c;而我们所做的只有完整的后端开发工作&#xff0c;前端已经写好&#xff0c;故不做任何开发&#xff0c;仅开发后端。项目包含完整的后端中前台和后台的代码编写 前端项目下载链接&#xff1a; https://pan.baidu.c…

Git仓库迁移记录

背景&#xff1a;gitlab私服上面&#xff0c;使用 import project的方式&#xff0c;从旧项目迁移到新地址仓库&#xff0c;但是代码一直没拉过去。所以使用命令的方式&#xff0c;进行代码迁移。 第一步&#xff1a;使用git clone --mirror git地址&#xff0c;进行代码克隆 …

建立数据科学基础设施的绝佳指南 数据工程师都该人手一册

《Effective数据科学基础设施》由Netflix工程师Ville Tuulos撰写&#xff0c;以Metaflow为对象&#xff0c;介绍了数据科学所需要的基础设施&#xff0c;囊括数据准备、特征工程、模型训练、模型部署、服务和持续监控等环节。Metaflow专注于构建生产流程&#xff0c;更适合具有…

《理解深度学习》2023最新版本+习题答案册pdf

刚入门深度学习或者觉得学起来很困难的同学看过来了&#xff0c;今天分享的这本深度学习教科书绝对适合你。 就是这本已在外网获13.1万次下载的宝藏教科书《理解深度学习》。本书由巴斯大学计算机科学教授Simon J.D. Prince撰写&#xff0c;全书共541页&#xff0c;目前共有21…

【嵌入式C内存管理】

记录嵌入式C内存划分&#xff0c;后续会更新动态内存管理 1. 内存划分 栈区 stack有时也称为堆栈&#xff0c;重点在栈字&#xff0c;存放函数内部临时变量堆区 heap也就是动态申请&#xff08;malloc&#xff09;、释放(free)的内存区域数据区 data初始化的全局变量和静态变量…

opengauss数据备份(docker中备份)

首先如果想直接在宿主机上进行使用gs_dump备份需要glibc的版本到2.34及以上&#xff0c;查看版本命令为 ldd --version 如图所示&#xff0c;本宿主机并不满足要求&#xff0c;所以转向在docker容器中进行备份&#xff0c; 然后进入opengauss容器中&#xff0c;命令为 docker…

Vue3 + Ts实现NPM插件 - 定制loading

目录 你的 Loading&#x1f916; 安装&#x1f6f9; 简介苍白请 您移步文档&#xff1a;✈️ 使用方法&#x1f6e0;️ 配置 loading 类型&#x1f3b2; 定制 loading 色彩 &#x1f4a1; 注意事项 前期回顾 你的 Loading 开箱即可用的 loading&#xff0c; 说明&#xff1a;vu…