Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >字节码编程|使用Javassist动态生成Hello World

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

作者头像
冰河
发布于 2022-06-15 09:12:22
发布于 2022-06-15 09:12:22
57800
代码可运行
举报
文章被收录于专栏:冰河技术冰河技术
运行总次数:0
代码可运行

大家好,我是冰河~

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

好了,我们今天就使用Javassist动态生成一个HelloWorld案例,可以直接到Github和Gitee获取。

Github:https://github.com/sunshinelyz/bytecode Gitee:https://gitee.com/binghe001/bytecode

开发环境

  • JDK 1.8
  • IDEA 2018.03
  • Maven 3.6.0

Maven依赖

在项目的pom.xml文件中添加如下环境依赖。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<properties>
    <javassist.version>3.20.0-GA</javassist.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>${javassist.version}</version>
    </dependency>
</dependencies>

案例效果

整体案例效果其实也是很简单的,学习Java语言时,我们会在命令行打印第一个Hello World程序。今天,我们学习Javassist字节码编程时,也来实现一个HelloWorld程序。

案例的效果就是要生成如下的程序代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package io.binghe.bytecode.javassist.test;

public class HelloWorld {
    public static void main(String[] var0) {
        System.out.println("Javassist Hello World by 冰河(公众号:冰河技术)");
    }

    public HelloWorld() {
    }
}

看看这个效果,像不像我们自己在IDEA中写的Java代码呢?就让我们一起使用Javassist来实现它吧。

案例实现

这个案例其实还是蛮简单的,这里就先直接给出源代码了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * @author binghe (公众号:冰河技术)
 * @version 1.0.0
 * @description 测试使用Javassist生成第一个类HelloWorld
 */
public class GenerateHelloWorldClass {

    /**
     * 创建HelloWorld的类,并返回HelloWorld的Class实例
     */
    public static Class createHelloWorld()throws Exception{
        //使用默认的ClassPool
        ClassPool pool = ClassPool.getDefault();
        //创建一个空类
        CtClass ctClass = pool.makeClass("io.binghe.bytecode.javassist.test.HelloWorld");
        //添加一个main方法
        CtMethod ctMethod = new CtMethod(CtClass.voidType, "main", new CtClass[]{pool.get(String[].class.getName())}, ctClass);
        //将main方法声明为public static类型
        ctMethod.setModifiers(Modifier.PUBLIC + Modifier.STATIC);
        //设置方法体
        ctMethod.setBody("{" +
                "System.out.println(\"Javassist Hello World by 冰河(公众号:冰河技术)\");" +
                "}");
        ctClass.addMethod(ctMethod);

        //将生成的类的class文件输出的磁盘
        ctClass.writeFile();

        //返回HelloWorld的Class实例
        return ctClass.toClass();

    }

    public static void main(String[] args) throws Exception {
        Class clazz = createHelloWorld();
        Object obj = clazz.newInstance();
        Method mainMethod = clazz.getMethod("main", new Class[]{String[].class});
        mainMethod.invoke(obj, new String[1]);
    }
}

接下来,我们根据上述代码来看看Javassist是如何生成完整字节码的。

(1) 在createHelloWorld()方法中创建一个ClassPool,ClassPool本质上就是个CtClass对象容器

(2) 调用ClassPool的makeClass()方法,传入完整的包名+类名生成一个空的类信息。这里传入的完整的包名+类名是io.binghe.bytecode.javassist.test.HelloWorld

(3) 给类添加方法,并设置方法的返回类型、方法名称、参数名(入参和出参)、访问修饰符以及方法体。这里设置的完整方法体如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] var0) {
    System.out.println("Javassist Hello World by 冰河(公众号:冰河技术)");
}

(4) 尽管我们在上述代码中没有显示的创建无参构造函数,但是在编译时,Javassist会自动创建一个HelloWorld类的无参构造函数。

(5) 通过 CtClass的writeFile()方法将内存中的类信息输出到磁盘,这样我们就可以通过IDEA清晰的看到Javassist生成的HelloWorld类了。

(6) 最终在createHelloWorld()方法中调用CtClass的toClass()方法返回Class对象。

(7) 在main()方法中调用createHelloWorld()方法获取Class对象。

(8) 通过反射实例化对象,并通过反射调用生成的HelloWorld类的main()方法。

效果演示

运行GenerateHelloWorldClass类的main()方法,会在顶级工程目录下的io/binghe/bytecode/javassist/test 目录下生成HelloWorld.class文件,具体如下所示。

查看IDEA的输出信息时,发现会输出如下内容。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Javassist Hello World by 冰河(公众号:冰河技术)

Process finished with exit code 0

案例总结

我们使用Javassist实现了创建一个HelloWorld类的功能,字节码编程听起来貌似挺难的,但是在Javassist强大的API下,实现起来还是蛮简单的。

在接下来的一段时间里,冰河会持续输出关于字节码编程的文章,让我们一起精通字节码编程。

好了,今天就到这儿吧,我是冰河,我们下期见~~

冰河从一名普通程序员,短短几年时间,一路进阶成长为互联网高级技术专家,一直致力于分布式系统架构、微服务、分布式数据库、分布式事务与大数据技术的研究。在高并发、高可用、高可扩展性、高可维护性和大数据等领域拥有丰富的架构经验。对HadoopStormSpark,Flink等大数据框架源码进行过深度分析,并具有丰富的实战经验。

出版过三本畅销书《深入理解分布式事务:原理与实战》、《海量数据处理与大数据技术实战》、《MySQL技术大全:开发、优化与运维实战》。写了一本《深入理解高并发编程》电子书全网累计下载45W+,发布了一本全网首个开源的以实战案例为背景的《冰河的渗透实战笔记》电子书,全网五星好评。写的文章多次被微信公众号官方推荐。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 冰河技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
字节码编程|使用Javassist生成JavaBean
在实际工作过程中,我们可以通过对Java的字节码进行插桩,以便拦截我们需要拦截的类和方法,对这些类和方法进行改造或者直接动态生成相应的类来实现拦截的逻辑。
冰河
2021/11/30
1.1K0
字节码编程|使用Javassist生成JavaBean
字节码编程,Javassist篇一《基于javassist的第一个案例helloworld》
在字节码编程方面有三个比较常见的框架;ASM、byte-buddy、Javassist,他们都可以对这字节码进行操作,只是操作方式和控制粒度不同。
小傅哥
2020/04/20
5740
字节码编程,Javassist篇一《基于javassist的第一个案例helloworld》
字节码编程,Javassist篇五《使用Bytecode指令码生成含有自定义注解的类和方法》
到本章为止已经写了四篇关于字节码编程的内容,涉及了大部分的API方法。整体来说对 Javassist 已经有一个基本的使用认知。那么在 Javassist 中不仅提供了高级 API 用于创建和修改类、方法,还提供了低级 API 控制字节码指令的方式进行操作类、方法。
小傅哥
2020/04/30
1.1K0
字节码编程,Javassist篇五《使用Bytecode指令码生成含有自定义注解的类和方法》
字节码编程,Javassist篇二《定义属性以及创建方法时多种入参和出参类型的使用》
在上一篇 Helloworld 中,我们初步尝试使用了 Javassist字节编程的方式,来创建我们的方法体并通过反射调用运行了结果。大致了解到创建在使用字节码编程的时候基本离不开三个核心类;ClassPool、CtClass、CtMethod,它们分别管理着对象容器、类和方法。但是我们还少用一样就是字段;CtFields,在这一章节中我们不止会使用字段,还会创建多个不同入参类型和返回值的学习。
小傅哥
2020/04/21
1.3K0
字节码编程,Javassist篇二《定义属性以及创建方法时多种入参和出参类型的使用》
javassist编程指南==读、写字节码
Javassist是一个处理字节码的类库。Java字节码存储在一个叫做*.class的二进制文件中。每个class文件包含一个java类或者接口。
青山师
2023/05/05
4210
Javassist | 字节码增强技术
Javassist 是一个开源的分析、编辑和创建Java字节码的类库. 其主要优点在于简单快速. 直接使用 java 编码的形式, 而不需要了解虚拟机指令, 就能动态改变类的结构, 或者动态生成类.
一个架构师
2022/06/27
1.1K0
Java 字节码操作示例
Javassist (Java Programming Assistant) makes Java bytecode manipulation simple. It is a class library for editing bytecodes in Java; it enables Java programs to define a new class at runtime and to modify a class file when the JVM loads it. Unlike other similar bytecode editors, Javassist provides two levels of API: source level and bytecode level. If the users use the source-level API, they can edit a class file without knowledge of the specifications of the Java bytecode. The whole API is designed with only the vocabulary of the Java language. You can even specify inserted bytecode in the form of source text; Javassist compiles it on the fly. On the other hand, the bytecode-level API allows the users to directly edit a class file as other editors.
bboy枫亭
2021/12/07
9070
Java 字节码操作示例
javassist编程指南(一)
Javassist是一个处理字节码的类库。Java字节码存储在一个叫做*.class的二进制文件中。每个class文件包含一个java类或者接口。
青山师
2023/05/05
6970
Java Agent(二)、Javassist入门
在 Java Agent 开发中,动态字节码增强是一项核心技术,而 Javassist 是一个高效且易用的字节码操作库。相比其他工具(如 ASM),Javassist 的语法更加接近 Java 源码,降低了学习成本,非常适合作为初学者的入门工具。
有一只柴犬
2025/01/01
1150
Java Agent(二)、Javassist入门
Java字节码修改 - javassist
AOP的实现一般使用了动态代理和字节码修改,本文介绍使用javassist实现类的创建和修改 添加依赖 <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.28.0-GA</version> </dependency> 使用字节码创建一个类 初始化ClassPool ClassPool pool = ClassPool.getDefault();
十毛
2021/11/24
2.3K0
第16次文章:Java字节码
在上一期讲解java的动态性的时候,我们主要提到了java中的反射机制,可以在java代码运行的时候,改变类的结构,属性等信息,而这一节我们通过另一种实现方式来讲解java的动态性,主要就是java的字节码操作。
鹏-程-万-里
2019/09/27
6110
第16次文章:Java字节码
字节码编程|工作多年的你是否接触过这种技术?
最近和不少小伙伴聊天,发现大部分小伙伴,其中可能就包括正在看文章的你和我,工作时间已经不短了,有些小伙伴工作3~5年了,有些甚至超过8年了。
冰河
2022/06/15
5140
字节码编程|工作多年的你是否接触过这种技术?
Java字节码编程之非常好用的javassist
我开发的这个框架,有一个注解,当用户输入变量名,类名的时候,我这个框架可以为其自动生成一个对象,并加载到内存中供以后使用。
手撕代码八百里
2021/04/20
4.2K0
Java字节码编程之非常好用的javassist
字节码操作的手术刀-Javassist
前面文章介绍的 ASM 入门门槛还是挺高的,需要跟底层的字节码指令打交道,优点是小巧、性能好。Javassist 是一个性能比 ASM 稍差但是使用起来简单很多的字节码操作库,不需要了解字节码指令,由东京工业大学的数学和计算机科学系的教授 Shigeru Chiba 开发.
架构狂人
2023/08/16
6700
字节码操作的手术刀-Javassist
使用Javassist来动态创建,修改和代理类
执行以后我们可以在E:\IOC\target\classes\com\guanjian\assist中看见这个.class文件
算法之名
2019/08/20
3.2K0
使用Javassist来动态创建,修改和代理类
Javassist使用指南1
1.创建了一个非默认的classpool,加入当前线程的上下文类加载器作为额外的类搜索路径
老马的编程之旅
2022/06/22
5340
Javassist使用指南1
调研字节码插桩技术,用于系统监控设计和实现
周末熟睡的深夜,突然接到老板电话☎的催促。“赶紧看微信、看微信,咋系统出问题了,我们都不知道,还得用户反馈才知道的!!!”深夜爬起来,打开电脑连上 VPN ,打着哈欠、睁开朦胧的眼睛,查查系统日志,原来是系统挂了,赶紧重启恢复!
小傅哥
2021/07/23
1.1K0
APM - Javassist 入门 生成一个简单类
http://www.javassist.org/tutorial/tutorial.html
小小工匠
2021/08/17
5600
【追光者系列】HikariCP源码分析之字节码修改类库Javassist委托实现动态代理
很多人都会问HikariCP为什么那么快?之前的两篇文章【追光者系列】HikariCP源码分析之FastList 和 【追光者系列】HikariCP源码分析之ConcurrentBag 是第一第二弹,本文就是第三弹。
用户1655470
2018/07/24
2.9K0
【追光者系列】HikariCP源码分析之字节码修改类库Javassist委托实现动态代理
字节码编程,Javassist篇三《使用Javassist在运行时重新加载类》
通过前面两篇 javassist 的基本内容,大体介绍了;类池(ClassPool)、类(CtClass)、属性(CtField)、方法(CtMethod),的使用方式,并通过创建不同类型的入参出参方法,基本可以掌握如何使用这样的代码结构进行字节码编程。
小傅哥
2020/04/22
2.9K1
字节码编程,Javassist篇三《使用Javassist在运行时重新加载类》
推荐阅读
相关推荐
字节码编程|使用Javassist生成JavaBean
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验