您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > JAVA

Alibaba Java诊断工具Arthas查看Dubbo动态代理类

时间:2022-04-08 09:51:51  来源:博客园  作者:程序那点事

阅读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源码中的例子,分别启动了提供者与消费者。

Alibaba Java诊断工具Arthas查看Dubbo动态代理类

 

首先,启动提供者方法——

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,随便放到一个目录当中,例如——

Alibaba Java诊断工具Arthas查看Dubbo动态代理类

 

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

Alibaba Java诊断工具Arthas查看Dubbo动态代理类

 

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

Alibaba Java诊断工具Arthas查看Dubbo动态代理类

 

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

Alibaba Java诊断工具Arthas查看Dubbo动态代理类

 

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

Alibaba Java诊断工具Arthas查看Dubbo动态代理类

 

其中,这里的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工具类可以在线上生产环境查看一些我们新部署的代码,看是否是新改动的。

作者:朱季谦

出处:
https://www.cnblogs.com/zhujiqian/p/16114954.html



Tags:诊断工具   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Kubernetes 自动化诊断工具:K8sgpt-Operator
背景在 Kubernetes 上,从部署 Deployment 到正常提供服务,整个流程可能会出现各种各样问题,有兴趣的可以浏览 Kubernetes Deployment 的故障排查可视化指南(2021 中文版)[1]。...【详细内容】
2023-05-04  Search: 诊断工具  点击:(411)  评论:(0)  加入收藏
JVM诊断工具中的深堆、浅堆、支配树,你都明白吗
大家在用jvm诊断工具,比如Eclipse MAT或者 Jprofiler分析堆内存的时候,都会看到一些概念或者关键词,如Shallow Heap, Retained Heap, Dominator Tree等,你们知道他们是干嘛的吗?...【详细内容】
2023-02-27  Search: 诊断工具  点击:(182)  评论:(0)  加入收藏
Alibaba Java诊断工具Arthas查看Dubbo动态代理类
阅读Dubbo源码过程中,会发现,Dubbo消费端在做远程调用时,默认通过 Javassist 框架为服务接口生成动态代理类,调用javassist框架下的JavassistProxyFactory类的getProxy(Invoker...【详细内容】
2022-04-08  Search: 诊断工具  点击:(476)  评论:(0)  加入收藏
带着8个问题5分钟教你学会Arthas诊断工具
Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决: 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception...【详细内容】
2021-08-13  Search: 诊断工具  点击:(348)  评论:(0)  加入收藏
线上诊断工具-Arthas
性能评估根据github上相关的issues,arthas的定位是问题诊断与排查,只需要在进行问题诊断时运行并attach到进程上即可,其对系统的影响取决于所监控的JAVA进程的并发情况。http:/...【详细内容】
2021-06-29  Search: 诊断工具  点击:(1201)  评论:(0)  加入收藏
你需要的阿里开源内核诊断工具:diagnose-tools
今天为大家介绍一款实用工具——阿里开源内核诊断工具diagnose-tools。diagnose-tools是由阿里巴巴开发的linux内核诊断工具,用于linux性能分析,特别是大规模集群系统中的抖动问题分析。...【详细内容】
2020-11-03  Search: 诊断工具  点击:(570)  评论:(0)  加入收藏
Alibaba开源Java诊断工具Arthas简单介绍
​Alibaba开源Java诊断工具Arthas Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。在线排查问题,无需重启;动态跟踪Java代码;实时监控JVM状态。当你遇到以下类似问题而束...【详细内容】
2020-07-22  Search: 诊断工具  点击:(311)  评论:(0)  加入收藏
阿里内部的那个牛逼带闪电的Java诊断工具终于开源了
在阿里巴巴内部,有很多自研工具供开发者使用,其中有一款工具,是几乎每个Java开发都使用过的工具,那就是Arthas,这是一款Java诊断工具,是一款牛逼带闪电的工具。该工具已于2018年9...【详细内容】
2019-07-29  Search: 诊断工具  点击:(1162)  评论:(0)  加入收藏
细说诊断工具ping
介绍ping的工作原理很简单,一台网络设备发送请求等待另一网络设备的回复,并记录下发送时间。接收到回复之后,就可以计算报文传输时间了。只要接收到回复就表示连接是正常的。耗...【详细内容】
2019-05-07  Search: 诊断工具  点击:(1910)  评论:(0)  加入收藏
▌简易百科推荐
Java 8 内存管理原理解析及内存故障排查实践
本文介绍Java8虚拟机的内存区域划分、内存垃圾回收工作原理解析、虚拟机内存分配配置,以及各垃圾收集器优缺点及场景应用、实践内存故障场景排查诊断,方便读者面临内存故障时...【详细内容】
2024-03-20  vivo互联网技术    Tags:Java 8   点击:(18)  评论:(0)  加入收藏
如何编写高性能的Java代码
作者 | 波哥审校 | 重楼在当今软件开发领域,编写高性能的Java代码是至关重要的。Java作为一种流行的编程语言,拥有强大的生态系统和丰富的工具链,但是要写出性能优异的Java代码...【详细内容】
2024-03-20    51CTO  Tags:Java代码   点击:(25)  评论:(0)  加入收藏
在Java应用程序中释放峰值性能:配置文件引导优化(PGO)概述
译者 | 李睿审校 | 重楼在Java开发领域,优化应用程序的性能是开发人员的持续追求。配置文件引导优化(Profile-Guided Optimization,PGO)是一种功能强大的技术,能够显著地提高Ja...【详细内容】
2024-03-18    51CTO  Tags:Java   点击:(29)  评论:(0)  加入收藏
Java生产环境下性能监控与调优详解
堆是 JVM 内存中最大的一块内存空间,该内存被所有线程共享,几乎所有对象和数组都被分配到了堆内存中。堆被划分为新生代和老年代,新生代又被进一步划分为 Eden 和 Survivor 区,...【详细内容】
2024-02-04  大雷家吃饭    Tags:Java   点击:(60)  评论:(0)  加入收藏
在项目中如何避免和解决Java内存泄漏问题
在Java中,内存泄漏通常指的是程序中存在一些不再使用的对象或数据结构仍然保持对内存的引用,从而导致这些对象无法被垃圾回收器回收,最终导致内存占用不断增加,进而影响程序的性...【详细内容】
2024-02-01  编程技术汇  今日头条  Tags:Java   点击:(77)  评论:(0)  加入收藏
Java中的缓存技术及其使用场景
Java中的缓存技术是一种优化手段,用于提高应用程序的性能和响应速度。缓存技术通过将计算结果或者经常访问的数据存储在快速访问的存储介质中,以便下次需要时可以更快地获取。...【详细内容】
2024-01-30  编程技术汇    Tags:Java   点击:(77)  评论:(0)  加入收藏
JDK17 与 JDK11 特性差异浅谈
从 JDK11 到 JDK17 ,Java 的发展经历了一系列重要的里程碑。其中最重要的是 JDK17 的发布,这是一个长期支持(LTS)版本,它将获得长期的更新和支持,有助于保持程序的稳定性和可靠性...【详细内容】
2024-01-26  政采云技术  51CTO  Tags:JDK17   点击:(96)  评论:(0)  加入收藏
Java并发编程高阶技术
随着计算机硬件的发展,多核处理器的普及和内存容量的增加,利用多线程实现异步并发成为提升程序性能的重要途径。在Java中,多线程的使用能够更好地发挥硬件资源,提高程序的响应...【详细内容】
2024-01-19  大雷家吃饭    Tags:Java   点击:(111)  评论:(0)  加入收藏
这篇文章彻底让你了解Java与RPA
前段时间更新系统的时候,发现多了一个名为Power Automate的应用,打开了解后发现是一个自动化应用,根据其描述,可以自动执行所有日常任务,说的还是比较夸张,简单用了下,对于office、...【详细内容】
2024-01-17  Java技术指北  微信公众号  Tags:Java   点击:(104)  评论:(0)  加入收藏
Java 在 2023 年仍然流行的 25 个原因
译者 | 刘汪洋审校 | 重楼学习 Java 的过程中,我意识到在 90 年代末 OOP 正值鼎盛时期,Java 作为能够真正实现这些概念的语言显得尤为突出(尽管我此前学过 C++,但相比 Java 影响...【详细内容】
2024-01-10  刘汪洋  51CTO  Tags:Java   点击:(82)  评论:(0)  加入收藏
站内最新
站内热门
站内头条