技术控

    今日:136| 主题:49228
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] 字节码操纵技术探秘

[复制链接]
橘虞 发表于 3 天前
96 4

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
大家可能已经非常熟悉下面的处理流程:将一个“.java”文件输入到Java编译器中(可能会使用javac,也可能像ANT、Maven或Gradle这样的构建工具),编译器对其进行分析,最终生成一个或多个“.class”文件。
   
字节码操纵技术探秘-1 (example,machine,虚拟机,编译器,java)

  图1:什么是Java字节码?
  如果从命令行中运行构建,并启用verbose的话,我们能够看到解析文件直到生成“.class”文件这一过程的输出。
  [code]javac -verbose src/com/example/spring2gx/BankTransactions.java[/code]

字节码操纵技术探秘-2 (example,machine,虚拟机,编译器,java)

  所生成的“.class”文件包含了字节码,本质上来讲它就是Java虚拟机(Java virtual machine,JVM)所使用的指令,当程序运行时,它会由Java运行时类加载器进行加载。
  在本文中,我们将会研究Java字节码以及如何对其进行操纵,并探讨人们为何想要这样做。
  字节码操纵框架

  最为流行的字节码操纵框架包括:
  
       
  • ASM   
  • AspectJ   
  • BCEL   
  • Byte Buddy   
  • CGLIB   
  • Cojen   
  • Javassist   
  • Serp  
  本文将会主要关注Javassist和ASM。
  我们为什么应该关注字节码操纵呢?

  很多常用的Java库,如Spring和Hibernate,以及大多数的JVM语言甚至我们的IDE,都用到了字节码操纵框架。另外,它也确实非常有趣,所以这是一项很有价值的技术,掌握它之后,我们就能完成一些靠其他技术很难实现或无法完成的任务。一旦学会之后,我们的发挥空间将是无限的!
  一个很重要的使用场景就是程序分析。例如,流行的bug定位工具FindBugs在底层就使用了ASM来分析字节码并定位bug。有一些软件商店会有一定的代码复杂性规则,比如方法中if/else语句的最大数量以及方法的最大长度。静态分析工具会分析我们的字节码来确定代码的复杂性。
  另外一个常见的使用场景就是类生成功能。例如,ORM框架一般都会基于我们的类定义使用代理的机制。或者,在考虑实现应用的安全性时,可能会提供一种语法来添加授权的注解。在这样的场景下,都能很好地运用字节码操纵技术。
  像Scala、Groovy和Grails这样的JVM语言都使用了字节码操纵框架。
  考虑这样一种场景,我们需要转换库中的类,这些类我们并没有源码,这样的任务通常会由Java profiler来执行。例如,在New Relic,采用了字节码instrumentation技术实现了对方法执行的计时。
  借助字节码操纵,我们可以优化或混淆代码,甚至可以引入一些功能,比如为应用添加重要的日志。本文将会关注一个日志样例,这个样例提供使用这些字节码操纵框架的基本工具。
  我们的样例

  Sue负责一家银行的ATM编程,她有了一项新的需求:针对一些指定的重要操作,在日志中添加关键的数据。
  如下是一个简化的银行交易类,它允许用户通过用户名和密码进行登录、进行一些处理、提取一些钱,然后打印“交易完成”。这里的重要操作就是登录和提款。
  [code]public void login(String password, String accountId, String userName) {
// 登录逻辑
}
public void withdraw(String accountId, Double moneyToRemove) {
// 交易逻辑
}[/code]  为了简化编码,[email protected][email protected]参数索引。借助这一点,她就可以为login和withdraw方法添加注解了。
  [code]/**
* 方法注解,用于识别
* 重要的方法,这些方法的调用需要进行日志记录。
*/
public @interface ImportantLog {
/**
* 需要进行日志记录的方法参数索引。
* 例如,如果有名为
* hello(int paramA, int paramB, int paramC)的方法,我们
* 希望以日志的形式记录paramA和paramC的值,那么fields
* 应该是["0","2"]。如果我们只想记录
* paramB的值,那么fields将会是["1"]。
*/
String[] fields();
}[/code]  对于login方法,Sue希望记录账户Id和用户名,那么她的fields应该设置为“1”和“2”(她不希望将密码展现出来!)。对于withdraw方法,她的fields应该设置为“0”和“1”,因为她希望输出前两个域:账户ID以及要提取的金额,其审计日志理想情况下应该包含如下的内容:
友荐云推荐




上一篇:BitUnmap: Attacking Android Ashmem
下一篇:10 key security terms devops ninjas need to know
酷辣虫提示酷辣虫禁止发表任何与中华人民共和国法律有抵触的内容!所有内容由用户发布,并不代表酷辣虫的观点,酷辣虫无法对用户发布内容真实性提供任何的保证,请自行验证并承担风险与后果。如您有版权、违规等问题,请通过"联系我们"或"违规举报"告知我们处理。

柔安 发表于 3 天前
加关注!
回复 支持 反对

使用道具 举报

1551 发表于 3 天前
说不通啊,楼下的你说咋办?
回复 支持 反对

使用道具 举报

gk7896330 发表于 前天 03:00
泥泞路上的奔驰,永远跑不过高速路上的夏利。说明:”平台很重要!”
回复 支持 反对

使用道具 举报

chaijunbo 发表于 昨天 03:39
钓鱼岛是中国的,沙发是我的!
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表手机版
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )|网站地图 酷辣虫

© 2001-2016 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表