JVM监控之图形化工具

article/2025/10/10 18:16:44

一、工具概述

使用命令行工具存在以下的局限性:

  • 无法获取方法级别的分析数据,如方法之间的调用关系、各方法的调用次数和调用时间等
  • 要去用户登陆到java应用所在的宿主机上
  • 分析数据通过终端输出,结构不够直观

随着java应用的官方使用,越来越多的图形化工具问世

1、JDK自带工具

  • jConsole:查看应用运行概况、监控堆信息、永久区使用情况、类加载情况等
  • Visual VM:提供了可视化界面,用户查看JVM运行居于java技术应用程序的详细信息
  • JMC:Java Mission Contorl 内置Java Flight Recorder,能够以极低的性能开销收集JVM的性能数据

2、第三方工具

  • MAT:一个快速、功能丰富的Java heap分析工具,能够帮助使用者查找内存泄漏和减少内存消耗
  • JProfiler:商业软件,功能强大
  • Arthas:阿里提供的开源Java诊断工具
  • Btrace:java运行时追踪工具,可以在不停机的情况下,跟踪指定的方法调用、构造函数调用和系统内存等信息

二、jConsole

1、基本概述

  • 从jd1.5开始,在JDK自带的java监控和管理控制台
  • 用于对JVM中内存、线程和类等的监控,是一个机遇JMX的GUI性能监控工具

2、启动

直接在cmd中输入jconsole,或者在bin下执行exe文件。

3、三种链接方式

  • 本地:运行程序和启动用户需要是一个
  • 远程
  • Advanced

4、主要作用

三、Visual VM

1、基本概述

  • 功能强大、多合一故障诊断和性能监控的可视化功能
  • 显示进程、进程配置和环境信息,监控程序的CPU、GC、堆、方法区及线程信息等
  • JDK6 开始之后,Visual VM随着JDK一起发布

2、插件的安装

Visual VM 自己可以安装插件 Update Center documentationhttps://visualvm.github.io/uc/release211/updates.html

3、连接方式

  • 本地连接
  • 远程连接
    • 确定远程服务器的IP
    • 田佳JMX
    • 修改tomcat catalina.sh
    • 在../conf中添加jmxremote.access和jmxremite.password文件
    • 将服务器地址修改为公网IP地址
    • 设置防火墙
    • 启动tomcat,查看tomcat启动日志和端口日期
    • JMX中输入端口号、用户名、密码登陆

4、主要功能

  1. 生成和读取dump文件,还可以针对两个不同的dump文件进行对比
  2. 查看JVM参数和系统属性
  3. 查看运行中的JVM进程
  4. 生成和读取线程快照
  5. 程序资源的实时监控
  6. JXM代理连接、远程环境监控、CPU分析和内存分析

四、eclipse MAT(分析Dump文件

1、基本概述

MAT是一款功能强大的JAVA堆内存分析工具。用于查找内存泄漏以及查看内存消耗情况。如果需要分析dump文件,那么推荐使用MAT,因为MAT主要功能就是分析dump文件。

2、获取堆dump文件

  • dump文件内容
    • 所有对象信息,包括对象实例、成员变量、存储于栈中的基本类型和存储于堆中的其它对象引用值
    • 所有类信息,包括ClassLoader、类名称、父类、静态变量等
    • GCRoot到所有这些对象的引用路径
    • 线程信息,包括线程的调用栈及此线程的线程局部变量(TLS)
  • 两点说明
    • MAT是一种工具,但是格式也是有要求的,主流的JVM生产的dump都能识别
    • 最吸引人的地方,就是生成内存泄漏报表
  • 获取dump文件
    • 使用jmap生成 dump文件
    • 配置jvm参数,当出现OOM的时候,生成dump文件,获取FUllGC之前生成
    • 使用VisualVM,也是可以生成
    • MAT也可以生成dump文件进行导出,生产情况下常见组合就是MAT+jmap

3、分析堆dump文件

打开一个dump文件:

打开完成后:

文件夹会生成相关文件:

  • histogram:
    • 可以查看某个类的强引用、GCRoot、ClassLoader
    • 对比2个dump文件
  • thread overview
    • 查看某个线程执行情况
    • <local> 就是线程的局部变量,同时可以局部变量的内存接口、存储的类型
    • 线程局部变量引用信息,查看一个对象,可能存在某个静态变量或者生命周期比较长的对象对其进行引用了,导致对象无法回收,这样我们可以修改成为弱引用
  • 获得对象相互引用的关系
    • 浅堆与深堆 
      • shallow heap:浅堆,所消耗的内存,不包含引用的对象大小,只包含引用的大小
      • retained heap:深堆,对象保留集中所有对象的浅堆之和,也就是对象回收后可以释放的真实空间
        • 对象的保留集:只能通过A对象直接或间接访问到的所有对象的集合,仅被A持有的对象的集合
      • 补充:对象实际大小,对象可以触及的所有对象的浅堆之和,和垃圾回收没关系
        • A浅堆:A自己
        • A深堆:A+D
        • A对象:A+C+D
  • 支配树:体现对象实例之间的支配关系。所有指向B的路径都经过了对象A,则称为A支配B,如果对象A是离对象B最近的支配者,那么称为A是B的直接支配者,MAT中的支配树,就是显示了一个对象的深堆

五、内存泄漏

1、内存泄漏的理解与分类

对象不会被使用,但是GC无法回收,或者对象的生命中后期跟JVM一样,都可以称为内存泄漏。一个对象在被使用,但是并不被需要。内存泄漏时间长了就会出现内存溢出。

2、java中内存泄漏的8中情况

  • 静态集合类:定义静态集合,一直添加对象,导致对象无法回收
  • 单例模式:和静态集合类类似,因为单例的静态特征,它的生命周期和JVM相同,所以单例对象如果持有外部对象的引用,那么这些对象也不会被释放
  • 内部类持有外部类:一个外部类的实例返回了一个内部的实例,这个内部类被长期饮用了,即使外部类实例不在被使用,但由于内部类持有外部类的实例,这个外部类不会被垃圾回收
  • 各种连接:数据流连接、数据流需要显示的关闭,就会内存泄漏
  • 变量不合理的作用域
  • 改变哈希值:当一个对象放入HashSet中后,就不能改变这个对象那些参与计算哈希值的字段了,否则由于修改后哈希值与当初存入HashSet集合中的哈希值就不同了,在这种情况下,即使在contains方法使用该对象当前的引用作为参数去HashSet检索对象,也讲返回找不到对象的结果,也会导致无法从HashSet单独删除当前对象
    package memory.leak;import java.util.HashSet;public class ChangeHashCode {public static void main(String[] args) {HashSet<Point> hs = new HashSet<>();Point cc = new Point();cc.setX(10);hs.add(cc);cc.setX(20);System.out.println("hs.remove = " + hs.remove(cc));//hs.remove = falsehs.add(cc);System.out.println("hs.size = " + hs.size());//hs.remove = false}
    }class Point{int x;public int getX() {return x;}public void setX(int x) {this.x = x;}@Overridepublic int hashCode(){final int prime = 31;int result = 1;result = prime * result + x;return result;}@Overridepublic boolean equals(Object obj) {if(this == obj) return true;if(obj == null) return false;if(getClass() != obj.getClass()) return false;Point other = (Point) obj;if(x != other.x) return false;return true;}
    }
    
  • 缓存泄漏:内存中的HashMap需要及时清理,可以改用WeakHashMap
  • 监听器和回调

3、内存泄漏案例分析

package memory.leak.c2;import java.util.Arrays;
import java.util.EmptyStackException;public class Stack {private Object[] elements;private int size = 0;private static final int DEFAULT_INITIAL_CAPACITY = 16;public Stack(){ensureCapacity();elements = new Object[DEFAULT_INITIAL_CAPACITY];}public void push(Object e){elements[size ++] = e;}public Object popLeak(){if(size == 0){throw  new EmptyStackException();}//只是把置针向下移动了,数组内的对象并没有回收。就是数组内的对象并没有回收return elements[--size];}public Object pop(){if(size == 0){throw  new EmptyStackException();}Object result = elements[--size];elements[size] = null;return result;}private void ensureCapacity(){if(elements.length == size){elements = Arrays.copyOf(elements, 2 * size + 1);}}}

六、支持OQL语言查询对象信息

  • SELECT:select * from "包名"
  • FROM
  • WHERE
  • 内置对象于方法 

七、JProfiler

1、基本概念

1、特点

  • 使用方便、界面操作友好(简单且强大)
  • 对被分析的应用影响很小
  • CPU、Thread、Memory分析功能尤其强大
  • 支持对jdbc、noSql、jsp、servlet、socket等进行分析
  • 支持多种模式(离线、在线)
  • 支持本地、远程JVM监控
  • 跨平台、拥有多中操作系统的安装版本

2、主要功能

  • 方法调用:对方法调用的分析可以帮助使用者了解程序在做什么
  • 内存分配:通过分析堆上对象、引用链和垃圾手机能助于修复内存泄漏、优化内存使用
  • 线程和锁:提供多种针对线程和锁的分析试图
  • 高级子系统:许多性能问题都发生在更高的语义级别上,例如JDBC的调用

2、安装与配置

在idea直接下载插件即可

3、具体使用

1、数据采集方式

  • 重构模式(Instrumentation):功能强大、信息准确,但是消耗性能、影响应用,可以过滤不分析的类
  • 抽样模式(Sampling):不能提供全部的功能,但是CPU消耗小、对应用影响小

正在运行的应用,建议使用抽样的方式,这样对应用影响比小。

2、遥感监测(Telemetries)

对整个监控应用的一个概览,上面能够看到内存、类、GC等相关内容 

3、内存试图(Live Memory)

  • 所有对象:包含名称、大小、个数,可以点击“标记当前”,跟点击时间点进行对比
  • 分配调用树:显示一个请求树或者方法、类、包或对已选择类有逮住是的饭呢佩信息的J2EE组件
  • 分配热点:显示列表,包括类、方法、包或分配已选择的J2EE组件
  • 类追踪器:类跟踪试图可以包含任意的数量的图表,显示选定的类和包的实例与时间

分析:内存中对象情况

  • 频繁创建的对象:就是图中很多的对象,死循环、循环次数过多
  • 存在大对象:查看对象的大小
  • 存在内存泄漏的问题:每次垃圾就回收之后,都有内存没有被回收,并且逐步增加,这个时候可以开启记录对象

4、堆遍历(heap walker)

5、CPU试图(CUP Views)

主要是针对应用中方法的调用时间判断,调用时间越长占用CPU时间越长

调用百分比、执行时间、调用次数、方法所在类的完整路径

6、线程试图(threads)

线程分析:

  1. web容器线程最大数,例如tomcat线程容量应该大于并发数
  2. 线程阻塞
  3. 线程死锁
  • 线程历史:显示一个与线程活动和线程状态一起的活动时间表
  • 线程监控:显示一个列表,包括所有活动的线程以及它们目前的活动情况
  • 线程转出:显示有所线程的堆栈信息(Thread dump)

 

7、监视器和锁(Monitor&lock)

八、Arthas(线上排查问题)

1、基本概述

1、背景

真正的项目都是在服务器上的,所以如果使用图形化界面,那么一定需要参数配置和网络连接,不仅不方便并且消耗性能。居于这个场景,Arthas诞生了。

2、概述

Arthas是一款开源、流行的命令行诊断工具,在线上排查问题,无需重启,动态跟踪代码,实时监控JVM状态。

能够解决的问题:

  • 这个类从哪个jar包加载的?为什么会报各种类相关的Exception
  • 改的代码为什么没有被执行到?没有commit?分支搞错了?
  • 遇到线程问题无法debug,难道只能通过日志重新发布吗?
  • 线上遇到某个用户的数据处理有问题,但是线上无法debug,线下无法重现
  • 是否有一个全局视角查看系统运行的状况
  • 有什么办法可以监控到JVM实时运行状态

3、基于哪些工具开发而来

4、官方使用文档

Arthas 应用诊断利器

2、安装和使用

解压完毕之后:

 直接启动 arthas-boot.jar即可,启动后选择一个进程去监控,也可以直接跟着PID监控指定进程:

 http://127.0.0.1:8563/,使用web控制台进行查看。

查看日志:cat ~/logs/arthas/arthas.log,也可以使用 java -jar arthas-boot.jar -h 查看帮助文档。

3、相关诊断命令

1、基础指令

  • help:帮助
  • cat:打印文件内容
  • echo:打印相关参数
  • grep:匹配查找
  • tee:复制标准输入到标准输出和指定文件
  • pwd:返回当前工作目录
  • cls:清屏
  • session:查看当前回话信息
  • reset:重置增强类,arthas增强过类全部还原,关闭时候也会重置
  • version:输出当前目标进程所加载的arthas的版本号
  • history:打印历史命令
  • quite:退出当前客户端
  • stop:关闭arthas服务器,所有客户端都退出
  • keymap:自定义快捷键

2、JVM相关

  • dashboard:查看程序控制面板 -i 时间间隔、-n 打印次数
  • thread,查看线程情况,可以根据线程ID查询详情,-b 参数是查看是否有死锁,-i 统计时间段内线程cpu使用率, -n 查询cpu使用率最高的几个线程
  • jvm:查看jvm相关信息
  • heapdump:保存线程dump文件,可以使用--live只查看或者的对象

3、class/classLoader相关

  • mc、redefine:mc编译文件,redefine进行替换
  • sc:JVM已经加载类的信息,-d -f 类的详细信息
  • sm:JVM已经加载类方法的信息
  • jad:查看类的源码,也可以针对某个方法
  • classloader 查看类的加载器 

4、monitor、watch、trace相关

  • stack:输出方法当前被调用的调用路径
  • monitor:方法执行监控
  • trace:方法内部调用路径,并输出方法路径上的耗时
  • watch:方法执行数据观测
  • tt:方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下进行观测

5、其它

  • profiler/火焰图
  • options

九、Java Mission Control

JDK自带的工具,取样的方式比较优秀,对程序营销非常非常的小

十、其它工具

  • 火焰图:展示CPU时间分配的工具,改善接口性能,x轴是CUP时间,y轴是栈调用情况
  • Tprofiler:阿里提供的性能,能够定位性能瓶颈代码
  • Btrace:动态追踪java应用
  • YourKit、JProbe、Spring Insight等工具

http://chatgpt.dhexx.cn/article/W3BAYBaD.shtml

相关文章

Java 知识结构图

简介 《 值得去的地方&#xff0c;没有捷径&#xff1b;难走的路才更值得开始 》 为什么要说这个【知识结构图】呢&#xff0c;其实是针对于刚开始学习&#xff0c;工作或工作一段时间的人&#xff0c;每天忙&#xff0c;杂七杂八&#xff0c;自己身心巨累&#xff0c;又想要偷…

Java程序员必备基础结构图

前言 最近看了深入理解Java虚拟机第三版&#xff0c;整理了一些基础结构图&#xff0c;算是比较全的了&#xff0c;做一下笔记&#xff0c;大家一起学习。 1.Java虚拟机运行时数据区图 JVM内存结构是Java程序员必须掌握的基础。 程序计数器 程序计数器&#xff0c;可以看作…

JVM 结构图

一&#xff1a;Java技术体系模块图 二&#xff1a;JVM内存区域模型 1.方法区 也称"永久代” 、“非堆”&#xff0c; 它用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域。默认最小值为16MB&#xff0c;最大值为64MB&#xff0c;可以通过-XX:Per…

JVM结构、GC工作机制详解

题外话&#xff1a;最近在应聘阿里2015暑期实习&#xff0c;感触颇多。机会总是留给有准备的人的&#xff0c;所以平常一定要注意知识的巩固和积累。知识的深度也要有一定的理解&#xff0c;不比别人知道的多&#xff0c;公司干嘛选你&#xff1f;关于JVM和GC&#xff0c;我相信…

详解 JVM Garbage First(G1) 垃圾收集器

前言 Garbage First(G1)是垃圾收集领域的最新成果,同时也是HotSpot在JVM上力推的垃圾收集器,并赋予取代CMS的使命。如果使用Java 8/9,那么有很大可能希望对G1收集器进行评估。本文详细首先对JVM其他的垃圾收集器进行总结,并与G1进行了简单的对比;然后通过G1的内存模型、G1…

【JVM】JVM内存结构之——G1收集器

目录 1. 什么是G12. G1收集器发展历程3. G1收集器分区划分3.1 为什么G1收集器需要设计巨型对象3.2 G1收集器参数设置 3.3 G1收集器回收的细节3.4 G1收集器Rset问题&#xff08;记忆集&#xff09;3.5 G1两种回收策略4. G1收集器优缺点 5. G1收集器核心配置参数 1. 什么是G1 G1…

Visual Studio C# WinForm开发入门(5):TabControl 控件使用

TabContrl选项卡控件可创建标签化窗口&#xff0c;在实际 编程中经常用到&#xff0c;该控件的作用是将相关的组件组合到一系列选项卡页面上。 比如下面的例子&#xff0c;在tabPage1页面和tabPage2页面各放了2个checkBox控件&#xff0c;通过点击不同page即可切换&#xff1a;…

WPF自定义TabControl样式

WPF自定义TabControl样式 原文: WPF自定义TabControl样式 WPF自定义TabControl&#xff0c;TabControl美化 XAML代码&#xff1a; <TabControl x:Class"SunCreate.Common.Controls.TabControlEx"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/present…

C# WinForm TabControl美化

窗口Load加下面代码&#xff0c;ItemSize根据自己显示文本长度调整 #region tabMainItem属性设置this.tabModuleMainItem.DrawMode TabDrawMode.OwnerDrawFixed;this.tabModuleMainItem.Alignment TabAlignment.Top;this.tabModuleMainItem.SizeMode TabSizeMode.Fixed;this…

浅谈C#tabcontrol应用

作为Winfrom开发者来说&#xff0c;我们很多时候会用到tabcontrol来实现和网页标签页相关的效果。同时微软自带的控件样式不符合我们的需求&#xff0c;我们该如何去实现更加美观且可以自定义的组合控件呢&#xff1f;带着这个问题进入我们今天的主题&#xff0c;组合控件tabco…

C# WPF TabControl控件用法详解

概述 TabControl我之前有讲过一节&#xff0c;内容详见&#xff1a; C# WPF TabControl用法指南(精品)&#xff0c;上节主要讲解了tabcontrol控件的左右翻页&#xff0c;以及页面筛选&#xff0c;以及数据绑定等内容&#xff0c;这节内容继续接续上节内容进行扩展讲解&#xff…

WPF 自定义控件TabControl

WPF 自定义控件TabControl 新TabControl效果&#xff1a; 新添加一个自定义控件ZTabControl&#xff1a; public class ZTabControl : TabControl{#region Private属性#endregion#region 依赖属性定义public static readonly DependencyProperty TypeProperty;#endregion#r…

Winform TabControl标签美化

前期工作&#xff1a; 加载资源文件&#xff0c;双击“Resources.resx" 类型选择Images 【添加资源】——【添加现有文件】 选择需要添加的图片文件&#xff0c;保存即可。 在下面的资源文件夹中即可看到添加的图片列表 **方法一&#xff1a;**重绘标签及背景 新建窗体…

WPF 自定义TabControl控件样式(转)

WPF 自定义TabControl控件样式 一、前言 程序中经常会用到TabControl控件&#xff0c;默认的控件样式很普通。而且样式或功能不一定符合我们的要求。比如&#xff1a;我们需要TabControl的标题能够居中、或平均分布&#xff1b;或者我们希望TabControl的标题能够进行关闭。要…

WPF TabControl 数据绑定

WPF TabControl in Binding’s world 首先&#xff0c;TabControl是间接继承自ItemControl的控件&#xff0c;因此可以像ItemControl那样自如的使用。 自此&#xff0c;我们知道了ItemControl的派生控件有&#xff1a; ItemControl–>Selector–>ListBox ItemControl…

WPF TabControl Styles

WPF TabControl Styles 水平使用的TabControl 效果&#xff1a; 样式资源 <!-- 顶部TabControl控件样式 --><SolidColorBrush x:Key"TabItem.Static.Background" Color"White"/><SolidColorBrush x:Key"TabItem.Static.Border&quo…

MFC tabcontrol切换界面

1.添加控件tabcontrol。 2.切换到资源界面->Dialog->插入Dialog&#xff0c;创建两个Dialog界面。 3.为新建的两个Dialog添加类&#xff0c;在新建的Dialog界面右键类向导添加对应的类。 4.添加TabSheet.cpp 和TabSheet.h 这两个文件从网上下载即可&#xff0c;具体源码如…

TabControl控件

点餐用到的控件&#xff1a; 1&#xff09;TabControl: 管理并向用户显示可以包含控件和组件的相关选项卡的信息 2&#xff09;ComboBox: 显示一个可编辑的文本框&#xff0c;其中包含一个允许值下拉列表 3&#xff09;DateTimePicker: 允许用户设定日期和时间&#x…

WPF 控件专题 TabControl控件详解

1、TabControl 介绍 TabControl 表示包含多个项的控件&#xff0c;这些项共享屏幕上的同一空间&#xff0c;每个区域都可以通过单击通常位于控件顶部的选项卡标题来访问。 也叫选项卡控件。 *******************************************************************************…

WPF 基础控件之 TabControl样式

其他基础控件 1.Window2.Button3.CheckBox4.ComboBox5.DataGrid 6.DatePicker7.Expander8.GroupBox9.ListBox10.ListView11.Menu12.PasswordBox13.TextBox14.RadioButton15.ToggleButton16.Slider 17.TreeView TabControl 实现下面的效果 1&#xff09;TabControl来实现动画&…