JAVA內(nèi)存模型
運(yùn)行時(shí)數(shù)據(jù)區(qū)域晤揣,JVM在執(zhí)行JAVA程序是將其所管理的內(nèi)存劃分為不同的數(shù)據(jù)區(qū)域
程序計(jì)數(shù)器,線程私有
記錄當(dāng)前線程執(zhí)行字節(jié)碼的行號(hào)睁蕾,多線程切換后能夠正確的恢復(fù)到程序執(zhí)行的位置
虛擬機(jī)棧 ,線程私有,生命周期與線程相同
虛擬機(jī)棧描述的是JAVA方法執(zhí)行的內(nèi)存模型
方法執(zhí)行時(shí)會(huì)創(chuàng)建一個(gè)棧幀的數(shù)據(jù)結(jié)構(gòu)揭北,棧幀存儲(chǔ)了局部變量表(方法的參數(shù)扳炬,方法中的局部變量),操作棧搔体,動(dòng)態(tài)鏈接恨樟,方法出口等信息
方法的執(zhí)行過程就是棧幀進(jìn)棧和出棧的過程
本地方法棧,與虛擬機(jī)棧功能類似疚俱,為本地方法服務(wù)
Java堆區(qū)(Heap) ?線程共享的
虛擬機(jī)管理的最大一塊區(qū)域?
用來存放對(duì)象實(shí)例
也是垃圾收集器主要工作的區(qū)域 ? 按照內(nèi)存回收的角度又分為
? ? ? ? ? ? ? ? ? ? ? ? 新生代(Eden 劝术,survivor) 經(jīng)驗(yàn)性 死亡率高達(dá)97%需老年代提供擔(dān)保 ?用少量存活對(duì)象的復(fù)制代價(jià)完成清理
? ? ? ? ? ? ? ? ? ? ? ? 老年代 ? 存活率高 用 ?標(biāo)記-清除 ? 或 ? 標(biāo)記-整理算法 ?為新生代提供擔(dān)保空間呆奕,一旦存活對(duì)象survivor無法容納直接進(jìn)入老年代?
方法區(qū) 線程共有的
主要用來存放類信息 养晋,靜態(tài)變量 ,常量
內(nèi)存回收目標(biāo)有兩個(gè)登馒;類型的卸載 ? 常量池的回收
? ? 運(yùn)行時(shí)常量池 :用來存放 字面量 匙握,符號(hào)引用 。
對(duì)象是否存活陈轿?
引用計(jì)數(shù)法:為對(duì)象添加一個(gè)計(jì)數(shù)器圈纺,對(duì)象每被引用一次計(jì)數(shù)器加一,當(dāng)一個(gè)引用失效計(jì)數(shù)器減一麦射,當(dāng)計(jì)數(shù)器為0時(shí)說明對(duì)象不可用
缺點(diǎn):無法解決循環(huán)引用的問題 A.S=B ,B.S=A ?python用次算法
可達(dá)性分析算法(跟搜索算法)
通過一系列的‘’GC Roots‘’ 的對(duì)象向下搜索 搜索走過的路徑稱為引用鏈 若對(duì)象到GC Roots沒有任何引用鏈時(shí) 對(duì)象就是不可用的
可作為GC Roots 的對(duì)象
? ? ? ? ? ? ? ? ? ? ? ? ? ?方法區(qū)的靜態(tài)變量蛾娶,常量 引用的對(duì)象
? ? ? ? ? ? ? ? ? ? ? ? ? ?虛擬機(jī)棧 局部變量表中引用的對(duì)象
? ? ? ? ? ? ? ? ? ? ? ? ? ?本地方法棧 中本地方法引用的對(duì)象
標(biāo)記-清除算法
首先標(biāo)記出所有要回收的對(duì)象,標(biāo)記完成后統(tǒng)一清理所用被標(biāo)記的對(duì)象
缺點(diǎn):產(chǎn)生大量的空間碎片潜秋,分配大對(duì)象是無法找到足夠的連續(xù)內(nèi)存
標(biāo)記-整理算法
讓所有存活的對(duì)象移動(dòng)到內(nèi)存的一端蛔琅,清理掉邊界外的內(nèi)存。
復(fù)制算法?
將新生代分為一塊Eden區(qū) 和兩塊Survivor區(qū)域(8:1:1)峻呛,每次使用Eden區(qū)和一塊Survivor區(qū)罗售,回收時(shí)將存活的對(duì)象復(fù)制到另一塊Survivor區(qū)
最后清理掉Eden區(qū),和Survivor區(qū)钩述。
利用了新生代的朝生夕死的特性寨躁,付出少量的存活對(duì)象的復(fù)制代價(jià)完成清理 ,需要老年代擔(dān)保
分代收集算法:根據(jù)對(duì)象存活周期不同分為 新生代牙勘,老年代
垃圾收集器
serial收集器
單線程收集垃圾职恳,用戶線程 STOP THE WORD
優(yōu)點(diǎn):無線程交互的開銷 ,專心做垃圾收集工作
ParNew收集器 多線程版serial ??
Parallel Scavenge收集器(吞吐量)
吞吐量=用戶線程時(shí)間 / CPU總消耗時(shí)間 ?適合后臺(tái)運(yùn)算不需要太多交互的任務(wù)
CMS 垃圾收集器(Concurrent Mask Sweep)最短停頓時(shí)間 重視服務(wù)的響應(yīng)速度
1 初始標(biāo)記 ?快速掃描GC Roots直接引用的對(duì)象 ?需要STOP THE WORD
2 并發(fā)標(biāo)記 ?與用戶線程并行?
3 重新標(biāo)記 ?STOP THE WORD 標(biāo)記那些并發(fā)標(biāo)記因用戶線程改變的對(duì)象引用
4 并發(fā)清理 ?
缺點(diǎn):標(biāo)記-清除算法 產(chǎn)生空間碎片 ??
? ? ? ? ? ? 并發(fā)清理時(shí)產(chǎn)生的垃圾無法進(jìn)行收集方面,產(chǎn)生浮動(dòng)垃圾
? ? ? ? ? ? ?并發(fā)標(biāo)記與用戶線程并行效率不高
G1 垃圾收集器(Garbage first)
致力于非常精確的控制停頓
G1將堆內(nèi)存劃分為多個(gè)大小固定的獨(dú)立區(qū)域(Region)放钦,并跟蹤每塊區(qū)域的垃圾堆積程度,計(jì)算垃圾回收價(jià)值(回收需要的時(shí)間恭金,回收獲得的空間)在后臺(tái)維護(hù)一個(gè)優(yōu)先表操禀,根據(jù)每次允許的收集時(shí)間來優(yōu)先回收價(jià)值最大的區(qū)域。
對(duì)象優(yōu)先分配在Eden區(qū)?
大對(duì)象直接進(jìn)入老年代横腿,避免在Eden區(qū)和Srvivor區(qū)發(fā)生大量內(nèi)存拷貝
長期存活的對(duì)象進(jìn)入老年代颓屑,對(duì)象每熬過一次minor GC年齡+1 增加到15晉升老年代
動(dòng)態(tài)年齡劃分:在Survivor空間中所有相同年齡的所有對(duì)象大小大于Survivor的一半辙培,大于等于與該年齡的對(duì)象進(jìn)入老年代
類加載機(jī)制
加載 ?
通過類的權(quán)限名獲取次類的二進(jìn)制字節(jié)流,將字節(jié)流代表的靜態(tài)儲(chǔ)存結(jié)構(gòu)轉(zhuǎn)換為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)
在java堆生成java.lang.Class對(duì)象作為方法區(qū)這些數(shù)據(jù)的訪問入口
?連接 ? 分為三個(gè)階段(驗(yàn)證邢锯,準(zhǔn)備扬蕊,解析)
驗(yàn)證是連接的第一個(gè)階段
1文件格式驗(yàn)證 字節(jié)流是否滿足Class文件要求 ,
2元數(shù)據(jù)驗(yàn)證(父類是否繼承final修飾的類丹擎,不是抽象類是否實(shí)現(xiàn)了父類或接口的全部方法)
3字節(jié)碼驗(yàn)證
4符號(hào)引用驗(yàn)證
準(zhǔn)備
準(zhǔn)備階段是正式為類變量分配內(nèi)存(方法區(qū))并設(shè)置初始值(零值)的階段尾抑,
解析
符號(hào)引用(用符號(hào)描述所引用的目標(biāo))變成直接引用(直接指向?qū)ο蟮闹羔樆蚓浔?/p>
?初始化
執(zhí)行java代碼
雙親委派模型
兩個(gè)類是否相等,不僅要求是同一個(gè)Class文件還必須是一個(gè)類加載器加載的
如果一個(gè)類加載器收到了類加載的請求蒂培,它首先不會(huì)嘗試自己去加載這個(gè)類再愈,而是把這個(gè)請求委托給父類去完成,因此所有類加載的請求都應(yīng)該傳送到頂層的啟動(dòng)類加載器护戳,只有當(dāng)父類反饋?zhàn)约簾o法完成這個(gè)加載請求(他的搜索范圍沒有找到這個(gè)類)時(shí)子類加載器才會(huì)自己去嘗試加載這個(gè)類翎冲。