invokespecial指令
new一個物件包括:類是否載入、為物件分配記憶體、併發處理、記憶體空間初始化、物件設定等步驟,當然new之後有時候會執行<init>,這主要依據位元組碼中是否包含invokespecial指令。下面主要說一下該指令
主要目的:得到物件存在堆中的地址,這樣就可以用當前類,父類,父父類,即繼承層的所有物件。
把繼承層的所有物件的資料和方法為自己當前物件使用。
描述一、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.class
Constant 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; } |
#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 bytes | stack() [before]---[after] | 功能 |
new | bb | 1011 1011 | 2: indexbyte1, indexbyte2 | → objectref | create new object of type identified by class reference in constant pool index (indexbyte1 << 8 + indexbyte2) |
aload_0 | 2a | 0010 1010 | → objectref | load a reference onto the stack from local variable 0 |
invokespecial | b7 | 1011 0111 | 2: indexbyte1, indexbyte2 | objectref, [arg1, arg2, ...] → result | invoke 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) |
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
相關文章
- 指令
- 【Linux】find指令和grep指令!!!Linux
- 庫物件指令碼抽取指令碼物件指令碼
- 巧用shell指令碼生成快捷指令碼指令碼
- DOCKERFILE的CMD指令和ENTRYPOINT指令Docker
- 生成insert指令碼的指令碼指令碼
- SCSS @if() 指令CSS
- SCSS @for 指令CSS
- jcxz指令
- MOV指令
- doc指令
- [指令碼例項]——統計系統資訊指令碼指令碼
- 前端js指令碼與防止js指令碼前端JS指令碼
- iOS逆向 Shell指令碼+指令碼重簽名iOS指令碼
- 常用指令碼學習手冊——Bat指令碼指令碼BAT
- Shell指令碼匯入外部指令碼內容指令碼
- 指令碼新選擇——用C做指令碼指令碼
- 史丹佛新作:無指令調優的指令遵循
- ORG 偽指令
- perl指令碼指令碼
- npm常用指令NPM
- nginx location指令Nginx
- Dockerfile常用指令Docker
- git 指令速查Git
- calico 指令速查
- Git 常用指令Git
- SCSS @while指令CSSWhile
- Git指令大全Git
- ubuntu常用指令Ubuntu
- Bash指令碼指令碼
- Nmap指令整理
- git常用指令Git
- Sybase 常用指令
- java 指令碼Java指令碼
- JMeter指令碼JMeter指令碼
- vue基本指令Vue
- 常用 Git 指令Git
- MySQL指令碼MySql指令碼