Javassist动态生成类使用,以及Arthas 查看动态代理生成类内容

news2025/2/27 22:58:34

java反射

反射的弊端:

性能开销:
因为反射涉及到动态解析的类型,所以某些Java虚拟机的优化不能被执行(因为它不能真正了解你在做什么)。因此,反射操作的性能比非反射操作的性能要慢,应该避免在对性能敏感的应用程序中频繁调用的代码部分。

Javassist

  1. 操作Java字节码简单,是一个用于编辑Java字节码的类库,可以在运行时定义一个新类,并在JVM加载类文件是修改它
  2. Javassist提供了两种级别的API:源级别和字节码级别。如果用户使用源代码级API,可以不需要了解Java字节码的规范的前提下编辑类文件。整个API仅使用Java语言的词汇表设计。甚至你可以以源文本的形式插入字节码中;Javassist动态编译它。另一方面,字节码级API允许用户作为编辑器直接编辑类文件。
  3. Javassist允许检查、编辑和创建Java二进制类。
  4. Javassist并不是唯一处理字节码的库,但它有一个特别功能,使其成为一个重要的开始来尝试字节码工作:你可以使用Javassist改变一个Java类的字节码而不需要学习任何关于字节码或Java虚拟机(JVM)的体系结构。
  5. 面向切面编程:Javassist可以向类中添加新方法,以及在调用方和被调用方两边插入before/after通知。
  6. 反射:Javassist另一个应用就是运行时反射;Javassist允许Java程序使用一个元对象,该元对象控制基级别对象上的方法调用。不需要专门的编译器或虚拟机。
  7. Javassist还提供了用于直接编辑类文件的低级API。要使用此级别的API,需要了解Java字节码和类文件格式,而此级别的API允许您对类文件进行任何类型的修改。

Maven 依赖

<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.25.0-GA</version>
</dependency>

常用类常用方法

ClassPool常用方法:
  • getDefault : 返回默认的ClassPool 是单例模式的,通过该方法创建ClassPool对象;
  • appendClassPath, insertClassPath : 将一个ClassPath加到类搜索路径的末尾位置 或 插入到起始位置。通常通过该方法写入额外的类搜索路径,以解决多个类加载器环境中找不到类的尴尬;
  • toClass : 将修改后的CtClass加载至当前线程的上下文类加载器中,并转换成Class对象。一旦调用该方法,则无法继续修改已经被加载的class;
  • get , getCtClass : 根据类路径名获取该类的CtClass对象(如果类路径名不存在,抛异常),用于后续的编辑。get()并不搜索所记录的包。只有编译器会搜索它。
  • makeClass:创建一个新的公共类。如果已经存在同名的类/接口,则新类将覆盖前一个类。 如果没有显式地向创建的新类添加构造函数,Javassist将生成构造函数,并在生成类文件时添加它。它为超类的每个构造函数生成一个新的构造函数。新的构造函数接受相同的参数集,并调用超类的相应构造函数。所有接收到的参数都传递给它。
  • importPackage:记录包名,以便Javassist编译器搜索包以解析类名。不要记录java.Lang包,默认情况下已隐式记录。 从3.14版开始,packageName可以是一个完全限定的类名。
CtClass常用方法:
  • freeze : 冻结一个类;
  • isFrozen : 判断一个类是否已被冻结;
  • prune : 删除类不必要的属性,以减少内存占用。调用该方法后,许多方法无法将无法正常使用,慎用;
  • defrost : 解冻一个类,使其可以被修改。如果事先知道一个类会被defrost, 则禁止调用 prune 方法;
  • detach : 将该class从ClassPool中删除;
  • writeFile : 根据CtClass生成 .class 文件;
  • toClass : 通过类加载器加载CtClass。转换成Class对象
  • addMethod:在目标类中添加一个方法
  • removeMethod : 对目标类删除一个方法

上面我们创建一个新的方法使用了CtMethod类。CtMthod代表类中的某个方法,可以通过CtClass提供的API获取或者CtNewMethod新建,通过CtMethod对象可以实现对方法的修改。

CtMethod常用方法:

实现自CtBehavior的方法

  • insertBefore : 在方法的起始位置插入代码;
  • insterAfter : 在方法的所有 return 语句前插入代码以确保语句能够被执行,当抛出异常时,它不会执行;
  • insertAt : 在指定的位置插入代码;
  • setBody : 将方法的内容设置为要写入的代码,当方法被 abstract修饰时,该修饰符被移除;

自己的方法

  • make : 创建一个新的方法。

CtField常用方法:

使用Javassist注意事项

javassist中写入函数体时:

  1. 对于范型符号需要特殊处理 例如 /*<?>*/
  2. 对饮用的外部类显式声明包路径 例如 com.example.javassist.IJavassistService

例如下面构造函数体内容

public static String buildMethod(String impl) throws Exception {

    String methodString = "   public String hello(String name) {\n"
            + "        System.out.println(\"before iJavassistService method ..\");\n"
            + "        String className = \"com.example.javassist." + impl + "\";\n"
            + "        Class/*<?>*/ serviceClassName = Class.forName(className);\n "
            + "        com.example.javassist.IJavassistService iJavassistService = (com.example.javassist.IJavassistService) serviceClassName.newInstance();\n"
            + "        String nameMethod = iJavassistService.hello(name);\n"
            + "        System.out.println(\"after iJavassistService method ..\");\n"
            + "        return nameMethod;\n"
            + "    }";
    return methodString;
}

手写Dubbo中spi扩展机制的 protocolSPI.export(Invoker invoker)

简单根据代码模仿dubbo SPI机制中 使用javassist 的思想

IJavassistService 接口

public interface IJavassistService {
    String hello(String name);
}

IJavaServiceImplPlus 和 IJavassistServiceImpl 实现类

public class IJavassistServiceImpl implements IJavassistService{
    @Override
    public String hello(String name) {
        System.out.println( "javassist service impl " + name);
        return "javassist service impl " + name;
    }
}
// - - - - - - - - - - - - - - - - - - - - -
public class IJavaServiceImplPlus implements IJavassistService{
    @Override
    public String hello(String name) {
        System.out.println( "service plus    " + name);
        return "service plus" + name;
    }
}

JavassistTest 测试类

public static void main(String[] args) throws Exception {
    classPoolTest("IJavaServiceImplPlus","lucy");
}

public static void classPoolTest(String implName,String hello) throws Exception {
    ClassPool cp = ClassPool.getDefault();
    // makeClass 构造一个类
    CtClass ctClass = cp.makeClass("com.example.javassist.IJavassistServiceImplProxy");
//        CtField age = new CtField(cp.get("java.lang.Integer"), "age", ctClass);
//        age.setModifiers(Modifier.PUBLIC);
    // 添加实现接口
    ctClass.setInterfaces(new CtClass[]{cp.getCtClass("com.example.javassist.IJavassistService")});

    // 添加自定义方法
    CtMethod make = CtNewMethod.make(buildMethod(implName), ctClass);
    ctClass.addMethod(make);
    // 实例化类
    IJavassistService iJavassistService = (IJavassistService) ctClass.toClass().newInstance();
    String hello1 = iJavassistService.hello(hello);
    // 输出返回结果
    System.out.println(hello1);
}

public static String buildMethod(String impl) throws Exception {

    String methodString = "   public String hello(String name) {\n"
            + "        System.out.println(\"before iJavassistService method ..\");\n"
            + "        String className = \"com.example.javassist." + impl + "\";\n"
            + "        Class/*<?>*/ serviceClassName = Class.forName(className);\n "
            + "        com.example.javassist.IJavassistService iJavassistService = (com.example.javassist.IJavassistService) serviceClassName.newInstance();\n"
            + "        String nameMethod = iJavassistService.hello(name);\n"
            + "        System.out.println(\"after iJavassistService method ..\");\n"
            + "        return nameMethod;\n"
            + "    }";
    return methodString;
}

javassist为什么慢

首先javassist 内部使用的反射,本身反射就慢,不能使用jvm内部的一些优化

查看代理类内容

使用Arthas查看

arthas官网:

https://arthas.aliyun.com/doc

Arthas(阿尔萨斯)能为你做什么?

Arthas 是 Alibaba 开源的 Java 诊断工具,深受开发者喜爱。

当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:

  1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
  2. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
  3. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
  4. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
  5. 是否有一个全局视角来查看系统的运行状况?
  6. 有什么办法可以监控到 JVM 的实时运行状态?
  7. 怎么快速定位应用的热点,生成火焰图?
  8. 怎样直接从 JVM 内查找某个类的实例?

Arthas 支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

怎么查看代理类?

下载后 cmd进入arthas-boot.jar 目录进入命令行 执行jar文件

img

sc *目标代理类名称*命令 查找目标代理类位置

以Dubbo中的Protocol@Adaptive 为例

sc *Protocol$Adaptive* 搜索 类名字 所在包位置

jad org.apache.dubbo.rpc.Protocol$Adaptive查看 目标类字节码文件

img

img

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/426743.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++记录总结及面试常见问题

C记录总结及面试常见问题指针和函数内存分区模型访问权限struct & class创建类构造函数静态成员this指针const 修饰成员函数友元friend重载运算符和重载函数继承读文件ifstream/fstreamvector中resize和reserve的区别智能指针左值与右值struct、class区别引用指针和函数 函…

Zabbix6.0升级到Zabbix6.4

1&#xff1a;现在的版本是6.0.3 2&#xff1a;停止Zabbix Server进程。 systemctl stop zabbix-server 若升级Zabbix proxy版本&#xff0c;需也停止Zabbix proxy服务 。 systemctl stop zabbix-proxy 3&#xff1a;我用的是MariaDB数据库名称是zabbix。 4&#xff1a; 查看…

windows11安装pytorch2.0

换了新电脑&#xff0c;好久没用windows了&#xff0c;配置一下环境&#xff0c;顺便记录一下方便帮助AI小白不会浪费时间在装环境上&#xff08;一星期不夸张hah&#xff09; 打开命令行&#xff0c;然后输入 nvidia-smi&#xff0c;检查自己的显卡驱动 也可以通过图形界面查…

Python轻量级Web框架Flask(6)——Flask中的单表操作(增删改“查”)

0、前言&#xff1a;Python轻量级Web框架Flask&#xff08;5&#xff09;中生成的新模板就是包含数据库操作的Flask模板。 在pycharm中用flask写表结构时需用用到数据类型的定义如下&#xff1a; 下面总结一些常用到的数据类型&#xff1a; 1、Python轻量级Web框架Flask&…

传智健康项目总结

耗时一个半月终于把传智健康项目跟着做完了&#xff0c;下面是对项目的一点心得体会。 项目知识点总结 Maven中parent父工程聚合 聚合模块(父工程)作用&#xff1a;父工程是一个pom工程&#xff0c;通常只是用来帮助其子模块构建的工具&#xff0c;本身并没有实质的内容。具体…

【Pytorch】搭建网络模型的实战

【Pytorch】搭建网络模型的实战CIFAR10 model structure搭建网络使用Sequential进行搭建网络模型使用tensorboard查看网络结构对CIFAR10数据集进行分类&#xff0c;根据图片内容识别这是哪一类 CIFAR10 model structure 输入input:3通道的32 x 32 图片卷积操作的通道数不变 那…

C#,码海拾贝(16)——求“矩阵秩”的全选主元“高斯消去法(Gauss Elimination)”C#源代码,《C#数值计算算法编程》源代码升级改进版

1 矩阵的秩 Rank of Matrix 矩阵的秩是线性代数中的一个概念。在线性代数中&#xff0c;一个矩阵A的列秩是A的线性独立的纵列的极大数&#xff0c;通常表示为r(A)&#xff0c;rk(A)或rank A。 在线性代数中&#xff0c;一个矩阵A的列秩是A的线性独立的纵列的极大数目。类似地&…

全面解析反欺诈(羊毛盾)API,助你识别各类欺诈风险

前言 反欺诈&#xff08;羊毛盾&#xff09;反机器欺诈 API&#xff0c;是一种基于大数据分析和模型产品的技术&#xff0c;通过输入手机号、手机 IP 地址进行检测&#xff0c;帮助客户识别大量存在恶意的账号。 反欺诈&#xff08;羊毛盾&#xff09;API 的作用 反欺诈&…

Spring自定义参数解析器~

1. 什么是参数解析器 RequstBody、RequstParam 这些注解是不是很熟悉&#xff1f; 我们在开发 Controller 接口时经常会用到此类参数注解&#xff0c;那这些注解的作用是什么&#xff1f;我们真的了解吗&#xff1f; 简单来说&#xff0c;这些注解就是帮我们将前端传递的参数…

基于Sikuli GUI图像识别框架的PC客户端自动化测试实践

目录&#xff1a;导读 引言 一、GUI图像识别框架元祖&#xff1a;Sikuli 二、Sikuli运行原理 三、Sikuli安装 四、Sikuli IDE主界面基本使用 五、Sikuli 脚本语法 六、Sikuli 应用示例 七、Sikuli 优势及局限 1.优势 2.局限 Sikuli 使用小结 引言 Sikuli是一种基于…

【Hello Network】网络基础1

作者&#xff1a;小萌新 专栏&#xff1a;网络 作者简介&#xff1a;大二学生 希望能和大家一起进步 本篇博客简介&#xff1a;简单介绍网络的基础概念 网络基础1网络基础网络的起源网络在哪里认识协议网络协议协议分层OSI七层模型TCP/IP协议网络传输流程局域网的两台主机通信两…

跟姥爷深度学习3 神经网络的调试实操

一、前言 前面我们做了一次天气预测的模型&#xff0c;训练的结果都还好&#xff0c;网络好歹是“拟合”了&#xff0c;但预测数据不合预期让我一直耿耿于怀。所以我又花了很长时间来研究为什么&#xff0c;我的理论依据明明没有问题&#xff08;今日*均温度与*一周*均温度具有…

全球6G技术大会总结报告

全球6G技术大会 论坛B&#xff1a;天地融合智能组网技术 论坛D&#xff1a;2030技术发展趋势 论坛E&#xff1a;6G无线空口传输技术 论坛F&#xff1a;6G通感算架构及关键技术 论坛H&#xff1a;6G网络架构及关键技术 论坛B&#xff1a;天地融合智能组网技术 论坛B中包含…

【Java 并发编程】一文了解线程间有哪些通信方式?

一文了解线程间有哪些通信方式&#xff1f;1. synchronized 内置锁2. volatile 关键字3. 等待/通知机制3.1 等待wait()wait(long)wait(long, int)等待方需遵循如下原则3.2 通知notify()notifyAll()通知方需遵循如下原则notify() 和 notifyAll() 应该用谁&#xff1f;4. 管道输入…

第18章_JDK8-17新特性(下)

第18章_JDK8-17新特性&#xff08;下&#xff09; 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 6. 新语法结构 新的语法结构&#xff0c;为我们勾勒出了 Java 语法进化的一个趋势&#xff0c…

STM32 库函数 GPIO_SetBits、GPIO_ResetBits、GPIO_WriteBit、GPIO_Write 区别

问题&#xff1a;当我使用STM32库函数对 I/O 口进行赋值时&#xff0c;在头文件中发现有四个相关的函数可以做这个操作&#xff0c;那么它们有什么区别呢&#xff1f; 一、GPIO_SetBits //eg: GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2);解释&#xff1a;置位(置1)选择的数…

十、市场活动-分页查询

功能需求 ①、当市场活动主页面加载完成之后,显示所有数据的第一页; ②、用户在市场活动主页面填写查询条件,点击"查询"按钮,显示所有符合条件的数据的第一页&#xff0c;保持每页显示条数不变 ③、实现翻页功能. *在市场活动主页面,显示市场活动列表和记录的总条…

Spring MVC(Boot) Servlet 3.0异步处理,DeferredResult和Callable(续篇)

目录背景意外发现结论背景 上篇Spring MVC(Boot) Servlet 3.0异步处理&#xff0c;DeferredResult和Callable&#xff0c;我把WebMvcConfig 代码加入项目后&#xff0c;会报冲突的问题。如下所示。 requestMappingHandlerMapping: defined by method ‘requestMappingHandlerM…

The 1st Universal Cup Stage 12: ̄Ookayama, April 15-16, 2023 题解

A XOR Tree Path 给一颗树&#xff0c;树上点有黑白两色&#xff0c;每次可以选一个叶子节点&#xff0c;翻转其到根路径上所有点的颜色&#xff0c;问最大黑色点数。 树dp #include<bits/stdc.h> using namespace std; #define MAXN (10000010) #define ll long long…

计及氢能的综合能源优化调度研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…