商務(wù)部網(wǎng)站市場體系建設(shè)司子站微信如何引流推廣精準(zhǔn)加人
這里寫目錄標(biāo)題
- JVM的組成部分
- 1.類裝載子系統(tǒng)
- 1.1一個類加載到JVM的過程
- 1.2類加載機(jī)制
- 1.3為什么設(shè)計雙親委派機(jī)制
- 1.4怎么打破雙親委派機(jī)制
- 2.運(yùn)行時數(shù)據(jù)區(qū)
- 2.1線程私有及共享
- 2.2JVM內(nèi)存區(qū)結(jié)構(gòu)
- 2.3JVM參數(shù)設(shè)置經(jīng)驗
- 3.Java對象的生命周期
- 3.1.對象的創(chuàng)建
- 3.2.對象大小的計算(64位)
- 3.3.對象在內(nèi)存上的分配
- 3.4.對象的回收
- 4.垃圾收集器和收集算法
- 4.1分代收集理論:
- 4.2垃圾收集算法:
- 4.3 Serial:(需要STW)
- 4.4 Serial Old:
- 4.5 Paralle:(需要STW)
- 4.6 Paralle Old:
- 4.7ParNew:
- 4.8 CMS:
- 4.9 垃圾收集算法底層實現(xiàn):
- 4.10 記憶集和卡表:
- 4.11 G1垃圾收集器:
- 4.12 ZGC:
- 4.13 如何選擇垃圾收集器?
JVM的組成部分
- 類裝載子系統(tǒng):將磁盤文件加載到運(yùn)行時數(shù)據(jù)區(qū)的方法區(qū)
- 運(yùn)行時數(shù)據(jù)區(qū):常說的JVM內(nèi)存區(qū)
- 執(zhí)行引擎:將字節(jié)碼翻譯成底層指令交給CPU執(zhí)行
- 本地庫接口:執(zhí)行引擎需要借助本地庫接口實現(xiàn)將指令交給CPU執(zhí)行
1.類裝載子系統(tǒng)
1.1一個類加載到JVM的過程
加載:將磁盤上的字節(jié)碼文件通過IO讀入方法區(qū)
驗證:驗證字節(jié)碼格式正確性
準(zhǔn)備:類的靜態(tài)變量賦值默認(rèn)值,分配內(nèi)存
解析:符號引用替換為直接引用(靜態(tài)方法執(zhí)行內(nèi)存所在的指針)
初始化:對類的靜態(tài)變量賦值指定值,執(zhí)行靜態(tài)代碼塊
1.2類加載機(jī)制
雙親委派機(jī)制:類加載時先判斷自己有沒有加載過,如果沒有加載就委派父類執(zhí)行同樣的過程,如果父類沒有加載不到在執(zhí)行自行加載
類加載器:
- 引導(dǎo)類加載器
- 擴(kuò)展類加載器
- app類加載器
類加載器定義:在Java代碼的Lancher類中構(gòu)建了擴(kuò)展類加載器和app類加載,父子關(guān)系也是在這里構(gòu)建,引導(dǎo)類加載器在C中構(gòu)建的,所以在Java中體現(xiàn)就是null
1.3為什么設(shè)計雙親委派機(jī)制
沙箱安全機(jī)制:jdk中的類不能被程序員修改
避免類的重復(fù)加載:一個類只會被一個加載器加載一次
1.4怎么打破雙親委派機(jī)制
重新類加載方法,判斷如果是自定義類,就指定自定義類加載器加載,如果不是就使用原來的機(jī)制。
2.運(yùn)行時數(shù)據(jù)區(qū)
2.1線程私有及共享
私有:棧、本地方法棧、程序計數(shù)器
共享:堆、方法區(qū)
2.2JVM內(nèi)存區(qū)結(jié)構(gòu)
程序計數(shù)器:記錄著當(dāng)前線程的程序執(zhí)行位置
本地方法棧:虛擬機(jī)調(diào)用native方法
棧:局部變量表(存局部變量)、操作數(shù)棧(供變量計算)、動態(tài)鏈接(將方法指向內(nèi)存中真正的方法指針)、方法出口
堆:幾乎所有的對象都在這里分配
方法區(qū):用于存儲加載后的類信息、常量、靜態(tài)變量、編譯后的代碼
2.3JVM參數(shù)設(shè)置經(jīng)驗
線程棧:-Xss 每個線程棧的大小,這個參數(shù)越小,那么一個線程運(yùn)行的方法就越少,而虛擬機(jī)內(nèi)部運(yùn)行的線程數(shù)變多
堆:盡量指定堆的大小參數(shù)一致避免擴(kuò)容;分析對象在內(nèi)存中的分布盡量讓對象在年輕代被回收減少full gc次數(shù)。
(方法區(qū))元空間:元空間默認(rèn)為21m,元空間滿了之后會觸發(fā)full gc,所以盡量設(shè)置值
3.Java對象的生命周期
3.1.對象的創(chuàng)建
- 類加載檢查:當(dāng)遇到new關(guān)鍵字時,先判斷常量池中能否找到類的符號引用
- 分配內(nèi)存:對象所需的內(nèi)存,在類加載后就能確定。直接為對象分配確定大小的內(nèi)存
- 初始化零值:程序能訪問的數(shù)據(jù),設(shè)置對應(yīng)字段的零值
- 設(shè)置對象頭:對象頭包含:Mark word,Klass pointer(對象執(zhí)行類元信息的指針)
- 執(zhí)行Init方法:按照程序員的意愿進(jìn)行屬性的賦值,和執(zhí)行構(gòu)造方法
3.2.對象大小的計算(64位)
對象頭 :
- (header)Markword:8字節(jié)
- Klass pointer:開啟指針壓縮(默認(rèn)開啟)4字節(jié)
對象數(shù)據(jù):
- 基本數(shù)據(jù)類型:占數(shù)據(jù)類型大小
- 對象、字符串(引用指針):開啟指針壓縮 4字節(jié)
- 數(shù)組:數(shù)組長度 4 字節(jié)(只要是數(shù)組,不區(qū)分?jǐn)?shù)組的類型)
對象填充:
- 保證對象大小是8的倍數(shù),不夠時填充
3.3.對象在內(nèi)存上的分配
對象在棧上分配:棧上分配依賴與逃逸分析和標(biāo)量替換。
- 逃逸分析:分析對象作用域,是否只在本地方法使用,無外部引用
- 標(biāo)量替換:棧上沒有大塊連續(xù)的內(nèi)存,所以JVM不會直接創(chuàng)建對象,而是將成員變量分解為被方法使用的變量,存在棧幀寄存器
對象在堆上分配:
- Eden區(qū):正常對象放在Eden區(qū)
- 老年代:對象滿足一定條件會分配到老年代
大對象:超過JVM設(shè)置的大對象參數(shù)值
長期存活對象:經(jīng)過多次minorGC后存活的對象
對象動態(tài)年齡判斷:一批對象的總大小超過survivor區(qū)域內(nèi)存大小的50%。那最大年齡的一批對象進(jìn)入老年代。
老年代空間分配擔(dān)保:老年代的可用空間小于年輕代所有對象之和
3.4.對象的回收
1.回收那些對象?
- 引用計數(shù)法:對象存在引用,計數(shù)+1,引用消失計數(shù)減1,不能判斷互相引用
- 可達(dá)性分析算法:從GCRoots節(jié)點向下搜索引用的對象,未被標(biāo)記到的是垃圾對象
2.GC Roots對象:本地方法棧變量、靜態(tài)變量(局部變量和全局變量即類中定義的變量)
3.常見的引用類型: - 強(qiáng)引用:普通變量引用
- 弱引用:弱引用類型對象包裹
- 軟引用:軟引用對象包裹
- 虛引用:最弱的引用關(guān)系
4.垃圾收集器和收集算法
4.1分代收集理論:
- 根據(jù)年齡帶不同,選擇不同的垃圾收集算法
4.2垃圾收集算法:
- 標(biāo)記復(fù)制:將存活的對象復(fù)制到另一個區(qū)域(適合年輕代S0,S1)
- 標(biāo)記清楚:標(biāo)記垃圾對象清除(或者反過來)會產(chǎn)生內(nèi)存碎片
- 標(biāo)記整理:同標(biāo)記清楚,只是垃圾對象清除后會整理內(nèi)存空間(適合來年代)
4.3 Serial:(需要STW)
單線程收集器,進(jìn)行垃圾收集工作時需要暫停其它所有工作線程
4.4 Serial Old:
和Serial收集器一樣,一個用于年輕代,一個用于老年代
4.5 Paralle:(需要STW)
多線程收集器,進(jìn)行垃圾收集工作時由多個線程進(jìn)行
4.6 Paralle Old:
和Paralle收集器一樣,但是Paralle用于年輕代,Paralle Old用于老年代
4.7ParNew:
多線程收集器,和Paralle相同,但是ParNew可以和CMS收集器配合使用
4.8 CMS:
第一次基本上實現(xiàn)了用戶線程和垃圾收集線程同時工作
工作過程:
- 初始標(biāo)記:通過GCRoots查找引用對象,速度很快。需要STW
- 并發(fā)標(biāo)記:通過GCRoots直接引用對象查找其它的引用,可以和用戶線程同時運(yùn)行
- 重新標(biāo)記:重新標(biāo)記是為了修正并發(fā)標(biāo)記階段用戶線程導(dǎo)致的對象變動,主要用到了三色標(biāo)記
- 并發(fā)清理:用戶線程和垃圾收集線程同時運(yùn)行,回收垃圾對象
- 并發(fā)重置:重置本次GC過程中標(biāo)記的對象
4.9 垃圾收集算法底層實現(xiàn):
三色標(biāo)記:
- 黑色:對象存活,且所有關(guān)系都已經(jīng)掃描
- 灰色:至少有一個引用對象未掃描
- 白色:分析開始階段都是白色,如果分析結(jié)束對象仍然是白色,代表對象是垃圾對象
漏標(biāo)對象處理: - 增量更新:當(dāng)一個黑色對象插入新的引用指向一個白色對象時,先將引用記錄保存。等并發(fā)標(biāo)記結(jié)束后,重新掃描。
- 原始快照(SATB):當(dāng)一個灰色對象刪除一個指向白色對象時,將要刪除的引用記錄下來
增量跟新和原始快照中記錄的引用,通過寫屏障實現(xiàn)
寫屏障:在賦值前(賦值對象引用,或賦值引用null)后,加入一些處理
4.10 記憶集和卡表:
當(dāng)涉及跨代對象引用會收時,不直接掃描跨代區(qū)域,而是引入卡表。將存在跨代指針的對象所在卡頁(卡表中的元素)表示為1,表示該元素變臟,GC時只收集卡表變臟的元素加入GCRoots中
4.11 G1垃圾收集器:
概念: 面向服務(wù)器的垃圾收集器,主要針對多核大容量內(nèi)存的機(jī)器
區(qū)域劃分: G1保留了年輕代和來年代的概念,但是沒有物理上的隔閡。針對于大對象存放,G1增加了Humongous區(qū)專門放大對象。G1收集器將堆劃分為大小相等的獨立區(qū)域Region,Region默認(rèn)大小是堆內(nèi)存的1/2048,可以使用參數(shù)指定。
垃圾收集分類:
- Young GC: 不同于其它收集器,在Eden區(qū)滿了就做Young GC,而不是先判斷當(dāng)前Eden區(qū)滿了后所做GC花費(fèi)的時間,如果還不夠設(shè)置的停頓時間,設(shè)置更多的Region為Eden區(qū),直到下次滿了之后時間也符合。
- Mixed GC:老年代的堆占有率達(dá)到參數(shù)設(shè)置時觸發(fā),回收所有的Young和部分Old以及大對象區(qū),G1垃圾收集器優(yōu)先做Mixed GC在回收對象時采用復(fù)制方法,如果剩余的Region不足以復(fù)制,就會產(chǎn)生Full GC.
- Full GC:停止程序采用單線程標(biāo)記、清理、壓縮
G1調(diào)優(yōu)關(guān)鍵參數(shù):調(diào)節(jié)-XX:MaxGCPauseMills GC停頓時間設(shè)置
4.12 ZGC:
特點:基于內(nèi)存布局,暫停時不設(shè)置分代
區(qū)域劃分:
- 小型Region:固定2M,用于放置小于256k的小對象
- 中型Region:固定32M
- 大型Region:容量不固定,可以動態(tài)變化
4.13 如何選擇垃圾收集器?
總結(jié):.如果內(nèi)存小于100M使用Serial,如果內(nèi)存小于4G可以使用paralle,內(nèi)存介于4-8G可以用ParNew+CMS
8G以上可以用G1,幾百G以上用ZGC