Javassist

article/2025/9/15 5:13:32

Javassist

Javassist是一个开源的分析、编辑和创建Java字节码的类库,可以直接编辑和生成Java生成的字节码。 相对于bcel, asm等这些工具,开发者不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。javassist简单易用, 快速。

(opens new window)

# 一、核心工具类

核心类解释
ClassPooljavassist的类池,使用ClassPool 类可以跟踪和控制所操作的类,它的工作方式与 JVM 类装载器非常相似
CtClassCtClass提供了类的操作,如在类中动态添加新字段、方法和构造函数、以及改变类、父类和接口的方法。
CtField类的属性,通过它可以给类创建新的属性,还可以修改已有的属性的类型,访问修饰符等
CtMethod类中的方法,通过它可以给类创建新的方法,还可以修改返回类型,访问修饰符等, 甚至还可以修改方法体内容代码
CtConstructor与CtMethod类似

# 二、API

# 2.1 ClassPool

// 类库, jvm中所加载的classClassPool pool = ClassPool.getDefault();// 加载一个已知的类, 注:参数必须为全量类名CtClass ctClass = pool.get("com.itheima.Student");// 创建一个新的类, 类名必须为全量类名CtClass tClass = pool.makeClass("com.itheima.Calculator");
1 2 3 4 5 6

# 2.2 CtField

// 获取已知类的属性CtField ctField = ctClass.getDeclaredField("name");// 构建新的类的成员变量CtField ctFieldNew = new CtField(CtClass.intType,"age",ctClass);// 设置类的访问修饰符为publicctFieldNew.setModifiers(Modifier.PUBLIC);// 将属性添加到类中ctClass.addField(ctFieldNew);
1 2 3 4 5 6 7 8

# 2.3 CtMethod

// 获取已有方法//创建新的方法, 参数1:方法的返回类型,参数2:名称,参数3:方法的参数,参数4:方法所属的类CtMethod ctMethod = new CtMethod(CtClass.intType, "calc", new CtClass[]
{CtClass.intType,CtClass.intType}, tClass);// 设置方法的访问修饰ctMethod.setModifiers(Modifier.PUBLIC);// 将新建的方法添加到类中ctClass.addMethod(ctMethod);// 方法体内容代码 $1代表第一个参数,$2代表第二个参数ctMethod.setBody("return $1 + $2;"); CtMethod ctMethod = ctClass.getDeclaredMethod("sayHello");
1 2 3 4 5 6 7 8 9 10 11 12

# 2.4 CtConstructor

// 获取已有的构造方法, 参数为构建方法的参数类型数组CtConstructor ctConstructor = ctClass.getDeclaredConstructor(new CtClass[]{});// 创建新的构造方法CtConstructor ctConstructor = new CtConstructor(new CtClass[]{CtClass.intType},ctClass); ctConstructor.setModifiers(Modifier.PUBLIC);ctConstructor.setBody("this.age = $1;");ctClass.addConstructor(ctConstructor);// 也可直接创建ctConstructor = CtNewConstructor.make("public Student(int age){this.age=age;}", ctClass);
1 2 3 4 5 6 7 8

# 三、示例

public class User {private String name;public User() {}public User(String name) {this.name = name;}public String sayJavassist() {return "Hello Javassist";}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +'}';}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

# 3.1 修改方法

// 类库池, jvm中所加载的classClassPool pool = ClassPool.getDefault();// 获取指定的Student类CtClass ctClass = pool.get("com.example.test.User");// 获取sayHello方法CtMethod ctMethod = ctClass.getDeclaredMethod("sayJavassist");// 在方法的代码后追加 一段代码ctMethod.insertAfter("System.out.println(\"I'm Javassist.\");");// 使用当前的ClassLoader加载被修改后的类Class<?> newClass = ctClass.toClass();User user = (User) newClass.newInstance();System.out.println(user.sayJavassist());
1 2 3 4 5 6 7 8 9 10 11 12

# 3.2 动态添加方法

// 类库池, jvm中所加载的classClassPool pool = ClassPool.getDefault();// 获取指定的Student类CtClass ctClass = pool.get("com.example.test.User");// 增加方法CtMethod ctMethod = new CtMethod(CtClass.intType, "getAgeSum",new CtClass[]{CtClass.intType, CtClass.intType}, ctClass);// 设置方法的访问修饰ctMethod.setModifiers(Modifier.PUBLIC);// 设置方法体代码ctMethod.setBody("return $1 + $2;");// 添加新建的方法到原有的类中ctClass.addMethod(ctMethod);// 加载修改后的类ctClass.toClass();// 创建对象User stu = new User();// 获取calc方法Method dMethod = User.class.getDeclaredMethod("getAgeSum", new Class[]{int.class, int.class});// 反射调用 方法Object result = dMethod.invoke(stu, 10, 20);System.out.println(result);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

# 3.3 动态创建类

// 类库池, jvm中所加载的classClassPool pool = ClassPool.getDefault();// 创建一个学校类CtClass schoolClass = pool.makeClass("com.example.test.School");// 设置为公有类schoolClass.setModifiers(Modifier.PUBLIC);// 获取String类型CtClass stringClass = pool.get("java.lang.String");// 获取list类型CtClass listClass = pool.get("java.util.List");// 获取学生的类型CtClass userClass = pool.get("com.example.test.User");// 给学校添加一个校名属性CtField nameField = new CtField(stringClass, "schoolName", schoolClass);nameField.setModifiers(Modifier.PUBLIC);schoolClass.addField(nameField);// 给学校添加一个学生集合CtField studentList = new CtField(listClass, "users", schoolClass);studentList.setModifiers(Modifier.PUBLIC);schoolClass.addField(studentList);// 给学校一个空构造CtConstructor ctConstructor = CtNewConstructor.make("public School() " +"{this.schoolName=\"湖畔小学\";this.users = new java.util.ArrayList();}", schoolClass);schoolClass.addConstructor(ctConstructor);// 给学校一个addUser的方法CtMethod m = new CtMethod(CtClass.voidType, "addUser", new CtClass[]{userClass}, schoolClass);m.setModifiers(Modifier.PUBLIC);// 添加学生对象到students属性中, $1代表参数1m.setBody("this.users.add($1);");schoolClass.addMethod(m);// 给学校添加一个介绍的方法CtMethod introduce = new CtMethod(CtClass.voidType, "introduce", new CtClass[]{}, schoolClass);introduce.setBody("System.out.println(\"The School name is \" + this.schoolName);");introduce.insertAfter("System.out.println(this.users);");schoolClass.addMethod(introduce);// 加载修改后的学校Class<?> schoolLoadClass = schoolClass.toClass();// 构建一个学校(空构造)Object school = schoolLoadClass.newInstance();// 获取添加用户方法Method addUserMethod = schoolLoadClass.getDeclaredMethod("addUser", userClass.toClass());addUserMethod.invoke(school, new User("小明"));addUserMethod.invoke(school, new User("小张"));// 获取介绍方法,把刚才的信息给打印处理Method introduceMethod = school.getClass().getDeclaredMethod("introduce");introduceMethod.invoke(school);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
The School name is 湖畔小学
[User{name='小明'}, User{name='小张'}]
1 2

http://chatgpt.dhexx.cn/article/ZpDihBHC.shtml

相关文章

[Java基础]—Javassist

Javassist Javassist (JAVA programming ASSISTant) 是在 Java 中编辑字节码的类库;它使 Java 程序能够在运行时定义一个新类, 并在 JVM 加载时修改类文件。原理与反射类似&#xff0c;但开销相对较低。 常用API ClassPool getDefault : 返回默认的 ClassPool 是单例模式的&…

Javassist基本用法

Javassist概述 Javassist是可以动态编辑Java字节码的类库。它可以在Java程序运行时定义一个新的类&#xff0c;并加载到JVM中&#xff1b;还可以在JVM加载时修改一个类文件&#xff0c;添加新的方法&#xff0c;或者是修改已有的方法。Javassist使用户不必关心字节码相关的规范…

Java中的高性能字节码工具:Javassist

前言 一般常见的动态方法调用使用Reflection或者字节码生成技术。虽然JDK已对反射进行了优化但在追求性能的场景中仍然显得性能不佳。本文即是介绍一个面向程序员友好的字节码操作类库javassist。根据benchmark其展现的性能已几乎无异于直接调用。 开源地址&#xff1a;javas…

Java字节码技术javassist

一、Javassist入门 &#xff08;一&#xff09;Javassist是什么 Javassist是可以动态编辑Java字节码的类库。它可以在Java程序运行时定义一个新的类&#xff0c;并加载到JVM中&#xff1b;还可以在JVM加载时修改一个类文件。Javassist使用户不必关心字节码相关的规范也是可以编…

java--javassist学习

Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba &#xff08;千叶 滋&#xff09;所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态AOP框架。javassist是jb…

javassist使用指南

目录 一、快速入门1.1 创建class文件1.2 ClassPool的相关方法1.3 CtClass的相关方法1.4 CtMethod的相关方法1.5 调用生成的类对象1.5.1 通过反射调用1.5.2 通过接口调用 1.6 修改现有的类对象 二、将类冻结三、类搜索路径四、$开头的特殊字符五、ProxyFactory的使用 我们知道Ja…

systemd介绍

由来 Linux 的启动一直采用init进程&#xff0c;这种方法有两个缺点。一是启动时间长。init进程是串行启动&#xff0c;只有前一个进程启动完&#xff0c;才会启动下一个进程&#xff0c;二是启动脚本复杂。init进程只是执行启动脚本&#xff0c;不管其他事情。脚本需要自己处理…

systemd man手册

SYSTEMD&#xff08;1&#xff09;systemd SYSTEMD&#xff08;1&#xff09; 名称 systemd&#xff0c;init-systemd系统和服务管理器 概要 /lib/systemd/systemd [OPTIONS...]init [OPTIONS...] {COMMAND}描述 systemd是Linux操作系统的系统和服务管理器。在启动时作为PID的…

systemd wsl 测试笔记

文章目录 systemd 简介WSL systemdsystemctljournalctlhello serviceSleep 与 Timeout 测试Requires 测试After 测试 systemd 简介 Linux 从关闭到运行, 完整的启动和启动过程有三个主要部分: 硬件启动(Hardware boot): 初始化系统硬件Linux 引导(Linux boot): 加载 Linux 内核…

Linux systemd启动流程

以Ubuntu 18.04.2 LTS为例&#xff0c;列出Systemd启动target中涉及单元(Unit). default.target ( graphical.target by default) graphical.targetRequiresmulti-user.targetWantsdisplay-manager.serviceConflictsrescue.service rescue.targetAftermulti-user.target rescu…

关于 Linux中systemd的一些笔记

写在前面 嗯&#xff0c;准备RHCA&#xff0c;学习整理这部分知识博文内容涉及&#xff1a; systemd简述对于unit的信息的介绍通过systemctl命令控制Service unit的DemoService unit配置文件内容,权值的一些介绍 傍晚时分&#xff0c;你坐在屋檐下&#xff0c;看着天慢慢地黑下…

Linux-Systemd

目录 一、Systemd概述 二、Systemd优势 2.1兼容性 2.2启动速度 2.3systemd 提供按需启动能力 2.4采用 linux 的 cgroups 跟踪和管理进程的生命周期 2.5启动挂载点和自动挂载的管理 2.6实现事务性依赖关系管理 2.7日志服务 2.8 依赖关系 2.9systemd 事务 三、unit(单…

Systemd 简介

一 概述 Linux 服务管理有两种方式service和systemctl。而systemd是Linux系统最新的初始化系统(init)&#xff0c;作用是提高系统的启动速度&#xff0c;尽可能启动较少的进程&#xff0c;尽可能更多进程并发启动&#xff0c;systemd对应的进程管理命令就是systemctl。值得一提…

systemd简介

Systemd 是一个专用于 Linux 操作系统的系统与服务管理器,其目的是要取代Unix时代以来一直在使用的init系统。 systemd概述Systemd 是 Linux 系统中最新的初始化系统(init),它主要的设计目标是克服 sysvinit 固有的缺点,提高系统的启动速度。 systemd框架图 根据 Linux 惯…

Systemd 入门及常用命令

目录 Systemdsystemd架构systemd 系统管理管理系统查看启动耗时查看当前主机的信息 Unit 资源查看当前系统的所有 Unit查看系统状态和单个 Unit 的状态 Unit 管理依赖关系Unit 配置文件查看配置文件的内容 Targettarget&#xff08;Systemd&#xff09; 与 runlevel&#xff08…

systemd 介绍

转自&#xff1a;https://www.linuxidc.com/Linux/2018-03/151291.htm 从 init 系统说起 Linux 操作系统的启动首先从 BIOS 开始&#xff0c;接下来进入 boot loader&#xff0c;由 bootloader 载入内核&#xff0c;进行内核初始化。内核初始化的最后一步就是启动 PID 为 1 的 …

[2020.1.10]systemd介绍

1 systemd基本概念 systemd:a system daemon&#xff0c;相当于以前的init进程&#xff0c;pid1&#xff0c;systemd是1号进程!!! sbin/init --> /lib/systemd/systemd unit: 一个进程,例如lightdm.service job: 一个动作,启动是个job,关闭是个job。开机启动时,systemd…

systemd教程(三)

下来会通过示例来描述不同Service Type值的应用场景。在此之前&#xff0c;强烈建议先阅读前后台进程父子关系和daemon类进程来搞懂进程之间的关系和Daemon类进程的特性。 systemd service&#xff1a;Typeforking 当使用systemd去管理一个长久运行的服务进程时&#xff0c;最…

dpkg打包笔记

dpkg 安装软件 dpkg -i xxx.deb 查看安装目录 dpkg -L xxx 显示版本 dpkg -l xxx 详细信息 dpkg -s xxx 罗列内容 dpkg -c xxxx 卸载软件 dpkg -r xxxx 构建deb包 dpkg -p

dpkg和apt

文章目录 Ubuntu软件安装Deb包安装Deb包简介dpkg常用命令 apt-get源安装apt-get简介apt工作原理apt相关文件常用的apt命令参数apt-getapt-cache dpkg和apt-get的区别 Ubuntu软件安装 Linux有很多种发行版本&#xff0c;各种发行版本之间安装软件方式和命令不一样&#xff0c;同…