在接下來的幾天想總結下,JVM相關的一些內容,好比下面的這三個內容算是比較核心知識點了java
1.運行時數據區域: 在運行時數據區裏存儲類Class文件元數據(方法區),對象和數組(堆),方法參數局部變量(棧)等。算法
2.垃圾回收機制: java 語言的優點之一就是它的自動內存管理,主要回收運行時數據區域的堆內存裏的數據數組
3.類加載機制: 虛擬機首先須要把編譯完成的字節碼文件經過類加載器來加載到運行時數據區域服務器
一個段Java代碼的生命週期都會少不了上圖這幾個步驟,也就是Java代碼首先會被編譯成字節碼文件,以後被類加載器加載到運行時數據區域,以及運行,垃圾收集器回收對象等等。數據結構
但今天我想介紹第一個知識點《運行時數據區域》函數
Java虛擬機定義了一系列邏輯數據區域,有些是隨着虛擬機的啓動而建立,虛擬機的關閉而銷燬。還有一部分是隨着線程生命週期建立銷燬的。性能
咱們有必要深刻了解這塊的內容,由於它將決定服務器性能,首先咱們須要對整個運行時區域由總體的認識而且瞭解了每一個區域的生命週期以及做用以後才能經過相應的調參來提高系統性能。除此以外還有助於快速定位虛擬機的相關Error.this
邏輯上能夠劃出一下6個區域分別是 線程
全名叫作 Program Counter Register 既然是叫作寄存器了那麼確定是須要存東西,那到底存的是什呢?
因爲JVM同時能夠處理多個線程因此就涉及到一些線程調度,當cpu暫停運行線程A把時間片讓給線程B的時候咱們須要保存線程A被暫停執行前的一些現場狀態,須要記錄當前執行到那一行字節碼了,因此具有保存現場的功能。cdn
每條線程都有本身的pc寄存器,在任意時刻虛擬機只會執行一個方法
若是執行的是方法不是native方法 pc寄存器則保存指向當前執行字節碼的指令地址
若是執行的是native方法 pc寄存器會保存undefined
虛擬機棧也是每條線程私有的區域,裏頭存儲棧幀(Frame),後面會重點介紹棧幀算是重點內容。方法的調用與返回基於棧幀來實現的。
在Java虛擬機中堆是全部線程均可以共享的內存區域,是存放全部類實例和數組對象的地方。在虛擬機啓動就根據相關堆參數,建立堆,他也是垃圾收集器工做的主要區域。 堆內存裏的對象不會被顯式的回收,而是由垃圾回收器回收
爲了配合垃圾收集器的特性咱們能夠把堆分爲年輕代和老年代
年輕代又分了Eden和survivor區,主要是爲了配合垃圾回收算法而這麼搞得。
在Java虛擬機中 方法區是可提供各個線程共享的運行時內存區域,它存儲了每個類的結構信息,例如運行時常量池,字段和方法數據,構造函數和普通函數的字節碼內容,一句話總結就是存儲元數據地方
運行時常量池是class文件中每一個類或接口常量池表的表示形式。它包括了若干不一樣的常量,好比 從編譯期可知的數值字面量到運行時才能解析得到的方法或字段引用等等。
建立時機 每一個運行時常量池都在Java虛擬機的方法區中分配,在加載類和接口到虛擬機以後建立對應的運行時常量池
若是咱們想再Java底層裏調用別的語言代碼的話就須要用到別的方法棧了,好比Java虛擬機的實現會用到傳統的棧(C stack)來調用native方法,這個就是本地方法棧的應用,固然這個不是必須實現的,徹底取決於虛擬機的實現。
首先看下棧幀在虛擬機內存中在什麼位置,
棧幀是用來存儲數據和部分過程結果的數據結構,同時也用來處理動態連接,方法返回,異常分派等工做。棧幀的生命週期是跟方法一致的,隨着方法的調用而建立,方法的結束或者異常而銷燬。 每一個棧幀都由局部變量表,操做數棧,動態連接組成的
每一個棧幀內部都包含一組稱爲局部變量表的列表,變量表的長度在編譯期決定。 一個局部變量能夠存儲一個基本數據類型或一個對象引用(referance),returnAddress的數據。存儲long或double須要兩個局部變量才能存儲。
當虛擬機要使用局部變量表裏的數據時經過索引來定位,默認從0開始,因爲long和double佔用兩個局部變量因此它的索引較特殊,取決於最小的那個值,好比某個long類型數據在索引n和n+1裏存儲了,那麼它對應的索引值就是n. 虛擬機經過局部變量表來完成方法調用時的參數傳遞。若是是類方法,它的參數依次從0開始的位置傳遞到局部變量表,若是是實例方法則第0位置存儲所在對象的引用(this),從1開始傳遞參數。
操做數棧是屬於棧幀中的棧,其實它的全名叫作當前棧幀的初操做數棧。棧,棧幀,操做數棧的關係須要梳理清楚:
動態連接是用來完成運行時綁定操做的。在棧幀中有一個指向常量池的當前類的一個引用。在class文件裏一個方法要是調用其餘方法或者方法其餘成員變量,則須要經過符號引用來表示。