Java 虚拟机诊断利器

Java 虚拟机诊断利器

背景

======

最近学习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 次,然后看执行结果:

Java 虚拟机诊断利器

可以看到在 15 次调用 foo 方法后,第 16 次调用 foo 方法是走的 GeneratedMethodAccessor1 来调用的。我嘞个擦,怎么回事,调着调着就不一样了,于是跟代码,跟到了下面这个类:

Java 虚拟机诊断利器

其中这句代码就是对反射调用的次数做了控制

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(阿尔萨斯)了。

Java 虚拟机诊断利器

首先下载 arthas:

curl -O https://alibaba.github.io/arthas/arthas-boot.jar

然后启动 arthas:

java -jar arthas-boot.jar

启动之后界面长这个样子:

Java 虚拟机诊断利器

其中什么 23012, 28436 等是当前环境中现有的 java 进程,然后需要连接到哪个进程就输前面的编号(1234 啥的),输了之后回车。那么我首先改写一下最开始的那个程序,让他不退出:

package com.example.classstudy;

import java.lang.reflect.Method;

/**

  • @author TY

*/

public class ReflectionTest {

private static int count = 0;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值