1. 程式人生 > >JVM虛擬機深入理解+GC回收+類加載

JVM虛擬機深入理解+GC回收+類加載

bae base class class對象 對象復制 可用內存 虛擬機棧 程序設計 訪問

旭日Follow_24 的CSDN 博客 ,全文地址請點擊:

https://blog.csdn.net/xuri24/article/details/81455449

一,前言

本文章是讀了“深入理解java虛擬機”一書的筆記記錄和心得。作為一名Java的開發從業者或愛好者,想要在這條路繼續和深入發展下去,了解和熟練掌握JVM虛擬機結構原理是作為技術人員的一項基礎能力,掌握的深淺在某個方面衡量了一個技術人員的基本功個編程造詣。

很多時候,我們去掌握一項技術知識,都是從工作中去學習並實踐掌握真的印證那句:實踐是檢驗真理的唯一標準!

但是,作為技術人員,想要紮實並深刻的掌握一項技術知識學習的先後順序應為:。基本原理 - >學會使用 - >實踐 - >回顧這樣才會把一項技術知識學的透徹並牢固掌握。

二,JVM的基本介紹

Java程序設計語言,java虛擬機,javaApi類庫三部分統稱為JDK,JDK是用戶支持java程序開發的最小環境。把java文件列入javaSe API子集和java虛擬機這兩部分統稱為JRE, JRE是支持的java程序運行的標準環境。

三,JVM基本結構

技術分享圖片技術分享圖片?

四,運行時數據區域

運行時數據區包括以下部分:

技術分享圖片技術分享圖片?

  • 程序計數器

程序計數器可以簡單理解為:程序中每個線程運行時,當前線程所執行的字節碼的行號指示器字節碼工作時,通過這個計數器的值來選取下一條需要執行的字節碼指令。分支,循環,跳轉,異常處理,線程恢復等基礎功能都需要依賴這個計數器來完成。每個線程的指令計數器獨立互不影響。

  • Java的虛擬機棧

Java的虛擬機棧,是程序運行時,每個Java的方法創建的一個單獨私有棧楨用以存儲:。局部變量表,操作數棧,動態鏈接,方法出口燈信息每個方法從調用到執行完成,就對應著一個棧楨在虛擬機中從入棧到出棧的過程局部變量表存放了包括編譯器產生的各種基本的java數據類型:布爾,字節,字符,短型,整型,浮點型,長,雙等。它是一個對象引用,即指向對象起始地址的引用指針。

  • 本地方法棧

跟虛擬機棧類似,虛擬機棧存放的是為Java的方法服務的棧楨,而本地方法棧存放的是為虛擬機本身使用到的本地方法,可以理解為JDK加載時,調用JRE類庫裏面的本機方法所用到的棧楨。

  • Java的堆

java堆(Java Heap),是java虛擬機所管理的內存中最大的一塊。是被所有線程共享的一塊內存區域,在虛擬機啟動時創建。唯一目的是:存放所有對象實例.java堆也是垃圾收集管理的主要區域(GC堆)。新生代,老年代/伊甸園,從幸存者空間,到幸存者空間等。

通常的Java堆是物理上不連續的內存空間,邏輯上連續的。類似磁盤空間,可以固定大小,也可以可擴展大小的。-XMX和-Xms控制等。

  • 方法區

方法區跟java的堆一樣,各個線程共享的內存區域,它用於存放已經被虛擬機加載的類信息,常量,靜態變量,即時編譯的代碼等數據。

這部分也是GC堆回收到的內存區域只是這部分,是比較難以回收到的區域,可類似看做:。永久代如常量池的回收和類型的卸載之類的工作。

  • 運行時常量池

運行時常量池是方法區的一部分,類文件中除了有類的版本,字段,方法,接口等描述信息外,還有一些是常量池,用於存放編譯期間生成的各種字面量和符號引用。這部分內容將在類加載後進入方法區的運行時常量池中存放。

  • 直接內存

直接內存,並不是虛擬機運行時數據區的一部分也不是Java的虛擬機的內存區域可以簡單理解為:。程序運行時的工作內存。

五,類加載機制

技術分享圖片技術分享圖片?

  • 加載

加載是“類加載”過程的一個階段,這個階段虛擬機需要完成以下三個事情:

1.通過一個類的全限定名來獲取定義此類的二進制字節流。

2.將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構。

3.在內存中生成一個代表這個類的java的,lang.Class對象,作為方法區這個類的各種數據的訪問入口。

  • 驗證

驗證是連接階段的第一步,這一階段的目的是為了確保類文件的字節流中包含的信息符合當前虛擬機的要求,並且不會危害虛擬機自身的安全。

有如下驗證:

1.文件格式驗證,驗證字節流是否符合類文件格式的規範,並且能夠被當前版本的虛擬機處理如:主次版本號是否在當前虛擬機處理範圍之內;常量池的常量中是否有不被支持的常量類型;類文件中各個部分及其文件本身是否有被刪除的或附加的信息。

2.元數據驗證,對字節碼描述的信息進行語義分析,以保證其描述的信息符合的Java語言規範的要求,這個階段可能包括:這個類是否有父類(除了java.lang.Object繼承外,其他類都應有父類),這個類的父類是否繼承了不允許被繼承的類,這個類是不是抽象類,是否實現了其父類或接口之中要求實現的所有方法。

3.字節碼驗證,驗證過程中最復雜的一個階段,主要通過數據流和控制流分析,確定程序語義是合法的,符合邏輯的。對元數據信息中的數據類型做完校驗後,這個階段會對類的方法體進行校驗分析,保證被校驗類的方法在運行時不會做出危害虛擬機安全的事件。

4.符號引用驗證,驗證階段最後步驟是發生在虛擬機將符號引用轉化為直接引用的時候,這個轉化動作將在連接的第三階段 - 解析階段中發生符號引用驗證可以看做是對類自身以外的信息進行匹配性校驗。

  • 準備

準備階段是正式為類變量分配內存並設置類變量初始值的階段,這些變量所使用的內存都將在方法區中進行分配註意是給變量分配初始值,區分:無最後普通變量定義準備階段後,初始值為數據類型零值。當有最後的修飾的變量,準備階段後該變量的初始值為定義的初始值。

  • 解析

。解析階段是虛擬機將常量池內的符號引用替換為直接引用的過程包括如下內容:

1.類或接口的解析。

2.字段解析

3.類方法解析

4.接口方法解析

  • 初始化

初始化時類加載過程的最後一個階段,前面階段都是由虛擬機主導和控制,加載類的過程(除了用戶自定義類加載器外)。初始化階段,是執行類中定義的Java的程序代碼(字節碼)。

  • 類加載器

技術分享圖片技術分享圖片?

雙親委派模型,JAVA虛擬機存在兩種不同的類加載器:

1.啟動類加載器(Bootstrap ClassLoader),這個是虛擬機自身的一部分。通常虛擬機啟動的時候,加載自身的一些類庫的時候,也會由這個類加載器加載。

2.另外的是獨立於虛擬機外的加載器,都繼承自(java.lang.ClassLoader的)抽象類加載器。

從開發人員角度來看更細區分,而ClassLoader還分為:擴展類加載器(Extenxion ClassLoader)由sun.misc.Launcher&ExtClassLoader,負責加載<JAVA_HOME> \ lib \ ext目錄中或被java.ext.dirs變量所指定路徑中的所有類庫,開發者可以直接使用擴展類加載器。

應用程序類加載器(Application ClassLoader),由sun.misc.Launcher和AppClassLoader實現。同時這個類是ClassLoader中的getSystemClassLoader()方法的返回值,一般稱為系統類加載器。負責加載用戶類路徑(ClassPath)上指定的類庫,開發者可以直接使用這個類加載器。

六,GC垃圾收集器

(1)垃圾收集算法

由於垃圾收集算法的實現涉及大量的程序細節,而且各個平臺的虛擬機操作內存的方法又各不相同,簡單介紹幾種垃圾收集算法。

  • 標記 - 清除算法

最基礎的收集算法是“標記 - 清除”算法,首先標記出所有需要回收的對象,在標記完成後統一回收所有被標記的對象。

技術分享圖片技術分享圖片?

  • 復制算法

將可用內存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當這一塊內存用完了,就將還存活的對象復制到另外一塊上面,然後再把已經使用的內存空間一次清理掉。

技術分享圖片技術分享圖片?

  • 標記 - 整理算法

復制收集算法在對象存活率較高時就要進行較多的復制操作,效率將會降低與“標記 - 清除”。算法一樣,後續步驟不是直接對可回收對象進行清理,而是把所有存活對象都向一端移動。然後直接清理掉端邊界以外的內存。

技術分享圖片技術分享圖片?

  • 分代收集算法

這種算法的思想是:把Java的堆分為新生代和老年代,這樣就可以根據各個年代的特點采用適當的收集算法新生代每次垃圾回收都有大批對象死去,只有少量存活,采用復制。算法老年代因為對象存活率高,沒有額外的空間對它進行分配擔保,必須采用“標記 - 清除”或“標記 - 整理”算法來進行回收。

(2)垃圾收集器

垃圾收集器就是內存回收的具體實現,為收集算法的內存回收方法提供具體實現。

  • 串行收集器

串行收集器是最基本的歷史最悠久的收集器,是一個單一線程的收集器意思是:。當它在工作時,進行垃圾收集時其他所有工作線程必須暫停服務知道它收集結束有個優點是:當為他專門開一個線程來進行垃圾收集的時候,可以獲得最高的單線程收集效率。

  • PARNER收集器

ParNew收集器,是串行收集器的多線程版本,使用了多條線程進行垃圾收集而且可以進行參數控制(-XX:SurvivorRatio / -XX:PretenureSizeThreshold等),但是收集算法,對象分配規則,回收策略等都與串行相同。

  • Parallel Scavenge收集器

是一個新生代收集器,也是使用復制算法的收集器。又是並行的多線程收集器。特點是:可控制的吞吐量:吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)。高吞吐量以為著高效的利用了CPU時間。

  • Serial Old收集器

它是串行收集器的老年代版本,同樣是一個單線程收集器使用“標記 - 整理”算法。

  • 並行舊收集器

它是Parallel Scavenge收集器的老版年代本,使用多線程和“標記 - 整理”算法。

  • CMS收集器

是一種以獲取最短回收停頓時間為目標的收集器目前很大一部分的Java應用集中在互聯網站或者B / S系統的服務器上,這類應用尤其重視服務器的相擁速度應用“標記。 - 清除“算法。

  • G1收集器

它是目前收集器技術發展最前沿的成果之一:

並行與並發

分代收集

空間整合

可預測的停頓

七,虛擬機性能調優

JVM虛擬機深入理解+GC回收+類加載