1.创建了一个非默认的classpool,加入当前线程的上下文类加载器作为额外的类搜索路径

val classPool = ClassPool(false)
classPool.appendClassPath(LoaderClassPath(contextClassLoader))

ClassPool

ClassPool是CtClass对象的容器,每一个CtClass对象都必须从ClassPool中获取。

ClassPool自身可以形成层级结构,其工作机制与java的类加载器类似,只有当父节点找不到类文件时,才会调用子节点的get()方法。通过设置 ClassPath.childFirstLookup 属性可以调整其工作流程。

需要注意的是ClassPool会在内存中维护所有被它创建过的CtClass,当CtClass数量过多时,会占用大量的内存,API中给出的解决方案是周期性的调用compress方法 或 重新创建ClassPool 或 有意识的调用CtClass的detach()方法以释放内存。

需要关注的方法:

1.getDefault : 返回默认的ClassPool,单例模式!一般通过该方法创建我们的ClassPool。

2.appendClassPath, insertClassPath : 将一个ClassPath加到类搜索路径的末尾位置 或 插入到起始位置。通常通过该方法写入额外的类搜索路径,以解决多个类加载器环境中找不到类的尴尬。

3.toClass : 将修改后的CtClass加载至当前线程的上下文类加载器中,CtClass的toClass方法是通过调用本方法实现。需要注意的是一旦调用该方法,则无法继续修改已经被加载的class。

4.get , getCtClass : 根据类路径名获取该类的CtClass对象,用于后续的编辑。

ClassPath

lassPath是一个接口,代表类的搜索路径,含有具体的搜索实现。当通过其它途径无法获取要编辑的类时,可以尝试定制一个自己的ClassPath。API提供的实现中值得关注的有:

1.ByteArrayClassPath : 将类以字节码的形式加入到该path中,ClassPool 可以从该path中生成所需的CtClass。

2.ClassClassPath : 通过某个class生成的path,通过该class的classloader来尝试加载指定的类文件。

3.LoaderClassPath : 通过某个classloader生成path,并通过该classloader搜索加载指定的类文件。需要注意的是该类加载器以弱引用的方式存在于path中,当不存在强引用时,随时可能会被清理。

CtClass

javassist为每个需要编辑的class都创建了一个CtClass对象,通过对CtClass对象的操作来实现对class的编辑工作。

该类方法较多,此处列出需要重点关注的方法:
1.freeze : 冻结一个类,使其不可修改。
2.isFrozen : 判断一个类是否已被冻结。
3.prune : 删除类不必要的属性,以减少内存占用。调用该方法后,许多方法无法将无法正常使用,慎用。
4.defrost : 解冻一个类,使其可以被修改。如果事先知道一个类会被defrost, 则禁止调用 prune 方法。
5.detach : 将该class从ClassPool中删除。
6.writeFile : 根据CtClass生成 .class 文件。
7.toClass : 通过类加载器加载该CtClass。

CtMethod

CtMthod代表类中的某个方法,可以通过CtClass提供的API获取或者CtNewMethod新建,通过CtMethod对象可以实现对方法的修改。

需要注意的是写入方法体的代码无法访问在其它地方定义的成员变量,一些比较重要的方法:

1.insertBefore : 在方法的起始位置插入代码。

2.insterAfter : 在方法的所有 return 语句前插入代码以确保语句能够被执行,除非遇到exception。

3.insertAt : 在指定的位置插入代码。

4.setBody : 将方法的内容设置为要写入的代码,当方法被 abstract修饰时,该修饰符被移除。

5.make : 创建一个新的方法。

CtNewMethod

提供各种静态方法来操作CtMethod,不进行详细描述,有兴趣可以看下API。

特殊符号
$0, $1, $2, … this and actual parameters
$args An array of parameters. The type of $args is Object[].
Allactualparameters.Forexample,m(All actual parameters.For example, m(Allactualparameters.Forexample,m() is equivalent to m($1,$2,…)
$cflow(…) cflow variable
$r The result type. It is used in a cast expression.
$w The wrapper type. It is used in a cast expression.
$_ The resulting value
$sig An array of java.lang.Class objects representing the formal parameter types
$type A java.lang.Class object representing the formal result type.
$class A java.lang.Class object representing the class currently edited.

使用场景总结

1.实现代码插入功能:

CtClass ctClass = classPool.getCtClass("com.netease.HelloWorld");
CtMethod ctMethod = ctClass.getDeclaredMethod("sayHello");
ctMethod.insertAfter("System.out.println(\"Hello world!\");");
ctClass.toClass();

2.创建一个完整的类:

ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.makeClass("com.netease.Class");CtField ctField = new CtField(classPool.get("java.lang.String"), "teacher", ctClass);
ctField.setModifiers(Modifier.PRIVATE);
ctClass.addField(ctField);ctClass.addMethod(CtNewMethod.setter("setTeacher", ctField));
ctClass.addMethod(CtNewMethod.getter("getTeacher", ctField));
ctClass.writeFile();

3.实现拦截器功能:

CtMethod ctMethod = clazz.getDeclaredMethod(method);
String newName = method + "New";
ctMethod.setName(newName);
CtMethod newCtMethod = CtNewMethod.copy(ctMethod, method, clazz, null);
String type = ctMethod.getReturnType().getName();
StringBuilder body = new StringBuilder();
body.append("{\n System.out.println(\"Before Method Execute...\");\n");
if(!"void".equals(type)) {body.append(type).append(" result = ");
}
body.append(newName).append("($$);\n");
body.append("System.out.println(\"After Method Execute...\");;\n");
if(!"void".equals(type)) {body.append("return result;\n");
}
body.append("}");
newCtMethod.setBody(body.toString());
clazz.addMethod(newCtMethod);

Javassist使用指南1相关推荐

  1. javassist编程指南(一)

    javassist编程指南(主译) javassist是什么? Javassist(Java 编程辅助)使得Java字节码操作更简单. Javassist可用于编辑字节码的类库. 允许Java程序可以 ...

  2. Javassist 使用指南(一)

    本文译自: Javassist Tutorial-1 原作者: Shigeru Chiba 完成时间:2016年11月 1. 读写字节码 我们知道 Java 字节码以二进制的形式存储在 class 文 ...

  3. javassist编程指南==读、写字节码

    读.写字节码 Javassist是一个处理字节码的类库.Java字节码存储在一个叫做*.class的二进制文件中.每个class文件包含一个java类或者接口. javassist.CtClass代表 ...

  4. Javassist 使用指南

    说明:翻译的太好,怕原文丢失就转载了. 1. 读写字节码 我们知道 Java 字节码以二进制的形式存储在 class 文件中,每一个 class 文件包含一个 Java 类或接口.Javaassist ...

  5. Javassist 使用指南 侵立删

    1. 读写字节码 我们知道 Java 字节码以二进制的形式存储在 class 文件中,每一个 class 文件包含一个 Java 类或接口.Javaassist 就是一个用来处理 Java 字节码的类 ...

  6. Javassist 指南1

    1.读写字节码 Javassist 是一个能处理 Java字节码 的类库,Java字节码存储在class文件中,每一个class文件都包含了一个Java类或一个接口类. 在Javassist中,使用J ...

  7. Java降落伞_javassist使用指南

    Java 字节码以二进制的形式存储在 .class 文件中,每一个 .class 文件包含一个 Java 类或接口.Javaassist 就是一个用来 处理 Java 字节码的类库.它可以在一个已经编 ...

  8. Android 中使用Javassist

    Javassist Javassist 是一个执行字节码操作的库.它可以在一个已经编译好的类中添加新的方法,或者是修改已有的方法,并且不需要对字节码方面有深入的了解. Javassist 可以绕过编译 ...

  9. Java字节码instrument研究

    MyAgent项目 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="h ...

最新文章

  1. Java基类共同属性设置_java – 你有一个Hibernate实体的基类吗?
  2. 将图片的每个像素进行分类
  3. mysql 查询字段语句_mysql查询语句常用字段操作函数
  4. PHP空指针,PHP 5.3.7之前版本空指针引用拒绝服务漏洞
  5. 计算机c盘用户,windows 7 c盘的用户文件夹users如何转移
  6. Html 按钮button加超链接
  7. java应用诊断工具-Cubic v1.3.0
  8. Hadoop日志分析工具——White Elephant
  9. 题解——loj6278 数列分块入门2 (分块)
  10. [翻译] DBCamera 轻量级定制摄像头
  11. matlab 图片最多显示几张_matlab 如何一次显示多个图像,subplot不合适
  12. 开发前奏曲之添加Android SDK平台工具
  13. 如何为计算机设置ip地上,电脑ip地址设置为多少
  14. [翻译]pb技巧、代码和实用工具[程序员家园论坛]
  15. ArrayList.toArray()的用法
  16. 我仿佛又看到了岳父亲坐在办公桌前孜孜不倦读书的情景
  17. 华为笔记本转轴坏了修复指南记录
  18. ES6面试、复习干货知识点汇总
  19. 解决Win10/11有线网(包括校园网)频繁掉线问题
  20. 移动开发——问卷调查

热门文章

  1. 几分钟搞懂Vuex(State,Mutations,Actions)
  2. 堕落之后重新开始学习
  3. 神秘的移动电商:服务三低人群
  4. 设计模式概述 以及 23种设计模式的介绍
  5. 【约稿】给自己交一份年度总结——我的2014年
  6. Matlab里电抗模块,MATLABsimulink在电机中的仿真全解.ppt
  7. UE4 动画系统 源码及原理剖析
  8. 深度学习实战---猫狗大战(pytorch实现)
  9. asp.net WebApi 返回html页面
  10. c语言括号表示法画树怎么画,树的画法分类讲解