死磕JVM (死磕到底)

技术教程 2025-05-13 10:00:07 浏览
死磕JVM

死磕JVM | 用Arthas排查JVM内存 真爽!

2021-06-01 09:29:43Arthas 是Alibaba开源的Java诊断工具,采用命令行交互模式,提供了较为丰富的功能,主要还是他是免费里面的算是好用且功能比较强大的一个JVM排查的插件,在了解这个利器之后,发现还是挺好用的,而且支持的功能也比较全面,那么Arthas到底可以为我们做哪些事情呢?

Arthas是啥

当我们系统遇到JVM或者内存溢出等问题的时候,如何对我们的程序进行有效的监控和排查,就发现了几个比较常用的工具,比如JDK自带的 jconsole、jvisualvm还有一个最好用的工具——jprofiler,但是这个是收费的,或者除了很有钱的公司,一般很少人会用这个,还有一个就是我们今天的主角——Arthas ,为什么今天会重点讲这个呢?

官网地址:

GitHub地址:

Arthas 是Alibaba开源的Java诊断工具,采用命令行交互模式,提供了较为丰富的功能,主要还是他是免费里面的算是好用且功能比较强大的一个JVM排查的插件,在了解这个利器之后,发现还是挺好用的,而且支持的功能也比较全面,那么Arthas到底可以为我们做哪些事情呢?

1.提供性能看板,包括线程、cpu、内存等信息,并且会定时的刷新。

2.根据各种条件查看线程快照。找出cpu占用率最高的n个线程

3.输出jvm的各种信息,如gc算法、jdk版本、ClassPath等

4.遇到问题无法在线上 debug,热部署加日志直接替换

5.查看某个类的静态属性,也可以通过ognl语法执行一些语句

6.查看已加载的类的详细信息,这个类从哪个jar包加载的,查看类的方法的信息

7.dump 类的字节码到指定目录

8.直接反编译指定的类

9.快速定位应用的热点,生成火焰图

10.可以监控到JVM的实时运行状态

以前,你碰到这些问题,解决的办法大多是,修改代码,重新上线。但是在大公司里,上线的流程是非常繁琐的,如果为了多加一行日志而重新发布版本,无疑是非常折腾人的。但是阿里巴巴开源的Arthas 有了更为优雅的线上调试方法。

Arthas 支持JDK6,同时可以在 Linux/Mac/Windows上运行,自动Tab 补全功能,更方便我们定位问题和诊断

下载地址:你可以下载zip的包我下载的是arthas-packaging-3.5.0-bin.zip 或者通过命令去下载

wget

使用手册

1. 快速启动

当我们下载好之后,我们直接通过命令启动就可以java -jar arthas-Boot.jar,但是在此之前我们需要通过检测的代码来挂靠到Arthas上面

这个是上篇文章讲述的案例,感兴趣的可以了解一下。

首先我们需要使用javac 命令将Java文件进行编译javac FullGCTest.java进行编译,然后打印GC日志,进行风险监控打印GC日志:

Arthas启动命令:java -jar arthas-boot.jar,get一下

我们就看到了我们刚才启动的FullGCTest的应用程序,我们输入编号 1 回车,这样我们就把Arthas挂靠到我们的程序上,接下来我们只需要做对应的命令操作就可以了

命令详情文档:

2. 功能列表

死磕到底
命令 详细说明
查看当前JVM信息
查看当前JVM的线程堆栈信息
方法执行数据观测
当前系统的实时数据面板
方法内部调用路径,并输出方法路径上的每个节点上耗时
输出当前方法被调用的调用路径
方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
查看,更新JVM已加载的类信息
查看JVM已加载的类信息
查看已加载类的方法信息
反编译指定已加载类的源码
classloader 查看classloader的继承树,urls,类加载信息
类似jmap命令的heap dump 功能

OPERATING-SYSTEM:系统相关参数

THREAD相关:

FILE-DESCRIPTOR(文件描述符相关):

thread 命令

参数说明:

命令 详细说明
线程id
指定最忙的前N个线程并打印堆栈
找出当前阻塞其他线程的线程
指定cpu使用率统计的采样间隔,单位为毫秒,默认值为200
显示所有匹配的线程

打印当前最忙的N个线程并打印堆栈

thread 查看所有线程

thread 17:显示指定线程的运行堆栈

thread -i: 指定采样时间间隔

thread -i 1000 : 统计最近1000ms内的线程CPU时间。thread -n 3 -i 1000 : 列出1000ms内最忙的3个线程栈

dashboard 命令

运行程序时,会显示当前程序的实时信息,如qps, rt, 错误数, 线程池信息等等

数据说明:

参数说明:

参数名称 详细说明
刷新实时数据的时间间隔 (ms),默认5000ms
刷新实时数据的次数

sc 命令

查看JVM已加载的类信息,通过SC我们可以看到我们这个类的详细信息,包括是从哪个jar包读取的,他是不是接口/枚举类等,甚至包括他是从哪个类加载器加载的。

参数说明:

参数名称 详细说明
class-pattern 类名表达式匹配
method-pattern 方法名表达式匹配
开启正则表达式匹配,默认为通配符匹配

sc -d *CardInfo:打印类的详细信息

sc -d -f *CardInfo:打印类的Fiedld信息

heapdump + jhat分析

heapdump:类似于jmap命令

创建到指定文件夹下:

创建成功后,我们就可以在指定文件夹下看到对应的dump文件,然后使用命令jhat dump.hprof,生成文件,成功后我们就可以通过IP+端口进行访问了

访问:

然后我们就可以通过IP+端口去访问它了,里面有个他的other,我们拉到最底下,找

Show instance counts for all classes (including platform)

从下面我们可以分析出来哪个类包含的对象最多,分析出来哪个类产生的对象

这个里面最强大的功能还是叫做 Execute Object Query Language (OQL) query,这个里面可以显示有哪些对象,对象有多少个字节和引用,可以观察到哪个对象产生了问题,如下图所示,显示所有String对应的对象

搜索点进去之后我们还能看到这个对象到底占用了多少个字节,有多少个引用指向了这个Object,这个OQL的语法也是很灵活,我们可以使用where条件去过滤

jad:反编译某个类,或者反编译某个类的某个方法,动态代理生成类的问题定位 第三方的类(观察代码) 版本问题(确定自己最新提交的版本是不是被使用)

有人可能会问这个有啥用,源码我不是自己就知道吗?因为有时我们经常会不确定线上或者测试环境的包是否是我们修改过的,这时候就可以通过jad反编译来看下,是否是最新的代码

redafine:热替换,动态更新代码,不用重启jvm目前有些限制条件:只能改方法实现(方法已经运行完成),不能改方法名, 不能改属性 m() -> mm()

比如我们在线上环境有个class确认有问题,想要重新替换,一般情况下只能停掉 服务器 重新发布,在普通的小公司这样是可以的,但是在大规模公司京东淘宝这样的是不能停的,因为整个流程是非常复杂的,那怎么办呢?大家可以看到下面的案例

首先我们新建一个测试案例:

使用命令javac *.java,编译成class文件,然后运行 T 文件

当我们输入a的时候打印2,但是我们上线以后才发现,我们需要输出的1,这个是如果要从本地更改要重新发布上线,为了这一个修改,明显是不值当的,但是如果我们用 redafine 热部署就可以帮助我们直接替换,不用重新发布jvm

然后我们将 T 这个程序挂靠到 Arthas 上面去

然后我们直接修改 TT.java 程序 vi TT.java,将里面打印2的值修改成1

然后编译执行 javac TT.java文件

在回到我们挂靠的Arthas 上面执行 redefine /usr/local/mxn/fuccGc/t/TT.class文件

执行成功 大家可以看到我们在没有重新启动的情况下成功替换了class文件图片

watch:方法执行的数据观测,可以通过watch指令,来监控某个类,监控后,运行下你的功能,复现下场景,arthas会提供给你具体的出参和入参,帮助你排查故障

输出方法调用路径,并输出耗时,这个指令对于优化代码非常的有用,可以看出具体每个方法执行的时间,如果是for循环等重复语句,还能看出n次循环中的最大耗时,最小耗时,和平均耗时,完美!

在我们对某个方法开启tt后,会记录每一次调用(我们可以设置最大监控次数)的入参和返回参数,并能对这些不同时间下调进行观测

命令参数解析-t tt 命令有很多个主参数,-t 就是其中之一。这个参数的表明希望记录下类 *Test 的 print 方法的每次执行情况。-n 3 当你执行一个调用量不高的方法时可能你还能有足够的时间用 CTRL+C 中断 tt 命令记录的过程,但如果遇到调用量非常大的方法,瞬间就能将你的 JVM 内存撑爆。

此时你可以通过 -n 参数指定你需要记录的次数,当达到记录次数时 Arthas 会主动中断tt命令的记录过程,避免人工操作无法停止的情况。

ognl表达式

ognl表达式

OGNL特殊用法请参考:OGNL表达式官方指南:

调用静态函数:ognl ‘@[emailprotected](“hello”)’方法 获取静态类的静态字段:ognl ‘@FullGCTest@random’方法

Arthas还支持Web Console,详见:

总结

Arthas是一个线上Debug神器,相比于其他工具,Arthas有着比较全面的功能,上手也比较容易,对于刚开始入门的小伙伴也是可以轻松掌握的,对于文中有不懂或者有问题的小伙伴,大家可以在下面留言评论。


计算机语言分类

计算机高级编程语言按其程序的执行方式可以分为两种:编译型,解释型 1.编译型语言是指使用专门的编译器、针对特定平台(操作系统)将某种高级语言源程序一次性“翻译”成可被该平台硬件运行的机器码(包括指令和操作数),并包装成该平台的操作系统所能识别和运行的格式。 这种语言的程序执行时效率高,可以脱离开发环境独立运行,但如果要移植必须修改源程序,或者针对不同的平台采用不同的编译器进行重新编译。 现在的多试高级语言,如c,c++,Pascal,LISP等都是编译型的。 2.解释型是指用专门的解释器将某种高级语言源程序逐条解释成特定平台的机器码指令并立即执行,解释一句执行一句,而不进行整体的编译和链接处理。 语言是解释型和编译型的结合,先采用通用的java编译器将java源程序编译成为与平台无关的中间产物,然后利用java虚拟机(JVM:Java Virtual Maching)进行解释执行。

java编程语言有哪些特点

Java是一种跨平台,适合于分布式计算环境的面向对象编程语言。 具体来说,它具有如下特性:简单性、面向对象、分布式、解释型、可靠、安全、平台无关、可移植、高性能、多线程、动态性等。 Java有许多值得称道的优点,如简单、面向对象、分布式、解释性、可靠、安全、结构中立性、可移植性、高性能、多线程、动态性等。 Java摈弃了C++中各种弊大于利的功能和许多很少用到的功能。 Java可以运行与任何微处理器,用Java开发的程序可以在网络上传输,并运行于任何客户机上。 希望能帮到你

详细的比较一下Java和C/C++的优劣

我觉得这是刚接触编程同学的一个通病,就是比来不去,其实,这两种编程语言大厅相同,你学好了那一种,钻研了那一种,都会受益匪浅,应该把思考这些问题的时间去用来多思考一下怎样去学习。 下边说一下区别吧:1,最大的区别:比较明显的是C++能被操作系统(Window,Linux)直接运行,而Java不行,需要有个JVM.也就是说,java编译好的文件需要通过jvm来让操作系统运行。 jvm可以安装到任何系统。 2:JAVA的应用在高层,C++在中间件和底层…… JAVA离不开业务逻辑,而C++可以离开业务为JAVA们服务…… JAVA的一堆框架,一堆中间件,我们都只能跟在后头,除非你是greate master!而C++可以创造出属于自己的东西,尽管不是那种greate master. 3:还有一点就是效率问题:JAVA更注重于面向对象的思想(为了完全面向对象,可以适当的牺牲效率),面向对象使复杂的事情简单化而C++更注重于效率(为了更好的效率,可以适当的牺牲面向对象) ,所以C++更复杂一些。 希望这些对你有用。

本文版权声明本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系本站客服,一经查实,本站将立刻删除。

发表评论

热门推荐