java虚拟机内存告警_Java虚拟机总结
JVM體系四大塊:
類的加載
JVM內(nèi)存結(jié)構(gòu)
GC算法 垃圾回收
GC分析 性能調(diào)優(yōu)
執(zhí)行引擎
JVM架構(gòu)圖
jvm.arch
一、類的加載機(jī)制
類的加載
類的加載,將class文件讀入方法區(qū),然后在堆中創(chuàng)建java.lang.Class對(duì)象。類的加載最終是生成堆區(qū)中的Class對(duì)象。Class對(duì)象封裝類在方法區(qū)中的數(shù)據(jù)結(jié)構(gòu),并提供訪問(wèn)方法區(qū)中的數(shù)據(jù)結(jié)構(gòu)的接口。
類的生命周期
類的生命周期包括:加載、連接、初始化、使用和卸載,其中前三步是類的加載過(guò)程。
class.lifecycle
加載,查找并加載類的二進(jìn)制數(shù)據(jù),在Java堆中創(chuàng)建Class類的對(duì)象。
鏈接,
驗(yàn)證,文件格式、元數(shù)據(jù)、字節(jié)碼、符號(hào)引用的驗(yàn)證。
準(zhǔn)備,為類的靜態(tài)變量分配內(nèi)存,并初始化為默認(rèn)值。
解析,把類中的符號(hào)引用轉(zhuǎn)換為直接引用。
初始化,為類的靜態(tài)變量賦予手動(dòng)設(shè)置的初始值。
使用,new出對(duì)象,在程序中使用。
卸載,執(zhí)行垃圾回收。
幾個(gè)小問(wèn)題
1、JVM初始化步驟 ? 2、類初始化時(shí)機(jī) ?3、哪幾種情況下,Java虛擬機(jī)將結(jié)束生命周期?
類加載器
啟動(dòng)類加載器:Bootstrap ClassLoader,擴(kuò)展類加載器:Extension ClassLoader,應(yīng)用程序類加載器:Application ClassLoader。
類加載機(jī)制
全盤(pán)負(fù)責(zé),當(dāng)一個(gè)類加載器負(fù)責(zé)加載某個(gè)Class時(shí),該Class所依賴的和引用的其他Class也由該類加載器負(fù)責(zé)載入,除非顯示使用另外一個(gè)類加載器來(lái)載入。
父類委托,先讓父類加載器嘗試加載該類,只有在父類加載器無(wú)法加載時(shí)才從自己的類路徑中加載該類。
緩存機(jī)制,緩存機(jī)制保證所有加載過(guò)的Class都會(huì)被緩存。當(dāng)程序中需要使用某個(gè)Class時(shí),類加載器先從緩存區(qū)尋找該Class,只有緩存區(qū)中不存在,系統(tǒng)才會(huì)讀取該類對(duì)應(yīng)的二進(jìn)制數(shù)據(jù),并將其轉(zhuǎn)換成Class對(duì)象存入緩存區(qū)。這就是為什么修改了Class后,必須重啟JVM,程序的修改才會(huì)生效。
二、JVM內(nèi)存結(jié)構(gòu)
jvm內(nèi)存結(jié)構(gòu)
Java堆(Heap),只存放對(duì)象實(shí)例,幾乎所有的對(duì)象實(shí)例都在這里。
方法區(qū)(Method Area),存儲(chǔ)已被加載的類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼。
程序計(jì)數(shù)器(Program Counter Register),當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。
JVM棧(JVM Stacks),其生命周期與線程相同。虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型:方法被執(zhí)行的時(shí)候同時(shí)會(huì)創(chuàng)建一個(gè)棧幀(Stack Frame)用于存儲(chǔ)局部變量表、操作棧、動(dòng)態(tài)鏈接、方法出口等信息。方法從被調(diào)用到執(zhí)行完成的過(guò)程,就對(duì)應(yīng)著棧幀在棧中從入棧到出棧的過(guò)程。
本地方法棧(Native Method Stacks),與虛擬機(jī)棧類似,虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java方法(字節(jié)碼)服務(wù),而本地方法棧為虛擬機(jī)使用到的Native方法服務(wù)。
對(duì)象分配規(guī)則
對(duì)象優(yōu)先分配在Eden區(qū),如果Eden區(qū)沒(méi)有足夠空間時(shí),執(zhí)行minor GC。
大對(duì)象直接進(jìn)入老年代。可以避免在eden區(qū)和兩個(gè)survivor區(qū)之間發(fā)生大量的內(nèi)存拷貝(新生代采用復(fù)制算法收集內(nèi)存)。
長(zhǎng)期存活的對(duì)象進(jìn)入老年代。虛擬機(jī)為對(duì)象定義了一個(gè)年齡計(jì)數(shù)器,如果對(duì)象經(jīng)過(guò)了1次minor GC那么對(duì)象會(huì)進(jìn)入survivor區(qū),之后每經(jīng)過(guò)一次minor GC那么對(duì)象的年齡加1,直到達(dá)到閥值,對(duì)象進(jìn)入老年區(qū)。
動(dòng)態(tài)判斷對(duì)象的年齡。如果survivor區(qū)中相同年齡的所有對(duì)象大小的總和大于survivor空間的一半,年齡大于或等于該年齡的對(duì)象直接進(jìn)入老年代。
空間分配擔(dān)保。每次進(jìn)行minor GC時(shí),JVM計(jì)算survivor區(qū)移至老年區(qū)的對(duì)象的平均大小,如果這個(gè)值大于老年區(qū)的剩余值則進(jìn)行一次full GC。如果小于檢查HandlePromotionFailure參數(shù)值,則只進(jìn)行minor GC,否則進(jìn)行Full GC。
三、GC算法 垃圾回收
1、對(duì)象存活判斷方式
引用計(jì)數(shù):每個(gè)對(duì)象有一個(gè)引用計(jì)數(shù)屬性,新增一個(gè)引用時(shí)計(jì)數(shù)加1,引用釋放時(shí)減1,計(jì)數(shù)為0時(shí)可以回收。此方法簡(jiǎn)單,但無(wú)法解決對(duì)象循環(huán)引用的問(wèn)題。
可達(dá)性分析:從GC roots向下搜索,搜索所走過(guò)的路徑稱為引用鏈。當(dāng)對(duì)象到GC Roots沒(méi)有任何引用鏈相連時(shí),則證明此對(duì)象是不可用的,不可達(dá)對(duì)象。
GC roots包括:虛擬機(jī)棧中引用的對(duì)象。本地方法棧中JNI引用的對(duì)象。 方法區(qū)中類靜態(tài)屬性、常量引用的對(duì)象。
2、GC算法
標(biāo)記 -清除(Mark-Sweep)算法,分為“標(biāo)記”和“清除”兩個(gè)階段:首先標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成后回收所有被標(biāo)記的對(duì)象。
復(fù)制算法(Copying),將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)這一塊的內(nèi)存用完了,就將還存活的對(duì)象復(fù)制到另外一塊上,然后再把已使用過(guò)的內(nèi)存空間一次清理掉。
標(biāo)記-整理算法,標(biāo)記過(guò)程與“標(biāo)記-清除”算法一樣,但后續(xù)步驟是讓所有存活的對(duì)象向一端移動(dòng),然后清理掉端邊界以外的內(nèi)存。
分代收集算法(Generational Collection),把堆分為新生代和老年代,根據(jù)各年代的特點(diǎn)采用適當(dāng)?shù)氖占惴ā?**常用)
分區(qū)
3、垃圾回收器
Serial回收器,是最古老,最穩(wěn)定以及效率高的收集器,可能會(huì)產(chǎn)生較長(zhǎng)的停頓,只能用一個(gè)線程回收。
ParNew回收器,ParNew收集器是Serial收集器的多線程版本。
Parallel Scavenge回收器,類似ParNew收集器,Parallel收集器更關(guān)注系統(tǒng)的吞吐量。
CMS(Concurrent Mark Sweep)收集器,以獲取最短回收停頓時(shí)間為目標(biāo)的收集器。
G1(Garbage-First)收集器,是面向服務(wù)器的垃圾收集器,主要針對(duì)配備多顆處理器及大容量?jī)?nèi)存的機(jī)器。以極高概率滿足GC停頓時(shí)間的同時(shí),還具備高吞吐量。
三、GC分析 性能調(diào)優(yōu)
1、GC日志分析
[GC [: -> , secs] -> , secs] [Times: user=secs sys=secs, real=secs]
GC收集器的名稱
新生代在GC前占用的內(nèi)存
新生代在GC后占用的內(nèi)存
新生代局部收集時(shí)jvm暫停處理的時(shí)間
JVM Heap 在GC前占用的內(nèi)存
JVM Heap 在GC后占用的內(nèi)存
GC過(guò)程中jvm暫停處理的總時(shí)間
用戶時(shí)間
系統(tǒng)時(shí)間
實(shí)際時(shí)間
4.231: [GC 4.231: [DefNew: 4928K->512K(4928K), 0.0044047 secs] 6835K->3468K(15872K), 0.0045291secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
4.445: [Full GC (System) 4.445: [Tenured: 2956K->3043K(10944K), 0.1869806 secs] 4034K->3043K(15872K), [Perm : 3400K->3400K(12288K)], 0.1870847secs] [Times: user=0.05 sys=0.00, real=0.19 secs]
最前面的數(shù)字 4.231 和 4.445 代表虛擬機(jī)啟動(dòng)以來(lái)的秒數(shù)。
接下來(lái)的 [DefNew , [Tenured , [Perm 表示 GC 發(fā)生的區(qū)域,區(qū)域的名稱與使用的 GC 收集器相關(guān)。 Serial 收集器中新生代名為 "Default New Generation",顯示的名字為 "[DefNew"。ParNew收集器顯示的是 "[ParNew", “Parallel New Generation”。 Parallel Scavenge 收集器新生代名為 "PSYoungGen"。年老代和永久代名稱也都由收集器決定。
方括號(hào)內(nèi)部顯示的 “4928K->512K(4928K)” 表示 “GC 前該區(qū)域已使用容量 -> 垃圾回收后該區(qū)域已使用容量 (該區(qū)域內(nèi)存總?cè)萘? ”。
再往后的 “0.0044047 secs” 表示該區(qū)域GC所用時(shí)間,單位是秒。
再往后的 “6835K->3468K(15872K)” 表示 “GC 前Java堆已使用容量 -> GC后Java堆已使用容量 (Java堆總?cè)萘?”。
再往后的 “0.0045291 secs” 是Java堆GC所用的總時(shí)間。
最后的 “[Times: user=0.00 sys=0.00, real=0.00 secs]” 分別代表用戶態(tài)消耗的CPU時(shí)間、內(nèi)核態(tài)消耗的CPU時(shí)間和操作從開(kāi)始到結(jié)束所經(jīng)過(guò)的墻鐘時(shí)間。
墻鐘時(shí)間包括各種非運(yùn)算的等待耗時(shí),如IO等待、線程阻塞。CPU時(shí)間不包括等待時(shí)間,當(dāng)系統(tǒng)有多核時(shí),多線程操作會(huì)疊加這些CPU時(shí)間,所以u(píng)ser或sys時(shí)間會(huì)超過(guò)real時(shí)間。
2、調(diào)優(yōu)命令
JDK監(jiān)控和故障處理命令
jps,顯示指定系統(tǒng)內(nèi)所有的HotSpot虛擬機(jī)進(jìn)程。
jstat,用于監(jiān)視虛擬機(jī)運(yùn)行時(shí)狀態(tài)信息,可以顯示出虛擬機(jī)進(jìn)程中的類裝載、內(nèi)存、垃圾收集、JIT編譯等運(yùn)行數(shù)據(jù)。
jmap,生成heap dump文件。
jhat,與jmap搭配使用,分析jmap生成的dump,jhat內(nèi)置了一個(gè)微型的HTTP/HTML服務(wù)器,生成dump的分析結(jié)果后,可以在瀏覽器中查看。
jstack,生成java虛擬機(jī)當(dāng)前時(shí)刻的線程快照。
jinfo,實(shí)時(shí)查看和調(diào)整虛擬機(jī)運(yùn)行參數(shù)。
3、調(diào)優(yōu)工具
常用調(diào)優(yōu)工具分為兩類,jdk自帶監(jiān)控工具:jconsole和jvisualvm;第三方有:MAT(Memory Analyzer Tool)。
jconsole,是從java5開(kāi)始,JDK自帶的java監(jiān)控和管理控制臺(tái),用于對(duì)JVM中內(nèi)存,線程和類等的監(jiān)控。
jvisualvm,jdk自帶全能工具,可以分析內(nèi)存快照、線程快照;監(jiān)控內(nèi)存變化、GC變化等。
MAT,Memory Analyzer Tool,基于Eclipse的內(nèi)存分析工具,是一個(gè)快速、功能豐富的Java heap分析工具,它可以幫助我們查找內(nèi)存泄漏和減少內(nèi)存消耗。
四、執(zhí)行引擎
分配給運(yùn)行時(shí)數(shù)據(jù)區(qū)的字節(jié)碼將由執(zhí)行引擎執(zhí)行,執(zhí)行引擎讀取字節(jié)碼并逐個(gè)執(zhí)行。
(1) 解釋器:解釋器更快地解釋字節(jié)碼,但執(zhí)行緩慢。解釋器的缺點(diǎn)是當(dāng)一個(gè)方法被調(diào)用多次時(shí),每次都需要一個(gè)新的解釋。
(2) JIT編譯器:JIT編譯器消除了解釋器的缺點(diǎn)。執(zhí)行引擎將在轉(zhuǎn)換字節(jié)碼時(shí)使用解釋器的幫助,但是當(dāng)它發(fā)現(xiàn)重復(fù)的代碼時(shí),將使用JIT編譯器,編譯整個(gè)字節(jié)碼并將其更改為本地代碼。這個(gè)本地代碼將直接用于重復(fù)的方法調(diào)用,這提高了系統(tǒng)的性能。JIT的構(gòu)成組件為:
中間代碼生成器(Intermediate Code Generator):生成中間代碼。
代碼優(yōu)化器(Code Optimizer):優(yōu)化上面生成的中間代碼。
目標(biāo)代碼生成器(Target Code Generator):生成機(jī)器代碼或本地代碼。
分析器(Profiler):查找熱點(diǎn),即該方法是否被多次調(diào)用。
(3) 垃圾收集器(Garbage Collector):收集和刪除未引用的對(duì)象。可以通過(guò)調(diào)用“System.gc()”觸發(fā)垃圾收集,但不保證立即執(zhí)行。
Java本機(jī)接口(JNI):JNI與本機(jī)方法庫(kù)進(jìn)行交互,并提供執(zhí)行引擎所需的本機(jī)庫(kù)。
本地方法庫(kù)(Native Method Libraries):它是執(zhí)行引擎所需的本機(jī)庫(kù)的集合。
參考
總結(jié)
以上是生活随笔為你收集整理的java虚拟机内存告警_Java虚拟机总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java接收的文件转换成临时文件_And
- 下一篇: Java在使用时需要注意那些问题_jav