当前位置: 首页 > news >正文

JVM调优与线上问题监控工具安利

JVM调优与线上问题监控工具

首先命令行输入java -version,查看本机的Java版本信息以及JVM相关信息

可以看到的Java8,HotSpot虚拟机,Client模式启动,混合编译模式

XXX>java -version
java version "1.8.0_251"
Java(TM) SE Runtime Environment (build 1.8.0_251-b08)
Java HotSpot(TM) Client VM (build 25.251-b08, mixed mode)

JVM运行参数

JVM的运行参数总的来说可以分为三类:

标准参数:

  • -help
  • -version
  • -server、-client

​ -server、-client 是设置JVM的运行模式的参数。JVM启动会根据硬件与操作系统自动选择运行模式:

  • 32位系统如果是Windows,无论其余硬件配置如何,都默认client模式,其余操作系统如果是2G以上内存并且有2个以上CPU,默认是server模式启动。
  • 64位操作系统默认server模式,不支持client

​ 之前在做GC测试的时候也介绍过,这两种运行模式的区别在于:

  • server模式启动时,堆空间可能默认大一点,JDK9以前默认是UseParallelGC,JDK9以后是UseG1GC。server模式启动慢,运行快
  • client模式初始化堆空间小,默认是UseSerialGC。client模式下,JVM启动速度更快,但是运行速度慢

-X参数(非标准参数),不同JVM版本可能不同。可以在命令行使用java -X命令查看。

  • -Xint、-Xcomp、-Xmixed,这三个参数是JVM启动时的编译模式,默认是mixed混合模式

-Xint:interpreted mode,解释器模式。编译与运行同时进行,在编译Java程序的时候一边编译一边执行,编译多少执行多少

-Xcomp:compile mode,编译模式。JVM在第一次使用时,会把所有的字节码编译成本地代码,即一次性编译完再使用,并且没有启用JIT编译器

-Xmixed:混合模式,解释器模式与编译模式混合使用,由JVM自己决定。

-XX参数(非标准参数,使用频率较高),主要用于jvm调优与debug操作。-XX参数使用有两种方式:

  • 一种是非boolean类型,即key-value

    格式是-XX:key=value,如:

    -XX:newRatio=1

  • 一种是boolean类型

    格式是-XX:[±],+表示启用,-表示禁用。如:

    -XX:+UseSerialGC

JDK四个调优工具

jinfo

jinfo是JDK自带的查看JVM配置参数的工具。

查看所有的JVM配置参数:

jinfo -flags [pid] 

如:

XXX> jinfo -flags 15628
Attaching to process ID 15628, please wait...
Debugger attached successfully.
Client compiler detected.
JVM version is 25.251-b08
Non-default VM flags: -XX:-BytecodeVerificationLocal -XX:-BytecodeVerificationRemote -XX:InitialHeapSize=16777216 -XX:+ManagementServer -XX:MaxHeapSize=268435456 -XX:MaxNewSize=89456640 -XX:MinHeapDeltaBytes=131072 -XX:NewSize=5570560 -XX:OldSize=11206656 -XX:TieredStopAtLevel=1 -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation
Command line: ....

如果只想查看单个:

jinfo -flag <name> [pid]

jstak

jstak命令可以查看编译统计,GC发生次数,以及加载的类数量。命令格式:

 jstat -<option> [-t] [-h<lines>] <vmid> [<间隔时间/ms> [<查询次数>]]

如查看编译统计:

XXX> jstat -compiler 18100
Compiled Failed Invalid   Time   FailedType FailedMethod
     126      0       0     0.06          0

查看加载类数量:

XXX> jstat -class 18100
Loaded  Bytes  Unloaded  Bytes     Time
  1365  1350.2        0

查看GC次数:

XXX> jstat -gc 18100
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
512.0  512.0  438.4   0.0    4416.0   2694.9   10944.0     899.3    4416.0 4309.8  0.0    0.0        2    0.006   0      0.000    0.006

S0C:survivor0区总共大小;S0U:survivor0区已用大小

S1C:survivor1区总共大小;S1U:survivor1区已用大小

EC:Eden区总大小;EU:Eden区已用大小

OC:老年代总大小;OU:老年代已用大小

MC:元空间总大小;MU:元空间已用大小

CCSC:压缩类空间容量 ;CCSU:压缩类已用空间大小

YGC:Minor GC/Young GC的次数;YGCT:Minor GC/Young GC停顿时间

FGC:FullGC次数;FGCT:FullGC停顿时间

GCT:GC总停顿时间

jmap

当前程序堆使用情况,命令格式:

    jmap [option] <pid>
        (to connect to running process) 查看当前程序
    jmap [option] <executable <core>
        (to connect to a core file)
    jmap [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)

jmap -heap

查看当前程序的堆情况,命令格式:

jmap -heap [pid]

jmap -histo

查看内存中对象数量及大小,命令格式:

jmap -histo:live [pid] | more 查看活跃对象,去掉live就是查看所有对象

jamp -dump

将当前内存的情况dump以二进制格式输出到文件,然后再配合日志分析工具进行分析,命令格式:

jmap -dump:format=b,file=dumpFileName

dump文件分析工具

jhat

我们可以利用jhat工具分析查看dump文件

在这里插入图片描述

MAT

除了jhat,我们也可以使用MAT,Memory Analyzer Tool,一个功能丰富的堆分析工具,可以帮忙查找内存泄露等问题,并可以通过报表的形式直观的看到那些对象在阻止垃圾回收,比如这样:

在这里插入图片描述

jstack

打印所有线程及其状态,是用来分析死锁的利器

在https://blog.csdn.net/qq_20952591/article/details/121428062,死锁的这一节也介绍过,这里就不再介绍了

监控工具

JVisualVM

​ JDK自带的性能检测工具,路径在%JAVA_HOME%/bin下面,是个JVM性能监控神器,功能包括:

  • 监控本地和远程的JAVA进程,包括监控内存、线程、方法执行时间
  • 对堆内存进行dump、快照
  • 性能可视化分析
  • 安装插件对堆外内存进行分析(我用Buffer Pool)

Btrace

​ Btrace是一种安全、动态跟踪分析一个运行中的Java应用程序的工具。 BTrace动态地向目标应用程序的字节码注入追踪代码(字节码追踪),这些追踪字节码追踪代码使用Java语言表达,也就是BTrace的脚本。

​ 安装btrace后需编写btrace脚本,功能包括:

​ 对生产环境下的代码进行监控调试,比如获取生产环境下某个方法的参数、返回值、异常、执行的行号等等。(Arthas也可以做,个人认为Arthas更牛逼点)

github:https://github.com/btraceio/btrace

Arthas

Arthas是阿里巴巴开源的一个性能监控神器,可以用来做:

1.线上修改代码(比如线上出bug了,但是忘记在关键地方输出日志,这个时候可以利用arthas的reset命令来增强类)

2.查看系统运行状况

3.监控JVM实时状况

4.定位应用热点,生成火焰图

5.监控指定方法的数据统计与观测

6.死锁监控

​ …

官方使用文档:https://arthas.aliyun.com/doc/

GC日志分析

GC参数设置

GC日志相关参数共一下几个:

-XX:+PrintGC:输出GC日志
-XX:+PrintGCDetails:输出GC详细日志
-XX:+PrintGCTimeStamps:输出GC的时间,这个时间是JMV启动时间偏移量
-XX:+PrintGCDateStamps:输出GC时间,
-XX:+PrintHeapAtGC:在GC前后打印出堆的详细信息
-Xloggc:将GC日志输出到指定文件

GC日志分析工具

GCEasy网站

我们可以将GC日志文件上传到https://gceasy.io/,GCEasy官网去分析

我的测试代码(是我之前测试软连接的测试代码,就是不断产生大对象):

    private static final int _4MB = 4 * 1024 * 1024;
@Test
    public void softReference() throws InterruptedException {
        System.out.println("=======================begin===============");
       // Thread.sleep(50000);
        List<SoftReference<byte[]>> list = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            System.out.println("==================i " + i +
                    "insert begin=======================");
            SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB]);
            System.out.println("=======================this is i " + i + "  " + ref.get()+
                    "=======================");
            list.add(ref);
            System.out.println("list = " + list.stream().map(SoftReference::get).collect(Collectors.toList()));
        }
        System.out.println("=======================循环结束=============");
        System.gc();
        System.out.println("list = " + list.stream().map(SoftReference::get).collect(Collectors.toList()));
    }

JVM参数:

-Xmx20m -XX:+PrintGCDetails -verbose:gc -Xloggc:D:/tmp/gc.log -XX:+PrintGCDateStamps

日志分析:

JVM内存情况:

在这里插入图片描述

一些关键指标,例如吞吐量、GC暂停时间等

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

详细的GC统计

在这里插入图片描述

对象状态,包括创建的对象大小、对象从新生代晋升到老年代的大小等。

在这里插入图片描述

还有很多,自己去网站上看一下吧,不一一介绍了。
官方网站:https://gceasy.io/

相关文章:

  • Kafka的事务实现
  • Kafka的高可靠性保证
  • Kafka集群
  • 线程池の优雅使用
  • 优雅的退出
  • 分布式架构演进
  • synchronized关键字
  • 分布式锁的几种实现方式
  • 延时队列的几种实现方式(只有原理,并没有源码)
  • DDD整理(概念篇)
  • DDD的分层架构设计
  • 面试记录之synchronized的惨败经历
  • 面试复盘整理
  • Go语言基础_数据类型、基本语法篇
  • Go学习笔记_环境搭建
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • 【挥舞JS】JS实现继承,封装一个extends方法
  • Android优雅地处理按钮重复点击
  • css选择器
  • Cumulo 的 ClojureScript 模块已经成型
  • JavaScript函数式编程(一)
  • Java-详解HashMap
  • Object.assign方法不能实现深复制
  • springMvc学习笔记(2)
  • Vue全家桶实现一个Web App
  • vue数据传递--我有特殊的实现技巧
  • 测试开发系类之接口自动化测试
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 扑朔迷离的属性和特性【彻底弄清】
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 深度学习在携程攻略社区的应用
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • Spring第一个helloWorld
  • 通过调用文摘列表API获取文摘
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • ​MySQL主从复制一致性检测
  • ​queue --- 一个同步的队列类​
  • ###C语言程序设计-----C语言学习(6)#
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (利用IDEA+Maven)定制属于自己的jar包
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (三分钟)速览传统边缘检测算子
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转)Mysql的优化设置
  • (转)关于如何学好游戏3D引擎编程的一些经验
  • **CI中自动类加载的用法总结
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • *2 echo、printf、mkdir命令的应用
  • .bat批处理出现中文乱码的情况
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .NET delegate 委托 、 Event 事件