最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java垃圾收集之對(duì)象存活判定、回收流程與內(nèi)存策略詳解

 更新時(shí)間:2026年03月08日 10:28:07   作者:鈕祜祿愛因斯晨  
Java對(duì)象的內(nèi)存分配主要發(fā)生在堆內(nèi)存(新生代、老年代),少數(shù)情況可能分配在棧(棧上分配)或直接內(nèi)存(堆外內(nèi)存),這篇文章主要介紹了Java垃圾收集之對(duì)象存活判定、回收流程與內(nèi)存策略的相關(guān)資料,需要的朋友可以參考下

一、引言

在 Java 技術(shù)體系里,垃圾收集器(Garbage Collection,GC)與內(nèi)存分配策略是自動(dòng)內(nèi)存管理的核心支撐。深入探究其原理與機(jī)制,對(duì)優(yōu)化程序內(nèi)存性能、規(guī)避內(nèi)存泄漏與溢出等問題意義重大,是理解 Java 運(yùn)行時(shí)環(huán)境的關(guān)鍵環(huán)節(jié)

二、GC 基礎(chǔ)與核心問題

(一)GC 概念溯源

垃圾收集技術(shù)并非 Java 首創(chuàng),早在 1960 年,Lisp 語言已應(yīng)用內(nèi)存動(dòng)態(tài)分配與垃圾收集。GC 需解決三個(gè)核心問題:

  1. 識(shí)別待回收內(nèi)存:確定哪些對(duì)象已 “死亡”,即無被使用可能。
  2. 抉擇回收時(shí)機(jī):依據(jù)內(nèi)存使用狀況,選擇合適時(shí)機(jī)觸發(fā)回收。
  3. 選定回收方式:不同垃圾收集器采用各異的回收算法與實(shí)現(xiàn)邏輯 。

(二)對(duì)象存活判定算法

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

原理為給對(duì)象綁定引用計(jì)數(shù)器,引用建立時(shí)計(jì)數(shù)器加 1,引用失效時(shí)減 1,計(jì)數(shù)器為 0 則判定對(duì)象可回收。但存在循環(huán)引用缺陷,如代碼所示:

public class ReferenceCountingGC {
    public Object instance = null;
    private static final int _1MB = 1024 * 1024;
    private byte[] bigSize = new byte[2 * _1MB];
    public static void testGC() {
        ReferenceCountingGC objA = new ReferenceCountingGC();
        ReferenceCountingGC objB = new ReferenceCountingGC();
        objA.instance = objB;
        objB.instance = objA;
        objA = null;
        objB = null;
        System.gc();
    }
}

objAobjB相互引用,雖無實(shí)際訪問路徑,但引用計(jì)數(shù)不為 0,算法無法回收,故主流 Java 虛擬機(jī)棄用該算法。

2. 可達(dá)性分析算法

主流商用語言(如 Java、C#)采用的對(duì)象存活判定算法。以 “GC Roots” 為起始節(jié)點(diǎn)集,依據(jù)引用關(guān)系遍歷搜索,無引用鏈連接的對(duì)象判定為可回收。Java 中,GC Roots 涵蓋:

  • 虛擬機(jī)棧本地變量表引用對(duì)象,如方法內(nèi)參數(shù)、局部變量。
  • 方法區(qū)靜態(tài)屬性與常量引用對(duì)象,像類的靜態(tài)變量、字符串常量池引用。
  • 本地方法棧 JNI(Native 方法)引用對(duì)象。
  • 虛擬機(jī)內(nèi)部核心引用,包括 Class 對(duì)象、常駐異常對(duì)象(如 NullPointerException )等 。

三、引用分類及特性(JDK 1.2+)

JDK 1.2 拓展引用概念,按強(qiáng)度分為四類,各有獨(dú)特內(nèi)存管理行為:

(一)強(qiáng)引用

程序中最常見,如 Object obj = new Object() 。只要引用有效,對(duì)象不會(huì)被回收,是對(duì)象強(qiáng)存活的保障,支撐程序基本對(duì)象引用邏輯。

(二)軟引用

用于描述非必需但仍具使用價(jià)值的對(duì)象,內(nèi)存不足即將拋出溢出異常前,會(huì)觸發(fā)軟引用對(duì)象回收。通過 SoftReference 實(shí)現(xiàn),代碼示例:

SoftReference<Object> softRef = new SoftReference<>(new Object());
Object obj = softRef.get(); 

適用于緩存場景,內(nèi)存緊張時(shí)釋放非必需對(duì)象,平衡內(nèi)存使用與功能需求。

(三)弱引用

強(qiáng)度弱于軟引用,垃圾收集時(shí),無論內(nèi)存是否充足,弱引用關(guān)聯(lián)對(duì)象都會(huì)被回收。借助 WeakReference 實(shí)現(xiàn):

WeakReference<Object> weakRef = new WeakReference<>(new Object());
Object obj = weakRef.get(); 

常用于弱關(guān)聯(lián)對(duì)象管理,如觀察者模式中臨時(shí)關(guān)聯(lián),避免因?qū)ο笕跻脤?dǎo)致內(nèi)存無法釋放。

(四)虛引用

又稱幽靈 / 幻影引用,不影響對(duì)象生命周期,也無法通過其獲取對(duì)象,主要用于接收對(duì)象回收系統(tǒng)通知,由 PhantomReference 實(shí)現(xiàn)。是內(nèi)存回收事件監(jiān)聽的特殊手段,可在對(duì)象回收時(shí)執(zhí)行特定資源清理等操作 。

四、對(duì)象回收流程與機(jī)制

對(duì)象經(jīng)可達(dá)性分析判定為不可達(dá)后,需歷經(jīng)兩次標(biāo)記才會(huì)被回收:

(一)首次標(biāo)記與篩選

對(duì)象無 GC Roots 引用鏈時(shí),觸發(fā)首次標(biāo)記。隨后篩選是否需執(zhí)行 finalize() 方法,未重寫該方法或方法已執(zhí)行過的對(duì)象,直接判定為可回收。

(二)二次標(biāo)記與挽救

需執(zhí)行 finalize() 的對(duì)象,被移入F - Queue隊(duì)列,由 Finalizer 線程執(zhí)行該方法。若對(duì)象在 finalize() 中重新建立引用鏈(如關(guān)聯(lián)到類變量 ),二次標(biāo)記時(shí)會(huì)被移出回收隊(duì)列;否則,執(zhí)行回收。但 finalize() 存在運(yùn)行代價(jià)高、不確定性大、無法保證調(diào)用順序等問題,推薦以 try - finally 替代,示例代碼展現(xiàn)對(duì)象自我拯救過程:

public class FinalizeEscapeGC {
    public static FinalizeEscapeGC SAVE_HOOK = null;
    public void isAlive() {
        System.out.println("yes, i am still alive :)");
    }
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize method executed!");
        FinalizeEscapeGC.SAVE_HOOK = this;
    }
    public static void main(String[] args) throws Throwable {
        // 首次拯救邏輯
        SAVE_HOOK = new FinalizeEscapeGC();
        SAVE_HOOK = null;
        System.gc();
        Thread.sleep(500); 
        if (SAVE_HOOK != null) {
            SAVE_HOOK.isAlive();
        } else {
            System.out.println("no, i am dead :(");
        }
        // 二次拯救(失敗,因 finalize 僅執(zhí)行一次)
        SAVE_HOOK = null;
        System.gc();
        Thread.sleep(500); 
        if (SAVE_HOOK != null) {
            SAVE_HOOK.isAlive();
        } else {
            System.out.println("no, i am dead :(");
        }
    }
}

五、方法區(qū)的回收機(jī)制

方法區(qū)(如 HotSpot 的元空間 / 永久代 )常被誤解為無垃圾收集,實(shí)則不然,其回收聚焦以下兩部分:

(一)常量池回收

若常量池中的常量(如字符串 )無對(duì)象引用,且虛擬機(jī)無其他引用,可被回收。如字符串 “java” ,若系統(tǒng)無對(duì)應(yīng)引用,內(nèi)存回收時(shí)可能被清理,優(yōu)化常量池內(nèi)存占用。

(二)無用類回收

判定類為 “無用” 需滿足三個(gè)條件:

  1. 類及派生子類無實(shí)例,Java 堆中不存在該類相關(guān)實(shí)例。
  2. 加載該類的類加載器被回收,此條件在自定義類加載器場景中較難滿足,需精心設(shè)計(jì)。
  3. 該類對(duì)應(yīng)的 java.lang.Class 對(duì)象無引用,無法通過反射訪問類方法。

Java 虛擬機(jī)允許回收滿足條件的類,但非強(qiáng)制。在反射、動(dòng)態(tài)代理等場景,需虛擬機(jī)具備類型卸載能力,可通過 -verbose:class、-XX:+TraceClassLoading、-XX:+TraceClassUnLoading(部分需 FastDebug 版支持 )查看類加載 / 卸載信息,保障方法區(qū)內(nèi)存健康。

六、結(jié)論

Java 垃圾收集器與內(nèi)存分配策略,構(gòu)建起自動(dòng)內(nèi)存管理的核心體系。從對(duì)象存活判定的算法演進(jìn),到引用分類的精細(xì)管控,再到對(duì)象回收流程的嚴(yán)謹(jǐn)執(zhí)行與方法區(qū)回收的特殊處理,共同保障程序內(nèi)存高效利用。深入理解該體系,是優(yōu)化程序性能、解決內(nèi)存問題的關(guān)鍵。后續(xù)將進(jìn)一步探究具體垃圾收集器(如 Serial、G1 等 )的實(shí)現(xiàn)與內(nèi)存分配策略細(xì)節(jié),持續(xù)深化 Java 內(nèi)存管理研究,為 Java 開發(fā)者筑牢技術(shù)根基,助力打造更高效、穩(wěn)定的Java應(yīng)用 。

到此這篇關(guān)于Java垃圾收集之對(duì)象存活判定、回收流程與內(nèi)存策略的文章就介紹到這了,更多相關(guān)Java對(duì)象存活判定、回收流程與內(nèi)存策略內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java 如何復(fù)制非空對(duì)象屬性值

    java 如何復(fù)制非空對(duì)象屬性值

    這篇文章主要介紹了java 如何復(fù)制非空對(duì)象屬性值的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java多線程的臨界資源問題解決方案

    Java多線程的臨界資源問題解決方案

    這篇文章主要介紹了Java多線程的臨界資源問題解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Java中使用Thread類和Runnable接口實(shí)現(xiàn)多線程的區(qū)別

    Java中使用Thread類和Runnable接口實(shí)現(xiàn)多線程的區(qū)別

    這篇文章主要介紹了使用Thread類和Runnable接口實(shí)現(xiàn)多線程的區(qū)別,本文給大家介紹了兩種實(shí)現(xiàn)方式的步驟,除了以上兩種多線程實(shí)現(xiàn)方式,還可以使用 Callable 接口實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • 詳解Java實(shí)現(xiàn)緩存(LRU,FIFO)

    詳解Java實(shí)現(xiàn)緩存(LRU,FIFO)

    本篇文章主要介紹了詳解Java實(shí)現(xiàn)緩存(LRU,FIFO) ,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • maven如何使用profiles多環(huán)境配置

    maven如何使用profiles多環(huán)境配置

    在軟件開發(fā)過程中,我們經(jīng)常需要在不同的環(huán)境中部署和運(yùn)行我們的應(yīng)用程序,例如開發(fā)環(huán)境、測試環(huán)境和生產(chǎn)環(huán)境,為了方便管理和配置不同環(huán)境下的參數(shù),我們可以使用Maven的profiles功能,本文給大家介紹maven如何使用profiles多環(huán)境配置,感興趣的的朋友一起看看吧
    2024-02-02
  • IDEA中使用jclasslib插件可視化方式查看類字節(jié)碼的過程詳解

    IDEA中使用jclasslib插件可視化方式查看類字節(jié)碼的過程詳解

    查看JAVA字節(jié)碼有兩種方式一種是使用 jdk命令 javap,還有一種就是 使用 插件了,今天給大家分享IDEA中使用jclasslib插件可視化方式查看類字節(jié)碼的過程詳解,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • Java實(shí)現(xiàn)格式化打印慢SQL日志的方法詳解

    Java實(shí)現(xiàn)格式化打印慢SQL日志的方法詳解

    不管我們使用何種語言開發(fā),一旦程序發(fā)生異常,日志是一個(gè)很重要的數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)格式化打印慢SQL日志的相關(guān)資料,需要的朋友可以參考下
    2022-10-10
  • Java中字符串拼接的一些細(xì)節(jié)分析

    Java中字符串拼接的一些細(xì)節(jié)分析

    這篇文章主要介紹了Java中字符串拼接的一些細(xì)節(jié)分析,本文著重剖析了字符串拼接的一些性能問題、技巧等內(nèi)容,需要的朋友可以參考下
    2015-01-01
  • 詳解spring注解式參數(shù)校驗(yàn)

    詳解spring注解式參數(shù)校驗(yàn)

    本篇文章主要介紹了詳解spring注解式參數(shù)校驗(yàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-06-06
  • JAVA中AES加密方法實(shí)例分析

    JAVA中AES加密方法實(shí)例分析

    這篇文章主要介紹了JAVA中AES加密方法,實(shí)例分析了java中AES加密與解密的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07

最新評(píng)論

巨野县| 福建省| 黄石市| 汝州市| 孟州市| 梁山县| 理塘县| 马山县| 河东区| 高平市| 赞皇县| 白玉县| 玉龙| 呼玛县| 涿鹿县| 洪洞县| 南江县| 博罗县| 安庆市| 施秉县| 东丰县| 株洲县| 泸溪县| 武安市| 中牟县| 大姚县| 阿克苏市| 常宁市| 巴里| 孝义市| 德州市| 恩平市| 咸丰县| 京山县| 昔阳县| 翁牛特旗| 临邑县| 肃宁县| 大同市| 北川| 米脂县|