【Javassist】快速入门系列07 当检测到字段被访问时使用语句块替换访问

news2024/10/7 4:22:58

系列文章目录

01 在方法体的开头或结尾插入代码
02 使用Javassist实现方法执行时间统计
03 使用Javassist实现方法异常处理
04 使用Javassist更改整个方法体
05 当有指定方法调用时替换方法调用的内容
06 当有构造方法调用时替换方法调用的内容
07 当检测到字段被访问时使用语句块替换访问


文章目录

  • 系列文章目录
  • 前言
  • 引入Javassist jar包
    • 当检测到字段被访问时使用语句块替换访问
  • 总结
  • 说明


前言

上一章我们介绍了当构造方法调用时替换方法调用的内容,学习了 method.instrument的用法。以及参数为ConstructorCall的重载方法的含义。本章主要介绍当检测到字段被访问时使用语句块替换访问。


引入Javassist jar包

在上几篇文章已经引入了javassist的jar包,如果你是第一次观看本系列文章,也可以复制以下maven依赖将jar包导入工程。

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

当检测到字段被访问时使用语句块替换访问

/**
 * 【Javassist】快速入门系列07 当检测到字段被访问时使用语句块替换访问
 * 公众号&B站:精致的王同学
 * @author wangfengxi1
 * @date 2022/12/25 18:02
 */
public class Basic07FieldAccess {
    public static void main(String[] args) throws Exception{
        // 获取javassist默认类池
        ClassPool pool = ClassPool.getDefault();
        // 获取basic.Basic07Test的ctClass对象
        CtClass ctClass = pool.get("basic.Basic07Test");

        // 获取basic.Basic07Test的cmain方法
        CtMethod method = ctClass.getDeclaredMethod("main");
        // 当检测到字段被访问时使用语句块替换访问
        method.instrument(new ExprEditor() {
            @Override
            public void edit(FieldAccess f) throws CannotCompileException {
                try {
                    if (f.getClassName().equals("basic.Basic07Test") && f.getFieldName().equals("name")) {
                        f.replace("System.out.println(\"FieldAccess\");$_=$proceed($$);");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        // 将类写成文件
        ctClass.writeFile();
        //获取basic.Basic07Test类修改后的class对象
        Class<?> clazz = ctClass.toClass();
        // 获取basic.Basic07Test类修改后的实例
        Object obj = clazz.newInstance();
        // 获取修改后的main方法
        Method main = clazz.getDeclaredMethod("main", String[].class);
        // 调用修改后的main方法
        main.invoke(obj,(Object) new String[0]);
    }
}

以上Basic07FieldAccess类创建了一个main方法,该方法中首先获取javassist的类池pool,然后调用pool.get(“basic.Basic07Test”)方法获取到basic包下的Basic07Test类。Basic07Test类源码如下:

/**
 * 第7节测试类
 *
 * @author wangfengxi1
 * @date 2022/12/25 20:16
 */
public class Basic07Test {
    private String name;

    public Basic07Test() {
    }

    public Basic07Test(String name) {
        this();
        this.name = name;
    }

    public static void main(String[] args) {
        Basic07Test basic07Test = new Basic07Test("小明");
        System.out.println(basic07Test.name);
    }
}

该类中有一个main方法创建了一个Basic07Test对象,然后调用System.out.println(basic07Test.name);输出姓名。这个语句访问了basic07Test.name

回到Basic07FieldAccess 的main方法,在获取到basic07Test类的ctClass的对象之后,获取其main方法的方法对象。

接着调用method.instrument(ExprEditor editor)方法搜索method内的字段访问。判断如果其类是basic.Basic07Test且被访问的字段是name则调用f.replace(“System.out.println(“FieldAccess”); = _= =proceed($$);”);方法替换字段的访问。

instrument方法接收一个ExprEditor 类型的对象,该类有很多重载的edit方法,其中参数为FieldAccess 的重载方法代表搜索方法内的字段访问。

如果表达式是读访问,则必须在源文本中为$_赋值。$_的类型是字段的类型。

在replace的代码块中,以下符号有特殊含义:

$0  包含表达式访问的字段的对象。这并不等同于thisthis表示调用包含表达式的方法的对象。如果字段是静态的,则$0为空。
$1  如果表达式是写访问,则代表存储在字段中的值。否则,$1不可用。
$_  如果表达式是读取访问,则代表字段访问的结果值。否则,$_中存储的值将被丢弃。
$r  如果表达式是读取访问,则代表字段的类型。否则,$r无效。
$class  表示声明字段的类的java.lang.class对象。
$type  表示字段类型的java.lang.Class对象。
$proceed  执行原始字段访问的虚拟方法的名称。

最后模拟调用修改后的main方法结果如下:
在这里插入图片描述

总结

本篇文章介绍了使用Javassist当检测到字段被访问时使用语句块替换访问,学习了 method.instrument的用法。以及参数为FieldAccess 的重载方法edit的含义。

说明

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

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

相关文章

一个最基本的lLinux驱动开发框架和编译驱动方式

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、编写驱动文件1.相关头文件2.驱动入口 &出口3.申明完整代码二、编译驱动的方式三、编译驱动1. 和内核一起编译&#xff1a;2. 编译成驱动模块&#xff1a…

Kafka消息写入流程

Kafka消息写入流程 0,写入消息简要流程图 1,从示例开始 在Kafka中,Producer实例是线程安全的,通常一个Producer的进程只需要生成一个Producer实例. 这样比一个进程中生成多个Producer实例的效率反而会更高. 在Producer的配置中,可以配置Producer的每个batch的内存缓冲区的大小…

如何下载最新的NDVI数据?需要翻墙,安装MRT,如何处理下载的NDVI数据?

一、下载NDVI数据 参照网站&#xff1a; https://www.zhihu.com/question/48176218 1、先在网站https://modis.gsfc.nasa.gov/data/dataprod/mod13.php查看要下载的数据 其实没什么要看的&#xff0c;就看下面这个图就可以了&#xff0c;根据下图找到自己要下载的数据简称&am…

Python实现猎人猎物优化算法(HPO)优化支持向量机分类模型(SVC算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 猎人猎物优化搜索算法(Hunter–prey optimizer, HPO)是由Naruei& Keynia于2022年提出的一种最新的优…

Hibernate-Validator的使用(一)

文章目录学习建议全部的约束注解关于NotEmpty和NotBlank的注意事项关于Size的注意事项约束注解可以放的位置JavaBeanValidator接口约束注解的继承性普通方法和构造方法入参和返回值ExecutableValidator 接口约束注解的继承性错误信息国际化显示定义message使用的消息key定义Val…

模仿现实生活中的通讯录(2)

距离第一篇已经过去很久&#xff0c;我之所以暂时放下通讯录&#xff0c;是因为学业颇多&#xff0c;无暇顾及。现在放假已经有一段时间了&#xff0c;脱离每天忙碌的生活后&#xff0c;我只想享受一下整日无事&#xff0c;浑浑噩噩过一天的感觉&#xff0c;只不过差点没收得住…

leetcode150/155. 逆波兰表达式求值、最小栈;剑指 Offer 31. 栈的压入、弹出序列

目录 题目链接与简介 题目一 1.算法思路 2.总结心得 3.可执行代码 题目二 1.算法思路 2.总结心得 3.可执行代码 题目三 1.算法思路 2.总结心得 3.可执行代码 题目链接与简介 1.逆波兰表达式求值 2.最小栈 3.剑指 Offer 31. 栈的压入、弹出序列 题目一 LeetCod…

软件测试 -- 进阶 8 软件测试流程和过程

盖天下之事&#xff0c;不难于立法&#xff0c;而难于法之必行&#xff1b;不难于听言&#xff0c;而难于言之必效。-- 明 张居正 释译&#xff1a;天下大事&#xff0c;困难的不在于要制定什么法律&#xff0c;而在于立了法就一定要执行&#xff1b;重要的不在于说什么&a…

【实时数仓】DWS层之地区主题表(FlinkSQL)、关键词主题表(FlinkSQL)

文章目录一 DWS层-地区主题表(FlinkSQL)1 分组开窗和聚合计算&#xff08;1&#xff09;分组窗口&#xff08;2&#xff09;选择分组窗口的开始和结束时间戳&#xff08;3&#xff09;系统内置函数&#xff08;4&#xff09;完整代码2 将动态表转换为流&#xff0c;写入ClickHo…

计算机基础(五):C语言的程序的处理过程

一段C语言程序 打开任何一个C语言的教程&#xff0c;首先自然是展示一段 Hello World 的程序&#xff0c;类似于下面这段&#xff1a; #include <stdio.h>int main() {/* 我的第一个 C 程序 */printf("Hello, World! \n");return 0; }运行上面这段程序也很简…

Qt中的数据库(简单使用)

在Qt中支持对数据库的操作 Qt中数据库的类有&#xff1a; 驱动层&#xff1a;为具体的数据库和SQL接口层之间提供底层的桥梁SQL层&#xff1a;提供对数据库的访问 QSqlDateBase类用来创建连接QSqlQuery可以使用SQL语句实现交互用户接口层&#xff1a;实现将数据库中的数据链接…

36. 卷积神经网络(LeNet)

通过之前几节&#xff0c;我们学习了构建一个完整卷积神经网络的所需组件。 回想一下&#xff0c;之前我们将softmax回归模型和多层感知机模型应用于Fashion-MNIST数据集中的服装图片&#xff0c;为了能够应用softmax回归和多层感知机&#xff1a; 我们首先将每个大小为的图像…

【Web开发】Python实现Web服务器(Ubuntu下Flask使用MySQL数据库)

&#x1f37a;基于Python的Web服务器系列相关文章编写如下&#x1f37a;&#xff1a; &#x1f388;【Web开发】Python实现Web服务器&#xff08;Flask快速入门&#xff09;&#x1f388;&#x1f388;【Web开发】Python实现Web服务器&#xff08;Flask案例测试&#xff09;&a…

大数据-玩转数据-Kafka实战

一、kafka使用要点 要点一&#xff1a;Producer即生产者&#xff0c;向Kafka集群发送消息&#xff0c;在发送消息之前&#xff0c;会对消息进行分类&#xff0c;即Topic&#xff0c;topic1&#xff0c;topic2。Topic即主题&#xff0c;通过对消息指定主题可以将消息分类&#…

工具-能写会看正则表达式【强烈建议收藏!】

正则表达式,很常用的一个技能点,但是一般的开发流程中都是这样的: 需要验证数据上网搜一下正则表达式CV 搞定!!!今天有时间回看了一下文档,简单整理了一下里面需要注意的点,并且通过分析几个常见的正则表达式,下次遇到正则争取不再只依靠 CV 大法! 基础部分 基本语法 …

初识指针(9)

目录 1、指针是什么&#xff1f; 2、指针和指针类型 1、指针- 整数 2、指针的解引用 3、野指针 1、野指针成因 2、如何规避野指针 4、指针运算 1、指针- 整数 2、指针- 指针 3、指针的关系运算 5、指针和数组 6、二级指针 7、指针数组 1、指针是什么&#xff1f;…

04-Hystrix

服务熔断Hystrix 1. Hystrix是什么 分布式系统环境下&#xff0c;服务间类似依赖非常常见&#xff0c;一个业务调用通常依赖多个基础服务。如下图&#xff0c;对于同步调用&#xff0c;当库存服务不可用时&#xff0c;商品服务请求线程被阻塞&#xff0c;当有大批量请求调用库…

SpringBoot-2 读取properties;自动加载127个类原理总结;全部加载,按需配置

读取properties 方式一&#xff1a;非配置类填写&#xff1a;ComponentConfigurationProperties 1)建立bean&#xff1a; /只有在容器中的组件才拥有springboot提供的强大功能 Component ConfigurationProperties(prefix "mycar") public class Car {private Stri…

【机器学习】模型评估与选择

模型评估与选择 目录一、评估方法1、留出法2、交叉验证法3、自助法二、性能度量1、错误率与准确率2、查准率、查全率阈值对查准率、查全率的影响3、F1度量&#xff08;基于查准率与查全率的调和平均&#xff09;4、P-R Curve5、ROC CurvePRC和ROC的选用准则PRC和ROC的差异6、代…

python 中文转带音调的拼音

python 中文转带音调的拼音 前言python 中文转带音调的拼音1、1.1 安装pinyin模块1.2 试验1.3 效果图1.4 代码实现前言 今天整理中药材,每个药材上标上带音调的拼音,查了些,有的易形成乱码,如Shān Mi Dōnɡ,想到python自已动手转算了 python 中文转带音调的拼音 1、 …