• JVM工具


    性能监控工具

    jconsole

    JConsole工具是JDK自带的图形化性能监控工具。并通过JConsole工具, 可以查看Java应用程序的运行概况, 监控堆信息、 元空间使用情况及类的加载情况等。

    JConsole程序在%JAVA_HOM E%/bin目录下

    或者你可以直接在命令行对他进行打印

    image.png

    会显示如下界面:

    image.png

    JConsole的连接方式

    JConsole分为本地连接以及远程连接,一般我们本地连接在小型单体项目中用于本地分析较多,大型项目以及线上生产环境一般采用远程连接的方式。

    本地连接:

    Jconsole会在本地自动寻找当前的可监控进程,所以我们可以只要本地启动项目,就可以自动匹配并点击进去。

    image.png

    远程连接:
    1. 设置被监控的Java虚拟机启动的參数,一般的情况下,会有下面三个參数,各自是:

    -Dcom.sun.management.jmxremote.port=1090

    -Dcom.sun.management.jmxremote.ssl=false

    -Dcom.sun.management.jmxremote.authenticate=false

    也就是说,你需要在启动参数后面加上这几个参数

    image.png

    被监控的虚拟机启动以后,我们就能够其他电脑上通Jconsole进行远程连接。

    连接的过程例如以下:

    1.打开cmd,输入jconsole,就会出现jconsole控制台,

    然后,我们输入要被监控的Java虚拟机的IP地址和port号,如果输入正确,连接button就上生效如果设计的监控port号为8082,连接的IP为:10.20.618.11(这个需要你防火墙以及端口都处于开放状态),例如以下图所看到的:

    image.png

    点击连接后,就会进入到正常的显示界面,说明就连接成功了。

    JConsole的显示界面:

    image.png

    概述 :记录了“堆内存使用情况”、“线程”、“类”、“CPU使用情况”共四个资源的实时情况;

    image.png

    并且在时间范围可以选择从1分钟到1年的显示情况

    image.png

    内存 :可以选择查看“堆内存使用情况”、“非堆内存使用情况”、“内存池"PS Eden Space"”等内存占用的实时情况;界面右下角还有图形化的堆一级、二级、三级缓存(从左到右)占用情况,当然,如果三级缓存被全部占用也就是很可能内存溢出啦!这时可以去查看服务器的tomcat日志,应该会有“outofmemory"的异常日志信息。界面右上角处还提供了一个“执行GC”的手动垃圾收集功能,这个也很实用~而且界面下方还有详细的GC信息记录。,整个界面提供了关于垃圾收集必须的各项基础指标查询。

    image.png

    线程 :界面上部显示实时线程数目。下部还能查看到详细的每个进程及相应状态、等待、堆栈追踪等信息;

    image.png

    并且在右下角,我们还可以检测死锁的情况。如果当前线程没有出现死锁,那么会显示未出现死锁。

    image.png

    但是如果出现了死锁,这里也会进行相应的检测。会直接显示死锁的页面,并且我们可以通过点击对应的线程来查看死锁的信息。

    image.png

    :显示“已装入类的数目”、“已卸载类的数目”信息;

    image.png

    VM摘要 :显示服务器详细资源信息,包括:线程、类、OS、内存等;

    image.png

    image.png

    MBean : 可在此页进行参数的配置。

    MBean就是被JMX管理的资源。 一般有两种类型的MBean,标准的和动态的。 标准类型的MBean最简单,它能管理的资源(包括属性,方法,时间)必须定义在接口中,然后MBean必须实现这个接口。它的命名也必须遵循一定的规范,例如我们的MBean为User,则接口必须为UserMBean。 动态MBean必须实现javax.management.DynamicMBean接口,所有的属性,方法都在运行时定义。

    这个一般情况下互联网交互式企业级开发用到的可能性没有那么高。因为现在JMX架构用得没那么多。

    测试垃圾回收案例:

    package com.example.jvmcase.test;
    
    
    import com.google.common.collect.Lists;
    
    import java.util.ArrayList;
    
    public class JconsoleTest1 {
        //将bytes设置为全局变量
        public byte[] bytes = new byte[1024*1024];
        //测试内存的变化情况
        public static void main(String[] args) {
            try {
                Thread.sleep(3000);//为了能看到效果
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("开始..");
            fillHeap(1000);
        }
    
        public static void fillHeap(int count){
            ArrayList<JconsoleTest1> jts = Lists.newArrayList();
    
            for(int i=0;i<count;i++){
                try {
                    //这里睡3S,出效果
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                jts.add(new JconsoleTest1());
            }
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    监控JVM内存情况,发现持续不回收,内存持续上升。

    接下来,将bytes放进构造函数中,变成局部变量。如果没有使用的情况下,垃圾回收器是会光顾。现在再去看内存情况,发现内存在垃圾回收时候会形成波峰。

     public  JconsoleTest2(){
            //将bytes设置为局部变量
            byte[] bytes = new byte[1024 * 1024];
        }
    
    • 1
    • 2
    • 3
    • 4

    jvisualvm

    官网:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jvisualvm.html

    官方描述:

    Description
    Java VisualVM is an intuitive graphical user interface that provides detailed information about Java technology-based applications (Java applications) while they are running on a specified Java Virtual Machine (JVM). The name Java VisualVM comes from the fact that Java VisualVM provides information about the JVM software visually.
    
    Java VisualVM combines several monitoring, troubleshooting, and profiling utilities into a single tool. For example, most of the functionality offered by the standalone tools jmap, jinfo, jstat, and jstack were integrated into Java VisualVM. Other functionality, such as some that offered by the jconsole command, can be added as optional plug-ins.
    
    Java VisualVM is useful to Java application developers to troubleshoot applications and to monitor and improve the applications' performance. Java VisualVM enables developers to generate and analyze heap dumps, track down memory leaks, perform and monitor garbage collection, and perform lightweight memory and CPU profiling. You can expand the Java VisualVM functionality with plug-ins. For example, most of the functionality of the jconsole command is available through the MBeans Tab and JConsole Plug-in Wrapper plug-ins. You can choose from a catalog of standard Java VisualVM plug-ins by selecting Tools and then Plugins in the Java VisualVM menus.
    
    Start Java VisualVM with the following command:
    
    %  jvisualvm 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    大致意思:

    Java VisualVM 是一个直观的图形用户界面,可在基于 Java 技术的应用程序(Java 应用程序)在指定的 Java 虚拟机 (JVM) 上运行时提供有关它们的详细信息。

    Java VisualVM 将多个监控、故障排除和分析实用程序组合到一个工具中。例如,独立工具jmap、jinfo和提供jstat,的大部分功能jstack都集成到 Java VisualVM 中。其他功能,例如jconsole命令提供的一些功能,可以作为可选插件添加。

    Java VisualVM 对于 Java 应用程序开发人员对应用程序进行故障排除以及监控和改进应用程序的性能非常有用。Java VisualVM 使开发人员能够生成和分析堆转储、跟踪内存泄漏、执行和监视垃圾收集以及执行轻量级内存和 CPU 分析。

    使用以下命令启动 Java VisualVM:

    % jvisualvm <选项>

    监控本地Java进程

    可以监控本地的java进程的CPU,类,线程等

    监控远端Java进程

    (1)在visualvm中选中“远程”,右击“添加”

    (2)主机名上写服务器的ip地址,比如39.100.39.63,然后点击“确定”

    (3)右击该主机"39.100.39.63",添加“JMX”,也就是通过JMX技术具体监控远端服务器哪个Java进程

    (4)要想让服务器上的tomcat被连接,需要改一下Catalina.sh这个文件

    注意下面的8998不要和服务器上其他端口冲突

    JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -
    Djava.rmi.server.hostname=39.100.39.63 -Dcom.sun.management.jmxremote.port=8998
    -Dcom.sun.management.jmxremote.ssl=false -
    Dcom.sun.management.jmxremote.authenticate=true -
    Dcom.sun.management.jmxremote.access.file=../conf/jmxremote.access -
    Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    (5)在…/conf文件中添加两个文件jmxremote.access和jmxremote.password

    jmxremote.access

    guest readonly
    manager readwrite
    
    • 1
    • 2

    jmxremote.password

    guest guest
    manager manager
    
    • 1
    • 2

    授予权限:chmod 600 jmxremot

    (6)将连接服务器地址改为公网ip地址

    hostname -i   查看输出情况
    	172.26.225.240 172.17.0.1
    vim /etc/hosts
    	172.26.255.240 39.100.39.63
    
    • 1
    • 2
    • 3
    • 4

    (7)设置上述端口对应的阿里云安全策略和防火墙策略

    (8)启动tomcat,来到bin目录

    ./startup.sh
    
    • 1

    (9)查看tomcat启动日志以及端口监听

    tail -f ../logs/catalina.out
    lsof -i tcp:8080
    
    • 1
    • 2

    (10)查看8998监听情况,可以发现多开了几个端口

    lsof -i:8998    得到PID
    netstat -antup | grep PID
    
    • 1
    • 2

    (11)在刚才的JMX中输入8998端口,并且输入用户名和密码则登录成功

    端口:8998
    用户名:manager
    密码:manager
    
    • 1
    • 2
    • 3

    arthas

    github:https://github.com/alibaba/arthas

    Arthas allows developers to troubleshoot production issues for Java
    applications without modifying code or restarting servers.
    
    • 1
    • 2

    Arthas 是Alibaba开源的Java诊断工具,采用命令行交互模式,是排查jvm相关问题的利器。

    3.3.3.1 下载安装

    curl -O https://alibaba.github.io/arthas/arthas-boot.jar
    java -jar arthas-boot.jar
    or 
    java -jar arthas-boot.jar -h
    # 然后可以选择一个Java进程
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.3.3.2 常用命令

    具体每个命令怎么使用,大家可以自己查阅资料

    version:查看arthas版本号
    help:查看命名帮助信息
    cls:清空屏幕
    session:查看当前会话信息
    quit:退出arthas客户端
    ---
    dashboard:当前进程的实时数据面板
    thread:当前JVM的线程堆栈信息
    jvm:查看当前JVM的信息
    sysprop:查看JVM的系统属性
    ---
    sc:查看JVM已经加载的类信息
    dump:dump已经加载类的byte code到特定目录
    jad:反编译指定已加载类的源码
    ---
    monitor:方法执行监控
    watch:方法执行数据观测
    trace:方法内部调用路径,并输出方法路径上的每个节点上耗时
    stack:输出当前方法被调用的调用路径
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    内存分析工具

    MAT(Memory Analyzer Tool)

    MAT是一款非常强大的内存分析工具,在Eclipse中有相应的插件,同时也有单独的安装包。在进行内存分析时,只要获得了反映当前设备内存映像的hprof文件,通过MAT打开就可以直观地看到当前的内存信息。一般说来,这些内存信息包含:

    • 所有的对象信息,包括对象实例、成员变量、存储于栈中的基本类型值和存储于堆中的其他对象的引用值。
    • 所有的类信息,包括classloader、类名称、父类、静态变量等
    • GCRoot到所有的这些对象的引用路径
    • 线程信息,包括线程的调用栈及此线程的线程局部变量(TLS)

    那么接下来 我们可以尝试去分析一下内存泄漏场景:

    package com.example.jvmcase.controller;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    
    @RestController
    public class TLController {
        @GetMapping(value = "/tl")
        public String tl(HttpServletRequest request) {
            ThreadLocal<Byte[]> tl = new ThreadLocal<Byte[]>();
            tl.set(new Byte[1024 * 1024]);
            return "ok";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这个代码中,很明显我们的代码没有去进行remove,所以会造成内存泄漏。而内存泄漏的堆积会导致内存溢出。所以我考虑用这个场景进行分析。

    项目启动参数

    -Xms100M -Xmx100M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=jvm.hprof 
    
    • 1

    这个时候hprof文件导出,一般生产环境中,我们的要考虑远程导出可能会导致系统卡断或者直接宕机。或者dump出的文件特别大,这个时候需要设置内存。

    需要在mat目录下的MemoryAnalyzer.ini文件种改一下配置,最大占用内存设大一点,Xmx参数

     -Xmx10240M            这个数字根据你文件大小设置
    
    • 1

    设置后重启生效

    手动转储

    jmap -histo:live PID | more
    获取到jvm.hprof文件,上传到指定的工具分析,比如MAT
    
    • 1
    • 2

    heaphero

    https://heaphero.io/

    perfma

    笨马是一个JVM调优工具,甚至会给你相应的JVM调优建议,但是他是一个收费工具,不过如果你仅仅是希望调优参数,可以使用试用版。但是他的调优建议都是简单的参数设置。

    https://console.perfma.com/

    日志分析工具

    要想分析日志的信息,得先拿到GC日志文件才行,所以得先配置一下,根据前面参数的学习,下面的配置很容易看懂。比如打开windows中的catalina.bat,在第一行加上

    XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps 
    -Xloggc:$CATALINA_HOME/logs/gc.log
    
    • 1
    • 2

    不同收集器日志

    这样使用startup.bat启动tomcat的时候就能够在当前目录下拿到gc.log文件,可以看到默认使用的是ParallelGC。

    (1)Parallel GC

    【吞吐量优先】

    2019-06-10T23:21:53.305+0800: 1.303: [GC (Allocation Failure) [PSYoungGen: 65536K[Young区回收前]->10748K[Young区回收后](76288K[Young区总大小])] 65536K[整个堆回收前]->15039K[整个堆回收后](251392K[整个堆总大小]), 0.0113277 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
    
    • 1

    注意如果回收的差值中间有出入,说明这部分空间是Old区释放出来的

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mQU2D4yj-1661400923383)(images/54.png)]

    (2)CMS

    【停顿时间优先】

    参数设置:-XX:+UseConcMarkSweepGC -Xloggc:cms-gc.log
    
    • 1

    重启tomcat获取gc日志,这里的日志格式和上面差不多,不作分析。

    (3)G1

    G1日志格式参考链接:https://blogs.oracle.com/poonam/understanding-g1-gc-logs

    【停顿时间优先】

    参数设置:-XX:+UseG1GC -Xloggc:g1-gc.log
    
    • 1
    -XX:+UseG1GC  # 使用了G1垃圾收集器
    
    # 什么时候发生的GC,相对的时间刻,GC发生的区域young,总共花费的时间,0.00478s,
    # It is a stop-the-world activity and all
    # the application threads are stopped at a safepoint during this time.
    2019-12-18T16:06:46.508+0800: 0.458: [GC pause (G1 Evacuation Pause)
    (young), 0.0047804 secs]
    
    # 多少个垃圾回收线程,并行的时间
    [Parallel Time: 3.0 ms, GC Workers: 4]
    
    # GC线程开始相对于上面的0.458的时间刻
    [GC Worker Start (ms): Min: 458.5, Avg: 458.5, Max: 458.5, Diff: 0.0]
    
    # This gives us the time spent by each worker thread scanning the roots
    # (globals, registers, thread stacks and VM data structures).
    [Ext Root Scanning (ms): Min: 0.2, Avg: 0.4, Max: 0.7, Diff: 0.5, Sum: 1.7]
    
    # Update RS gives us the time each thread spent in updating the Remembered
    Sets.
    [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
    ...
    
    # 主要是Eden区变大了,进行了调整
    [Eden: 14.0M(14.0M)->0.0B(16.0M) Survivors: 0.0B->2048.0K Heap:
    14.0M(256.0M)->3752.5K(256.0M)]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PwZPR4ex-1661400923384)(images/55.png)]image.png

    GCViewer

    java -jar gcviewer-1.36-SNAPSHOT.jar

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k707wOuU-1661400923384)(images/56.png)]image.png

    gceasy

    http://gceasy.io

    image.png

    image.png

    gcplot

    https://it.gcplot.com/

    这个是young区的信息

    image.png

    课程章节总结:

    1.JVM之走进类加载

    你了解类加载嘛

    装载 链接 初始化

    类加载器 双亲委派 三大特性 以及打破双亲委派 SPI

    2.JVM之深入运行时数据区

    栈帧 要把运行时数据区跟其他知识结合起来

    3.对象的内存布局

    指针压缩问题:

    4.内存模型以及对象已死问题

    面试问到对象生命周期即可 第三方的图片缓存 图片缓存导致内存泄漏

    5.垃圾回收算法

    动态分配规则 常规的三大垃圾回收算法 整理算法 分代回收三大假说

    6.垃圾收集器浅析

    常用参数 以及常规的垃圾收集器

    7.CMS垃圾收集器

    • CMS的两种模式与一种特殊策略
    • 可中止的预处理
    • 三色标记
    • CMS的参数调优

    8.G1垃圾收集器

    Rset三大数据类型

    G1特性

    G1参数

    9.G1垃圾收集器(下)

    三大回收流程

    10.ZGC深入解析

    ZGC三大核心技术

    ZGC垃圾回收触发时机

    11.JVM命令以及执行引擎

    JVM的分层编译5大级别:

    code cache

    12.JVM的性能优化

    案例优化 你要找到一个高并发的案例

    13.JVM常见工具使用

    监控工具

    内存分析

    日志分析

    1. 有一个50万PV的资料类网站(从磁盘提取文档到内存)原服务器32位,1.5G 的堆,用户反馈网站比较缓慢,因此公司决定升级,新的服务器为64位,16G 的堆内存,结果用户反馈卡顿十分严重,反而比以前效率更低了
    2. 为什么原网站慢?
      很多用户浏览数据,很多数据load到内存,内存不足,频繁GC,STW长,响应时间变慢
    3. 为什么会更卡顿?
      内存越大,FGC时间越长
    4. 咋办?
      PS -> PN + CMS 或者 G1
    5. 系统CPU经常100%,如何调优?(面试高频)
      CPU100%那么一定有线程在占用系统资源,
    6. 找出哪个进程cpu高(top)
    7. 该进程中的哪个线程cpu高(top -Hp)
    8. 导出该线程的堆栈 (jstack)
    9. 查找哪个方法(栈帧)消耗时间 (jstack)
    10. 工作线程占比高 | 垃圾回收线程占比高
    11. 系统内存飙高,如何查找问题?(面试高频)
    12. 导出堆内存 (jmap)
    13. 分析 (jhat jvisualvm mat jprofiler … )

    如果面试官问你是怎么定位OOM问题的?如果你回答用图形界面(错误)
    1:已经上线的系统不用图形界面用什么?(cmdline arthas)
    2:图形界面到底用在什么地方?测试!测试的时候进行监控!(压测观察)

  • 相关阅读:
    与“客户”沟通技巧
    如何使用Arduino构建3D打印的电子动画眼睛
    2023年亚太杯数学建模亚太赛B题思路解析+代码+论文
    Python:实现factorial recursive阶乘递归算法(附完整源码)
    MVC第三波书店购物车展示页面
    C++回顾<二>:类-this指针-构造函数-析构函数-隐式/显式调用explicit-初始化列表 -static静态成员变量/函数-常对象|常函数
    parallelStream并行流性能
    【遗传算法】【机器学习】【Python】常见交叉方法(一)、单点交叉和两点交叉
    使用.net 构建 Elsa Workflow
    【配电变电站的最佳位置和容量】基于遗传算法的最优配电变电站放置(Matlab代码实现)
  • 原文地址:https://blog.csdn.net/w1lgy/article/details/126521899