java字节码解析

原文地址:http://blog.csdn.net/wzju64676266/article/details/5874703

相信学java的人都对new  Object();创建对象都很熟悉,但想要真正了解原理就没那么容易!以以下例子为例,解释class代码及执行过程,如有错误,还望各位高手多多指教!

帧的创建如下所示:

 

 

 

class文件格式如下:

 

 

 

程序计数器(pc):每一个Java线程都有一个程序计数器来用于保存程序执行到当前方法的哪一个指令,对于非Native方法,这个区域记录的是正在执行的VM原语的地址,如果正在执行的是Natvie方法,这个区域则为空(undefined)。

程序计数器 例子和图就拿现成的了,直接引用同事的

[java]  view plain copy
  1. public class Demo {  
  2.     public static void foo() {  
  3.         int a = 1;  
  4.         int b = 2;  
  5.         int c = (a + b) * 5;  
  6.     }  
  7. }  

 

 

 

 

 

接下来来看一个例子,源代码如下:

 

[java]  view plain copy
  1. public class Dog {  
  2.     public String name;  
  3.     public int age;  
  4.     public Dog() {  
  5.     }  
  6.     public Dog(String name)  
  7.     {  
  8.         this.name = name;  
  9.     }  
  10.     public Dog(String name, int age)  
  11.     {  
  12.         this.name = name;  
  13.         this.age = age;  
  14.     }  
  15.     public static void  getStaticValue(int j)  
  16.     {  
  17.         int i=j;  
  18.         System.out.println(i);  
  19.     }  
  20.     public  void  getValue(int j)  
  21.     {  
  22.         int i=j;  
  23.         System.out.println(i);  
  24.     }  
  25.     public static void main(String[] args) {  
  26.         try {  
  27.             new Dog().getValue(10);  
  28.         } catch (Exception e) {  
  29.             e.printStackTrace();  
  30.         }  
  31.     }  
  32. }  

如上代码很简单,main方法加上try catch只是为了  让大家看一下java文件生产字节码是怎么样的

 

执行javac  Dog.java文件,生成class文件。然后使用javap -verbose Dog反编译出class代码。

 

生成如下代码:

[java]  view plain copy
  1. Compiled from "Dog.java"  
  2. public class Dog extends java.lang.Object  
  3.   SourceFile: "Dog.java"  
  4.   minor version: 0   // minor version: major version:这两个是表示class文件的主要、副版本号,                           
  5.   major version: 50   //详细见http://blog.csdn.net/xiaxiaorui2003/archive/2009/07/07/4327029.aspx这位兄弟的blog  
  6.   Constant pool:      //常量池,如下以const开头的都是常量池信息,每个class文件都有一些常量池信息  
  7.                      //当线程调用一个方法的时候,jvm会开辟一个帧出来,这个帧包括操作栈、局部变量列表、常量池的引用  
  8.                      //如下以#开头的表示偏移量编号,相当于id号,接下来解释如下代码的作用  
  9. 如下 #11.#31; 这段代码什么作用呢?很简单,就是表示创建Object对象。  
  10. 首先来看.号左边的#11,找到常量池中#11,跳到const #11 = class       #42;    //  java/lang/Object  
  11. 这个表示是一个Object类型,class后面的 #42;表示接下来要跳到常量池中#42  
  12. 找到const #42 = Asciz       java/lang/Object;  表示生成Object类型  
  13. 接下来看.号右边的#31。  
  14. const #31 = NameAndType #16:#17;     //解释:这里指定到#16 #17  
  15. const #16 = Asciz       <init>;  
  16. const #17 = Asciz       ()V;      //解释:到这里完成初始化工作  
  17. //NameAndType表示名字和类型   调用构造方法 的Name都是<init>,   V表示没有返回值     ,()  括号里面是空的表示没有参数  
  18. //到这里完成Dog  
  19. //  
  20. 如下有  :  
  21. Method   //方法  
  22. Field   //类名.属性  
  23. class   //类型  
  24. Asciz   //方法签名  
  25. NameAndType   //变量名和类型  
  26. java类型对应的class文件方法签名的标识符:  
  27. invokespecial  //调用构造方法、父类方法  
  28. invokevirtual  //调用普通方法(非构造方法、static方法)  
  29. invokestatic   //调用static方法  
  30. Ljava/lang/String;;  //这表示String类型,这里要全路径,java/lang/String;;前面的L表示非java八大基本类型  
  31. void V  
  32. int char byte short long float double 都是类型第一个字母(大写)  
  33. boolean 比较特别,用J表示  ,因为B被byte给占用了  
  34. const #1 = Method       #11.#31;        //  java/lang/Object."<init>":()V     解释:初始化Object  
  35. const #2 = Field        #6.#32//  Dog.name:Ljava/lang/String;      Dog类中定义的String name  
  36. const #3 = Field        #6.#33//  Dog.age:I        Dog类中定义的int age  
  37. const #4 = Field        #34.#35;        //  java/lang/System.out:Ljava/io/PrintStream;  
  38. const #5 = Method       #36.#37;        //  java/io/PrintStream.println:(I)V      解释:调用println(int value), V表示返回值是void  
  39. const #6 = class        #38;    //  Dog  
  40. const #7 = Method       #6.#31//  Dog."<init>":()V     解释:初始化Dog,调用构造函数,"<init>"是初始化标识符, V表示返回值是void  
  41. const #8 = Method       #6.#39//  Dog.getValue:(I)V      解释:调用getValue(int j)方法, V表示返回值是void  
  42. const #9 = class        #40;    //  java/lang/Exception  
  43. const #10 = Method      #9.#41//  java/lang/Exception.printStackTrace:()V  
  44. const #11 = class       #42;    //  java/lang/Object  
  45. const #12 = Asciz       name;  
  46. const #13 = Asciz       Ljava/lang/String;;  
  47. const #14 = Asciz       age;  
  48. const #15 = Asciz       I;  
  49. const #16 = Asciz       <init>;  
  50. const #17 = Asciz       ()V;  
  51. const #18 = Asciz       Code;  
  52. const #19 = Asciz       LineNumberTable;  
  53. const #20 = Asciz       (Ljava/lang/String;)V;  
  54. const #21 = Asciz       (Ljava/lang/String;I)V;  
  55. const #22 = Asciz       getStaticValue;  
  56. const #23 = Asciz       (I)V;  
  57. const #24 = Asciz       getValue;  
  58. const #25 = Asciz       main;  
  59. const #26 = Asciz       ([Ljava/lang/String;)V;  
  60. const #27 = Asciz       StackMapTable;  
  61. const #28 = class       #40;    //  java/lang/Exception  
  62. const #29 = Asciz       SourceFile;  
  63. const #30 = Asciz       Dog.java;  
  64. const #31 = NameAndType #16:#17;//  "<init>":()V  
  65. const #32 = NameAndType #12:#13;//  name:Ljava/lang/String;  
  66. const #33 = NameAndType #14:#15;//  age:I  
  67. const #34 = class       #43;    //  java/lang/System  
  68. const #35 = NameAndType #44:#45;//  out:Ljava/io/PrintStream;  
  69. const #36 = class       #46;    //  java/io/PrintStream  
  70. const #37 = NameAndType #47:#23;//  println:(I)V  
  71. const #38 = Asciz       Dog;  
  72. const #39 = NameAndType #24:#23;//  getValue:(I)V  
  73. const #40 = Asciz       java/lang/Exception;  
  74. const #41 = NameAndType #48:#17;//  printStackTrace:()V  
  75. const #42 = Asciz       java/lang/Object;  
  76. const #43 = Asciz       java/lang/System;  
  77. const #44 = Asciz       out;  
  78. const #45 = Asciz       Ljava/io/PrintStream;;  
  79. const #46 = Asciz       java/io/PrintStream;  
  80. const #47 = Asciz       println;  
  81. const #48 = Asciz       printStackTrace;  
  82. {  
  83. public java.lang.String name;  
  84. public int age;  
  85.   
  86. //如下的Locals表示方法内局部变量个数,该例中是1,有些人疑惑的是Dog()中明明没有参数啊,应该是0啊!  
  87. //当线程调用一个方法的时候,jvm会开辟一个帧出来,这个帧包括操作栈、局部变量列表、常量池的引用  
  88. //非static方法,在调用的时候都会给方法默认加上一个当前对象(this)类型的参数,不需要在方法中定义,  
  89. //这个时候局部变量列表中index为0的位置保存的是this,其他索引号按变量定义顺序累加  
  90. //static方法不依赖对象,所以不用传this  
  91. //Args_size表示参数个数,public Dog();会传一个this进去,所以value是1  
  92. public Dog();  
  93.   Code:  
  94.    Stack=1, Locals=1, Args_size=1      
  95.    0:   aload_0    //加载局部变量表index为0的变量,在这里是this  
  96.    1:   invokespecial   #1//Method java/lang/Object."<init>":()V      //调用构造方法  
  97.    4:   return  
  98.   LineNumberTable:      //见如上的class文件结构图  
  99.    line 60  
  100.    line 74  
  101.   LocalVariableTable:     //见如上的class文件结构图  
  102.    Start  Length  Slot  Name   Signature  
  103.      0      5      0    this       LDog;  
  104. //这个构造方法与上个构造方法也是同理,只是多少个String参数和  给name赋值  
  105. public Dog(java.lang.String);  
  106.   Code:  
  107.    Stack=2, Locals=2, Args_size=2  
  108.    0:   aload_0  
  109.    1:   invokespecial   #1//Method java/lang/Object."<init>":()V       
  110.                     //这里的#1;表示对常量池的引用,创建一个类,必须先初始化父类,创建Dog之前创建Object  
  111.    4:   aload_0     //加载局部变量表index为0的变量,在这里是this  
  112.    5:   aload_1     //加载局部变量表index为1的变量,在这里是String name局部变量  
  113.    6:   putfield        #2//Field name:Ljava/lang/String;   赋值操作  
  114.    9:   return  
  115.   LineNumberTable:  
  116.    line 100  
  117.    line 114  
  118.    line 129  
  119.    LocalVariableTable:  
  120.    Start  Length  Slot  Name   Signature  
  121.    0      10      0    this       LDog;  
  122.    0      10      1    name       Ljava/lang/String;  
  123. public Dog(java.lang.String, int);  
  124.   Code:  
  125.    Stack=2, Locals=3, Args_size=3  
  126.    0:   aload_0  
  127.    1:   invokespecial   #1//Method java/lang/Object."<init>":()V  
  128.    4:   aload_0  
  129.    5:   aload_1  
  130.    6:   putfield        #2//Field name:Ljava/lang/String;  
  131.    9:   aload_0  
  132.    10:  iload_2  
  133.    11:  putfield        #3//Field age:I  
  134.    14:  return  
  135.   LineNumberTable:  
  136.    line 150  
  137.    line 164  
  138.    line 179  
  139.    line 1814  
  140.    LocalVariableTable:  
  141.    Start  Length  Slot  Name   Signature  
  142.    0      15      0    this       LDog;  
  143.    0      15      1    name       Ljava/lang/String;  
  144.    0      15      2    age       I  
  145.   
  146. //这里的Args_size=1,是因为是static方法,不会传进this  
  147. public static void getStaticValue(int);  
  148.   Code:  
  149.    Stack=2, Locals=2, Args_size=1  
  150.    0:   iload_0  
  151.    1:   istore_1     //istore_1其实是是有两部分组成,i表示int类型 ,1表示局部变量表中index为1。那合起来就是存储在局部变量表中,index为1的位置  
  152.    2:   getstatic       #4//Field java/lang/System.out:Ljava/io/PrintStream;         //引用常量池 #4;  
  153.    5:   iload_1  
  154.    6:   invokevirtual   #5//Method java/io/PrintStream.println:(I)V     //引用常量池 #5;  
  155.    9:   return  
  156.   LineNumberTable:  
  157.    line 210  
  158.    line 222  
  159.    line 239  
  160.   LocalVariableTable:  
  161.    Start  Length  Slot  Name   Signature  
  162.    0      10      0    j       I  
  163.    2      8      1    i       I  
  164.   
  165. public void getValue(int);  
  166.   Code:  
  167.    Stack=2, Locals=3, Args_size=2  
  168.    0:   iload_1  
  169.    1:   istore_2  
  170.    2:   getstatic       #4//Field java/lang/System.out:Ljava/io/PrintStream;  
  171.    5:   iload_2  
  172.    6:   invokevirtual   #5//Method java/io/PrintStream.println:(I)V  
  173.    9:   return  
  174.   LineNumberTable:  
  175.    line 260  
  176.    line 272  
  177.    line 289  
  178.   LocalVariableTable:  
  179.    Start  Length  Slot  Name   Signature  
  180.    0      10      0    this       LDog;  
  181.    0      10      1    j       I  
  182.    2      8      2    i       I  
  183. public static void main(java.lang.String[]);  
  184.   Code:  
  185.    Stack=2, Locals=2, Args_size=1  
  186.    0:   new     #6//class Dog       解释:创建Dog  
  187.    3:   dup       //复制引用到stack(栈)  
  188.    4:   invokespecial   #7//Method "<init>":()V  
  189.    7:   bipush  10      //压入一个常量10  
  190.    9:   invokevirtual   #8//Method getValue:(I)V  
  191.    12:  goto    20  
  192.    15:  astore_1        
  193.    16:  aload_1  
  194.    17:  invokevirtual   #10//Method java/lang/Exception.printStackTrace:()V  
  195.    20:  return  
  196.   Exception table:  
  197.    from   to  target type  
  198.      0    12    15   Class java/lang/Exception  //表示上面代码从1到12行之间如果发生Exception异常就goto到15处  
  199.   LineNumberTable:  
  200.    line 320  
  201.    line 3512  
  202.    line 3315  
  203.    line 3416  
  204.    line 3620  
  205.     
  206.   LocalVariableTable:  
  207.    Start  Length  Slot  Name   Signature  
  208.    0      21      0    args       [Ljava/lang/String;  
  209.    16      4      1    e       Ljava/lang/Exception;  
  210. }  

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值