作爲一個Java
開發,JVM
是我們必須要了解的,我們只有建立在瞭解它的基本運作原理,纔可能設計出一個最合理的代碼方案,在此之前我們已經瞭解了集合中的Map
接口,接下來溪源我將帶領大家瞭解一下JVM
,希望對大家略有幫助。
集合之Map接口可參考我的博客:溪源的Java筆記—集合之Map接口
JVM爲了達到給所有硬件提供一致的虛擬平臺的目的,犧牲了一些與硬件相關的特性。
Java
源文件可以通過編譯器轉化成字節碼文件(.class
文件),這些字節碼文件又可以被JVM
轉化成機器碼。JVM
是運行在操作系統之上的,它與硬件沒有直接交互。Java
的線程和原生操作系統線程有映射關係,Java
可以通過對應的操作系統線程來獲取計算機資源。線程共享的數據區:
java
文件)、方法、屬性等 (常量在JDK1.8移至JVM
堆中)GC
算法回收。知識點:
OOM
(內存溢出)導致觸發GC
。元空間並不在虛擬機中,而是使用本地內存。因此,默認情況下,元空間的大小僅受本地內存限制。默認在20M左右,放在元空間的永久代滿了即,達到MetaspaceSize
的閾值,同樣也會觸發FullGC
.JVM
堆中。線程隔離的數據區:
Natitve
方法知識點:
PC
寄存器和虛擬機棧。JVM堆的組成
1/3的新生代:(由 Minor GC進行清理,採用複製算法)
Eden
區和名爲「From」
的Survivor
區,Survivor
區「To」
是空的。Eden
區中所有存活的對象都會被複制到「To」
,而在「From」
區中,仍存活的對象會根據他們的年齡值來決定去向。Eden
區和From
區已經被清空,這個「To」
和「From」
互換角色,此時Survivor
區「To」
是空的,而「From」
保留上次GC
存活對象2/3的老年代:( 由Major GC進行清理,採用標記清除算法 )
知識點:
Survivor
區,只有所有的Survivor
區滿了纔會放到老年代。Survivor
區的作用是減少被送到老年代的對象,進而減少Full GC
的發生,Survivor
的預篩選保證,只有經歷16次Minor GC
還能在新生代中存活的對象,纔會被送到老年代。JVM確認垃圾回收對象的方式
GC ROOTS
)到某對象不可達時,對象死亡。GC ROOTS的對象包括:
JVM垃圾回收算法
Java
堆分爲新生代和老年代,根據年代將特徵選擇上述算法。新生代通常採用複製算法,老年代採用標記-清除算法或者標記-整理算法。常見的GC方式
GC
,通常來時Full GC
比Minor GC
至少慢10倍。觸發Full GC的情況 :
System.gc()
CMS
收集器發生"Concurrent Mode Failure」
異常時知識點:
JVM
的,所以即使有GC
機制還是可能存在無用但可達的對象沒有即時被回收而導致內存泄漏。垃圾收集器,又稱爲垃圾回收器,是垃圾回收算法(標記-清除算法、複製算法、標記-整理算法)的具體實現,不同版本的JVM
所提供的垃圾收集器可能會有很在差別,本文主要介紹HotSpot
虛擬機中的垃圾收集器。
選擇垃圾回收器考慮的因素:
選擇垃圾回收器的標準:
串行、並行和併發的區別:
CPU
或一條收集線程去完成垃圾收集工作 ,並且在進行垃圾收集時,必須暫停其他所有的工作線程。CPU
上;常見的收集器(7種)
Serial
、ParNew
、Parallel Scavenge
(複製算法)Serial Old
、Parallel Old
、CMS
; (1、2 採用標記整理算法 3採用標記清除算法)G1
;(標記整理,分區)ParNew收集器
ParNew
的特點:
「Stop The World」
應用場景:在多核的情況下和CMS
搭配使用,以滿足用戶交互頻繁實現低延遲的場景(最常見就是遊戲)
Parallel Scavenge收集器
Parallel Scavenge
的特點:
「Stop The World」
Parallel Scavenge
沒有采用傳統的GC
代碼框架,它相對於ParNew
的特點在於: JVM
會根據當前系統運行情況收集性能監控信息,動態調整這些參數,以提供最合適的停頓時間或最大的吞吐量,這種調節方式稱爲GC
自適應的調節策略應用的場景:在多核的情況下和Parallel Old
搭配使用,以滿足高併發的場景(默認的搭配,最常就是web應用)
Parallel Old收集器
Parallel Old
的特點:
「Stop The World」
Parallel Scavenge
搭配使用,以滿足高併發的場景(默認的搭配,最常就是web
應用)CMS收集器
CMS
的特點:
Parallel Scavenge
搭配使用,以滿足用戶交互頻繁實現低延遲的場景(最常見就是遊戲)CMS
運作的過程:
GC Roots
能直接關聯到的對象,速度很快,但會造成 「Stop The World」
「Stop The World」
,停頓時間比初始標記稍長,但遠比並發標記短;CMS
的缺陷:
CPU
資源非常敏感:當CPU
核數低於4時,性能會比較差"Concurrent Mode Failure」
失敗,JVM
會臨時啓用Serail Old
收集器,而導致另一次Full GC
的產生;G1收集器
G1
的特點:
"Stop The World」
停頓時間,也可以併發讓垃圾收集與用戶程序同時進行,減少停頓時間;Region
),能夠採用不同方式處理不同時期的對象;Region
間)看,是基於複製算法;應用場景:具有比較大的內存空間、對象相對比較大的場景。
G1
的運作流程:
GC Roots
能直接關聯到的對象,並且修改TAMS
(Next Top at Mark Start
),讓下一階段併發運行時,用戶程序能在正確可用的Region
中創建新對象,速度很快,但會造成 「Stop The World」
。Remembered Set Log
,並不能保證可以標記出所有的存活對象;Remembered Set Log
合併到Remembered Set
中; 會造成 「Stop The World」
,停頓時間比初始標記稍長,但遠比並發標記短;Region
的回收價值和成本,然後根據用戶期望的GC
停頓時間來制定回收計劃;,最後按計劃回收一些價值高的Region
中垃圾對象;採用複製算法和並行的方式,降低停頓時間、並增加併發量。Java四種引用類型
A a=new A()
只要引用a存在,垃圾回收器不會回收。SoftReference
類似於緩存的方式,不影響垃圾回收,可以提升速度,節省內存。若對象被回收,此時可以重新new
,主要是用來緩存服務器中間計算結果以及不需要實時保存的用戶行爲。通常放在用在對緩存比較敏感的應用中。WeakReference
用於監控對象是否被垃圾回收器回收。PhantomReference
,每次垃圾回收的時候都會被回收。主要用於判斷對象是否已經從內存中刪除。類加載器的任務就是.class
文件加載到到JVM
轉換成 java.lang.class
類
常見的類加載器
Java
的核心類;jre
的擴展目錄;JVM
啓動時加載來自Java
命令的-classpath
選項、java.class.path
系統屬性,或者CLASSPATH
換將變量所指定的JAR
包和類路徑。雙親委託模型
雙親委託模型,確保了加載的唯一性,當類收到加載請求時,它首先不會嘗試加載這個類,而是把請求委託給父類加載器執行,每個類都是如此(如果還有父類繼續上交),只有父類加載完或者父類不存在,子類纔會進行加載。
類加載過程
裝載:獲取類的二進制字節流,將其靜態存儲結構轉化爲方法區的運行時數據結構;
鏈接,可以細分爲:
static
變量分配內存並設置類變量數據類型默認的初始值,不包括實例變量,實例變量將會在對象實例化的時候隨着對象一起分配在Java
堆中;初始化:爲類的靜態變量賦予正確的初始值,使得Java
代碼中被顯式地賦予的值。
當我們要對基礎類進行修改時,打破雙親委託模型的方式:
ClassLoader
類重寫loadClass
方法。JDK
內置的一種服務提供發現機制:通過加載ClassPath
下META_INF/services
,自動加載文件裏所定義的類,通過ServiceLoader.load/Service.providers
方法通過反射拿到實現類的實例。