欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java怎樣判斷堆區(qū)中的對(duì)象可以被回收了

 更新時(shí)間:2024年12月25日 14:57:47   作者:高錳酸鉀_  
文章介紹了Java垃圾回收機(jī)制的工作原理,主要通過引用計(jì)數(shù)法和可達(dá)性分析法來判斷對(duì)象是否可以被回收,引用計(jì)數(shù)法存在循環(huán)引用問題,而可達(dá)性分析法則使用GCRoot對(duì)象來判斷對(duì)象是否可達(dá),從而決定是否回收,這兩種方法各有優(yōu)缺點(diǎn),但Java最終采用了可達(dá)性分析法來實(shí)現(xiàn)垃圾回收

如何判斷堆區(qū)中的對(duì)象可以被回收了

在Java中,垃圾回收機(jī)制會(huì)幫助我們自動(dòng)回收不再被使用的對(duì)象,已到達(dá)即使釋放內(nèi)存的效果,但是Java又是怎么知道哪些對(duì)象不會(huì)再被我們繼續(xù)使用了呢,希望你通過本篇文章,理解引用計(jì)數(shù)法與可達(dá)性分析法的運(yùn)行方式

垃圾回收機(jī)制

在C/C++中,一個(gè)對(duì)象如果不再使用,就要手動(dòng)將其釋放掉,但是很多程序員在編寫程序的時(shí)候經(jīng)常忘記將一些對(duì)象回收,從而就導(dǎo)致了內(nèi)存泄漏

在Java中為了簡(jiǎn)化對(duì)象的內(nèi)存釋放,引入了自動(dòng)的垃圾回收機(jī)制,通過垃圾回收器把不再使用的對(duì)象完成自動(dòng)回收,垃圾回收器主要負(fù)責(zé)堆上的內(nèi)存回收,那么垃圾回收器又是如何知道哪些對(duì)象可以被回收了呢?

在Java中,一個(gè)對(duì)象是否可以被回收,主要是看這個(gè)對(duì)象是否被引用,如果對(duì)象被引用了,說明對(duì)象還在使用,是不可以被回收的,比如說如下代碼中,堆內(nèi)存中的Demo對(duì)象被demo引用,那么堆中的Demo對(duì)象就不會(huì)被回收:

public class Demo {
    public static void main(String[] args) {
        Demo demo = new Demo();
    }
}

若此時(shí)將demo的引用設(shè)置為null:

demo = null;

那么此時(shí)Demo對(duì)象就處于了沒有被引用的狀態(tài):

此時(shí)Demo會(huì)被垃圾回收器進(jìn)行回收,那么垃圾回收器又是怎么知道Demo對(duì)象目前沒有被引用呢???

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

引用計(jì)數(shù)法會(huì)為每一個(gè)對(duì)象維護(hù)一個(gè)引用計(jì)數(shù)器,當(dāng)對(duì)象被引用時(shí)加一,取消引用時(shí)減一,在上面的代碼中,demo引用了堆上的Demo對(duì)象,所以Demo對(duì)象的引用計(jì)數(shù)器就加一,當(dāng)把demo賦值為null的時(shí)候,也就是取消了Demo的引用,此時(shí)Demo對(duì)象引用計(jì)數(shù)器將減一成為0,此時(shí)垃圾回收器就認(rèn)為Demo對(duì)象此時(shí)沒有被任何引用,可以回收

但是此時(shí)會(huì)出現(xiàn)一個(gè)問題,如果我new了兩個(gè)對(duì)象A與B,并且A對(duì)象與B對(duì)象的互為彼此的成員變量,那么就會(huì)出現(xiàn)循環(huán)引用的現(xiàn)象,此時(shí)A對(duì)象被棧內(nèi)存中的a1引用,也被B對(duì)象中的a變量引用,那么他的引用技術(shù)器應(yīng)該為2:

public class Demo {
    public static void main(String[] args) {
        A a1 = new A();
        B b1 = new B();
        a1.b = b1;
        b1.a = a1;

    }
}
class A {
    B b;
}
class B {
    A a;
}

那么此時(shí),我取消a1、b1對(duì)A與B的引用

a1 = null;
b1 = null;

我們已經(jīng)無法在程序中獲取到A與B對(duì)象了,因?yàn)樗麄儍蓚€(gè)除了彼此間的引用關(guān)系,已經(jīng)沒有任何引用能夠找到他們,所以按照常理來說,A與B對(duì)象都不會(huì)在程序中再使用了,理應(yīng)被垃圾回收器進(jìn)行回收,但是又由于存在彼此間的引用關(guān)系,引用計(jì)數(shù)器的值并不是0,那么此時(shí)垃圾回收器又會(huì)認(rèn)為A與B都存在被引用的關(guān)系,所以并不會(huì)回收這兩個(gè)類

那么這種情況顯然是不對(duì)的,無法回收的對(duì)象有可能會(huì)導(dǎo)致內(nèi)存泄漏,所以Java并沒有使用這種方法來判斷類是否應(yīng)該被回收,而是使用了另外一種方式

可達(dá)性分析法

Java使用的是可達(dá)性分析算法來判斷對(duì)象是否可以被回收

可達(dá)性分析法將對(duì)象分為兩類:

  • 垃圾回收根對(duì)象(GC Root)
  • 普通對(duì)象

對(duì)象與對(duì)象之間存在引用關(guān)系,形成一個(gè)引用鏈, 可達(dá)性分析算法就是指GC Root對(duì)象到某個(gè)對(duì)象間是可達(dá)的,即從GC Root對(duì)象開始,通過引用對(duì)象可以找到的對(duì)象愛國,即認(rèn)為該對(duì)象還不能被回收

此時(shí)B、C、D對(duì)象都可以通過引用被GC Root對(duì)象找到,即他們都是可達(dá)的,所以不會(huì)被視為可回收的對(duì)象,但是如果對(duì)象A與對(duì)象B之間取消引用關(guān)系,那么即使對(duì)象C與對(duì)象D任然存在引用關(guān)系,但他們是不可達(dá)的,因此他們會(huì)被回收

Java虛擬機(jī)會(huì)持有一個(gè)所有GC Root對(duì)象的列表,用來判斷哪些對(duì)象是不可達(dá)的,不可達(dá)的對(duì)象將被垃圾回收器進(jìn)行回收:

再次回看上面的案例,如果使用可達(dá)性分析法,那么堆內(nèi)存中應(yīng)該存在一個(gè)GC Root對(duì)象引用了主線程里面mian方法的棧幀中的對(duì)象,此時(shí)如果a1與b1不再引用堆中的對(duì)象,那么就算A對(duì)象與B對(duì)象存在引用關(guān)系,但是他們是不可達(dá)的,就會(huì)被視為等待回收的對(duì)象:

那么哪些對(duì)象可以被當(dāng)中GC Root對(duì)象呢?

主要有四種GC Root對(duì)象:

  • 1.線程Thread對(duì)象
  • 引用線程棧幀中的方法、參數(shù)、局部變量等等,上面我們的案例中就是線程Thread對(duì)象引用了mian方法棧幀中的a1與b1
  • 2.類加載器加載到的java.lang.Class對(duì)象
  • 引用類中的靜態(tài)變量
  • 3.監(jiān)視器對(duì)象
  • 用來保存同步鎖synchronized關(guān)鍵字持有的對(duì)象
  • 4.本地方法方法調(diào)用時(shí)使用的全局對(duì)象
  • 由Java虛擬機(jī)來控制調(diào)用

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論