在上篇blog的基础上我们来看下接下来两个问题:
- 如何查看生成Class文件
- 如何查看log文件内容
1.查看生成的Class文件
我们是通过ClassCreator来创建Class的。而他是继承自jw.asmsupport.creator.IClassContext的。我们通过调用IClassContext的setClassOutPutPath设置其生成的class的输出路径。比如:creator.setClassOutPutPath(".//target//");接下来我们就可以在当前文件夹下的target文件夹下找到我们生成的class。接下来我们用反编译器打开就可以看到结果。当然我们可能看到的结果格式上是会有错误的, 这是因为class文件里面保存的是堆栈操作的指令,所以只要class文件内的堆栈操作指令是合法的。这个class文件就是可以执行的,但未必反编译就正确,这些说的可能有点抽象。
打个比方:比如我要从上海去北京,我可以选择坐飞机,也可以坐高铁,但是公司只报销乘坐飞机的路费。现在就有两种方案可以选择坐飞机或者高铁。
这里就可以打个比喻来,我们的目的是从上海到北京,我们就可以将它比作class类。这个class类中有坐飞机或者做高铁的指令。最终我们是要拿到公司给报销的,这里的公司就相当于反编译器。具体如下:
- 上海到北京----class
- 坐飞机or坐高铁----指令
- 公司----反编译器
2.如果你是坐高铁,那这个class就只能达到目的不能报销了
以上描述如有不清楚就掠过吧 绞尽脑汁想出的例子
2.如何查看log文件内容
asmsupport采用log4j作为日志工具,配置直接采用log4j的配置。当配置了debug级别的时候会有如下log。 DEBUG [main] create method: ------------main([Ljava/lang/String;) //这里表示开始创建main(String[])方法
DEBUG [main] call method by variable :out //这里表示调用了out变量的方法
DEBUG [main] put variable reference to stack //既然要调用out变量的方法就需要将out变量的引用压入栈
DEBUG [main] get field out from class java.lang.System and push to stack! //通过这句话就能明白原来是调用我们最常见的System.out
DEBUG [main] Instruction : GETSTATIC //表执行JVM指令GETSTATIC(因为out是static类型的所以这里调用GETSTATIC指令获取out)
DEBUG [main] Stack states //接下来这个图表表示的是栈的模型,上面GETSTATIC执行的结果就是返回一个静态field并且压入栈
*********************************
| |Type |
*********************************
| ____ |Ljava/io/PrintStream;|
|/ ___| | |
|\___ \ | |
| ___) | | |
||____/ | |
*********************************
.....
DEBUG [main] store to local variable
DEBUG [main] local variables states //下面这个图表是本地变量的模型,通过图已经看出已经存放了两个本地变量,那他们分别表示什么呢
************************************************
| |Type |Name |Fragment|
************************************************
| _ |[Ljava/lang/String; |args |false | //[Ljava/lang/String;类型不就是上面方法的参数类型吗。没错,这里存放的就是我们方法的参数。
|| | |Ljava/io/PrintStream;|myOut|false | //这里存放的就是上面栈中的out,是如何存的呢,继续往下看
|| | | | | |
|| |___ | | | |
||_____| | | | |
| | | | |
************************************************
DEBUG [main] Instruction : ASTORE //找到了,就是这个指令ASTORE。它就是负责把栈顶元素弹出在然后存到本地变量的。
DEBUG [main] Stack states //往下看 发现栈里面没东西了吧,让ASTORE给拿到local variables里去了
****************
| |Type |
****************
| ____ | |
|/ ___| | |
|\___ \ | |
| ___) | | |
||____/ | |
****************
.....
DEBUG [main] Method : main([Ljava/lang/String;) Maxs(stack:1 locals:2) //这里值分配给栈和本地变量的最大值,通过上面的图就能看到栈和本地变量的最大值是多少了。
当然,这些log是需要你对jvm字节码有一定了解的才能看明白。这个给个网址可以参照:https://www.vmth.ucdavis.edu/incoming/Jasmin/jvmref.html
上文中"如何查看log"这部分内容可能格式看得比较不清楚可以下载如下内容直接用文本工具查看:https://amssupport.googlecode.com/files/READ-LOG.txt
ASMSupport源码地址:https://amssupport.googlecode.com/svn/trunk/
ASMSupport实例地址:http://amssupport.googlecode.com/svn/trunk/asmsupport/src/test/java/example/
以上代码均可通过svn下载
最新asmsupport下载地址:https://amssupport.googlecode.com/files/asmsupport-0.2-alpha-2013-03-25.jar
原文地址:http://my.oschina.net/wensiqun/blog/117382