目錄
1.JVM 簡介
2. JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)
2.1程序計(jì)數(shù)器
2.棧
3.堆
4.方法區(qū)
3.類加載
1.loading
2.linking
1.驗(yàn)證
2.準(zhǔn)備
3.解析
3.Initializing
4.雙親委派模型
5.JVM垃圾回收機(jī)制
1.劣勢(shì)
2.回收什么
3.垃圾回收具體怎么回收
1.找垃圾
方法:
問題:
2.釋放垃圾
1.JVM 簡介
JVM 是 Java Virtual Machine 的簡稱,意為 Java虛擬機(jī)。
2. JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)
2.1程序計(jì)數(shù)器
每個(gè)線程都有一個(gè)
1.作用:記錄當(dāng)前線程執(zhí)行的行數(shù)(相當(dāng)于一個(gè)書簽)
內(nèi)存中最小的區(qū)域,保存下一條要執(zhí)行的指令的地址在哪里.
程序要運(yùn)行,JVM要把字節(jié)碼加載起來,放在內(nèi)存中,程序就會(huì)一條一條把指令從內(nèi)存中放到CPU內(nèi)存上執(zhí)行,就要記住當(dāng)前執(zhí)行的是哪一條了
2.棧
1.存儲(chǔ)內(nèi)容:局部變量和方法調(diào)用信息
一個(gè)進(jìn)程只有一份
方法調(diào)用的時(shí)候,每次調(diào)用一個(gè)新的方法,就涉及到"入棧"操作,每次執(zhí)行完方法,就涉及到"出棧"操作
棧空間很小,如果遞歸條件沒有寫好,可能會(huì)出現(xiàn)棧溢出
3.堆
一個(gè)進(jìn)程有一份,多個(gè)線程共用一個(gè)堆
1.內(nèi)存中空間最大的區(qū)域
2.存儲(chǔ)內(nèi)容:new的對(duì)象,對(duì)象的成員變量(不包含靜態(tài)變量)
4.方法區(qū)
1.存儲(chǔ)內(nèi)容:類對(duì)象(包含靜態(tài)成員)
.java->.class(二進(jìn)制字節(jié)碼).class會(huì)被加載到內(nèi)存中,被JVM構(gòu)造成類對(duì)象
3.類加載
把.class文件,加載到內(nèi)存中,構(gòu)成類對(duì)象
1.loading
找到對(duì)應(yīng)的.class文件,打開并讀取.class文件,同時(shí)初步生成一個(gè)類對(duì)象
2.linking
建立多個(gè)實(shí)體直接的聯(lián)系
1.驗(yàn)證
驗(yàn)證讀到的內(nèi)容是不是和規(guī)范中規(guī)定的格式,完全匹配
如果讀到的數(shù)據(jù)格式不符合規(guī)范,就會(huì);類加載,并拋出異常
2.準(zhǔn)備
為類中的變量(靜態(tài)變量)分配內(nèi)存并設(shè)置類變量初始值
3.解析
java虛擬機(jī)把常量池中的符號(hào)引用替換成直接引用的過程,是初始化常量的過程
.class文件的結(jié)構(gòu)體中初識(shí)情況下是記錄了編號(hào),根據(jù)編號(hào)找到對(duì)應(yīng)內(nèi)容,填充到類對(duì)象中
3.Initializing
真正對(duì)類對(duì)象進(jìn)行初始化,尤其是針對(duì)靜態(tài)成員
4.雙親委派模型
JVN中類加載器,根據(jù)類的全限定名找到.class文件的過程
默認(rèn)的類加載器,主要是3個(gè)~~
1.BootStrapClassLoader負(fù)責(zé)加載標(biāo)準(zhǔn)庫中的類(String, ArrayList, Random, Scanner.....)
2.ExtensionClassLoader負(fù)責(zé)加載JDK擴(kuò)展的類.
3.ApplicationClassLoader 負(fù)責(zé)加載當(dāng)前項(xiàng)目目錄中的類
雙親委派模型:描述了找目錄的過程,就是上述類加載器是如何配合的
1)考慮加載 java.lang.String
1>程序啟動(dòng),進(jìn)入AppliactionClassLoader類加載器
2>ApplicationClassLoader就會(huì)檢查下,它的父加載器是否已經(jīng)加載過了.如果沒有,就調(diào)用父類加載器ExtensionClassLoader
3>ExtensionClassLoader也會(huì)檢查下,它的父加載器是否加載過了.如果沒有,就調(diào)用父類加載器BootStrapClassLoader
4>BootStrapClassLoader也會(huì)檢查下,它的父加載器是否加載過,自己沒有父親,于是自己掃描自己負(fù)責(zé)的目錄
5>java.lang.String這個(gè)類在標(biāo)準(zhǔn)庫中能找到!!!直接由BootStrapClassLoader負(fù)責(zé)后續(xù)的加載過程.查找環(huán)節(jié)就結(jié)束了
?
2)考慮加載自己寫的Test類
1>程序啟動(dòng),進(jìn)入AppliactionClassLoader類加載器
2>ApplicationClassLoader就會(huì)檢查下,它的父加載器是否已經(jīng)加載過了.如果沒有,就調(diào)用父類加載器ExtensionClassLoader
3>ExtensionClassLoader也會(huì)檢查下,它的父加載器是否加載過了.如果沒有,就調(diào)用父類加載器BootStrapClassLoader
4>BootStrapClassLoader也會(huì)檢查下,它的父加載器是否加載過,自己沒有父親,于是自己掃描自己負(fù)責(zé)的目錄,沒掃描到!回到子加載器繼續(xù)掃描
5>ExtensionClassLoader也掃描自己負(fù)責(zé)的目錄,也沒掃描到,回到子加載器繼續(xù)掃描.
6>ApplicationClassLoader也掃描自己負(fù)責(zé)的目錄,能找到Test類,于是進(jìn)行后續(xù)加載.查找目錄的環(huán)節(jié)結(jié)束.
如果最終ApplicationClassLoader 也找不到,就會(huì)拋出 ClassNotFoundException 異常!!
?
5.JVM垃圾回收機(jī)制
1.劣勢(shì)
1.影響額外的開銷
2.影響程序的流暢運(yùn)行
2.回收什么
1.程序計(jì)數(shù)器
固定大小,不涉及到釋放,不需要GC
2.棧
函數(shù)執(zhí)行完畢,對(duì)應(yīng)的棧幀就自動(dòng)釋放
3.堆
最需要GC的,代碼中大量的內(nèi)存都在堆上
4.方法區(qū)
進(jìn)行"類加載要釋放內(nèi)存,卸載操作很低頻的操作
只釋放完全不使用的
回收的基本單位是對(duì)象不是字節(jié)
3.垃圾回收具體怎么回收
1.找垃圾
方法:
1.基于引用計(jì)數(shù)
針對(duì)每個(gè)對(duì)象都有額外引入一小塊內(nèi)存,保存有對(duì)少個(gè)引用指向他
當(dāng)內(nèi)存不使用(引用計(jì)數(shù)為0),可以釋放
例如:函數(shù)調(diào)用創(chuàng)建對(duì)象,分配內(nèi)存,方法結(jié)束,局部變量和棧幀一起釋放,使引用計(jì)數(shù)為0,就認(rèn)為這個(gè)對(duì)象是個(gè)垃圾
缺陷:
1.空間利用率低,要是對(duì)象很小,空間利用率就降低
2.有循環(huán)引用的問題
兩個(gè)對(duì)象t1,t2分別引用對(duì)方的屬性,此時(shí)兩個(gè)對(duì)象的引用計(jì)數(shù)為2,要是兩個(gè)對(duì)象都設(shè)置為null,此時(shí)引用計(jì)數(shù)不為0,無法釋放,因?yàn)橐瞄L在彼此的身上,外界的代碼無法訪問到這兩個(gè)對(duì)象,此時(shí)兩個(gè)對(duì)象不能使用,不能釋放,就會(huì)出現(xiàn)內(nèi)存泄漏
2.基于可達(dá)性分析
通過額外的線程,定期對(duì)整個(gè)內(nèi)存空間的對(duì)象進(jìn)行掃描
有起始位置,把可以訪問到的對(duì)象標(biāo)記一遍,沒有標(biāo)記的就是不可達(dá),就是垃圾
起始位置:
棧上的局部變量
常量池中的引用指向?qū)ο?/p>
方法區(qū)中的靜態(tài)成員指向的對(duì)象
優(yōu)點(diǎn):克服引用計(jì)數(shù)的缺點(diǎn):空間利用率低,循環(huán)使用
缺點(diǎn):系統(tǒng)開銷大,遍歷一次很慢
問題:
2.釋放垃圾
1.標(biāo)記-清除
標(biāo)記:可達(dá)性分析的過程
清除:釋放內(nèi)存
直接釋放內(nèi)存,分布是離散的,問題"內(nèi)存碎片"
2.復(fù)制算法
把不是垃圾的拷貝到另一半,把原來 空間整體都釋放
問題:
內(nèi)存利用率低
保留對(duì)象多,釋放對(duì)象少時(shí),開銷大
3.標(biāo)記-整理
根據(jù)復(fù)制算法進(jìn)行改進(jìn)
把保留的對(duì)象拷貝到前面(直接覆蓋要釋放的對(duì)象),多余的刪除
空間利用率高,沒有解決復(fù)制/搬運(yùn)的開銷
JVM實(shí)現(xiàn)會(huì)把多種方案結(jié)合
分代回收
針對(duì)對(duì)象分類:(根據(jù)對(duì)象的年齡分類),一個(gè)對(duì)象熬過一輪GC的掃描,長一歲
不同年齡用不同的方案
1.剛創(chuàng)建的對(duì)象放在伊甸區(qū)
2.伊甸區(qū)對(duì)象熬過一輪GC掃描,被拷貝到幸存區(qū)(使用復(fù)制算法)
3.在后續(xù)的GC,幸存區(qū)對(duì)象在兩個(gè)幸存區(qū)中來回拷貝(復(fù)制算法),每輪都會(huì)淘汰幸存者
4.持續(xù)若干輪后,進(jìn)入老年的代文章來源:http://www.zghlxwxcb.cn/news/detail-428988.html
因此老年代的GC掃描頻率大大低于新生代,老年代中使用標(biāo)記整理的方式進(jìn)行回收文章來源地址http://www.zghlxwxcb.cn/news/detail-428988.html
到了這里,關(guān)于JVM(Java虛擬機(jī))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!