1.读写字节码

Javassist是用来处理java字节码的类库。字节码保存在二进制文件中称为类文件。每个类文件夹包括一个java类或接口。

Javasssist.CtClass这个类是一个类文件的抽象表示。一个CtClass(compile-time class编译时类)对象处理一个类文件。下面是个简单的例子:

ClassPool pool = ClassPool.getDefault();CtClass cc = pool.get("test.Rectangle");cc.setSuperclass(pool.get("test.Point"));cc.writeFile();

这个程序首先包括了一个ClassPool对象,它javassist是用来修改字节码的。ClassPool对象是一个CtClass对象容器。它读取类文件根据需要构建CtClass对象,并且记录构建的对象以便响应最新的访问。修改类的定义,用户首先必须从ClassPool对象引用到一个CtClass对象表示。ClassPool中的get()方法就是这个作用。上面的例子展示,CtClass对象表示了ClassPool中的test.Rectangle对象。ClassPool的getDefault()搜索默认的系统搜索路径。

从实现的角度说,ClassPool是一个CtClass对象的hash表,类名做为keyClassPoolget()搜索hash表找到与指定key关联的CtClass对象。如果没有找到CtClass对象,get()读一个类文件构建新的CtClass对象,它是被记录在hash表中然后返回这个对象。

在ClassPool对象中的CtClass对象可以被编辑修改(如何修改在后面说明)。上面的例子中,把test.Rectangle的父类改为了test.Point。这个改变在执行writeFile()后实现。

writeFile()转换CtClass对象到一个类文件中并写到本地磁盘。Javassist还提供了一个方法直接得到修改的字节码。得到字节码,执行toBytecode():byte[] b = cc.toBytecode(); 也以直接载入CtClass:Class clazz = cc.toClass();toClass()请求当前线程的类载入器载入CtClass表示的类文件。它返回一个java.lang.Class对象来表示载入的类。

定义一个新类 定义新类,在ClassPool中执makeClass().

ClassPool pool = ClassPool.getDefault();

CtClass cc = pool.makeClass("Point"); 

这个例子定义了没有成员的Point类。CtNewMethod的工厂方法可以构建Point的成员方法,用CtClass的addMethod()加入到Point中。    makeClass()不能建接口,ClassPool的makeInterface()可以。CtNewMethod的abstractMethod()可以为接口构建方法。 

2.冻结的类

如果CtClass通过writeFile(),toClass(),toBytecode()转换了类文件,javassist冻结了CtClass对象。以后是不允许修改这个 CtClass对象。这是为了警告开发人员当他们试图修改一个类文件时,已经被JVM载入的类不允许被重新载入。

一个冻结的CtClass可以被解冻,因为修改类定义可以被允许。例如:

CtClasss cc = ...;
   :
cc.writeFile();//冻结
cc.defrost();//解冻
cc.setSuperclass(...);   // OK since the class is not frozen.可以重新操作CtClass,因为被解冻了

Defrost()执行后,CtClass对象将可以再次修改。

如果ClassPool.doPruning被设置为true,javassist将修剪被冻结的CtClass对象的数据结构,以减少内存消耗。修剪会丢掉对象中不需要的属性(attribute_info structures)。例如,Code_attribute结构(method bodies)。因此,CtClass对象修剪后,方法的字节码除了方法名,方法签名和注释,其它将不可访问。修剪的CtClass对象并不能再解冻。ClassPool.doPruning默认的值为false。

不允许修剪执行了CtClass.stopPruning()的对象:

CtClasss cc = ...;
cc.stopPruning(true);//不允许修剪CtClass
cc.writeFile();         // convert to a class file.
// cc is not pruned.
注:如果提示例如com.samples.Programmer class is frozen,则肯定执行了writeFile(),toClass(),toBytecode()等操作,只要通过defrost()方法解冻即可,如果出现例如com.samples.Programmer was pruned.,则该CtClass被修剪了,只要通过
stopPruning(true)方法即可阻止修剪

注意:调试的时候,你可能想暂时的停止修剪和冻结并写一个类文件到磁盘,debugWriteFile()是为这个目的做的方法。它停止修剪,写一个类文件,解冻它,然后再次修剪(如果是初始化)。

3.类搜索路径

默认的ClassPool通过static方法ClassPool.getDefault()返回与JVM一样的搜索路径。如果程序运行在一个web服务器,如JBoss,Tomcat,ClassPool对象可以找不到用户的类,因为web 服务器用多个类载入器(class loader)作为载入器。这种情况,附加的类路径必须注册到ClassPool。应该为pool 提供一个ClassPool 对象:

pool.insertClassPath(new ClassClassPath(this.getClass()));

这段程序注册了用来载入类对象的类路径。可以用任何类对象作为参数替换this.getClass()。注册的路径用来载入类 。

可以注册一个目录名作为类搜索路径。例如,下面的例子加入了一个目录/usr/local/javalib作为搜索路径:

ClassPool pool = ClassPool.getDefault();

pool.insertClassPath("/usr/local/javalib");

这个搜索路径不仅可以是目录,还可以是URL:

ClassPool pool = ClassPool.getDefault();

ClassPath cp = new URLClassPath("www.javassist.org", 80, "/java/", "org.javassist.");

pool.insertClassPath(cp);

这个程序加入”http://www.javassist.org:80/java/” 到类搜索路径。这个URL只是搜索属于org.javassist包的类。例如,载入org.javassist.test.Main,它的类文件将被得到:

http://www.javassist.org:80/java/org/javassist/test/Main.class

另外,可以直接把一个byte数组给一个ClassPool对象,构建一个CtClass对象从这个数组。ByteArrayClassPath,例如:

ClassPool cp = ClassPool.getDefault();

byte[] b = a byte array;

String name = class name;

cp.insertClassPath(new ByteArrayClassPath(name, b));

CtClass cc = cp.get(name);

得到的CtClass对象表示通过b指定的一个类,ClassPool从ByteArrayClassPath读一个类文件,如果执行get(),需要用类名。

如果不知道类的全名,可以用ClassPool中的makeClass():ClassPool cp = ClassPool.getDefault();

InputStream ins = an input stream for reading a class file;

CtClass cc = cp.makeClass(ins);

makeClass()从输入流中返回CtClass对象。可以用makeClass()把想要修改的类放入ClassPool。如果搜索路径包括一个大的jar文件,它可以提高性能。当ClassPool需要读取一个类文件,它可以为每个类文件重复搜索整个jar文件夹。makeClass()可以有效的搜索。makeClass()构建的CtClass,保存在ClassPool,并且类文件不再被读。

用户可以扩展类搜索路径。可以定义一个实现ClassPath接口的新类,ClassPool的insertClassPath()给了一个类的实例。它允许一个非标准资源包含在搜索路径中。

Javassist 字节码操作的更多相关文章

  1. JAVAssist字节码操作

    Java动态性的两种常见实现方式 字节码操作 反射 运行时操作字节码可以让我们实现如下功能: 动态生成新的类 动态改变某个类的结构(添加/删除/修改  新的属性/方法) 优势: 比反射开销小,性能高 ...

  2. 字节码操作JAVAssist

    字节码操作Javassist 字节码:字节码是设计被用来将代码高效的传送给多种软件平台.硬件平台,字节码的设计也实现了Java的平台无关性,字节码比机器码更抽象,它通常被认为是包含了一个可执行文件的二 ...

  3. Javassist 字节码 简介 案例 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  4. Javassist 字节码 语法 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  5. 尚学堂 216 java中的字节码操作

    所谓的字节码操作就是操作我们已经加载的字节码 接下来我们重点来讲解javaassist类库 使用需要下载jar包,把jar包添加到对应的工程之后 package com.bjsxt.test; pub ...

  6. Java动态性 字节码操作

    Java动态性的两种常见方式:-字节码操作 - 反射;字节码操作比反射开销小,性能高,JAVAasist性能高于反射,低于ASM 运行时操作字节码可是实现  : 动态生成新的类:动态的改变某个类的结构 ...

  7. [19/04/20-星期六] Java的动态性_字节码操作(Javassist类库(jar包),assist:帮助、援助)

    一.概念 [基本] /** * */ package cn.sxt.jvm; import javassist.ClassPool; import javassist.CtClass; import ...

  8. 8.5(java学习笔记)8.5 字节码操作(javassist)

    一.javassist javassist让我们操作字节码更加简单,它是一个类库,允许我们修改字节码.它允许java程序动态的创建.修改类. javassist提供了两个层次的API,基于源码级别的和 ...

  9. 字节码操作、javassist使用

    一.功能 1.动态生成新的类 2.动态改变某个类的结构(添加.删除.修改   新的属性.方法) 二.优势 1.比反射开销小,性能高 2.JAVAasist性能高于反射,低于ASM 使用javassis ...

随机推荐

  1. Graphics绘图闪烁的问题

    加入获取的boardPanel.CreateGraphics()时候 用这个g去g.Clear(BackColor);时候会闪烁. 解决办法:  在绘图的时候 用 绘图的image的Graphics. ...

  2. NodeJs + mongodb模块demo

    代码比较通俗易懂,但是我还是在这个过程中浪费了不少时间,也算是看到了nodejs中异步的一个小坑.未来的坑还有很多,慢慢找坑填坑吧. 参考资料如下: 1.断言模块 : https://nodejs.o ...

  3. 浅谈系统架构<一>

    前言:博主刚刚从事于Web后端开发与学习不久,开发项目经验也是有限的.不过今天依旧将一些个人的想法记录下来,我的构想或许不太正确,还望各位大牛能给我多多建议. 首先:我们从编程开始讲起 博主是偏向于后 ...

  4. JavaScript中getBoundingClientRect()方法详解

    获取浏览器滚动的高度: scrollTop=document.documentElement.scrollTop || document.body.scrollTop getBoundingClien ...

  5. IIS错误处理集合

    1.编译器错误消息: CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\ya ...

  6. [Head First设计模式]饺子馆(冬至)中的设计模式——工厂模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  7. redis和memcached的区别(总结)

    1.Redis和Memcache都是将数据存放在内存中,都是内存数据库.不过memcache还可用于缓存其他东西,例如图片.视频等等: 2.Redis不仅仅支持简单的k/v类型的数据,同时还提供lis ...

  8. javascript数据结构与算法---列表

    javascript数据结构与算法---列表 前言:在日常生活中,人们经常要使用列表,比如我们有时候要去购物时,为了购物时东西要买全,我们可以在去之前,列下要买的东西,这就要用的列表了,或者我们小时候 ...

  9. 大熊君学习html5系列之------WebStorage(客户端轻量级存储方案)

    一,开篇分析 Hi,大家好!大熊君又和大家见面了,(*^__^*) 嘻嘻……,这系列文章主要是学习Html5相关的知识点,以学习API知识点为入口,由浅入深的引入实例, 让大家一步一步的体会" ...

  10. python 多个 %s 例子

    input = , ) input 为: '{"a" : 1234, "b" : "14289", "c": " ...