共计 2336 个字符,预计需要花费 6 分钟才能阅读完成。
作者 | 小白一只
【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:
curl -O https://alibaba.github.io/arthas/arthas-boot.jar
而后启动 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 等技术畛域、聚焦云原生风行技术趋势、云原生大规模的落地实际,做最懂云原生开发者的公众号。”