欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

java代碼可達性分析,可達性模型分析

可達性分析算法及4種引用說明

哪些對象可以被回收 徹底失去引用的對象? GC roots 可達性分析算法 可以判斷 沒有引用鏈的就可以被回收。這算第一次標記。第二次標記成功后會被回收。

馬龍ssl適用于網(wǎng)站、小程序/APP、API接口等需要進行數(shù)據(jù)傳輸應用場景,ssl證書未來市場廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18982081108(備注:SSL證書合作)期待與您的合作!

對象在內(nèi)存中的狀態(tài):

可達狀態(tài):

可恢復狀態(tài):

不可達狀態(tài):

? ? ? ? ? ? ?

判斷對象是否存活都與引用有關,下面介紹一下引用的分類:

引用分類:

強引用;Object obj = new Object()

軟引用;notmust

弱引用;

虛引用;

數(shù)組、對象

類似:Object obj = new Object()

只要存在強引用,垃圾收集器永遠不會回收掉被引用的對象

描述一些還有用但并非必須的對象。在系統(tǒng)將要發(fā)生內(nèi)存溢出異常之前,將會把這些對象列入回收范圍之中進行第二次回收。如果這次回收之后還沒有足夠的內(nèi)存——拋出內(nèi)存異常

內(nèi)存充足,不會回收

內(nèi)存不足,回收

非必需對象

垃圾回收機制運行時,不管內(nèi)存充足與否,都會回收

不能單獨存在,必須和引用隊列聯(lián)合使用。

無法通過虛引用來去的一個對象實例。

對象存活判定算法:

引用計數(shù)算法:

思路:

給對象添加一個引用計數(shù)器,每當一個地方引用它時,計數(shù)器加1;

當引用失效時,計數(shù)器值就減1;

任何時刻計數(shù)器為0的對象就是不能再被使用的。

缺點:

很難解決對象之間相互循環(huán)引用的問題。導致他們的引用計數(shù)都不為0,于是引用計數(shù)算法無法通知GC收集器回收他們。

思路:

通過一系列的成為“GC Roots”的對象作為起始點,

從這些節(jié)點開始向下搜索,搜索所走過的路徑成為引用鏈(Reference Chain),

當一個對象到GC Roots沒有任何引用鏈相連時,則證明此對象是不可用的。

應用:

現(xiàn)在主流的商用程序語言(java,C#)都是通過可達性分析來判斷對象是否存活的。

Java中,可作為GC Roots的對象包括:

虛擬機棧(棧幀中的本地變量表)中引用的對象;

方法區(qū)中類靜態(tài)屬性引用的對象;

方法區(qū)中常量引用的對象;

本地方法棧中JNI(即Native方法)引用的對象;

對象死亡(被回收)前的最后一次掙扎

??即使在可達性分析算法中不可達的對象,也并非是“非死不可”,這時候它們暫時處于“緩刑”階段,要真正宣告一個對象死亡,至少要經(jīng)歷兩次標記過程。

??第一次標記:如果對象在進行可達性分析后發(fā)現(xiàn)沒有與GC Roots相連接的引用鏈,那它將會被第一次標記;

??第二次標記:第一次標記后接著會進行一次篩選,篩選的條件是此對象是否有必要執(zhí)行finalize()方法。在finalize()方法中沒有重新與引用鏈建立關聯(lián)關系的,將被進行第二次標記。

??第二次標記成功的對象將真的會被回收,如果對象在finalize()方法中重新與引用鏈建立了關聯(lián)關系,那么將會逃離本次回收,繼續(xù)存活。

收集器?

淺談CMS垃圾收集器與G1收集器

Java之美[從菜鳥到高手演變]之JVM內(nèi)存管理及垃圾回收

jdk8:垃圾回收算法

怎么驗證java的gc是否會回收了某個不用的對象了。我有段代碼有性能問題,需要調(diào)優(yōu),想知道怎么看

1. 引用計數(shù)器算法

解釋

系統(tǒng)給每個對象添加一個引用計數(shù)器,每當有一個地方引用這個對象的時候,計數(shù)器就加1,當引用失效的時候,計數(shù)器就減1,在任何一個時刻計數(shù)器為0的對象就是不可能被使用的對象,因為沒有任何地方持有這個引用,這時這個對象就被視為內(nèi)存垃圾,等待被虛擬機回收

優(yōu)點

客觀的說,引用計數(shù)器算法,他的實現(xiàn)很簡單,判定的效率很高,在大部分情況下這都是相當不錯的算法

其實,很多案例中都使用了這種算法,比如 IOS 的Object-C , 微軟的COM技術(shù)(用于給window開發(fā)驅(qū)動,.net里面的技術(shù)幾乎都是建立在COM上的),Python語言等.

缺陷

無法解決循環(huán)引用的問題.

這就好像是懸崖邊的人采集草藥的人, 想要活下去就必須要有一根繩子綁在懸崖上. 如果有兩個人, 甲的手拉著懸崖, 乙的手拉著甲, 那么這兩個人都能活, 但是, 如果甲的手拉著乙, 乙的手也拉著甲, 雖然這兩個人都認為自己被別人拉著, 但是一樣會掉下懸崖.

比如說 A對象的一個屬性引用B,B對象的一個屬性同時引用A A.b = B() B.a = A(); 這個A,B對象的計數(shù)器都是1,可是,如果沒有其他任何地方引用A,B對象的時候,A,B對象其實在系統(tǒng)中是無法發(fā)揮任何作用的,既然無法發(fā)揮作用,那就應該被視作內(nèi)存垃圾予以清理掉,可是因為此時A,B的計數(shù)器的值都是1,虛擬機就無法回收A,B對象,這樣就會造成內(nèi)存浪費,這在計算機系統(tǒng)中是不可容忍的.

解決辦法

在語言層面處理, 例如Object-C 就使用強弱引用類型來解決問題.強引用計數(shù)器加1 ,弱引用不增加

Java中也有強弱引用

2. 可達性分析算法

解釋

這種算法通過一系列成為 "GC Roots " 的對象作為起始點,從這些節(jié)點開始向下搜索所有走過的路徑成為引用鏈(Reference Chain) , 當一個對象GC Roots沒有任何引用鏈相連(用圖論的話來說就是從GC Roots到這個對象不可達),則證明此對象是不可用的

優(yōu)點

這個算法可以輕松的解決循環(huán)引用的問題

大部分的主流java虛擬機使用的都是這種算法

3. Java語言中的GC Roots

在虛擬機棧(其實是棧幀中的本地變量表)中引用的對象

在方法區(qū)中的類靜態(tài)屬性引用對象

在方法區(qū)中的常量引用的對象

在本地方法棧中JNI(即一般說的Native方法)的引用對象

可達性分析起始點未定位原因

相對于引用計數(shù)算法而言,可達性分析算法不僅同樣具備實現(xiàn)簡單和執(zhí)行高效等特點,更重要的是該算法可以有效解決引用計數(shù)算法中循環(huán)引用的問題,防止內(nèi)存泄漏的發(fā)生

java選擇的就是可達性分析算法,這種類型的垃圾收集通常也叫做追蹤性垃圾收集

所謂GC ROOTS 根集合就是一組必須活躍的引用

基本思路:

1.可達性分析算法是以根對象集合(GC Roots)為起始點,按照從上至下的方式搜索被根對象集合所連接的目標對象是否可達

2.使用可達性分析算法后,內(nèi)存中的存活對象都會被根對象集合直接或間接連接著,搜索所走過的路徑稱為引用鏈

3.如果目標對象沒有任何引用鏈項鏈,則是不可達的,就意味著該對象已經(jīng)死亡,可以標記為垃圾對象

4.在可達性分析算法中,只有能夠被根對象集合直接或者間接連接的對象才是存活對象

JVM并發(fā)的可達性分析

j當面試扯到jvm這一部分的時候,面試官大概率會問你 jvm怎么判斷哪些對象應該回收呢 ?

你會脫口而出 引用計數(shù)算法 和 可達性分析算法 。

引用計數(shù)法: 在對象中添加一個引用計數(shù)器,每當一個地方引用它時,計數(shù)器就加一;當引用失效時,計數(shù)器值就減一;任何時刻計數(shù)器為零的對象就是不可能再被使用的。

但是這樣的算法有一個問題?

就是不能解決循環(huán)依賴的問題。

可達性分析算法的思路 就是通過一系列的“GC Roots”,也就是根對象作為起始節(jié)點,從根節(jié)點開始,根據(jù)引用關系向下搜索,搜索過程所走過的路徑稱為引用鏈,如果某個對象到GC Roots間沒有任何引用鏈相連。就是說從GC Roots到這個對象不可達時,則證明此對象是不可能再被使用的,是可以被回收的對象。

接下來面試官可能會問:

你剛剛談到了根節(jié)點,那你知道哪些對象可以作為根對象嗎?

你剛剛談到了引用,那你知道java里面有哪幾種引用嗎?

你剛剛談到了可達性分析算法,那如果在該算法中被判定不可達對象,是不是一定會被回收呢?

(這這些問題,文末會給出解答)

這些問題太常規(guī)了,本文要講一些不那么常見的: 并發(fā)標記 , 浮動垃圾 。

CMS和G1都有一個并發(fā)標記的過程,并發(fā)標記要解決什么問題?帶來了什么問題?怎么解決這些問題呢?

剛剛我們談到的可達性分析算法是需要一個理論上的前提的: 該算法的全過程都需要基于一個能保障一致性的快照才能夠分析,這意味著必須全程凍結(jié)用戶線程的運行。 而為了不凍結(jié)用戶線程的運行,那我們就需要讓垃圾回收線程和用戶線程同時運行。

那我們先假設不并發(fā)標記,即只有垃圾回收線程在運行的流程是怎樣的:

第一步:找到根節(jié)點,也就是我們常說的 根節(jié)點枚舉 。

在這個過程中,由于GC Roots是遠遠小與整個java堆中的全部對象,而且在OopMap此類優(yōu)化技巧的加持下,它帶來的停頓是非常短暫且固定的, 可以理解為不會隨著堆里的對象的增加而增加 ,如圖:

首先我們要搞清楚一個問題: 為什么遍歷對象圖的時候必須在一個能保證一致性的快照中?

為了說明這個問題,我們引入 “三色標記” 方法。

什么是“三色標記”?

在遍歷對象圖的過程中,把訪問的對象按照"是否訪問過"這個條件標記成以下三種顏色:

白色:表示對象未被垃圾回收器訪問過 。

顯然可達性分析剛開始的時候,所有的對象都是白色,若在結(jié)束的時候,仍是白色的對象,即代表不可達。

黑色:表示已經(jīng)被垃圾回收器訪問過,且這個對象的所有引用都已經(jīng)掃描過

黑色的對象代表已經(jīng)掃描過,它是安全存活的,如果有其它的對象引用指向了黑色對象,無須重新掃描一遍。黑色對象不可能直接(不經(jīng)過灰色對象)指向某個白色對象。

灰色:表示已經(jīng)被垃圾回收器掃描過,但這個對象至少存在一個引用還沒有被掃描 。

如下圖所示:

我們先看一下正常標記的過程:

首先是初始狀態(tài),很簡單,只有GC Roots是黑色的。同時需要注意下面的圖片的箭頭方向,代表的是有向的,比如其中的一條引用鏈是:

跟節(jié)點-5-6-7-8-11-10

如果在標記的過程中,用戶線程修改了引用關系,就會出現(xiàn)下面的情況:

有一個大佬叫Wilson,他在1994年在理論上證明了, 只有同時滿足以下兩個條件時 ,會產(chǎn)生“對象消失”的問題,原來應該是黑色的對象被標記成了白色。

增量更新要破壞的是第一個條件(賦值器插入了一條或者多條從黑色對象到白色對象的新引用),當黑色對象插入新的指向白色對象的引用關系時,就將這個新插入的引用 記錄下來 ,等并發(fā)掃描結(jié)束之后,再以這些記錄過的引用關系中的黑色對象為根, 重新掃描一次 。

可以簡化的理解為: 黑色對象一旦插入了指向白色對象的引用之后,它就變回了灰色對象 。

下面的圖就是一次并發(fā)掃描結(jié)束之后,記錄了黑色對象5新指向了白色對象9:

原始快照要破壞的是第二個條件(賦值器刪除了全部從灰色對象到該白色對象的直接或間接引用),當灰色對象要刪除指向白色對象的引用關系時,就將這個要刪除的引用記錄下來,在并發(fā)掃描結(jié)束之后,再以這些記錄過的引用關系中的灰色對象為根,重新掃描一次。

可以簡化理解為:無論引用關系刪除與否,都會按照剛剛開始掃描那一刻的對象圖快照開進行搜索。

接下來回答一下,上面遺留的幾個問題:

GC管理的主要區(qū)域是Java堆,一般情況下只針對堆進行垃圾回收。方法區(qū)、棧和本地方法區(qū)不被GC所管理,因而選擇這些區(qū)域內(nèi)的對象作為GC Roots,被GC Roots引用的對象不被GC回收。

Class - 由系統(tǒng)類加載器(system class loader)加載的對象,這些類是不能夠被回收的,他們可以以靜態(tài)字段的方式保存持有其它對象。

Thread - 活著的線程

Stack Local - Java方法的local變量或者參數(shù)

JNI Local、JNI Global

Monitor Used - 用于同步的監(jiān)控對象

在Java語言里,可以作為GC Roots對象的包括如下幾種:

你知道java里面有哪幾種引用嗎?

在可達性分析算法判定為不可達的對象,是不是一定會被回收呢?

即使在可達性算法中不可達的對象也不一定是非死不可的,這時候它們暫時處于“緩刑”階段,要真正宣告它的死亡還需要經(jīng)歷兩次的標記階段。

第一次標記

在對象可達性算法不可達時,進行第一次標記,并且進行一次篩選,篩選的條件是此對象是否有必要執(zhí)行finalize()方法。當對象沒有覆蓋finalize方法或者該方法被虛擬機調(diào)用過,虛擬機將這兩種情況視為“沒有必要去執(zhí)行”,回收。

如果該對象被判定為有必要執(zhí)行finalize()方法,那么這個對象會被放置到一個叫做F-Queue的隊列中,并在稍后由一個虛擬機自動建立的、低優(yōu)先級的Finalize線程去執(zhí)行它。這里所謂的執(zhí)行就是去觸發(fā)該方法,但是并不會承諾等待它執(zhí)行結(jié)束,這樣做的原因是,如果對象在finalize()方法中執(zhí)行緩慢,或者發(fā)生死循環(huán),將會導致整個隊列中的對象處于等待之中。

第二次標記

finalize()方法是對象逃脫死亡命運的最后一次機會,稍后GC將對F-Queue中的對象進行第二次小規(guī)模的標記,如果對象要在finalize()中拯救自己——只要重新與引用鏈上的一個對象重新建立關聯(lián)即可,比如將自己(this關鍵字)賦值給某個類變量或者成員變量,那么在第二次標記的時候就會被移除“即將回收”的集合;如果對象這時候還沒有逃脫,那么就會被真的回收了。

注意:第二次自救失敗是因為任何一個對象的finalize()方法只能執(zhí)行一次,如果第二次回收,就不會執(zhí)行finalize方法了!

(未完待續(xù))

Java可達性分析算法會不會出現(xiàn)循環(huán)引用問題

GC Root在對象圖之外,是特別定義的“起點”,不可能被對象圖內(nèi)的對象所引用。

一個常見的誤解是以為GC Root是一組對象。

實際情況是GC Root通常是一組特別管理的指針,這些指針是tracing GC的trace的起點。它們不是對象圖里的對象,對象也不可能引用到這些“外部”的指針,所以題主想像的情況無法成立。

另外,tracing GC能正確處理循環(huán)引用,保證每個活對象只會被訪問一次就能確定其存活性。對象圖里是否存在循環(huán)引用,tracing GC都能正確判斷對象的存活與否。

新聞標題:java代碼可達性分析,可達性模型分析
當前鏈接:http://chinadenli.net/article16/hedcgg.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設外貿(mào)建站網(wǎng)站改版網(wǎng)頁設計公司自適應網(wǎng)站靜態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

綿陽服務器托管