博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对象类JavaSist之ClassPool
阅读量:5757 次
发布时间:2019-06-18

本文共 3901 字,大约阅读时间需要 13 分钟。

查了好多资料,发现还是不全,干脆自己整理吧,至少保证在我的做法准确的,以免误导读者,也是给自己做个记录吧!

    

ClassPool

    

ClassPool对象是一个CtClass对象的容器。一个CtClass对象被构建后,它被记录在ClassPool中。这是因为当编译的原文件关联到CtClass表现的类, 编译器要访问CtClass对象。

    

 

    

  例如,假设一个新方法getter()要加入到CtClass对象表现的的Point类。程序试图编译Point中的方法getter()的源代码,用编译过的代码做为方法内容,将它加到另一个类Line中。如果CtClass对象表现的Point丧失了,编译器将不能编译getter()方法。注册初始的类不包括getter()方法。因此,为了准确的编译一个方法,ClassPool必须拥有程序运行时全部的CtClass实例。

    

 

    

防止内存溢出

    

ClassPool的特点决议了当 CtClass对象数量很多时,它所占的内存会非常大。为了防止这种情况产生,你可以明白的移除一个ClassPool中的不需要的CtClass对象。如果用CtClass的detach()方法,CtClass对象将从ClassPool中移除。例如:

CtClass cc = ... ;
cc.writeFile();
cc.detach();

    

执行deatach()后,将不能执行CtClass对象的任何方法。但是,可以执行ClassPool的get()方法失掉表现同一个类的CtClass实例。执行get()后,ClassPool再次读取类文件,重新建立CtClass对象。

    

 

    

 另一个办法是用新的ClassPool替换老的。如果老的 ClassPool当作垃圾被回收了,它里面的CtClass对象也会被回收,建立新的ClassPool实例,执行下面的代码片段:

       ClassPool cp = new ClassPool(true);
       // if needed, append an extra search path by appendClassPath()

    

 通过ClassPool.getDefault()构建默认行为的ClassPool对象。注意ClassPool.getDefault()是为了方便提供的单子工厂方法。它保持着独自的对象偏重用它。getDefault()返回的ClassPool对象没有特别的作用。getDefault()是一个方便的方法。

    

 注意new ClassPool(true)是个方便的构造器,它构建一个ClassPool对象并加入系统搜索路径。执行它等同于下面的代码:

ClassPool cp = new ClassPool();
cp.appendSystemPath(); // or append another path by appendClassPath()

    

 

    

级联的ClassPools

    

如果程序运行在web服务器中,可能需要建立多个ClassPool;要为每一个类载入器建一个ClassPool。程序将不必getDefault(),用ClassPool构造器建一个ClassPool对象。

    每日一道理
成熟是一种明亮而不刺眼的光辉,一种圆润而不腻耳的音响,一种不需要对别人察颜观色的从容,一种终于停止了向周围申诉求告的大气,一种不理会哄闹的微笑,一种洗刷了偏激的淡漠,一种无须声张的厚实,一种并不陡峭的高度。

    

多个CLassPool对象像java.lang.ClassLoader一样级联起来。例如,

       ClassPool parent = ClassPool.getDefault();
       ClassPool child = new ClassPool(parent);
       child.insertClassPath("./classes");

    

如果执行child.get(),孩子ClassPool首先去查找父ClassPool。如果说父查找失败,孩子再去./classes目录下查找类。

    

如果child.childFirstLookup为true,先在孩子中查找,再到父中查。例如:

  ClassPool parent = ClassPool.getDefault();
ClassPool child = new ClassPool(parent);
child.appendSystemPath();// the same class path as the default one.
child.childFirstLookup = true;   // changes the behavior of the child.

    

改变类名,定义一个新类

    

一个新类可以被定义为已经存在类的拷贝。看下面的程序:

     ClassPool pool = ClassPool.getDefault();CtClass cc = pool.get("Point");cc.setName("Pair");这个程序首先失掉Point作为CtClass对象,然后用setName()为CtClass设置了新的名字Pair,之后CtClass对象的类名被改成Pari,类定义的其他部分没有变。  注意 CtClass的setName()改变了ClassPool中的一个记录。从实现的角度 ,setName()改变的是ClassPool 的hash表中的CtClass对象关联的key。Key从初始的类名改到了新类名。

因此,如果get(“Point”) 再次被执行后,将不能返回cc引用的CtClass对象。ClassPool再次读取Point.class类文件,为Point构建新的CtClass对象。这是因为Point定名的CtClass对象已经不存在了。看下面例子:

     ClassPool pool = ClassPool.getDefault();CtClass cc = pool.get("Point");CtClass cc1 = pool.get("Point");  // cc1 is identical to cc.cc.setName("Pair");CtClass cc2 = pool.get("Pair");   // cc2 is identical to cc.CtClass cc3 = pool.get("Point");  // cc3 is not identical to cc.

Cc1和cc2引用同一个CtClass实例cc,而cc3不是。注意,cc.setName(“Pair”)执行后,CtClass对象Pair 被cc和cc1引用。

 

ClassPool对象用来维持类和CtClass对象之间一对一的关系映射。Javassist不允许用两个有区分的CtClass对象表现同一个类,除非建两个独自CLassPool。这是对程序转换前后有意义的功能。

建立另一个ClassPool默认实例的拷贝,用ClassPool.getDefault()失掉,执行下面代码:

        ClassPool cp = new ClassPool(true);如果有两个ClassPool对象,可以分别从ClassPool中失掉表现同一个类文件的有区分的CtClass对象。可以编辑不同的CtClass对象用来生成不同的类的版本。  改变冻结类名,定义一个新类

当CtClass对象通过writeFile()或toBytecode()转换为类文件,Javassist将拒绝CtClass对象的修改。因此CtClass表现的Point类是被转换到类文件中了,执行setName()不能定义Pair类作为Point的拷贝,它将被拒绝。下面的代码是错误的:

ClassPool pool = ClassPool.getDefault();CtClass cc = pool.get("Point");cc.writeFile();cc.setName("Pair");   // wrong since writeFile() has been called.

为了防止这个制约,可以执行ClassPool的getAndRename()方法,例如:

ClassPool pool = ClassPool.getDefault();

CtClass cc = pool.get("Point");cc.writeFile();CtClass cc2 = pool.getAndRename("Point", "Pair"); 如果执行getAndRename(),ClassPool首先读取Point.class建立一个新的CtClass。但是,它重定名CtClass从Point改成Pair之前,要先在CtClass的Hash表中作记录。因此,writeFile()或toBytecode()执行后可以执行getAndRename()。

文章结束给大家分享下程序员的一些笑话语录: 那是习惯决定的,一直保持一个习惯是不好的!IE6的用户不习惯多标签,但是最终肯定还是得转到多标签的浏览器。历史(软件UI)的进步(改善)不是以个人意志(习惯)为转移的!

--------------------------------- 原创文章 By

对象和类
---------------------------------

转载地址:http://onvkx.baihongyu.com/

你可能感兴趣的文章
我的友情链接
查看>>
HAProxy负载均衡原理及企业级实例部署haproxy集群
查看>>
开源中国动弹客户端实践(三)
查看>>
Win 8创造颠覆性体验:预览版关键更新
查看>>
vim在多文件中复制粘贴内容
查看>>
Android ContentObserver
查看>>
文章“关于架构优化和设计,架构师必须知道的事情”
查看>>
疯狂java学习笔记1002---非静态内部类
查看>>
ISA2006实战系列之一:实战ISA三种客户端部署方案(上)
查看>>
TCP服务器
查看>>
U-Mail邮件系统与泛微OA系统一体化操作指南
查看>>
AC旁挂三层交换机管理ap,二层接入ap心得
查看>>
JS中比较数字大小
查看>>
springcloud 学习-eureka搭建-为eureka添加认证
查看>>
jQuery插件的开发
查看>>
基础,基础,还是基础之JAVA基础
查看>>
如何成为一个C++高级程序员
查看>>
ant android 打包签名和渠道
查看>>
一个简单的接口,被调用并同步给出响应的方法
查看>>
Hadoop序列化与压缩
查看>>