分享:ASM动态修改类文件

Hi All,  

*          问题的提出

Unit Test 的运行需要基于MockEJB ,而产品不支持MockEJB ,客户也不同意添加支持,所以尝试通过不修改源文件的情况下,让产品支持MockEJB

研究发现,让产品支持MockEJB ,就需要修改ProxyFactorygetImplementationClass 方法。

 

*          解决之路:

Ø         简述:

一开始研究CglibASM ,发现在内存中直接修改ProxyFactory 类,实现起来很困难,原因有二:

1.     要修改的方法是一个静态的,无法用子类来修改它的行为。

2.     产品是间接调用ProxyFactory (没办法在调用的入口做手脚)

Cglib ASM 的一些使用例子,都是使用生成的子类或加载新构造的类来进行操作,在入口做了改变,而这对于我们行不通。

Aspectj 可以做到我们要的,但是性能太差,所以不予考虑(Gene 的建议)。

于是,我们尝试使用ASM 修改ProxyFactory 类,然后写成class 文件替代原class 文件(物理文件)。修改成功。

Ø         细节:

1)      研究 Cglib ,发现资料少,不能解决问题

2)     转研究ASM ,发现了解决问题的可能,但技术太底层,需要了解字节码

3)     使用ASM ,成功修改ProxyFactorygetImplementationClass 方法

4)     发现需要为ProxyFactory 添加一个无参的构造方法

无参构函的添加对于java 代码的添加很容易,对于字节码的添加却很难,因为需要初始化很多变量。

5)     研究发现:有工具(ASMifierClassVisitor )可以把普通类文件转换为对应的ASM 代码(使用ASMJAVA 代码),于是为了创建生成JAVA 类的ASM 代码,我们可以先写普通的JAVA 代码,然后使用这个工具来转换。

6)     基于工程的修改成功

7)     研究基于Build 安装后目录的(基于jar 包)动态修改

8)     发现奇怪的问题(Jar 包冲突)Ant Build 无法读取类(设置fork=true )等问题,解决它们

9)     修改后的Jar 在运行时报错,修改后的Jar 有问题

10)  研究发现第一次修改类并运行不成功,第二次运行可以成功

11)  AntBuild.xml 中,使用一个target 来运行修改类文件,另一个来运行JUnit ,运行成功

 

*          总结:

从这个问题的提出,到目前的解决,经历了一个漫长的探索,尝试过程,这个过程中对于以后的工作有几点借鉴:

ü         我们有成功的案例可以轻松的修改Class 文件,修改所有变量的值或方法的行为,这么做在有些特殊情况下能起到很好的效果

ü         问题的解决可以更加的灵活

比如对于修改Jar 文件中的特定Class 文件中,出现第一次修改运行失败,第二次运行成功,那么很明显在第一次的修改后运行的仍然是旧的Class 文件,于是很容易想到让JVM 重载修改后的类,可是这么做很麻烦,经过Bruce 的建议,我们尝试使用两个target 来运行我们的程序,一个专门用来修改类文件,另一个来运行Junit Test, 并设置运行时的fork=true, 那么第二次的运行将基于新的JVM ,那么就会使用最新的类来运行,于是问题得到了解决。

ü         可以请教身边的一些同事

对于这个问题我先后请教过 Gene , Shawn , June , Bruce

 

在此,也谢谢 June Bruce 的帮助!

Regards,

Rex Wu

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值