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
。此時符號引用integer1
和integer2
都直接指向常量池中值為127的constant_integer_info
。因此值為true
。而如果超出了範圍呢?會在堆中new出乙個integer
來存放值。
3.constant_string_info
:
constant_string_info
可以看到,這個表的本身不存放任何字串資料,而只是存放了乙個指向constant_utf8_info
的指標。
public
class
stringinfo
}//true
為什麼此時的string1
和string2
是一樣的?從下面的位元組碼檔案可以看出來在常量池中只儲存了乙個hello字串。兩個符號引用都指向constant_utf8_info
中hello字串的unicode位元組碼。因此,它們相等。
string3
和string4
不相等,因為string4是指向堆中的string
物件,因此他們是不等的。
public
class
stringinfo3
}//output:true
string5
和string6
相等,因為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為了提高效能和減少記憶體開...