柚子快報邀請碼778899分享:開發(fā)語言 Java之 jvm
jvm之管理內(nèi)存
程序計數(shù)器:當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器。程序計數(shù)器是唯一一個不會出現(xiàn)?OutOfMemoryError?的內(nèi)存區(qū)域,它的生命周期隨著線程的創(chuàng)建而創(chuàng)建,隨著線程的結(jié)束而死亡。Java虛擬機(jī)棧? 方法調(diào)用 一個方法調(diào)用都會有對應(yīng)的棧幀被壓入棧中? 局部變量表:各種數(shù)據(jù)類型、對象引用類型? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 操作數(shù)棧:用于存放方法執(zhí)行過程中產(chǎn)生的中間計算結(jié)果。另外,計算過程中產(chǎn)生的臨時變量也會放在操作數(shù)棧中。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?棧的內(nèi)存不允許動態(tài)鏈接,棧會出現(xiàn)StackOverFlowError,當(dāng)可以動態(tài)擴(kuò)展,但是在擴(kuò)展的時候沒有辦法申請到足夠的內(nèi)存空間,則拋出OutOfMemoryError異常。Java 方法有兩種返回方式,一種是 return 語句正常返回,一種是拋出異常。不管哪種返回方式,都會導(dǎo)致棧幀被彈出。也就是說, 棧幀隨著方法調(diào)用而創(chuàng)建,隨著方法結(jié)束而銷毀。無論方法正常完成還是異常完成都算作方法結(jié)束。Java本地方法棧:本地方法棧則為虛擬機(jī)使用到的 Native 方法服務(wù)。? 堆??大部分情況,對象都會首先在 Eden 區(qū)域分配,在一次新生代垃圾回收后,如果對象還存活,則會進(jìn)入 S0 或者 S1,并且對象的年齡還會加 1(Eden 區(qū)->Survivor 區(qū)后對象的初始年齡變?yōu)?1),當(dāng)它的年齡增加到一定程度(默認(rèn)為 15 歲),就會被晉升到老年代中。這里最容易出現(xiàn)OutOfMemoryError 當(dāng)jvm花太多時間執(zhí)行垃圾回收比關(guān)切只能回收很少的堆空間的時候,就會報這個錯誤 元空間是永久代的實現(xiàn) 把永久代換成元空間的原因——整個永久代有一個 JVM 本身設(shè)置的固定大小上限,無法進(jìn)行調(diào)整(也就是受到 JVM 內(nèi)存的限制),而元空間使用的是本地內(nèi)存,受本機(jī)可用內(nèi)存的限制,雖然元空間仍舊可能溢出,但是比原來出現(xiàn)的幾率會更小。 運行時常量池:常量池表會在類加載后存放到方法區(qū)的運行時常量池中。 字符串常量池?是 JVM 為了提升性能和減少內(nèi)存消耗針對字符串(String 類)專門開辟的一塊區(qū)域,主要目的是為了避免字符串的重復(fù)創(chuàng)建。 直接內(nèi)存:直接內(nèi)存是一種特殊的內(nèi)存緩沖區(qū),并不在 Java 堆或方法區(qū)中分配的,而是通過 JNI 的方式在本地內(nèi)存上分配的。 對象的創(chuàng)建——類加載檢查、分配內(nèi)存(指針碰撞、空閑列表,分配方式由Java堆是否規(guī)整決定?而 Java 堆是否規(guī)整又由所采用的垃圾收集器是否帶有壓縮整理功能決定。)——初始化零值——設(shè)置對象頭(這個對象是哪個類的實例、如何才能找到類的元數(shù)據(jù)信息、對象的哈希碼、對象的 GC 分代年齡等信息。?這些信息存放在對象頭中。)——執(zhí)行init方法 ?對象在內(nèi)存中的布局可以分為 3 塊區(qū)域:對象頭(Header)、實例數(shù)據(jù)(Instance Data)和對齊填充(Padding)。對齊填充起到占位作用,8字節(jié)的整數(shù)倍對象的訪問內(nèi)存分配以及回收原則
優(yōu)先在Eden區(qū)分配,當(dāng)內(nèi)存不夠的時候會觸發(fā)Minor GC,Survivor空間內(nèi)存足夠的情況下轉(zhuǎn)入,并將對象年齡設(shè)為 1(Eden 區(qū)->Survivor 區(qū)后對象的初始年齡變?yōu)?1)。不足的情況下通過?分配擔(dān)保機(jī)制?把新生代的對象提前轉(zhuǎn)移到老年代中去大對象直接進(jìn)老年代長期存活的對象將進(jìn)入老年代,對象在 Survivor 中每熬過一次 MinorGC,年齡就增加 1 歲,當(dāng)它的年齡增加到一定程度(默認(rèn)為 15 歲),就會被晉升到老年代中。 Java之垃圾回收
死亡對象判斷方法
引用計數(shù)法 有地方引用就加1,引用失效減一。 問題:循環(huán)引用可達(dá)性分析算法??GC Roots引用類型總結(jié):?強(qiáng)引用:不會回收,內(nèi)存不足,拋出OutOfMemoryError 錯誤,軟引用:可有可無,內(nèi)存不足會回收,與引用隊列聯(lián)合使用弱引用:一旦發(fā)現(xiàn),不管內(nèi)存是否足夠,都會回收。但是垃圾回收器是一個優(yōu)先級很低的線程,因此不一定會很快發(fā)現(xiàn)。與引用隊列聯(lián)合使用虛引用:任何時候都可能被回收。主要用來跟蹤對象被垃圾回收的活動。如何判斷一個常量是廢棄常量?運行時常量池主要回收的是廢棄的常量如何判斷一個類是無用的類?? (1)該類所有的實例都已經(jīng)被回收,也就是 Java 堆中不存在該類的任何實例。(2)加載該類的 ClassLoader 已經(jīng)被回收。(3)該類對應(yīng)的 java.lang.Class 對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。
垃圾收集算法
標(biāo)記清除算法:創(chuàng)建對象,標(biāo)記o;然后可達(dá)對象標(biāo)記為1 ,掃描階段清除為o的 。內(nèi)存碎片復(fù)制算法: 內(nèi)存縮小為原來的一半標(biāo)記-整理算法:老年代,標(biāo)記之后不是直接對可回收對象回收,而是讓所有存活的對象向一端移動,然后清理掉端邊界以外的內(nèi)存分代收集算法:根據(jù)對象存活周期的不同將內(nèi)存分為幾塊,采用不同的收集算法
垃圾收集器
serial收集器:暫停其他所有的工作線程,只用一條垃圾收集線程完成垃圾收集工作。 新生代采用標(biāo)記-復(fù)制算法,老年代采用標(biāo)記-整理算法。 簡單高效 parNew收集器:只是使用多線程區(qū)進(jìn)行垃圾收集 parallel scavenge收集器? 關(guān)注吞吐量 以及cpu資源的場合 CMS收集器?是一種以獲取最短回收停頓時間為目標(biāo)的收集器。第一款真正意義上的并發(fā)收集器,它第一次實現(xiàn)了讓垃圾收集線程與用戶線程(基本上)同時工作。 G1收集器?一款面向服務(wù)器的垃圾收集器,主要針對配備多顆處理器及大容量內(nèi)存的機(jī)器. 以極高概率滿足 GC 停頓時間要求的同時,還具備高吞吐量性能特征。G1 收集器在后臺維護(hù)了一個優(yōu)先列表,每次根據(jù)允許的收集時間,優(yōu)先選擇回收價值最大的 Region
柚子快報邀請碼778899分享:開發(fā)語言 Java之 jvm
精彩文章
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。