头图

监控jvm工具:visualVM

[TOC]

为什么要监控jvm

众所周知,jvm(java virtual mechine)是java的精髓

秉持着“一次编码,到处运行”的设计理念,可以说jvm让java在90年代火到了21世纪至今

由c++开发的jvm,它巧妙地设计了java的设计理念——即万物皆对象。并设计了这些对象应该如何存储,如何调用,并通过不断迭代设计让对象的存储和回收,执行更加合理,下图是jvm的发展历程。

image.png

时至今日,jvm这种“虚拟机”设计来运行的语言和生态仍然丰富。比如Kotlin,Groovy,JRuby(也就是说java可能会老,但jvm不会)。

也许开发者未必精通jvm,但对jvm的深入了解可以对开发,排错,调优有非常大的帮助。这里给出最基本的 jvm 入门知识,也是你监控 jvm并期待通过分析jvm来排错调优所必要的基础知识:

  • 堆(Heap):

    • 堆是用于存储对象实例的内存区域。在堆中分配的对象包括通过 new 关键字创建的对象以及数组。
    • 所有线程共享堆,但每个对象都有一个标识它的引用。
  • 栈(Stack):

    • 栈用于存储方法的局部变量、操作数栈、方法返回地址等。每个线程都有自己的栈。
    • 每个方法在执行时都会创建一个栈帧,栈帧包含了该方法的局部变量表、操作数栈、动态链接、方法返回地址等信息。
  • 程序计数器(Program Counter):

    • 程序计数器是每个线程私有的,用于存储当前线程执行的字节码指令的地址或索引。
    • 在多线程环境下,程序计数器用于记录每个线程执行的位置,确保线程切换后能够恢复到正确的执行位置。
  • 本地方法栈(Native Method Stack):

    • 本地方法栈类似于栈,但用于执行本地方法(非 Java 语言编写的方法)。
    • 本地方法栈的实现和栈类似,但用于执行本地代码。
  • 元空间(Metaspace):

    • 元空间是 JDK 8+ 版本中引入的(替代原来的方法区),使用本机内存存储类的元信息,包括类的结构信息、静态变量、方法信息等。
堆内提供垃圾回收,通过监视和清理不再使用的对象,释放内存空间,避免内存泄漏和提高程序性能

VisualVM分析

事实上,由于jvm的不断发展,官方(无论是jdk还是jvm)提供了很多命令和接口编程去帮助开发者监控jvm。

而其中本文详细介绍的VisualVM则是一款官方的,简单可视化的jvm监控工具。

下载安装

官网:https://visualvm.github.io/download.html

Q:如何汉化?

A:请从%JAVA_HOME%/bin下的jvisualvm.exe点击运行
image.png

快速上手

首先启动一个java程序(本地)

你可以查看本地和远程 Java 应用程序的列表

image.png
image.png

​ 点击该连接,可以看到该java程序的概述页,包括该进程的PID,主机ip,运行主类,jvm参数,jvm版本,JAVA_HOME等

image.png

点击《监视》页面,可以查看该进程的类,cpu,线程活动,堆占用情况。

在这里可以手动《执行垃圾回收》,jvm会对堆进行垃圾回收,它监视和清理不再使用的对象,释放内存空间,避免内存泄漏,以此提高程序性能。

image.png

可以看到这个进程设置堆内存为238,026,784B(200多M),最大堆设置为7xxx,堆内存已使用92,573,992B(92M)。

加载的类有15000多个,线程77个。其中活动线程为42个

tips:这里包括了springboot包和项目内部的线程和类。

堆分析

通过点击《堆dump》,可以生成堆的分析文件.hprof,

image.png

和很多软件和系统(如windows的bat,ps的psd,Android的apk)都会定制他们的格式一样,你不必管它如何打开,只需导入VisualVM即可查看文件内容

线程分析

通过点击《线程》,可以实时监控该进程的线程,如他们的状态,运行时间。

image.png

如线程之间发生了死锁,它会对你提醒。这里模拟一个死锁程序,如下所示Thread1和Thread0会发生死锁现象(可直接copy运行)

package com.xsrmall.portal;

public class DeadlockDemo {

    public static void main(String[] args) {
        // 创建两个资源对象
        Resource resource1 = new Resource("Resource 1");
        Resource resource2 = new Resource("Resource 2");

        // 创建并启动两个线程
        Thread thread1 = new Thread(() -> {
            try {
                resource1.method1(resource2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread thread2 = new Thread(() -> {
            try {
                resource2.method2(resource1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        thread1.start();
        thread2.start();
    }

    // 资源类
    static class Resource {
        private String name;

        public Resource(String name) {
            this.name = name;
        }

        // 获取资源1的锁,然后尝试获取资源2的锁
        public synchronized void method1(Resource otherResource) throws InterruptedException {
            System.out.println(name + " is holding " + name);
            Thread.sleep(100); // 模拟执行业务逻辑
            System.out.println(name + " is waiting for " + otherResource.name);
            otherResource.method2(this);
            System.out.println(name + " released " + otherResource.name);
        }

        // 获取资源2的锁,然后尝试获取资源1的锁
        public synchronized void method2(Resource otherResource) throws InterruptedException {
            System.out.println(name + " is holding " + name);
            Thread.sleep(100); // 模拟执行业务逻辑
            System.out.println(name + " is waiting for " + otherResource.name);
            otherResource.method1(this);
            System.out.println(name + " released " + otherResource.name);
        }
    }
}

image.png

你可以点击《线程dump》生成线程执行的日志。

image.png

如上所示,可以看到死锁线程和发生死锁的具体方法,这可以帮助开发者快速定位死锁问题。

tips: idea在执行这里旁边就有转储线程,
image.png
image.png

抽样器

类似vmWare的快照,它会对此时进程运行的cpu运行情况进行展示

image.png

可以看到这个本地的part方法占用了82%的总进程cpu时间。259s。

也可以对内存进行抽样,不再赘述。

Profiler

Profiler可以进行性能分析。目前笔者不需要这个就不看了,待更新。

事实上,VisualVM的很多执行都是去执行提供的类似jmap,jps,jmx规范等jvm/jdk命令

之后会写一篇jdk和jvm提供的监控jvm的命令或java对象。

参考:

https://www.cnblogs.com/liukaifeng/p/10052647.html

https://www.jianshu.com/p/bb4ba6612392

https://heapdump.cn/article/4481245

https://www.cnblogs.com/baby123/p/11551626.html

https://www.liaoxuefeng.com/wiki/1252599548343744/12823856876...

http://www.oracle.com/technetwork/java/javase/index-138283.html

https://visualvm.github.io/troubleshooting.html?Java_VisualVM

https://www.oracle.com/java/technologies/javase/troubleshooti...

https://www.51cto.com/article/704419.html


小薛cOde
4 声望1 粉丝

every day is a single day