作者:小傅哥
博客:https://bugstack.cn

沉淀、分享、成长,让自己和他人都能有所收获!

一、前言

通过前面两篇 javassist 的基本内容,大体介绍了;类池(ClassPool)、类(CtClass)、属性(CtField)、方法(CtMethod),的使用方式,并通过创建不同类型的入参出参方法,基本可以掌握如何使用这样的代码结构进行字节码编程。

那么,今天我们尝试使用 javassist 去修改一个正在执行中的类里面的方法内容。也就是在运行时重新加载类信息

可能在你平时的 CRUD 开发中并没有想到过这样的 烧操作,但它却有很多的应用场景在使用,例如;

  1. 热部署常用在生产环境中,主要由于这样的系统不能频繁启停且启动耗时较长的应用。
  2. 另外一些组件化风控模型包,给外部使用。当模型包进行升级时并不需要外部重新部署,甚至不需要让你知道升级了。
  3. 再者会用于开发、调试中,可以非常有效的提升编码效率,解放码农的右手左手

人的大脑很难创造未知的事物,所以需要学习。请多看小傅哥的码文,少搞CRUD

关于字节编程中所有涉及的代码,都可以通过关注公众号bugstack虫洞栈,回复:源码,进行获取。

二、开发环境

  1. JDK 1.8.0
  2. jdk1.8.0_161\lib\tools.jar - 需要使用到 jdi
  3. javassist 3.12.1.GA

三、案例目标

为了让案例目标更具色彩,我们模拟一个谢飞机老婆,通过系统查询自己男朋友前女友数量危机 方法,需要紧急处理的过程。

为了保障家庭的和谐化解危机,我们通过动态重新加载类,将谢飞机前女友数量修改为0并返回。依次安定家庭和谐。最终谢飞机会给我钱,当做报酬

让谢飞机很慌的方法

public class ApiTest {public String queryGirlfriendCount(String boyfriendName) {return boyfriendName + "的前女友数量:" + (new Random().nextInt(10) + 1) + " 个";}}

可预见的结果

你到底几个前女友!!!
谢飞机的前女友数量:3 个
谢飞机的前女友数量:5 个
谢飞机的前女友数量:8 个

四、技术实现

1. HotSwapper 操作类热加载

德莱联盟,王牌工程师,申请出

/*** 公众号:bugstack虫洞栈* 博客栈:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!* 本专栏是小傅哥多年从事一线互联网Java开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程,侧重点更倾向编写Java核心内容。如果能为您提供帮助,请给予支持(关注、点赞、分享)!*/
public class GenerateClazzMethod {public static void main(String[] args) throws Exception {ApiTest apiTest = new ApiTest();System.out.println("你到底几个前女友!!!");// 模拟谢飞机老婆一顿查询new Thread(() -> {while (true){System.out.println(apiTest.queryGirlfriendCount("谢飞机"));try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}).start();// 监听 8000 端口,在启动参数里设置// java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000HotSwapper hs = new HotSwapper(8000);ClassPool pool = ClassPool.getDefault();CtClass ctClass = pool.get(ApiTest.class.getName());// 获取方法CtMethod ctMethod = ctClass.getDeclaredMethod("queryGirlfriendCount");// 重写方法ctMethod.setBody("{ return $1 + \"的前女友数量:\" + (0L) + \" 个\"; }");// 加载新的类System.out.println(":: 执行HotSwapper热插拔,修改谢飞机前女友数量为0个!");hs.reload(ApiTest.class.getName(), ctClass.toBytecode());}}

2. 知识点讲解

  1. 多线程模拟循环调用,这个方法会一直执行查询。在后续修改类之后输出的结果信息会有不同。
  2. javassist.tools.HotSwapper,是 javassist 的包中提供的热加载替换类操作。在执行时需要启用 JPDA(Java平台调试器体系结构)。
  3. ctMethod.setBody,重写方法的内容在上面两个章节已经很清楚的描述了。$1 是获取方法中的第一个入参,大括号{}里是具体执行替换的方法体。
  4. 最后使用 hs.reload 执行热加载替换操作,这里的 ctClass.toBytecode() 获取的是处理后类的字节码。

五、测试结果

1. 引入tools.jar

2. 配置-agentlib

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000

3. 执行测试

Listening for transport dt_socket at address: 8000
你到底几个前女友!!!
谢飞机的前女友数量:3 个
谢飞机的前女友数量:5 个
谢飞机的前女友数量:8 个
:: 执行HotSwapper热插拔,修改谢飞机前女友数量为0个!
谢飞机的前女友数量:4 个
谢飞机的前女友数量:5 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
谢飞机的前女友数量:0 个
...Process finished with exit code -1

看到前女友数量为 0 时,谢飞机露出了羞涩的微笑,并兑现了承诺,将4毛钱给了王牌工程师小傅哥

4. 效果演示

六、总结

  1. 没得办法,即使再好的技术不加点段子也没人看。只能坑我兄弟飞机了!德莱联盟,王牌工程师,申请出
  2. 关于热加载修改类的操作,在实际场景中还是蛮多的,但一般都是比较苛刻的场景诉求。在平时开发中还是比较少遇到的,并且CRUD开发不会遇到。
  3. JavassistASM 这样的字节码操作封装起来提供的API确实很好操作,在一些场景下也不需要考虑 JVM 中局部变量和操作数栈。但如果需要更高的性能,可以考虑使用 ASM

字节码编程,Javassist篇三《使用Javassist在运行时重新加载类「替换原方法输出不一样的结果」》相关推荐

  1. 字节码编程,Byte-buddy篇二《监控方法执行耗时动态获取出入参类型和值》

    作者:小傅哥 博客:https://bugstack.cn - 汇总系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 案例是剥去外衣包装展示出核心功能的最佳学习方式! 就像是我们研 ...

  2. 字节码增强技术 Byte Buddy 、Javassist、Instrumentation

    概述 字节码增强技术 有 Byte Buddy .Javassist等多种. 如果是在同一个包中,没有问题,不需借助Instrumentation 如果是第三方包,想不修改代码的情况下实现代理技术,就 ...

  3. 牛散村:Java字节码编程javassist的详细介绍

    本篇文章将和大家分享一下关于Java字节码编程中一个非常之好用的技术javassist,下面将详细为大家介绍一下javassist技术,以及具体实例代码讲解. 一.Javassist入门 (一)Jav ...

  4. 字节码编程 | 使用Javassist动态生成Hello World

    大家好,我是冰河~~ 字节码编程在实际的业务开发(CRUD)中并不常用,但是随着网络编程,RPC.动态字节码增强技术和自动化测试以及零侵入APM监控的不断发展与大量使用,越来越多的技术需要使用到字节码 ...

  5. 字节码编程,Byte-buddy篇三《使用委托实现抽象类方法并注入自定义注解信息》

    作者:小傅哥 博客:https://bugstack.cn - 汇总系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 截至到本章节关于字节码框架 Byte-buddy 的大部分常用 ...

  6. 深入字节码操作:使用ASM和Javassist创建审核日志

    深入字节码操作:使用ASM和Javassist创建审核日志 原文链接:https://blog.newrelic.com/2014/09/29/diving-bytecode-manipulation ...

  7. aop 获取方法入参出参_ASM字节码编程 | JavaAgent+ASM字节码插桩采集方法名称及入参和出参结果并记录方法耗时...

    作者:小傅哥 博客:bugstack.cn ❝ 沉淀.分享.成长,让自己和他人都能有所收获! ❞ 一.前言 在我们实际的业务开发到上线的过程中,中间都会经过测试.那么怎么来保证测试质量呢?比如:提交了 ...

  8. 字节码编程 | 工作多年的你依然重复做着CRUD?是否接触过这种技术?

    大家好,我是冰河~~ 最近和不少小伙伴聊天,发现大部分小伙伴,其中可能就包括正在看文章的你和我,工作时间已经不短了,有些小伙伴工作3~5年了,有些甚至超过8年了. 但是大部分小伙伴平时的工作都是在简单 ...

  9. ASM字节码编程 | JavaAgent+ASM字节码插桩采集方法名称以及入参和出参结果并记录方法耗时

    作者:小傅哥 博客:bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 在我们实际的业务开发到上线的过程中,中间都会经过测试.那么怎么来保证测试质量呢?比如:提交了多少代码 ...

最新文章

  1. 2014-11-18--Hadoop的基础学习(五)--编写不同MapReudce程序及其特性(下)
  2. Keil使用 fromelf 生成bin文件
  3. 网易有毛病,我的账号被锁了,去解锁时候又几把提示不成功,浪费劳资感情啊
  4. B1013 数素数(20分)
  5. Android配置build.gradle解锁更高逼格玩法(多版本共存、分服务器打包等)
  6. 注意:C语言结构体里不能赋初始值!
  7. 必要商城MySQL开发规范
  8. 欧拉函数的性质及其证明
  9. MySQL详细知识点总结 可以收藏啦
  10. 【编译原理笔记08】语法制导翻译:语法制导定义,SSD的求值顺序,S属性定义与L属性定义
  11. library的英语怎么读音_英语元音与辅音
  12. 华三 h3c VRRP、MSTP、OSPF综合实验
  13. paip.C#.NET图形按钮制做
  14. Java-实现简单取色器
  15. Arcpy基础入门-1、如何使用arcpy
  16. iis6.0远程代码执行漏洞
  17. Excel密码保护怎么解密码
  18. PS选区工具和羽化的运用
  19. Microbiome | 水科院南海所姜敬哲团队揭示滤食性牡蛎体内巨大的病毒多样性
  20. 高企认定评分标准有哪些?

热门文章

  1. 第十四章 传奇的篇章仍将继续
  2. WORD研究:“允许标点溢出边界”在稿纸下有用,其他情况下很不明显
  3. 计算机存储和处理文档的汉字时 使用的是,理论练习题-04习题四文字处理与编辑排版...
  4. C/S、B/S架构,云服务
  5. 高端骨传导耳机来袭,最强旗舰机南卡Runner Pro4测评!
  6. js Notification 通知
  7. .net程序员转行做手游开发经历(四)
  8. jar包的main入口
  9. 大学生必须知道的外国典故
  10. windows本地建立ftp站点,ssl证书设置