Javaassist&ASM

Javaassist

API: http://www.javassist.org/html/index.html

0x00 介绍

Javassist是可以动态编辑Java字节码的类库。它可以在Java程序运行时定义一个新的类,并加载到JVM中;还可以在JVM加载时修改一个类文件。

在Javassist中每个需要编辑的class都对应一个CtCLass实例,CtClass的含义是编译时的类(compile time class),这些类会存储在ClassPool中(Classpool是一个存储CtClass对象的容器)。CtClass中的CtFieldCtMethod分别对应Java中的字段和方法。通过CtClass对象即可对类新增字段和修改方法等操作了。

我们挑几个重要的点去学习,更细节的用法查询文档即可。

  • ClassPool:一个基于HashMap实现的CtClass对象容器,其中键是类名称,值是表示该类的CtClass对象。默认的ClassPool使用与底层JVM相同的类路径,因此在某些情况下,可能需要向ClassPool添加类路径或类字节。
  • CtClass:表示一个类,这些CtClass对象可以从ClassPool获得。
  • CtMethods:表示类中的方法。
  • CtFields :表示类中的字段。

0x01 常用方法

ClassPool

ClassPool getDefault() 返回默认的类池。

ClassPath insertClassPath(String pathname) 在搜索路径的开头插入目录或jar(或zip)文件。

ClassPath insertClassPath(ClassPath cp) ClassPath在搜索路径的开头插入一个对象。

java.lang.ClassLoader getClassLoader() 获取类加载器。

CtClass get(String classname) 读取类文件,并返回CtClass 。

ClassPath appendClassPath(ClassPath cp) 将ClassPath对象附加到搜索路径的末尾。

CtClass makeClass(String classname) 创建一个新的public类

CtClass

void addConstructor(CtConstructor c) 添加构造器

void addMethod(CtMethod m) 添加方法

void setSuperclass(CtClass clazz) 更改超类,除非此对象表示接口。

Class<?> toClass(Lookup lookup) 将此类转换为java.lang.Class对象。

CtConstructor makeClassInitializer() 制作一个空的类初始化程序(静态构造函数)。

byte[] toBytecode() 将该类转换为类文件。

void writeFile() 将此CtClass 对象表示的类文件写入当前目录。

void writeFile(String directoryName) 将由此CtClass 对象表示的类文件写入本地磁盘。

CtMethod

void insertBefore (String src) 在正文的开头插入字节码。

void insertAfter (String src) 在正文的末尾插入字节码。

void setBody (CtMethod src, ClassMap map) 从另一个方法复制方法体

CtConstructor

void setBody(String src) 设置构造函数主体。

void setBody(CtConstructor src, ClassMap map) 从另一个构造函数复制一个构造函数主体。

CtMethod toMethod(String name, CtClass declaring) 复制此构造函数并将其转换为方法。

CtField

int getModifiers() 获取访问修饰符

void setModifiers(int mod) 设置访问权限

0x02 example

个人感觉Javaassist作为一个工具主要在于应用,因此写一个小demo来熟悉熟悉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.get("assist.Demo");
//CtClass ctClass = pool.makeClass("assist.Demo");
ctClass.setSuperclass(pool.get("java.lang.Object")); //设置父类
ctClass.setInterfaces(new CtClass[]{pool.get("java.io.Serializable")});//设置接口继承
//增加属性
CtField ctField0 = CtField.make(" private String field0 = \"value0\";", ctClass);
ctClass.addField(ctField0);
ctField0.setModifiers(Modifier.PRIVATE); //设置属性为私有
//增加方法
CtMethod ctMethod0 = CtMethod.make(" public String method0(String string){\n" +
" return \"method0\";\n" +
" }", ctClass);
ctClass.addMethod(ctMethod0);
//增加构造方法
CtConstructor ctConstructor1 = CtNewConstructor.make(" public Demo(int param){\n" +
" System.out.println(\"有参构造方法2,参数值:\"+param+\"\\n\");\n" +
" }", ctClass);
ctClass.addConstructor(ctConstructor1);

System.out.println(Base64.getEncoder().encodeToString(ctClass.toBytecode()));

ASM

https://space.bilibili.com/1321054247/channel/seriesdetail?sid=381716


Javaassist&ASM
http://example.com/2022/06/22/Javaassist&ASM/
Author
springtime
Posted on
June 22, 2022
Licensed under