位元組碼與常量池和JVM記憶體原理

2021-10-06 18:20:41 字數 2601 閱讀 1315

1.jvm主要包括了圖中的三塊,分別是方法區,堆,以及執行緒獨有的區域。

2.其中方法區中包括了類變數,類資訊,方法資訊以及常量池。

1.常量池以表的形式存在

2.常量池用於儲存編譯期間生成的字面量和符號引用。值得注意的是,執行期間產生的新的常量也可被儲存到常量池中,例如string中的intern方法。常量池就是這個型別用到的常量的乙個有序集合。包括直接常量(基本型別,string)和對其他型別、方法、欄位的符號引用.

常量池中每一項常量都是乙個表,jdk1.8有14種結構不同的表結構,這14個表有個共同特點,就是表開始的第一位都是乙個u1型別的標誌位,jvm根據這個標誌位[tag]來確定某個常量池項表示什麼型別的字面量,比如tag為1就是指constant_utf8_info。

1.constant_utf8_info:**中的輸出就是字串「你好世界的」utf8格式。即該常量表就是儲存字串的unicode編碼的。

public

classu8}

}//output: \u4f60\u597d\u4e16\u754c

2.constant_integer_info:

public

class

integerinfo

}//output: integer1 == integer2:true

// integer3 == integer4:false

上面的**片段中,integer1 == integer為真值,是因為直接賦值的integer型別在常量池中的範圍是-128~127。此時符號引用integer1integer2都直接指向常量池中值為127的constant_integer_info。因此值為true。而如果超出了範圍呢?會在堆中new出乙個integer來存放值。

3.constant_string_info:

constant_string_info
可以看到,這個表的本身不存放任何字串資料,而只是存放了乙個指向constant_utf8_info的指標。

public

class

stringinfo

}//true

為什麼此時的string1string2是一樣的?從下面的位元組碼檔案可以看出來在常量池中只儲存了乙個hello字串。兩個符號引用都指向constant_utf8_info中hello字串的unicode位元組碼。因此,它們相等。

string3string4不相等,因為string4是指向堆中的string物件,因此他們是不等的。

public

class

stringinfo3

}//output:true

string5string6相等,因為intern方法返回常量池裡字面值。如果常量池中沒有這個字面值,那麼先把這個字面值放入常量表裡之後返回。

public

class

stringinfo4

}//stringa == stringb: true

可以看到上邊的**中利用+拼接的字串和直接寫在一起的字串是相等的,下面上位元組碼:

可以看到在編譯的時候,兩個引用所指向的字串就已經是一樣的了,字串拼接是在編譯期間完成的。他們指向常量池中的同乙個string表。

JVM位元組碼執行引擎和動態繫結原理

編譯期就確定了需要多大的區域性變數表,多深的運算元棧,這些資訊全在位元組碼中。只有位於棧頂的棧幀才有效,稱為當前棧幀,所對應的方法就是當前正在執行的方法。容量以變數槽slot為單位,slot記憶體大小隨著需求而變化並且不固定。方法執行時jvm使用區域性變數表完成引數值到引數列表的傳遞過程。slot可...

Java位元組碼結構剖析一 常量池

這篇部落格開始,我打算帶大家去解讀一下jvm平台下的位元組碼檔案 熟悉而又陌生的感覺 眾所周知,class檔案包含了我們定義的類或介面的資訊。然後位元組碼又會被jvm載入到記憶體中,供jvm使用。那麼,類資訊到了位元組碼檔案裡,它們如何表示的,以及在位元組碼裡是怎麼分布的呢?帶著這些問題,讓我們去深...

JVM常量池與String類深入理解

建立乙個string有二種形式 第一種形式 string a abc string b abc a引用的字串存放在常量池中,當建立b引用的字串時,會先從常量池中查詢有沒有該字串,如果有,就返回常量池中的字串。如果沒有,就建立該字串物件並放在常量池中,因為字串非常常用,jvm為了提高效能和減少記憶體開...