六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 61|回复: 0

CLASS 文件使用例子四--AOP字节码增强探索二

[复制链接]

升级  1.33%

12

主题

12

主题

12

主题

秀才

Rank: 2

积分
52
 楼主| 发表于 2013-2-3 14:39:22 | 显示全部楼层 |阅读模式
上一篇中我们分析了
 
 
public class HelloWorld{        public static void main(String [] arvgs){          System.out.println("before log");          System.out.println("hello world");        System.out.println("after log");       }    }  和
 
public class HelloWorld{        public static void main(String [] arvgs){        System.out.println("hello world");     }    }  的class文件,最后我们是希望通过直接操作class文件能将简单版本(第二段代码)的行为修改为复杂版本(第一段代码);接下去我们看一下要做的事情:
 
根据上一篇的分析,我们只需要做两件事情,第一步是要新增4个常量,其中两个为
constant_UTF8类型;两个为
constant_String
 ,对应到新增的
before log和after log;第二步是要修改main 函数,改变他的行为;
 
为了方便查阅:我先把简单版本初始的class文件给出:
 
 
00000000h: CA FE BA BE 00 00 00 32 00 1D 0A 00 06 00 0F 09 ; 漱壕...2........00000010h: 00 10 00 11 08 00 12 0A 00 13 00 14 07 00 15 07 ; ................00000020h: 00 16 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 ; .....<init>...()00000030h: 56 01 00 04 43 6F 64 65 01 00 0F 4C 69 6E 65 4E ; V...Code...LineN00000040h: 75 6D 62 65 72 54 61 62 6C 65 01 00 04 6D 61 69 ; umberTable...mai00000050h: 6E 01 00 16 28 5B 4C 6A 61 76 61 2F 6C 61 6E 67 ; n...([Ljava/lang00000060h: 2F 53 74 72 69 6E 67 3B 29 56 01 00 0A 53 6F 75 ; /String;)V...Sou00000070h: 72 63 65 46 69 6C 65 01 00 0F 48 65 6C 6C 6F 57 ; rceFile...HelloW00000080h: 6F 72 6C 64 2E 6A 61 76 61 0C 00 07 00 08 07 00 ; orld.java.......00000090h: 17 0C 00 18 00 19 01 00 0B 68 65 6C 6C 6F 20 77 ; .........hello w000000a0h: 6F 72 6C 64 07 00 1A 0C 00 1B 00 1C 01 00 0A 48 ; orld...........H000000b0h: 65 6C 6C 6F 57 6F 72 6C 64 01 00 10 6A 61 76 61 ; elloWorld...java000000c0h: 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 01 00 10 6A ; /lang/Object...j000000d0h: 61 76 61 2F 6C 61 6E 67 2F 53 79 73 74 65 6D 01 ; ava/lang/System.000000e0h: 00 03 6F 75 74 01 00 15 4C 6A 61 76 61 2F 69 6F ; ..out...Ljava/io000000f0h: 2F 50 72 69 6E 74 53 74 72 65 61 6D 3B 01 00 13 ; /PrintStream;...00000100h: 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 ; java/io/PrintStr00000110h: 65 61 6D 01 00 07 70 72 69 6E 74 6C 6E 01 00 15 ; eam...println...00000120h: 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 ; (Ljava/lang/Stri00000130h: 6E 67 3B 29 56 00 21 00 05 00 06 00 00 00 00 00 ; ng;)V.!.........00000140h: 02 00 01 00 07 00 08 00 01 00 09 00 00 00 1D 00 ; ................00000150h: 01 00 01 00 00 00 05 2A B7 00 01 B1 00 00 00 01 ; .......*?.?...00000160h: 00 0A 00 00 00 06 00 01 00 00 00 01 00 09 00 0B ; ................00000170h: 00 0C 00 01 00 09 00 00 00 25 00 02 00 01 00 00 ; .........%......00000180h: 00 09 B2 00 02 12 03 B6 00 04 B1 00 00 00 01 00 ; ..?...?.?....00000190h: 0A 00 00 00 0A 00 02 00 00 00 03 00 08 00 04 00 ; ................000001a0h: 01 00 0D 00 00 00 02 00 0E                      ; .........  
 
接下去我们开始修改:
1、修改常量池大小,由28修改为32,就是将0x 1D 修改为 21;
2、找到常量池的结束点:0X 3B 29 56 ;在后面增加4个常量:
     08 00 1F
     08 00 20
     01 00 0A  62 5 66 6F 72 65 20 6C 6F 67
     01 00 09  61 66 74 65 72 20 6C 6F 67
第一个常量表示
constant_String
 类型 引用到第31号常量

第二个常量表示
constant_String
 类型 引用到第32号常量

第三个常量表示
constant_UTF8 类型 值为 
before log
第四个常量表示
constant_UTF8
 类型 值为
 after log
 
然后找到main方法:
3、首先找到code处;B2 00 02 12 03 B6 00 04 B1;从上一篇可以发现这段code其实就是System.out.println("hello world");
于是我们在其前后要各增加一段代码:
在前面增加 B2 00 02 12 1D B6 00 04 表示  System.out.println("before log")
在后面增加 B2 00 02 12 1E B6 00 04 表示  System.out.println("after log")
总体就是 B2 00 02 12 03 B6 00 04 B1  改为 B2 00 02 12 1D B6 00 04 B2 00 02 12 03 B6 00 04 B2 00 02 12 1E B6 00 04 B1
 
4、可以发现第三步将代码量增加了16个长度,所以需要修改两处地方,第一次是code的长度由9变为25 (也就是ox09--->ox 19);第二处就是main的长度由37变为53(也就是 ox 25--->ox 35)
 
经过上面的4步就完成了整个修改;最终如下:
 
 
 
00000000h: CA FE BA BE 00 00 00 32 00 21 0A 00 06 00 0F 09 ; 漱壕...2.!......00000010h: 00 10 00 11 08 00 12 0A 00 13 00 14 07 00 15 07 ; ................00000020h: 00 16 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 ; .....<init>...()00000030h: 56 01 00 04 43 6F 64 65 01 00 0F 4C 69 6E 65 4E ; V...Code...LineN00000040h: 75 6D 62 65 72 54 61 62 6C 65 01 00 04 6D 61 69 ; umberTable...mai00000050h: 6E 01 00 16 28 5B 4C 6A 61 76 61 2F 6C 61 6E 67 ; n...([Ljava/lang00000060h: 2F 53 74 72 69 6E 67 3B 29 56 01 00 0A 53 6F 75 ; /String;)V...Sou00000070h: 72 63 65 46 69 6C 65 01 00 0F 48 65 6C 6C 6F 57 ; rceFile...HelloW00000080h: 6F 72 6C 64 2E 6A 61 76 61 0C 00 07 00 08 07 00 ; orld.java.......00000090h: 17 0C 00 18 00 19 01 00 0B 68 65 6C 6C 6F 20 77 ; .........hello w000000a0h: 6F 72 6C 64 07 00 1A 0C 00 1B 00 1C 01 00 0A 48 ; orld...........H000000b0h: 65 6C 6C 6F 57 6F 72 6C 64 01 00 10 6A 61 76 61 ; elloWorld...java000000c0h: 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 01 00 10 6A ; /lang/Object...j000000d0h: 61 76 61 2F 6C 61 6E 67 2F 53 79 73 74 65 6D 01 ; ava/lang/System.000000e0h: 00 03 6F 75 74 01 00 15 4C 6A 61 76 61 2F 69 6F ; ..out...Ljava/io000000f0h: 2F 50 72 69 6E 74 53 74 72 65 61 6D 3B 01 00 13 ; /PrintStream;...00000100h: 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 ; java/io/PrintStr00000110h: 65 61 6D 01 00 07 70 72 69 6E 74 6C 6E 01 00 15 ; eam...println...00000120h: 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 ; (Ljava/lang/Stri00000130h: 6E 67 3B 29 56 08 00 1F 08 00 20 01 00 0A 62 65 ; ng;)V..... ...be00000140h: 66 6F 72 65 20 6C 6F 67 01 00 09 61 66 74 65 72 ; fore log...after00000150h: 20 6C 6F 67 00 21 00 05 00 06 00 00 00 00 00 02 ;  log.!..........00000160h: 00 01 00 07 00 08 00 01 00 09 00 00 00 1D 00 01 ; ................00000170h: 00 01 00 00 00 05 2A B7 00 01 B1 00 00 00 01 00 ; ......*?.?....00000180h: 0A 00 00 00 06 00 01 00 00 00 01 00 09 00 0B 00 ; ................00000190h: 0C 00 01 00 09 00 00 00 35 00 02 00 01 00 00 00 ; ........5.......000001a0h: 19 B2 00 02 12 1D B6 00 04 B2 00 02 12 03 B6 00 ; .?...?.?...?000001b0h: 04 B2 00 02 12 1E B6 00 04 B1 00 00 00 01 00 0A ; .?...?.?.....000001c0h: 00 00 00 0A 00 02 00 00 00 03 00 08 00 04 00 01 ; ................000001d0h: 00 0D 00 00 00 02 00 0E                         ; ........ 运行结果如下:


 
 
具体的修改点可以查看下图
 

 
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表