Alibaba Java诊断工具Arthas查看Dubbo动态代理类
原创/朱季谦
阅读Dubbo源码过程中,会发现,Dubbo消费端在做远程调用时,默认通过 Javassist 框架为服务接口生成动态代理类,调用javassist框架下的JavassistProxyFactory类的getProxy(Invoker invoker, Class<?>[] interfaces)方法,动态生成一个存放在JVM中的动态代理类。
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
那么,问题来了,如果我们想要一睹该动态生成的代理类内部结构是怎样的,如何才能便捷做到的?
这就是我想介绍的一款工具,它可以帮助我们查看JDK或者javassist生成的动态代理类,当然,它的功能远不止此,还可以在生产环境进行诊断。
Arthas 是Alibaba开源的Java诊断工具,官方在线文档地址:https://arthas.aliyun.com/doc/
根据官网上的介绍,它还可以解决以下问题————
当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:
这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
是否有一个全局视角来查看系统的运行状况?
有什么办法可以监控到JVM的实时运行状态?
怎么快速定位应用的热点,生成火焰图?
怎样直接从JVM内查找某个类的实例?
这些方案本文暂不展开,这里只展开通过该工具查看Dubbo生成的动态代理类。
我是直接在使用dubbo-parent源码中的例子,分别启动了提供者与消费者。

首先,启动提供者方法——
public class Application {
public static void main(String[] args) throws Exception {
startWithBootstrap();
}
private static boolean isClassic(String[] args) {
return args.length > 0 && "classic".equalsIgnoreCase(args[0]);
}
private static void startWithBootstrap() {
ServiceConfig<DemoServiceImpl> service = new ServiceConfig<>();
service.setInterface(DemoService.class);
service.setRef(new DemoServiceImpl());
DubboBootstrap bootstrap = DubboBootstrap.getInstance();
RegistryConfig registryConfig = new RegistryConfig("zookeeper://127.0.0.1:2181");
registryConfig.setTimeout(20000);
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setHost("192.168.100.1");
protocolConfig.setPort(20877);
bootstrap.application(new ApplicationConfig("dubbo-demo-api-provider"))
.registry(registryConfig)
.service(service)
.protocol(protocolConfig)
.start()
.await();
}
}
注意,需要配置RegistryConfig自己的zookeeper, protocolConfig.setHost("xxx.xxx.xxx.xxx")设置成你本地内网的ip即可;
DemoServiceImpl类详情——
public class DemoServiceImpl implements DemoService {
private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);
@Override
public String sayHello(String name) {
logger.info("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
}
@Override
public CompletableFuture<String> sayHelloAsync(String name) {
return null;
}
}
接着,启动消费者,这里可以设置一个休眠时间,这样就可以一直维持消费者运行在内存当中——
public class Application {
public static void main(String[] args) {
runWithRefer();
}
private static void runWithRefer() {
RegistryConfig registryConfig = new RegistryConfig("zookeeper://127.0.0.1:2181");
registryConfig.setTimeout(30000);
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setHost("192.168.200.1");
protocolConfig.setPort(20899);
ReferenceConfig<DemoService> reference = new ReferenceConfig<>();
reference.setApplication(new ApplicationConfig("dubbo-demo-api-consumer"));
reference.setRegistry(registryConfig);
reference.setInterface(DemoService.class);
DemoService service = reference.get();
String message = service.sayHello("dubbo");
System.out.println("打印了5555555"+message);
try {
Thread.sleep(100000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
当Dubbo的服务提供者与消费者都正常运行时,说明此时JVM虚拟机内存里已经存在动态生成的代理类,这时,我们就可以开始通过arthas-boot.jar工具进行查看了。
首先,将arthas-boot.jar工具下载到你本地,我的是Windows,随便放到一个目录当中,例如——

接着,直接在运行着Dubbo消费端进程的IDEA上打开Terminal——

然后,输入 java -jar C:\Users\92493\Downloads\12229238_g\arthas-boot.jar ,arthas正常运行成功话,将列出当前JVM上运行的进程——

可以看到我们刚刚启动的provider进程与consumer进程,这时,只需要输入对应进程前面的编号【5】,就可以将Arthas 关联到启动类为 org.apache.dubbo.demo.consumer.Application的 Java 进程上了——

到这一步,我们就可以通过指令 sc *.proxy *模糊查询带有proxy标志的类名了,动态代理生成的类一般都是以Proxy标志——

其中,这里的org.apache.dubbo.common.bytecode.proxy0就是消费者生成的动态代理类,我们可以直接反编译去查看它内部结构——
[arthas@57676]$ jad org.apache.dubbo.common.bytecode.proxy0
控制台就会打印出该动态代理类的内部结构——
/*
* Decompiled with CFR.
*
* Could not load the following classes:
* com.alibaba.dubbo.rpc.service.EchoService
* org.apache.dubbo.common.bytecode.ClassGenerator$DC
* org.apache.dubbo.demo.DemoService
* org.apache.dubbo.rpc.service.Destroyable
*/
package org.apache.dubbo.common.bytecode;
import com.alibaba.dubbo.rpc.service.EchoService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.concurrent.CompletableFuture;
import org.apache.dubbo.common.bytecode.ClassGenerator;
import org.apache.dubbo.demo.DemoService;
import org.apache.dubbo.rpc.service.Destroyable;
public class proxy0 implements ClassGenerator.DC,Destroyable,EchoService,DemoService {
public static Method[] methods;
private InvocationHandler handler;
public String sayHello(String string) {
Object[] objectArray = new Object[]{string};
Object object = this.handler.invoke(this, methods[0], objectArray);
return (String)object;
}
public CompletableFuture sayHelloAsync(String string) {
Object[] objectArray = new Object[]{string};
Object object = this.handler.invoke(this, methods[1], objectArray);
return (CompletableFuture)object;
}
public Object $echo(Object object) {
Object[] objectArray = new Object[]{object};
Object object2 = this.handler.invoke(this, methods[2], objectArray);
return object2;
}
public void $destroy() {
Object[] objectArray = new Object[]{};
Object object = this.handler.invoke(this, methods[3], objectArray);
}
public proxy0() {
}
public proxy0(InvocationHandler invocationHandler) {
this.handler = invocationHandler;
}
}
在Dubbo案例当中,当我们执行 String message = service.sayHello("dubbo")去调用远程接口时,其实是调用了动态代理生成的方法——
public String sayHello(String string) {
Object[] objectArray = new Object[]{string};
Object object = this.handler.invoke(this, methods[0], objectArray);
return (String)object;
}
举一反三,这个Arthas工具类可以在线上生产环境查看一些我们新部署的代码,看是否是新改动的。
Alibaba Java诊断工具Arthas查看Dubbo动态代理类的更多相关文章
- Alibaba Java诊断工具Arthas之快速安装和简单使用
Alibaba Java诊断工具Arthas简单介绍 : 当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决: 1.这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception ...
- java 诊断工具——Arthas
该说不说!小编做的这些功能,最讨厌的就是优化!某些前辈大佬写的代码小辈我实在不敢恭维!那逻辑!那sql! 接下来!今天的主角就登场了,阿里巴巴最近开源出来的一个针对 java 的工具,主要是针对 ja ...
- Java诊断工具Arthas
Java诊断工具Arthas 1. Arthas简介 Arthas是阿里开源的一个线上java诊断工具,发现阿里还是挺喜欢开源一些技术的,造福人类.昨天试用了一下,发现真是强大,解决了我工作两年的很多 ...
- 【Java】15分钟快速体验阿里Java诊断工具Arthas
[墙裂推荐]15分钟快速体验阿里Java诊断工具Arthas : https://alibaba.github.io/arthas/arthas-tutorials?language=cn&i ...
- Alibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas
Arthas 用户文档 — Arthas 3.1.0 文档https://alibaba.github.io/arthas/ alibaba/arthas: Alibaba Java Diagnost ...
- Java 诊断工具 Arthas 教程学习笔记
Java 诊断利器 Arthas,是阿里的一款开源工具.Github-alibaba/arthas 上可以看到它的介绍.了解它,主要是最近对分析 Java 错误堆栈比较感兴趣,机缘巧合看到了它. 本文 ...
- 阿里JAVA诊断工具Arthas的初步使用
Arthas 是Alibaba开源的Java诊断工具,主要解决以下问题: 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception? 我改的代码为什么没有执行到?难道是我没 comm ...
- 干货分享!JAVA诊断工具Arthas在Rainbond上实践~
别再担心线上 Java 业务出问题怎么办了,Arthas 帮助你解决以下常见问题: 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception? 我改的代码为什么没有执行到?难道是我没 ...
- 款阿里开源的 Java 诊断工具Arthas
Arthas是什么鬼? Arthas是一款阿里巴巴开源的 Java 线上诊断工具,功能非常强大,可以解决很多线上不方便解决的问题. Arthas诊断使用的是命令行交互模式,支持JDK6+,Linux. ...
随机推荐
- Linux 常用管理命令
系统 # uname -a # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue # 查看操作系统版本 # cat /proc/cpuinfo # 查看CPU信息 # ho ...
- Python 基于 selenium 实现不同商城的商品价格差异分析系统
1. 前言 selenium 原本是一款自动化测试工具,因其出色的页面数据解析和用户行为模拟能力而常用于爬虫程序中,致使爬虫程序的爬取过程更简单.快捷. 爬虫程序与其它类型程序相比较,本质一样,为数据 ...
- MATLAB绘制三角网及三维网线
今天博主给大家介绍一些比较常见的可视化操作,绘制三角网及三维网线. 三角网是由一系列连续三角形构成的网状的平面控制图形,是三角测量中布设连续三角形的两种主要扩展形式,同时向各方向扩展而构成网状,优点为 ...
- 『德不孤』Pytest框架 — 15、Pytest参数化
目录 1.Pytest参数化说明 2.Pytest参数化方式 3.parametrize装饰器参数说明 4.Pytest参数化(单个参数) 5.Pytest参数化(多个参数) 6.ids参数说明 1. ...
- vscode中使用git
vscode中使用git 使用vscode打开git的文件时,会自动的跟踪文件的改动, 如果要提交修改,首先点击+,这个相当于git add, 这样会暂时保存,然后点击上面的√,然后在输入栏中输入修改 ...
- WebGL 的 Hello World
本文整理自 div 侠于 凹凸 2022 年技术分享,简单介绍了 WebGL 画一个基础图形的流程,希望你了解之后,在使用 3d 渲染库的时候可以少点迷糊. 四种常用的页面绘图工具 关于h5页面的图形 ...
- HTTPS-各种加密方式
推荐阅读:https://www.cnblogs.com/zwtblog/tag/计算机网络/ 目录 HTTPS 对称加密(AES) 非对称加密(RSA) 工作过程 分析 优缺点 常用算法 混合加密 ...
- Java中的软引用、弱引用、虚引用的适用场景以及释放机制
Java的强引用,软引用,弱引用,虚引用及其使用场景 从 JDK1.2 版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引 ...
- elasticsearch 是如何实现 master 选举的 ?
想了解 ES 集群的底层原理,不再只关注业务层面了. 前置前提: 1.只有候选主节点(master:true)的节点才能成为主节点. 2.最小主节点数(min_master_nodes)的目的是防止脑 ...
- Java 中,DOM 和 SAX 解析器有什么不同?
DOM 解析器将整个 XML 文档加载到内存来创建一棵 DOM 模型树,这样可以 更快的查找节点和修改 XML 结构,而 SAX 解析器是一个基于事件的解析器, 不会将整个 XML 文档加载到内存.由 ...