现在的位置: 首页 > 综合 > 正文

java字节码

2013年04月14日 ⁄ 综合 ⁄ 共 2465字 ⁄ 字号 评论关闭

之前在做findbugs的时候经常会查看字节码,都是一知半解的
那天看到一个问题,刚好可以从字节码来解释

这些题目常见于面试题,通常要是谁敢这么写代码,完全是在找死。。

Java代码 复制代码
  1. public class Test {   
  2.     public static void main(String[] args) {   
  3.         int i=0;   
  4.         i=i++;   
  5.         System.out.println(i);   
  6.     }   
  7. }  

大家说这里为什么会输出0呢,这里我们从字节码的角度解释
通过反编命令javap –c classname来获得字节码

Java代码 复制代码
  1. Compiled from "Test.java"  
  2. public class Test extends java.lang.Object{   
  3. public Test();   
  4.   Code:   
  5.    0:   aload_0   
  6.    1:   invokespecial   #8//Method java/lang/Object."<init>":()V   
  7.    4:   return  
  8.   
  9. public static void main(java.lang.String[]);   
  10.   Code:   
  11.    0:   iconst_0   
  12.    1:   istore_1   
  13.    2:   iload_1   
  14.    3:   iinc    11  
  15.    6:   istore_1   
  16.    7:   getstatic   #16//Field java/lang/System.out:Ljava/io/PrintStream;   
  17.    10:  iload_1   
  18.    11:  invokevirtual   #22//Method java/io/PrintStream.println:(I)V   
  19.    14:  return  
  20.   
  21. }  

这里我们主要看main方法里面的,附上解释

Java代码 复制代码
  1. 0:  iconst_0        这里是声明了一个常量0,并压入堆栈   
  2. 1:  istore_1        将常量0弹出赋值给本地便量表index为1位置的变量(也就是i)   
  3.     以上完成了int i=0  
  4. 2:  iload_1     把本地变量表index为1的位置的值(也就是i的值)压入堆栈   
  5.   
  6. 3:  iinc    11        i的值加1也就是将本地便量表index为1的位置的值加1,但是相应的堆栈里面没有加   
  7. 上完成了i++   
  8. 6:  istore_1        将堆栈里面的0弹出赋值给i(也就是0赋值给了i)   
  9. 里完成了i=i++  

总的来说是因为在执行++的之前会先把i的值放入栈保存,然后在执行++,但是++仅改变了值不会改变堆栈里面的值,所以当执行完毕后,弹出堆栈的值仍然是0,所以i最后还是0

jvm的字节码就像C的汇编,会在根本上解决很多问题,另外熟悉也会提高我们代码效率

以下代码X可为a、d、f、l或者i。
其中a指引用、b指布尔类型、c指字符、d指双精度类型、f指浮点类型、i指整型、l指长整型、s指短整型。

堆栈操作。
pop、pop2:将堆栈的值弹出。pop2用来弹出64位的值(long、double),pop弹出32位的。
const_null将null的引用推送至堆栈。
bipush将单字节的常量值(-127~128)推送至堆栈。
sipush将一个短整型类型的常量值(-32K~32K)推送至堆栈。
ldc将常量值从常量池中推送至堆栈。
Xload,是将一个本地的X类型(参数或变量)推送至堆栈。
Xstore,将堆栈顶端的X类型的值弹出并放入本地分片中。
Xconst_Y 用来将X类型的常量Y值推送至堆栈。如,iconst_0就是将整数常量0推送至堆栈中。

分支与控制流。
nop,什么也不做。
if(条件),条件可以是null(==null)、notnull(!=null)、eq、ne、gt、lt、_icmpeq、_icmpne……。
goto N。跳至指令号N。
return和Xreturn。X可以为a、d、f、l或者i,从当前调用方返回,将堆栈顶端作为X类型返回。

【上篇】
【下篇】

抱歉!评论已关闭.