java學習之:JVM學習與總結

一、JVM結構

1、jvm概述

Java Virtua Machine:java虛擬機,它是java語言跨平臺的一個核心的東西。我們可以將它看作是一個虛擬的計算機,它負責將我們的class文件翻譯成我們各個操作系統中真正能夠讀懂的可執行語言,確保字節碼文件可以在不同的系統中正確運行。

2、jvm體系結構

如下圖所示:jvm體系結構主要分爲三大類:1、類加載器子系統,2、運行時數據區, 3、執行引擎
在這裏插入圖片描述

2.1 Class Loader SubSystem

類加載器子系統,處理java動態類加載功能,它是在運行時首次引用類的時候進行1、加載,2、連接3、初始化類文件。
加載由引導類加載器、擴展類加載器、應用程序類加載器幫助完成
連接過程分爲:驗證(驗證字節碼)、準備(爲所有靜態變量分配內存、默認值)、解析(用方法區的原始引用,代替所有符號內存引用)
初始化:所有靜態變量分配原始值,並執行靜態代碼塊

2.2 運行時數據區

方法區:存儲所有類級別的數據,每個jvm只有一個方法區,它是一個線程共享資源
堆區:存儲所有對象及其對應的實例,變量,數組,每個jvm只有一個堆區,它是一個線程共享資源
棧區:每個線程創建一個單獨的運行時棧,所有局部變量在棧內存生成。
PC寄存器: 保存當前正在執行的指令
本地方法棧:保存本機的方法信息

3.2 執行引擎

JIT:及時編譯器,通過熱點探測來及時編譯代碼,起到一個提高編譯效率的作用
GC:垃圾回收器,收集刪除未被引用的對象。
本地方法接口:與本地方法庫交互
本地方法庫:執行引擎需要本機庫的集合

二、JVM分代介紹

前面已經提到jvm中的堆內存主要是用於存放對象的實例,而這塊區域的空間也是有限的,不可能無限制的存放對象,所以這塊區域是我們垃圾回收機制的主要工作區域,回收那些沒有被引用的對象,但是我們的垃圾回收機制如果頻繁的對整塊區域進行垃圾回收的話勢必會影響我們的系統性能。所以,我們對這一塊區域經行了劃分,有些區域是可以頻繁的回收對象,有些區域是達到某個閾值纔會觸發一次垃圾回收,如下圖所示:
在這裏插入圖片描述
我們將JVM中的堆內存劃分爲:1、新生代,2、老年代,3、永久代(1.8以後已經將其移除),接下來我們來了解一下各個代的作用。

1、新生代

新生代可以分爲:1、Eden,2、From Survivor ,3 、 To Survivor 三個區域,它們的空間配置比例默認是8:1:1。Survivor 這兩個區域是用來存放週期較長的對象,並用於將對象轉移到老年代的過度區域。因爲在我們的實際開發中,大多數的對象的生命週期都不是很長,所以這種配置比例可以有效的利用空間。新生代是垃圾回收的主要地,在新生代中,常規的經行一次垃圾回收一般可收集70%~95%的空間。

1.1 Eden

這塊區域其實就是java對象的伊甸園(大對象直接進入老年代),換句話說就是對象的出生地。當這塊區域的空間沒有足夠的空間進行分配的時候,虛擬機就會發起一次MinorGC.

1.2 Survivor

From Survivor 和 To Survivor 被稱爲倖存區域,其實就是存活的對象,在上一次GC的時候,對象只存在與Eden 和 From Survivor 區域,To Survivor 這個區域是空的,下一次GC的時候,Eden中所有的存活的對象都會被複制到To Survivor這個區域,而在From Survivor這個區域任然存活的對象年齡閾值+1,當超過門限(默認15)變會被轉移到老年代,未超過閾值的被轉移到To Survivor。這個時候,From Survivor 和 To Survivor互相轉換角色,這樣就保證了每一次GC後, To Survivor這個區域是空的。

2、老年代

在這塊區域中存活的對象週期相對較高,GC的週期也是相對較慢。

三、JVM垃圾回收算法

1 、引用計數(Reference Counting)

原理:對象有一個引用,計數+1,刪除一個引用,計數-1,垃圾回收時,回收計數爲0的對象。
缺陷:無法處理循環引用的對象。

2、複製(copying)

原理:將內存劃分爲兩個相等的區域,每一次只使用一個區域(From Survivor 和 To Survivor就是使用的複製算法),垃圾回收時,遍歷當前的區域,把正在被使用的對象複製到另外一個區域中去。
優點:此算法只處理正在被使用的對象,複製成本小,複製後可以對另一個區域經行內存整理,可以有效避免內存碎片。
缺點:需要兩塊內存空間

3、標記-清除(Mark Sweep)

原理:此算法分兩個階段:第一階段,從引用根節點開始,標記所有被引用的對象;第二階段,遍歷整個堆,對未標記的對象經行清除。
缺點:會暫停整個應用,同時會產生內存碎片。

4、標記-整理(Mark-Compact)

原理:此算法結合了標記清除和複製算法的優點,同時也是分爲兩個階段:1、從根節點開始標記所有被引用對象;2、遍歷整個堆,清除未標記對象,將標記對象“壓縮”到堆中的一塊,按照順序排放。
優點:避免了空間碎片,不需要像複製算法那樣需要兩個空間。

四、垃圾收集器

不同的代有不同的垃圾回收器,jvm中有七個不同的收集器,每個收集器都有其特有的功能和特點,合理的選擇收集器是我們優化jvm的一個方向,如下圖所示:
在這裏插入圖片描述

1、Serial

串行收集器,它是Hotspot運行在Client模式下的默認新生代收集器。它的特點就是隻用了一個cpu的線程去完成GC工作,並且在垃圾回收的期間其它工作線程必須暫定,因此它有一個別名叫stop the world

2、ParNew

並行收集器,這種垃圾回收器其實是Serial的升級版本,其實就是多增加了幾個線程來完成GC工作,這種垃圾收集器適合多核的環境下使用。ParNew也沒有解決在垃圾回收時暫停其它工作線程的問題,只是說在多線程情況下,縮短了GC安全點的時間

3、Parallel Scaverage

這款並行收集器與ParNew類似,只是這一款垃圾收集器更加關注系統的吞吐量(系統吞吐量=運行用戶代碼時間/(運行用戶代碼時間+GC時間)),通過降低GC回收對象的時間,從而提高系統的性能。

4、CMS

Concurrent Mark Sweep 這款收集器是真正意義的併發收集器,它可以和新生代的Serial、ParNew配合工作。

5、Serial Old

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

6、Parallel Old

Parallel Old 是Parallel Scaverage 的老年代版本,使用多線程和“標記-整理”算法,這一款收集器只能和行省的的Parallel Scaverage配合使用。

7、G1

Garbage First 是一款面向服務器應用的收集器,主要目標用於配備多頻CPU的服務器治理大內容。
G1與其他分代收集器不同,它將整個堆空間劃分爲多個大小相等的獨立區域(Region),雖然還是保留有新生代和老年代的概念,但是新生代與老年代不再是物理隔離,它們是一部分region的集合。

五、JVM性能檢測工具

1、jps

jdk自帶的小工具,用於查看虛擬機線程
在這裏插入圖片描述

2、jstat

這款工具需要jps配合使用.用於查看虛擬機運行時信息。通過該工具可以實時查看堆不同分代的內存使用和GC時間的信息。
在這裏插入圖片描述

3、jvisualvm

這是一款圖形化界面的性能工具,通過這款工具可以查看我們本地或者遠程虛擬機的參數配置,CPU、堆內存、類、線程的信息。
在這裏插入圖片描述

六、JVM常見參數介紹

1、堆設置

-Xms:初始堆大小
-Xmx:最大堆大小 建議Xmx與-Xmx相同,避免每次垃圾回收完成後JVM重新分配內存
-Xmn:年輕代大小 (堆=年輕代+年老代+永久代 增大年輕代會減小年老代)建議堆*3/8
-Xss:每個線程的堆棧大小 (小應用 棧淺128k/ 大應用256k 對性能影響比較大,需要嚴格的測試)
-XX:NewSize=n:年輕代大小
-XX:NewRatio=n:年老代:年輕代比值
-XX:SurvivorRatio=n:年輕代中 Eden:SFrom:STO=n:1:1
-XX:PretenureSizeThreshold:直接晉升到老年代的對象大小
-XX:MaxTenuringThreshold=0:垃圾最大年齡.
設置0 年輕代對象不經過Survivor區,直接進入年老代. 對於年老代比較多的應用,可以提高效率.
如果將此值設置爲一個較大值,則年輕代對象會在Survivor區進行多次複製,這樣可以增加對象在年輕代的存活 時間,增加在年輕代即被回收的概率.
-XX:PermSize:永久代(perm gen)初始值。默認爲物理內存的1/64。
-XX:MaxPermSize:持久代最大值。物理內存的1/4。

2、垃圾回收統計信息

-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintGCDateStamps — 打印GC操作的時間戳
-Xloggc:filename :把相關日誌信息記錄到文件以便分析。
-XX:PrintHeapAtGC :打印GC前後的詳細堆棧信息

3、收集器設置

-XX:+UseSerialGC:串行收集器 虛擬機Client模式-Serial+Serial Old
-XX:+UseParallelGC:並行收集器 虛擬機server模式-Parallel Scavenge+Serial Old
-XX:+UseParNewGC:使用ParNew+SerialOld

-XX:+UseParalledlOldGC:並行年老代收集器 Parallel Scavenge+Parallel Old
-XX:+UseConcMarkSweepGC:併發收集器 ParNew+CMS+Serial Old(後備 CMS出現Concurrent Mode Failure失敗)

4、並行收集器設置

-XX:ParallelGCThreads=n:並行收集器收集時使用的CPU數.並行收集線程數.
-XX:MaxGCPauseMillis=n:並行收集最大暫停時間 Parallel Scavenge收集器
-XX:GCTimeRatio=n:垃圾回收時間佔程序運行時間的百分比.公式爲1/(1+n) 默認99爲1%的GC時間,使用Parallel Scavenge收集器時

5、併發收集器設置

-XX:+CMSIncrementalMode:爲增量模式.適用於單CPU情況.
-XX:ParallelGCThreads=n:併發收集器年輕代收集方式爲並行收集時,使用的CPU數.並行收集線程數.

6、其他:

-XX:-DisableExplicitGC — 讓System.gc()不產生任何作用
-XX:PrintTenuringDistribution — 設置每次新生代GC後輸出倖存者樂園中對象年齡的分佈
-XX:InitialTenuringThreshold / -XX:MaxTenuringThreshold:設置老年代閥值的初始值和最大值
-XX:TargetSurvivorRatio:設置倖存區的目標使用率
-XX:+UseAdaptiveSizePolicy:動態調整java堆中各個區域的大小以及進入老年代的年齡
-XX:+HandlePromotionFailure:是否允許分配擔保失敗,即老年代的剩餘空間不足以應付新生代的整個Eden和Survivor區的所有對象都存活的極端情況

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章