java內存區域介紹
我們先來介紹下虛擬機運行時數據區的結構:
我們項目中的每一個線程在運行時,都會有擁有自己獨立的棧數據和程序計數器。程序計數器可以看作字節碼命令的指示器,記錄了下個需要執行的字節碼指令,棧數據主要分為本地方法棧和java虛擬機棧。java虛擬機棧就是用來處理我們程序中代碼生成的字節碼的。
我們程序中的每個方法在執行時都會被分配給一個虛擬機棧幀,棧幀中包含局部變量表和操作數棧以及返回地址等,用來執行該方法生成的字節碼。我們的java程序在編譯期間編譯器會自動幫我們添加一個默認參數,這個參數就是該方法所屬類的引用,也就是我們開發中經常會用的this。this持有方法區中類對象的引用(注意類對象是被放在方法區的,而其他對象都是放在堆中的)。類對象中包含了類的基本信息,包括全限定名、簡單名、字段列表、方法列表等等,而這些屬性的值全部都被保存在常量池中。常量池又可以分為靜態常量池和運行時常量池,接下來我們介紹常量池。
靜態常量池和運行時常量池介紹
我們的java程序在編寫完成時是以java文件的形式存在的,在完成編譯后變成了class文件。如果大家比較了解class文件的話,應該會知道class文件中最重要的是常量池,類的所有屬性,包括字段名、方法名等等的值都存儲在class文件的常量池中,這里的常量池就是我們所說的靜態常量池。這時類屬性對class文件常量池中值的引用被稱為符號引用,因為這時常量池中的值仍然僅僅是符號,不是具體的內存地址。符號引用到內存地址引用的轉換要到運行期才會發生,所以我們稱java程序是動態鏈接的。
當我們class文件被加載到內存中時,內存中同樣存在一個常量池,這個常量池我們通常稱為運行時常量池。但是這里的運行時常量池僅僅是一個泛稱,而并不是說有這么一個大池子,實際上運行時常量池是字符串常量池、數字類型常量池等數據結構的統稱。這里我們以字符串常量池舉個?來說明靜態常量池到運行時常量池的轉變過程。虛擬機在將class文件加載到內存的過程中會先到class文件的常量池中尋找字符串類型的常量數據,找到后到內存中的運行時字符串常量池中尋找是否有相同的字符,若沒有就在堆中創建一個字符串對象,并且在字符串常量池添加這個字符串的引用,同時也會將class中所有原本的引用全部都改成新的引用。字符串常量的使用能夠大幅度的提升對象的利用率,減少程序中不必要的開銷。
?
?