JVM监控之图形化工具

一、工具概述

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

  • 无法获取方法级别的分析数据,如方法之间的调用关系、各方法的调用次数和调用时间等
  • 要去用户登陆到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 = false
            hs.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;
        }
    
        @Override
        public int hashCode(){
            final int prime = 31;
            int result = 1;
            result = prime * result + x;
            return result;
        }
    
        @Override
        public 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等工具
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值