溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

JVM中如何進(jìn)行對(duì)象引用

發(fā)布時(shí)間:2021-10-19 17:50:07 來(lái)源:億速云 閱讀:122 作者:柒染 欄目:大數(shù)據(jù)

本篇文章給大家分享的是有關(guān)JVM中如何進(jìn)行對(duì)象引用,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

1.Java對(duì)象的大小

基本數(shù)據(jù)的類型的大小是固定的,這里就不多說(shuō)了。對(duì)于非基本類型的Java對(duì)象,其大小就值得商榷。在Java中,一個(gè)空Object對(duì)象的大小是8byte,這個(gè)大小只是保存堆中一個(gè)沒(méi)有任何屬性的對(duì)象的大小。看
下面語(yǔ)句:
Object ob = new Object();
這樣在程序中完成了一個(gè)Java對(duì)象的生命,但是它所占的空間為:4byte+8byte。4byte是上面部分所說(shuō)的Java棧中保存引用的所需要的空間。而那8byte則是Java堆中對(duì)象的信息。因?yàn)樗械腏ava非基本類型的對(duì)象都需要默認(rèn)繼承Object對(duì)象,因此不論什么樣的Java對(duì)象,其大小都必須是大于8byte。

有了Object對(duì)象的大小,我們就可以計(jì)算其他對(duì)象的大小了。
Class NewObject {
int count;
boolean flag;
Object ob;
}
其大小為:空對(duì)象大小(8byte)+int大小(4byte)+Boolean大小(1byte)+空Object引用的大小(4byte)=17byte。但是因?yàn)镴ava在對(duì)對(duì)象內(nèi)存分配時(shí)都是以8的整數(shù)倍來(lái)分,因此大于17byte的最接近8的整數(shù)倍的是24,因此此對(duì)象的大小為24byte。


這里需要注意一下基本類型的包裝類型的大小。因?yàn)檫@種包裝類型已經(jīng)成為對(duì)象了,因此需要把他們作為對(duì)象來(lái)看待。包裝類型的大小至少是12byte(聲明一個(gè)空Object至少需要的空間),而且12byte沒(méi)有包含任何有效信息,同時(shí),因?yàn)镴ava對(duì)象大小是8的整數(shù)倍,因此一個(gè)基本類型包裝類的大小至少是16byte。這個(gè)內(nèi)存占用是很恐怖的,它是使用基本類型的N倍(N>2),有些類型的內(nèi)存占用更是夸張(隨便想下就知道了)。因此,可能的話應(yīng)盡量少使用包裝類。在JDK5.0以后,因?yàn)榧尤肓俗詣?dòng)類型裝換,因此,Java虛擬機(jī)會(huì)在存儲(chǔ)方面進(jìn)行相應(yīng)的優(yōu)化。

2.引用類型

對(duì)象引用類型分為:強(qiáng)引用、軟引用、弱引用、虛引用。

強(qiáng)引用:就是我們一般聲明對(duì)象是時(shí)虛擬機(jī)生成的引用,強(qiáng)引用環(huán)境下,垃圾回收時(shí)需要嚴(yán)格判斷當(dāng)前對(duì)象是否被強(qiáng)引用,如果被強(qiáng)引用,則不會(huì)被垃圾回收
軟引用:軟引用一般被做為緩存來(lái)使用。與強(qiáng)引用的區(qū)別是,軟引用在垃圾回收時(shí),虛擬機(jī)會(huì)根據(jù)當(dāng)前系統(tǒng)的剩余內(nèi)存來(lái)決定是否對(duì)軟引用進(jìn)行回收。如果剩余內(nèi)存比較緊張,則虛擬機(jī)會(huì)回收軟引用所引用的空間;如果剩余內(nèi)存相對(duì)富裕,則不會(huì)進(jìn)行回收。換句話說(shuō),虛擬機(jī)在發(fā)生OutOfMemory時(shí),肯定是沒(méi)有軟引用存在的。
弱引用:弱引用與軟引用類似,都是作為緩存來(lái)使用。但與軟引用不同,弱引用在進(jìn)行垃圾回收時(shí),是一定會(huì)被回收掉的,因此其生命周期只存在于一個(gè)垃圾回收周期內(nèi)。

虛引用: 與其他幾種引用都不同,虛引用并不會(huì)決定對(duì)象的生命周期。如果一個(gè)對(duì)象僅持有虛引用,那么它就和沒(méi)有任何引用一樣,在任何時(shí)候都可能被垃圾回收器回收。

從上面的定義中可以了解到,引用類型只和垃圾回收器回收規(guī)則,及jvm內(nèi)存有關(guān)系。 當(dāng)內(nèi)存空間還足夠時(shí),則能保留在內(nèi)存之中;如果內(nèi)存空間在進(jìn)行垃圾收集后還是非常緊張,則可以拋棄這些對(duì)象 。在java虛擬機(jī)中如何判斷對(duì)象回收規(guī)則

3.引用計(jì)數(shù)法

原理:給對(duì)象中添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它時(shí),計(jì)數(shù)器值就加1;當(dāng)引用失效時(shí),計(jì)數(shù)器值就減1;任何時(shí)刻計(jì)數(shù)器為0的對(duì)象就是不可能再被使用的。

優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單,判斷效率高。

缺點(diǎn):很難解決對(duì)象之間相互循環(huán)引用的問(wèn)題。(主流Java虛擬機(jī)里面沒(méi)有選用該種方法)。

4.可達(dá)性算法(根搜索算法)

原理:通過(guò)一系列的稱為"GC Roots"的對(duì)象作為起始點(diǎn),從這些節(jié)點(diǎn)開(kāi)始向下搜索,搜索所走過(guò)的路徑稱為引用鏈,當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈相連(用圖論的話說(shuō),就是從GC Roots到這個(gè)對(duì)象不可達(dá))時(shí),則證明此對(duì)象是不可用的。

JVM中如何進(jìn)行對(duì)象引用

上圖中GC Root引用不可達(dá),表示可以回收的對(duì)象,如果GC Root引用可達(dá),則對(duì)象還可存活。

可作為GC Roots的對(duì)象包括下面幾種:

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

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

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

  • 本地方法棧中JNI(即一般說(shuō)的Native方法)引用的對(duì)象

無(wú)論是通過(guò)引用計(jì)數(shù)算法判斷對(duì)象的引用數(shù)量,還是通過(guò)根搜索算法判斷對(duì)象的引用鏈?zhǔn)欠窨蛇_(dá),判定對(duì)象是否存活都與“引用”有關(guān)。

所以對(duì)象的引用可回收規(guī)則:強(qiáng)引用<軟引用<弱引用<虛引用

5.對(duì)象生命周期

我們?cè)購(gòu)膶?duì)象生命周期里看對(duì)象回收的階段和對(duì)應(yīng)的引用狀態(tài)

  1. 創(chuàng)建階段(Created):為對(duì)象分配存儲(chǔ)空間,開(kāi)始構(gòu)造對(duì)象,從超類到子類對(duì)static成員進(jìn)行初始化,超類成員變量按順序初始化,遞歸調(diào)用超類的構(gòu)造方法,子類成員變量按順序初始化,子類構(gòu)造方法調(diào)用,一旦對(duì)象被創(chuàng)建,并被分派給某些變量賦值,這個(gè)對(duì)象的狀態(tài)就切換到了應(yīng)用階段

  2. 應(yīng)用階段(In Use): 對(duì)象至少被一個(gè)強(qiáng)引用持有著。

  3. 不可見(jiàn)階段(Invisible): 當(dāng)一個(gè)對(duì)象處于不可見(jiàn)階段時(shí),說(shuō)明程序本身不再持有該對(duì)象的任何強(qiáng)引用,雖然該這些引用仍然是存在著的。
    簡(jiǎn)單說(shuō)就是程序的執(zhí)行已經(jīng)超出了該對(duì)象的作用域了。

  4. 不可達(dá)階段(Unreachable):

    對(duì)象處于不可達(dá)階段是指該對(duì)象不再被任何強(qiáng)引用所持有。與“不可見(jiàn)階段”相比,“不可見(jiàn)階段”是指程序不再持有該對(duì)象的任何強(qiáng)引用,這種情況下,該對(duì)象仍可能被 JVM等系統(tǒng)下的某些已裝載的靜態(tài)變量或線程或 JNI等強(qiáng)引用持有著,這些特殊的強(qiáng)引用被稱為” GC root”。存在著這些 GC root會(huì)導(dǎo)致對(duì)象的內(nèi)存泄露情況,無(wú)法被回收。

  5. 收集階段(Collected): 當(dāng)垃圾回收器發(fā)現(xiàn)該對(duì)象已經(jīng)處于“不可達(dá)階段”并且垃圾回收器已經(jīng)對(duì)該對(duì)象的內(nèi)存空間重新分配做好準(zhǔn)備時(shí),則對(duì)象進(jìn)入了“收集階段”。如果該對(duì)象已經(jīng)重寫(xiě)了finalize()方法,則會(huì)去執(zhí)行該方法的終端操作。

  6. 終結(jié)階段(Finalized): 當(dāng)對(duì)象執(zhí)行完finalize()方法后仍然處于不可達(dá)狀態(tài)時(shí),則該對(duì)象進(jìn)入終結(jié)階段。在該階段是等待垃圾回收器對(duì)該對(duì)象空間進(jìn)行回收。

  7. 對(duì)象空間重分配階段(De-allocated): 垃圾回收器對(duì)該對(duì)象的所占用的內(nèi)存空間進(jìn)行回收或者再分配了,則該對(duì)象徹底消失了,稱之為“對(duì)象空間重新分配階段”。

以上就是JVM中如何進(jìn)行對(duì)象引用,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

jvm
AI