Java 虚拟机诊断利器
作者 | 小白一只
【Arthas 官方社区正在举行征文活动,参加即有奖品拿~点击投稿】
背景
最近学习Java字节码过程中遇到了反射,有段代码是这样的:
package com.example.classstudy; import java.lang.reflect.Method; /** * @author TY */ public class ReflectionTest { private static int count = 0; public static void foo() { new Exception("test#" + (count++)).printStackTrace(); } public static void main(String[] args) throws Exception { Class<?> clz = Class.forName("com.example.classstudy.ReflectionTest"); Method method = clz.getMethod("foo"); for (int i = 0; i < 20; i++) { method.invoke(null); } } }
就是一段简单的反射调用 foo 方法,执行 20 次,然后看执行结果:
可以看到在 15 次调用 foo 方法后,第 16 次调用 foo 方法是走的 GeneratedMethodAccessor1 来调用的。我嘞个擦,怎么回事,调着调着就不一样了,于是跟代码,跟到了下面这个类:
其中这句代码就是对反射调用的次数做了控制
if (++this.numInvocations > ReflectionFactory.inflationThreshold() && !ReflectUtil.isVMAnonymousClass( this.method.getDeclaringClass())) { MethodAccessorImpl var3 = (MethodAccessorImpl) (new MethodAccessorGenerator()) .generateMethod(this.method.getDeclaringClass(), this.method.getName(), this.method.getParameterTypes(), this.method.getReturnType(), this.method.getExceptionTypes(), this.method.getModifiers()); this.parent.setDelegate(var3); }
this.numInvocations 的默认值是 0,而 ReflectionFactory.inflationThreshold() 默认是 15,当大于 15 的时候会通过 ASM 技术动态生成 GeneratedMethodAccessor1 类来调用 invoke 方法,但是,因为是动态生成的,我们怎么才能看到这个类实际长什么样子呢?
Arthas
这个时候,就可以用上阿里的 arthas(阿尔萨斯)了。
首先下载 arthas:
然后启动 arthas:
java -jar arthas-boot.jar
启动之后界面长这个样子:
其中什么 23012, 28436 等是当前环境中现有的 java 进程,然后需要连接到哪个进程就输前面的编号(1234 啥的),输了之后回车。那么我首先改写一下最开始的那个程序,让他不退出:
package com.example.classstudy; import java.lang.reflect.Method; /** * @author TY */ public class ReflectionTest { private static int count = 0; public static void foo() { new Exception("test#" + (count++)).printStackTrace(); } public static void main(String[] args) throws Exception { Class<?> clz = Class.forName("com.example.classstudy.ReflectionTest"); Method method = clz.getMethod("foo"); for (int i = 0; i < 20; i++) { method.invoke(null); } System.in.read(); } }
重新启动程序之后,查看 arthas 界面:
可以看到 32480 正是我们运行的程序,输入编号 2 去连接到该进程:
然后就可以将动态生成的类 dump 下来:
dump sun.reflect.GeneratedMethodAccessor1
可以看到字节码被 dump 下来了,找到该文件用 javap 来查看:
javap -c -v -p -l GeneratedMethodAccessor1.class
没有问题,可以查看到,然后剩下的就是人肉翻译字节码啦。。。
本篇关于Arthas的使用其实很少,我只是因为学到这个地方简单的用了下,但是已经感受到了 Arthas 的强大之处,它甚至还支持 web 界面。。。
相当厉害!
Arthas 征文活动火热进行中
Arthas 官方正在举行征文活动,如果你有:
- 使用 Arthas 排查过的问题
- 对 Arthas 进行源码解读
- 对 Arthas 提出建议
- 不限,其它与 Arthas 有关的内容
欢迎参加征文活动,还有奖品拿哦~点击投稿
“阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Arthas 初探--安装初步适用
作者 | agmtopy 【Arthas 官方社区正在举行征文活动,参加即有奖品拿~点击投稿】 由于在项目中遇到一种情况,某段代码在进行单元测试和在 tomcat 容器中运行的性能相差数百倍,因此需要分析在不同环境下某个方法执行的具体时间,从而确定问题。Arthas 可以做到无侵入的监控应用远行情况。 安装 github 项目地址:https://github.com/alibaba/arthas 文档地址:alibaba.github.io/arthas/ 安装: wget https://alibaba.github.io/arthas/arthas-boot.jar java -jar arthas-boot.jar linux 下直接执行,window 下载文件后执行。 执行完成后,显示当前 path 中指定的 JDK 中正在运行的 java 进程输入相应序号,进入 sh 命令,表示已连接成功。 初步使用 Arthas 命令初步使用,大概分为 5 类: 基础命令 help——查看命令帮助信息 cat——打印文件内容,和 linux 里的 cat 命令类似 pwd——返回当前的工...
- 下一篇
5千字的SpringMVC总结,我觉得你会需要!
思维导图 微信公众号已开启:【java技术爱好者】,还没关注的记得关注哦~ 文章已收录到我的Github精选,欢迎Star:https://github.com/yehongzhi/learningSummary 概述 SpringMVC再熟悉不过的框架了,因为现在最火的SpringBoot的内置MVC框架就是SpringMVC。我写这篇文章的动机是想通过回顾总结一下,重新认识SpringMVC,所谓温故而知新嘛。 为了了解SpringMVC,先看一个流程示意图:从流程图中,我们可以看到: 接收前端传过来Request请求。 根据映射路径找到对应的处理器处理请求,处理完成之后返回ModelAndView。 进行视图解析,视图渲染,返回响应结果。 总结就是:参数接收,定义映射路径,页面跳转,返回响应结果。 当然这只是最基本的核心功能,除此之外还可以定义拦截器,全局异常处理,文件上传下载等等。 一、搭建项目 在以前的老项目中,因为还没有SpringBoot,没有自动配置,所以需要使用web.xml文件去定义一个DispatcherServlet。现在互联网应用基本上都使用SpringBoo...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- MySQL8.0.19开启GTID主从同步CentOS8
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker安装Oracle12C,快速搭建Oracle学习环境