指令invokespecial

来源:互联网 发布:朱高煦 知乎 编辑:程序博客网 时间:2024/05/24 00:08

主要目的:得到对象存在堆中的地址,这样就可以用当前类,父类,父父类,即继承层的所有对象。

                    把继承层的所有对象的数据和方法为自己当前对象使用,太强大了。

描述一、The two types of compiler-generated methods that may appear in class files are instance

initialization methods (named <init) and class initialization methods  (named <clinit)

编译时产生两种类型方法:

          1、实例初始化方法:<init (),就是编译器为实例变量存放代码的地方。

                如果一个类没有默认无参数的构造器,编译器自动产生一个<init () 方法(在所有.class文件中)。

           2、类初始化方法:<clinit()  

              1>class variable initializers   static int size = 3 * (int) (Math.random() * 5.0);

              2>static initializers 

                static int size;
               static {size = 3 * (int) (Math.random() * 5.0);size = 3 * (int) (Math.random() * 5.0);

   哪么什么时候调用呢:1、类初始化方法 :在 load 一个类之后,jvm  就会调用  <clinit()   进行初始化值。

                                            1、实例初始化:当建立一个类的实例时(new)。

一般以变量的形式出现在源文件中:

一、实例变量(the object's instance variables)和类变量(classvariables

                      实例变量默认调用的方法:<init

                      类变量(带static)默认调用方法:<clinit

二、两种变量存在地方:

                 1、类成员里面

                 2、方法里面

三、  例子,Son .init ()-----Parent.init(),Parent.init()---object.init();           

  1、类成员实例变量 instansV  的方法:因为父,子类都没有构造函数,按理说,这是一个继承层调用方法,一直会调到父类object 对象为止,

           这里Parent<int> 没有调用 object  .<init>:()V 方法,留给父类Parent.class 类去调用。

  2、Son程序执行过程:  

           

     1》load:装入son.class

            第一:run Son application,jvm 根据 Son 找到Son.class,并读入

            第二:Jvm 取出 Son. 类定义数据the constant pool,main()方法的指令bytecodes ,并存入 methode area,

    2》Link:把常量池的所有项(类变量),分配内存空间,并设置一个默认值。

           这个类没有类变量,只有一个实例变量,因为对象还不需要建立,等建立对象后,再来分配实例变量instansV。

   3》initialize:初始化:就是设置实实在在的值。

        没有类变量,也不需要初始化。

   3>Jvm 调用 main() 方法,开始执行Main()方法,解释bytecodes 指令,同时维护指向the constant pool的指针。      

         0: new           #1                  // class Son

              2: indexbyte1, indexbyte2 :Constant pool#1,#2 来确定类,建立一个对象,MethodinstansV压入operand stack

  

         3: dup
         4: invokespecial #12                 // Method "<init>":()V
         7: astore_1
         8: return


 2、main()方法里的实例变量:和上面一样,只调用一次 Son. "<init>":()V

     4: invokespecial #12                 // Method "<init>":()V

public class Parent {
}

public class Son extends Parent {
   Son  instansV=new Son();   //类成员实例变量,objref

  static void main(String[] arg)
  {
 Son MethodinstansV=new Son();//方法里面实例变量 
 
  }
}

 javap -verbose -c -l -constants Son.classConstant pool:
   #1 = Class              #2             // Son
   #2 = Utf8               Son
   #3 = Class              #4             // Parent
   #4 = Utf8               Parent
   #5 = Utf8               instansV
   #6 = Utf8               LSon;
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Methodref          #3.#11         // Parent."<init>":()V
  #11 = NameAndType        #7:#8          // "<init>":()V
  #12 = Methodref          #1.#11         // Son."<init>":()V
  #13 = Fieldref           #1.#14         // Son.instansV:LSon;
  #14 = NameAndType        #5:#6          // instansV:LSon;
  #15 = Utf8               LineNumberTable
  #16 = Utf8               LocalVariableTable
  #17 = Utf8               this
  #18 = Utf8               main
  #19 = Utf8               ([Ljava/lang/String;)V
  #20 = Utf8               arg
  #21 = Utf8               [Ljava/lang/String;
  #22 = Utf8               MethodinstansV
  #23 = Utf8               SourceFile
  #24 = Utf8               Son.java
{
  Son instansV;
    descriptor: LSon;
    flags:

  public Son();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=1, args_size=1
         0: aload_0://
         1: invokespecial #10                 // Method Parent."<init>":()V
         4: aload_0
         5: new           #1                  // class Son
         8: dup
         9: invokespecial #12                 // Method "<init>":()V
        12: putfield      #13                 // Field instansV:LSon;
        15: return
      LineNumberTable:
        line 2: 0
        line 3: 4
        line 2: 15
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      16     0  this   LSon;


  static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #1                  // class Son
         3: dup
         4: invokespecial #12                 // Method "<init>":()V
         7: astore_1
         8: return
      LineNumberTable:
        line 7: 0
        line 9: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0   arg   [Ljava/lang/String;
            8       1     1 MethodinstansV   LSon;
}Parent.class
   #1 = Class              #2             // Parent
   #2 = Utf8               Parent
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Methodref          #3.#9          // java/lang/Object."<init>":()V
   #9 = NameAndType        #5:#6          // "<init>":()V
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               LParent;
  #14 = Utf8               SourceFile
  #15 = Utf8               Parent.java
{
  public Parent();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #8         // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 2: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LParent;
}


四、指令说明
      助记符 opcode (hex)opcode(bit)  other bytesstack() [before]---[after]功能newbb1011 10112: indexbyte1, indexbyte2→ objectrefcreate new object of type identified by class reference in constant pool index (indexbyte1 << 8 + indexbyte2)aload_02a0010 1010 → objectrefload a reference onto the stack from local variable 0invokespecialb71011 01112: indexbyte1, indexbyte2objectref, [arg1, arg2, ...] → resultinvoke instance method on object objectref and puts the result on the stack (might be void); the method is identified by method reference index in constant pool (indexbyte1 << 8 + indexbyte2)  Son  instansV=new Son();   //类成员实例变量,objref

1、aload_0:push objectref 入 operand stack, Son ,表示将instansV 放入堆栈中。

 2、 invokespecial  #10 :即对象instansV 的地址(堆中地址,堆中有地址指向method area)。

           表示将instansV 放入堆栈中,操作之后,把结果 放入堆栈中

     1》  2: indexbyte1, indexbyte2=#10 

      2》 operand stack:压入objectref ,

      3》然后得出结果,压入operand stack.

         结果:就是objectref 对象的地址

                  按理说:Parent  类 什么也没有,但是它有父类 object,所以会有一些成员数据和方法可以使用

                                 需要分配空间存对象和类数据。      

Mnemonic

         0: aload_0:
         1: invokespecial #10                 // Method Parent."<init>":()V
         4: aload_0
         5: new           #1                  // class Son
         8: dup
         9: invokespecial #12                 // Method "<init>":()V
        12: putfield      #13                 // Field instansV:LSon;
        15: return


参考文章:1、jvm 说明书(The Java® Virtual Machine Specification Java SE 7 Edition):

                      http://docs.Oracle.com/javase/specs/jvms/se7/html/

                2、http://wensiqun.iteye.com/blog/1125503

               3、Inside the Java Virtual Machine.pdf  

          by Bill Venners