JVM 运行时数据区详解,写得非常好!
作者:小小木的博客
www.cnblogs.com/wyc1994666/p/11795781.html
在接下來的幾天想總結下,JVM相關的一些內容,比如下面的這三個內容算是比較核心知識點了
1.運行時數據區域: 在運行時數據區里存儲類Class文件元數據(方法區),對象和數組(堆),方法參數局部變量(棧)等。
2.垃圾回收機制: java 語言的優勢之一就是它的自動內存管理,主要回收運行時數據區域的堆內存里的數據
3.類加載機制: 虛擬機首先需要把編譯完成的字節碼文件通過類加載器來加載到運行時數據區域
一個段Java代碼的生命周期都會少不了上圖這幾個步驟,也就是Java代碼首先會被編譯成字節碼文件,之后被類加載器加載到運行時數據區域,以及運行,垃圾收集器回收對象等等。
但今天我想介紹第一個知識點《運行時數據區域》
1 運行時數據區
Java虛擬機定義了一系列邏輯數據區域,有些是隨著虛擬機的啟動而創建,虛擬機的關閉而銷毀。還有一部分是隨著線程生命周期創建銷毀的。 我們有必要深入了解這塊的內容,因為它將決定服務器性能,首先我們需要對整個運行時區域由整體的認識并且了解了每個區域的生命周期以及作用之后才能通過相應的調參來提升系統性能。除此之外還有助于快速定位虛擬機的相關Error. 邏輯上可以劃出一下6個區域分別是?
1.1 PC寄存器
全名叫做?Program Counter Register?既然是叫做寄存器了那么肯定是需要存東西,那到底存的是什呢?
由于JVM同時可以處理多個線程所以就涉及到一些線程調度,當cpu暫停運行線程A把時間片讓給線程B的時候我們需要保存線程A被暫停執行前的一些現場狀態,需要記錄當前執行到那一行字節碼了,所以具備保存現場的功能。
每條線程都有自己的pc寄存器,在任意時刻虛擬機只會執行一個方法,如果執行的是方法不是native方法 pc寄存器則保存指向當前執行字節碼的指令地址,如果執行的是native方法 pc寄存器會保存undefined。
1.2 java虛擬機棧
虛擬機棧也是每條線程私有的區域,里頭存儲棧幀(Frame),后面會重點介紹棧幀算是重點內容。方法的調用與返回基于棧幀來實現的。
1.3 虛擬機堆
在Java虛擬機中堆是所有線程都可以共享的內存區域,是存放所有類實例和數組對象的地方。在虛擬機啟動就根據相關堆參數,創建堆,他也是垃圾收集器工作的主要區域。 堆內存里的對象不會被顯式的回收,而是由垃圾回收器回收,為了配合垃圾收集器的特性我們可以把堆分為年輕代和老年代。
年輕代又分了Eden和survivor區,主要是為了配合垃圾回收算法而這么搞得。
1.4 方法區和運行時常量池
在Java虛擬機中 方法區是可提供各個線程共享的運行時內存區域,它存儲了每一個類的結構信息,例如運行時常量池,字段和方法數據,構造函數和普通函數的字節碼內容,一句話總結就是存儲元數據地方
運行時常量池是class文件中每個類或接口常量池表的表示形式。它包括了若干不同的常量,比如 從編譯期可知的數值字面量到運行時才能解析獲得的方法或字段引用等等。
創建時機
每個運行時常量池都在Java虛擬機的方法區中分配,在加載類和接口到虛擬機之后創建對應的運行時常量池
1.5 本地方法棧
如果我們想再Java底層里調用別的語言代碼的話就需要用到別的方法棧了,比如Java虛擬機的實現會用到傳統的棧(C stack)來調用native方法,這個就是本地方法棧的應用,當然這個不是必須實現的,完全取決于虛擬機的實現。
2 棧幀:
首先看下棧幀在虛擬機內存中在什么位置,
棧幀是用來存儲數據和部分過程結果的數據結構,同時也用來處理動態鏈接,方法返回,異常分派等工作。
棧幀的生命周期是跟方法一致的,隨著方法的調用而創建,方法的結束或者異常而銷毀。
每個棧幀都由局部變量表,操作數棧,動態鏈接組成的
2.1 局部變量表 (Local variable)
每個棧幀內部都包含一組稱為局部變量表的列表,變量表的長度在編譯期決定。另外關注公眾號Java技術棧在后臺回復JVM獲取一份46頁的JVM調優教程。
一個局部變量可以存儲一個基本數據類型或一個對象引用(referance),returnAddress的數據。存儲long或double需要兩個局部變量才能存儲。
當虛擬機要使用局部變量表里的數據時通過索引來定位,默認從0開始,由于long和double占用兩個局部變量所以它的索引較特殊,取決于最小的那個值,比如某個long類型數據在索引n和n+1里存儲了,那么它對應的索引值就是n.
虛擬機通過局部變量表來完成方法調用時的參數傳遞。如果是類方法,它的參數依次從0開始的位置傳遞到局部變量表,如果是實例方法則第0位置存儲所在對象的引用(this),從1開始傳遞參數。
2.2 操作數棧 (Operating Stack)
操作數棧是屬于棧幀中的棧,其實它的全名叫做當前棧幀的初操作數棧。棧,棧幀,操作數棧的關系需要梳理清楚:
-
棧:是虛擬機運行時數據區的一個邏輯區域,里面存儲了一個個棧幀。
-
棧幀:棧幀代表一個方法的整個生命周期,里頭存儲了局部變量表,操作數棧,動態鏈接
-
操作數棧: 剛剛創建時操作數棧是空的。虛擬機提供一些指令從局部變量表把一些常量或者變量值加載到操作數棧,也提供了從操作數棧取走數據的指令。
調用方法時操作數棧用來準備調用方法參數以及接受方法的返回結果。
2.3 動態鏈接 (Dynamic Linking)。
動態鏈接是用來完成運行時綁定操作的。在棧幀中有一個指向常量池的當前類的一個引用。在class文件里一個方法要是調用其他方法或者方法其他成員變量,則需要通過符號引用來表示。
-
動態鏈接的作用就是將符號引用轉換為直接引用。
-
類加載的過程中將要解析尚未被解析的符號引用,并且把對變量的訪問轉換為正確的偏移量。
總結
以上是生活随笔為你收集整理的JVM 运行时数据区详解,写得非常好!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot +RabbitMQ
- 下一篇: Docker+Jenkins+Nginx