我们爱分享第二季 --- Javap 的使用

teemai 2014-04-07 10:13:02
加精
现在Java反编译工具或者插件非常多,也非常好用。比如我用的比较多得jd-gui。所以我们可能很少有机会使用到Javap命令。
这里我简单介绍下Javap,带各位入个门。介绍下这个命令不是使用它进行反编译,而是查看java编译器为我们生成 的字节码,通过比较字节码和源代码,我们可以发现很多的问题,一个很重要的作用就是了解很多编译器内部的工作机制。
下面我们通过具体的一个例子来简单的讲讲这个工具的作用,你不需要很深入的使用,这个简单的介绍和简单的使用就可以使你受益非浅。
首先我们先写一个非常简单的Java源文件:


class StringTest {
public static void main(String[] args) {
int i = 2;
int j = 3;
}
}

使用Javac 命令进行编译:

javac -g StringTest.java

最终有两个文件:


user ~/csdn_test/session1$ls -l
total 16
-rw-r--r-- 1 user staff 417 4 7 21:54 StringTest.class
-rw-r--r-- 1 user staff 99 4 7 21:53 StringTest.java


以上步骤涉及到JAVA环境变量配置,不会的自己google,或者发帖询问。这里使用了-g命令,意思是生成所有调试信息。(javac -help可以查看)
下面我们分2步来看看javap的显示结果:
1.不带任何参数使用javap StringTest

这里我们可以看到的信息有,从哪个文件(StringTest.java)编译过来的。类里面调用两个方法,一个是默认的构造函数,一个是main方法。在没有显式声明构造方法时,会产生一个默认构造方法。这也验证了,为什么一个对象,默认总是先执行构造函数,特别是在继承的场合下,使用这个命令就可以看的很清楚了。
2.使用-c参数javap -c StringTest

带-p参数将额外的打印字节码信息。前面的和不带参数的输出一样,后面的显示了方法的具体的字节码,从这个输出里面我们又可以了解更多的内容。
首先是编译器生成的的缺省构造方法的内容为调用父类的构造方法super(), main()方法的字节码信息的内容这里简单解释下:

Code:
0: iconst_2 //把2放到栈顶
1: istore_1 //把栈顶的值放到局部变量1中,即i中
2: iconst_3 //把3放到栈顶
3: istore_2 //把栈顶的值放到局部变量1中,即j中
4: return
所以再根据开始的java源码对照,对于 int i = 2;首先它会在栈中创建一个变量为i的引用,然后查找有没有字面值为2的地址,没找到,就开辟一个存放2这个字面值的地址,然后将i指向2的地址。j也是类似的。
延伸学习:
1、如果将main中的变量换成String 类型的,然后看看javap的结果。
比如:
String a = "a";
String b = "b";
String ab = "ab";
String ab1 = a + b;
String ab2 = "a" + "b"

2、使用更多的参数分析其结果,如javap -l xxx javap -p xxx(提示 -p会显示private相关的)


这几个参数几乎就可以构成javap的最常使用的集合,最常用的应该还是-c选项,因为可以打印字节码的信息,关于这些字节码的详细涵义在Java 虚拟机规范中定义,感兴趣的可以自己去找找相关资料。
...全文
1557 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
鸥翔鱼游1 2014-04-28
  • 打赏
  • 举报
回复
来占个座 楼主不介意吧
lhw7791086 2014-04-15
  • 打赏
  • 举报
回复
meiyouyangqideyu0 2014-04-12
  • 打赏
  • 举报
回复
真的很有用,赞
meiyouyangqideyu0 2014-04-12
  • 打赏
  • 举报
回复
cooldada 2014-04-11
  • 打赏
  • 举报
回复
你这讲 清晰多了
铁匠梁 2014-04-11
  • 打赏
  • 举报
回复
这个可以鼎,原来可以自己来反编译。前提是不要混淆
u014654468 2014-04-11
  • 打赏
  • 举报
回复
  • 打赏
  • 举报
回复
my03131302 2014-04-09
  • 打赏
  • 举报
回复
iGoach 2014-04-09
  • 打赏
  • 举报
回复
看看,顶一个
alwayshopping 2014-04-08
  • 打赏
  • 举报
回复
赞,总结的很好
alwayshopping 2014-04-08
  • 打赏
  • 举报
回复
很有用,顶一个
七神之光 2014-04-08
  • 打赏
  • 举报
回复
引用 4 楼 ygycomon 的回复:
[quote=引用 3 楼 haorengoodman 的回复:]

Code:  
   0:   iconst_2    //把2放到栈顶  
   1:   istore_1    //把栈顶的值放到局部变量1中,即i中  
   2:   iconst_3    //把3放到栈顶  
   3:   istore_2    //把栈顶的值放到局部变量1中,即j中  
   4:   return 
这些是汇编吗?
虚拟机原语。 LZ的分享很有价值,顶一记[/quote]这有什么价值?整本java虚拟机规范好多这个。。。。感觉这是带着别人读书
致知Fighting 2014-04-08
  • 打赏
  • 举报
回复
引用 3 楼 haorengoodman 的回复:

Code:  
   0:   iconst_2    //把2放到栈顶  
   1:   istore_1    //把栈顶的值放到局部变量1中,即i中  
   2:   iconst_3    //把3放到栈顶  
   3:   istore_2    //把栈顶的值放到局部变量1中,即j中  
   4:   return 
这些是汇编吗?
虚拟机原语。 LZ的分享很有价值,顶一记
haorengoodman 2014-04-08
  • 打赏
  • 举报
回复

Code:  
   0:   iconst_2    //把2放到栈顶  
   1:   istore_1    //把栈顶的值放到局部变量1中,即i中  
   2:   iconst_3    //把3放到栈顶  
   3:   istore_2    //把栈顶的值放到局部变量1中,即j中  
   4:   return 
这些是汇编吗?
  • 打赏
  • 举报
回复
dwtkdmaps1 2014-04-08
  • 打赏
  • 举报
回复
very good
wsay369 2014-04-08
  • 打赏
  • 举报
回复
总结的很好,很有用处
-江沐风- 2014-04-07
  • 打赏
  • 举报
回复
现在或许都去扫墓去了吧!
teemai 2014-04-07
  • 打赏
  • 举报
回复
看着活动参与者真的好少啊。 还是带个头写一篇吧。 博客原文:http://blog.csdn.net/withiter/article/details/23129655

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧