最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Java虛擬機(jī)-什么樣的對(duì)象能被判“死刑”

2020-10-04 11:47 作者:bili_93709487  | 我要投稿

在Java堆中存放著幾乎所有的對(duì)象實(shí)例,在程序運(yùn)行時(shí),堆中的對(duì)象不斷地變多,這樣下去遲早會(huì)將整個(gè)堆放滿。所以要對(duì)堆進(jìn)行垃圾回收,回收“已死”的對(duì)象,釋放內(nèi)存空間。

那在回收它們之前,如何判斷他們“已死”呢?(即該對(duì)象不可能再被任何途徑使用)

引用計(jì)數(shù)算法

這個(gè)算法是這樣的:給對(duì)象添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它,計(jì)數(shù)器就+1;當(dāng)引用失效時(shí),計(jì)數(shù)器值就-1;自然,當(dāng)計(jì)數(shù)器值為0時(shí),就說(shuō)明沒(méi)有任何地方會(huì)使用到該對(duì)象,那么這個(gè)對(duì)象就是“已死”的。

引用計(jì)數(shù)器算法實(shí)現(xiàn)簡(jiǎn)單,判定高效,也有一些著名的應(yīng)用案例,但是主流的Java虛擬機(jī)并沒(méi)有采用這個(gè)算法來(lái)管理內(nèi)存------它很難解決對(duì)象之間的循環(huán)引用問(wèn)題。

public class ReferenceCountGC {

? //?占據(jù)內(nèi)存
? private byte[] memory = new byte[1 << 20];
? public ReferenceCountGC instance;
? public static void main(String[] args) {
? ? ?ReferenceCountGC rca = new ReferenceCountGC(),
? ? ? ? ? ?rcb = new ReferenceCountGC();
? ? ?
? ? ?rca.instance = rcb;
? ? ?rcb.instance = rca;
? ? ?
? ? ?rca = null;
? ? ?rcb = null;
? ? ?System.gc();
? }
}

在上面這個(gè)例子中,我們已經(jīng)沒(méi)有任何途徑調(diào)用到cirA和cirB對(duì)象,但他們的引用計(jì)數(shù)器值都為1,無(wú)法被虛擬機(jī)回收。

可達(dá)性分析算法

對(duì)于上一個(gè)例子,實(shí)際的結(jié)果是虛擬機(jī)回收了這部分內(nèi)存,而虛擬機(jī)使用的正是可達(dá)性分析算法。

循環(huán)引用的“死亡”對(duì)象被回收


這個(gè)算法的基本思路就是通過(guò)一系列的“GC Roots”作為起始點(diǎn),從這些點(diǎn)向下搜索,當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈(從GC Roots下搜索走過(guò)的路徑時(shí),則說(shuō)明該對(duì)象不可達(dá)。不可達(dá)的對(duì)象將被判定為“死亡”。

藍(lán)色為可達(dá),白色為不可達(dá)

那么,哪些對(duì)象可以作為“GC Roots”呢?固定作為GC Roots包括以下幾種:

  • 虛擬機(jī)棧中引用的對(duì)象(在棧幀中本地變量表里)

  • 方法區(qū)中類(lèi)靜態(tài)屬性引用的對(duì)象

  • 方法區(qū)中常量引用的對(duì)象

  • 本地方法中的JNI(Native方法)引用的對(duì)象

  • 虛擬機(jī)內(nèi)部的引用,如基本類(lèi)型對(duì)應(yīng)的Class對(duì)象,一些常駐的異常對(duì)象(NullPointExcepition、OutOfMemoryError)

  • 被同步鎖(synchronized關(guān)鍵字)持有的對(duì)象

  • 反應(yīng)Java虛擬機(jī)內(nèi)部情況的JMXBean、JVMTI中注冊(cè)的回調(diào)本地代碼緩存

除了這些固定集合以外,根據(jù)用戶所選的垃圾收集器一季當(dāng)前回收的內(nèi)存區(qū)域的不同,還可以有其他對(duì)象“臨時(shí)性”地加入。

被判“死刑”對(duì)象的“掙扎”

一個(gè)對(duì)象被判斷“已死”(不可達(dá)),并不代表它不能繼續(xù)存活,要真正宣布一個(gè)對(duì)象的“死亡”,至少要經(jīng)歷兩次標(biāo)記過(guò)程??最多經(jīng)歷兩次標(biāo)記過(guò)程(書(shū)籍作者已將該問(wèn)題加入勘誤中。

至少要經(jīng)歷兩次標(biāo)記過(guò)程,對(duì)于這句話我對(duì)書(shū)中的說(shuō)法有些疑慮。如果一個(gè)對(duì)象沒(méi)有覆蓋finalize()方法,那么在回收前,它只會(huì)經(jīng)歷第一次標(biāo)記過(guò)程,它不會(huì)進(jìn)入F-Queue隊(duì)列中,自然也不會(huì)經(jīng)歷第二次標(biāo)記過(guò)程。不知道作者為什么要說(shuō)至少要經(jīng)歷兩次標(biāo)記過(guò)程,可能是我哪里有理解錯(cuò)誤。

對(duì)象在進(jìn)行可達(dá)性分析后,發(fā)現(xiàn)沒(méi)有任何引用鏈與之鏈接(不可達(dá))將會(huì)進(jìn)行第一次標(biāo)記,然后會(huì)對(duì)標(biāo)記過(guò)的對(duì)象進(jìn)行一次篩選,篩選條件為是否有必要執(zhí)行finalize()方法, 當(dāng)對(duì)象沒(méi)有覆蓋finalize()方法或者該方法已經(jīng)被調(diào)用過(guò),則會(huì)被判定為沒(méi)有必要執(zhí)行。如果被判定為有必要執(zhí)行,那么這個(gè)對(duì)象會(huì)被放入F-Queue隊(duì)列中,并在稍后由一個(gè)虛擬機(jī)建立的低優(yōu)先級(jí)的線程去執(zhí)行(這里的執(zhí)行指的是出發(fā)對(duì)象的finalize()方法,并不會(huì)等待方法結(jié)束,避免執(zhí)行時(shí)間過(guò)長(zhǎng)或者死循環(huán))。之后GC會(huì)對(duì)F-Queue中的對(duì)象進(jìn)行第二次標(biāo)記。

那么對(duì)象如何利用finalize()方法進(jìn)行最后的掙扎呢?只要對(duì)象在finalize()方法中與任何一個(gè)GC Roots可達(dá)的對(duì)象建立聯(lián)系(可以被它引用),那么它將在第二次標(biāo)記時(shí)被移出“即將回收”的集合,死里逃生。

再談引用

無(wú)論是通過(guò)引用計(jì)數(shù)法還是可達(dá)性分析法,判定對(duì)象是否存活都與引用有關(guān)。在JDK1.2以前,Java中對(duì)引用的定義很傳統(tǒng):如果reference類(lèi)型的數(shù)據(jù)中存儲(chǔ)的是另一塊內(nèi)存的起始地址,就稱這塊內(nèi)存為代表著一個(gè)引用。在這種定義下,對(duì)象只有被引用或者沒(méi)有被引用兩種狀態(tài)。

在JDK1.2以后,Java對(duì)引用的概念進(jìn)行了擴(kuò)充,將引用分為強(qiáng)引用,軟引用,弱引用虛引用。

  • 強(qiáng)引用:指代碼中普遍存在的,類(lèi)似"Object obj = new Object()"這類(lèi)引用。只要強(qiáng)引用還在,垃圾收集器就不會(huì)回收這個(gè)對(duì)象。

  • 軟引用:用來(lái)描述一些有用,但并非必須的對(duì)象。對(duì)于軟引用關(guān)聯(lián)的對(duì)象,在系統(tǒng)將要發(fā)生內(nèi)存溢出異常之前,將會(huì)對(duì)這些對(duì)象進(jìn)行二次回收。(JDK1.2之后提供了SoftReference類(lèi)實(shí)現(xiàn)軟引用)

  • 弱引用:用來(lái)描述非必須的對(duì)象,被弱引用關(guān)聯(lián)的對(duì)象,只能生存到下一次垃圾收集發(fā)生之前。(JDK1.2之后,提供了WeakReference類(lèi)來(lái)實(shí)現(xiàn)弱引用)

  • 虛引用:也稱為“幽靈引用”或“幻影引用”,是最弱的一種引用關(guān)系。一個(gè)對(duì)象是否有虛引用存在,完全不會(huì)對(duì)其生存時(shí)間造成影響,也無(wú)法通過(guò)虛引用來(lái)獲取一個(gè)對(duì)象的實(shí)例。為對(duì)象設(shè)置虛引用的唯一目的是能在這個(gè)對(duì)象被回收前收到一個(gè)系統(tǒng)通知。(JDK1.2之后,提供了PhantomReference類(lèi)實(shí)現(xiàn)虛引用)


Java虛擬機(jī)-什么樣的對(duì)象能被判“死刑”的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
曲阜市| 新晃| 晋州市| 博客| 高密市| 灌阳县| 墨玉县| 台山市| 三门县| 礼泉县| 德安县| 顺昌县| 肥东县| 张掖市| 临沂市| 黄冈市| 湖南省| 家居| 牡丹江市| 杂多县| 双牌县| 桃园市| 福建省| 曲松县| 盘山县| 淮滨县| 当雄县| 桃江县| 和硕县| 庄河市| 金昌市| 达拉特旗| 桐柏县| 康乐县| 朔州市| 福清市| 白山市| 奉贤区| 霞浦县| 旬邑县| 于田县|