国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

引用計數(shù) vs 根可達算法:深入比較對象存活判定

這篇具有很好參考價值的文章主要介紹了引用計數(shù) vs 根可達算法:深入比較對象存活判定。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

引用計數(shù) vs 根可達算法:深入比較對象存活判定,# JVM,算法,java,開發(fā)語言

?? 嗨,您好 ?? 我是 vnjohn,在互聯(lián)網(wǎng)企業(yè)擔任 Java 開發(fā),CSDN 優(yōu)質(zhì)創(chuàng)作者
?? 推薦專欄:Spring、MySQL、Nacos、Java,后續(xù)其他專欄會持續(xù)優(yōu)化更新迭代
??文章所在專欄:JVM
?? 我當前正在學習微服務(wù)領(lǐng)域、云原生領(lǐng)域、消息中間件等架構(gòu)、原理知識
?? 向我詢問任何您想要的東西,ID:vnjohn
??覺得博主文章寫的還 OK,能夠幫助到您的,感謝三連支持博客??
?? 代詞: vnjohn
? 有趣的事實:音樂、跑步、電影、游戲

目錄

前言

在 Java 中,判定對象是否存活指的是哪些不再被程序所引用,也無法通過任何方式訪問的對象;具體來說,當一個對象不再被任何活動線程所引用,并且沒有被其他對象所引用時,它就被認為是 “死亡” 對象;“死亡” 對象占用內(nèi)存空間但不再有任何實際的用途,因此需要通過垃圾收集機制將其從內(nèi)存中釋放,以便重新利用內(nèi)存資源;Java 垃圾收集機制會自動識別、回收這些 “死亡” 對象,無需程序員手動管理內(nèi)存釋放的過程

什么是垃圾?

沒有引用指向或根對象不可達的引用對象,被稱之為垃圾

Java 與 C++ 對垃圾的處理方式有所不同,如下:

Java:自動回收垃圾,由 GC 回收機制去自動回收,開發(fā)效率高,執(zhí)行效率低
C++:手動處理垃圾,若忘記回收時,容易發(fā)生內(nèi)存泄漏,回收多次,會出現(xiàn)非法訪問問題,一般手動回收的代碼(delete)會寫在析構(gòu)函數(shù)中;開發(fā)效率低,執(zhí)行效率高

如何定位垃圾

在堆里面存放著 Java 世界中幾乎所有的對象實例,垃圾收集器在對堆進行回收前,第一件事情就是要確定這些對象哪些還 “存活” 著,哪些對象已經(jīng) “死亡” 了

引用計數(shù)算法

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

引用指向一個對象,在它腦袋上寫一個數(shù)字,有幾個對象指向它就在它腦袋上寫一個幾,當這個數(shù)字變?yōu)?0 時,就說明沒有任何對象指向它,即為 “垃圾”

在 Java 領(lǐng)域中,至少主流的 Java 虛擬機都沒有選用引用計數(shù)算法來管理內(nèi)存,主要原因:一個看似很簡單的算法有很多例外情況要考慮,必須要配合大量額外處理才能正確地工作

譬如單純的引用計數(shù)算法就很難解決對象之間相互引用的問題,例如:A->B、B->A,A、B 計數(shù)器的值都為 1,所以在當前算法來說不是垃圾,但從此看來,沒有其他的引用會使用到它們,按理來說這幾個都應(yīng)該是為 “垃圾”

以上會出現(xiàn)的對象之間互相引用問題,通過代碼來演示,看 Java JVM 中是否使用到了引用計數(shù)算法來回收垃圾,如下:

/**
 * @author vnjohn
 * @since 2023/6/29
 */
public class ReferenceCountingGC {
    public Object instance = null;

    private byte[] bigSize = new byte[2 * 1024 * 1024];

    public static void main(String[] args) {
        ReferenceCountingGC objA = new ReferenceCountingGC();
        ReferenceCountingGC objB = new ReferenceCountingGC();
        objA.instance = objB;
        objB.instance = objA;

        objA = null;
        objB = null;

        System.gc();
    }
}

調(diào)整 JVM Options 參數(shù),增加打印 GC 回收詳情信息,如下:

# 打印 GC 回收時間、GC 回收詳情
-XX:+PrintGCTimeStamps -XX:+PrintGCDetails

控制臺打印結(jié)果如下:

0.107: [GC (System.gc()) [PSYoungGen: 6717K->608K(76288K)] 6717K->616K(251392K), 0.0044845 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
0.112: [Full GC (System.gc()) [PSYoungGen: 608K->0K(76288K)] [ParOldGen: 8K->378K(175104K)] 616K->378K(251392K), [Metaspace: 3100K->3100K(1056768K)], 0.0026966 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 76288K, used 3277K [0x000000076ab00000, 0x0000000770000000, 0x00000007c0000000)
  eden space 65536K, 5% used [0x000000076ab00000,0x000000076ae334d8,0x000000076eb00000)
  from space 10752K, 0% used [0x000000076eb00000,0x000000076eb00000,0x000000076f580000)
  to   space 10752K, 0% used [0x000000076f580000,0x000000076f580000,0x0000000770000000)
 ParOldGen       total 175104K, used 378K [0x00000006c0000000, 0x00000006cab00000, 0x000000076ab00000)
  object space 175104K, 0% used [0x00000006c0000000,0x00000006c005e9e8,0x00000006cab00000)
 Metaspace       used 3130K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 343K, capacity 388K, committed 512K, reserved 1048576K

重點看前面兩行日志信息

年輕代:0.107: [GC (System.gc()) [PSYoungGen: 6717K(回收前大?。?>608K(回收后大?。?/mark>(76288K)] 6717K->616K(251392K), 0.0044845 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
老年代:0.112: [Full GC (System.gc()) [PSYoungGen: 608K(回收前大小)->0K(回收后大?。?/mark>(76288K)] [ParOldGen: 8K->378K(175104K)] 616K->378K(251392K), [Metaspace: 3100K->3100K(1056768K)], 0.0026966 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]

以上標注黃色背景的日志內(nèi)容,可以看出 Java 虛擬機并沒有因為這兩個對象循環(huán)引用而放棄回收它們,這也從側(cè)面說明了 Java 虛擬機并不是通過引用計數(shù)算法來判斷對象是否存活的

JDK 8 默認使用的垃圾收集器:Parallel Scavenge、Parallel Old
Java中常見的垃圾收集器,如:Serial、Parallel、CMS、G1 等,并不使用引用計數(shù)算法,而是采用基于可達性分析的算法來進行垃圾回收,這個也是后面要講到的算法

可達性分析算法

可達性分析算法(Reachability Analysis):它是一個更廣泛的概念,它是一類以可達性作為判斷對象是否存活基礎(chǔ)的算法,除了根可達算法外,還有其他的可達性分析算法,如:可達性分析與復制算法、可達性分析與標記-清除算法等

根可達算法是可達性分析算法中的一種具體實現(xiàn)方式,根可達算法是從一組稱為 “GC Roots” 根對象開始,通過引用關(guān)系向下搜索,搜索過程所走過的過程稱為 “引用鏈”;若某個對象到 GC Roots 間沒有任何引用鏈相連或者用圖論的方式來說就是從 GC Roots 到這個對象不可達時,則證明此對象是不可能再被使用的

引用計數(shù) vs 根可達算法:深入比較對象存活判定,# JVM,算法,java,開發(fā)語言

如上圖,在 Java 技術(shù)體系中,固定可作為 GC Roots 對象包括以下幾種:

  1. 線程棧變量:在虛擬機棧(棧幀中的本地變量表)中引用的對象,譬如各個線程被調(diào)用的方法堆棧中使用到的參數(shù)、局部變量、臨時變量等

比如:main 方法主線程開始運行,主線程棧中變量調(diào)用了其他的方法,主線程棧中的方法訪問到的對象叫根對象

  1. 靜態(tài)變量:在方法區(qū)類靜態(tài)屬性引用的對象,譬如 Java 類引用類型的靜態(tài)變量

靜態(tài)變量初始化,能夠訪問到的對象稱之為根對象

  1. 常量池:在方法區(qū)中常量引用的對象,譬如字符串常量池(String Constant Pool)里面的引用

若一個 class 能夠用到其他的 class 對象稱之為根對象

  1. JNI 指針:在本地方法棧中 JNI(Java Native Interface)方法引用的對象
  2. 基礎(chǔ)數(shù)據(jù)類型 Class 對象:Java 虛擬機內(nèi)部的引用,如 int 類型對應(yīng) Class 對象是 Integer.TYPE 或 int.class、long 類型對應(yīng) Class 對象是 Long.TYPE 或 long.class
  3. 常駐異常對象:Java 虛擬機內(nèi)部的引用,如 NullPointException、OutOfMemoryError
  4. 系統(tǒng)類加載器
  5. 同步鎖持有對象:被同步鎖 synchronized 持有的對象

GC Roots 是垃圾收集器判斷對象是否存活的起點,不同的垃圾收集器會根據(jù) GC Roots 選擇合適的垃圾回收算法來進行垃圾回收、內(nèi)存管理,它們的共同協(xié)作以確保內(nèi)存的有效利用和程序的正常執(zhí)行

常見的垃圾回收算法:復制(Copying)算法、標記-清除 (Mark-Sweep)算法、標記-整理(Mark-Compact)算法

至于很多人說還有分代算法,在我看來,分代模型應(yīng)該是最準確的說法,分代算法不是指具體的一種算法,而是一種垃圾回收的策略或模型

由于對象的生命周期大部分是朝生夕死的,只有少數(shù)對象是長期存活的,基于此,垃圾收集器將堆內(nèi)存劃分為不同的代,分代模型將堆內(nèi)存主要劃分為新生代(Young Generation)和老年代(Old Generation)

G1 垃圾收集器邏輯分代,物理不分代

ZGC、Shenandoah 垃圾收集器沒有物理分代,也沒有邏輯分代

其他的垃圾收集器一般要么作用于新生代要么作用于老年代,例如:Parallel Scavenge-新生代、Parallel Old-老年代

關(guān)于垃圾回收算法、垃圾收集器后續(xù)文章見分曉,這里不過多展開~

總結(jié)

該篇博文講解判定對象是否存活的條件通過什么方式去做的,引用計數(shù)器算法、根可達算法,在引用計數(shù)器算法中,通過簡單的案例來演示在 Java 程序中并未通過該算法來判定對象是否存活,而是通過根可達算法去作判別的,羅列了 Java GC Roots 不同的種類,簡要闡述了為下文作鋪墊的垃圾回收算法、垃圾收集器,希望能先帶你一起了解這方面的前置知識!

參考文獻:《深入理解 Java 虛擬機》周志明著

博文放在 JVM 專欄里,歡迎訂閱,會持續(xù)更新!

如果覺得博文不錯,關(guān)注我 vnjohn,后續(xù)會有更多實戰(zhàn)、源碼、架構(gòu)干貨分享!

推薦專欄:Spring、MySQL,訂閱一波不再迷路

大家的「關(guān)注?? + 點贊?? + 收藏?」就是我創(chuàng)作的最大動力!謝謝大家的支持,我們下文見!文章來源地址http://www.zghlxwxcb.cn/news/detail-522473.html

到了這里,關(guān)于引用計數(shù) vs 根可達算法:深入比較對象存活判定的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Java虛擬機(JVM):引用計數(shù)算法

    Java虛擬機(JVM):引用計數(shù)算法

    我們學習了Java內(nèi)存運行時區(qū)域的各個部分,其中程序計數(shù)器、虛擬機棧、本地方法棧3個區(qū)域隨線程而生,隨線程而滅。棧中的棧幀隨著方法的進入和退出而有條不紊地執(zhí)行著出棧和入棧操作。每一個棧幀中分配多少內(nèi)存基本上是在類結(jié)構(gòu)確定下來就已知的,因此這幾個區(qū)域

    2024年02月12日
    瀏覽(21)
  • JavaScript引用數(shù)據(jù)類型(對象類型)和原始(基本)數(shù)據(jù)類型特點比較

    JavaScript引用數(shù)據(jù)類型(對象類型)和原始(基本)數(shù)據(jù)類型特點比較

    為講解JavaScript引用數(shù)據(jù)類型(對象類型)和原始(基本)數(shù)據(jù)類型特點比較,需要先回顧JavaScript數(shù)據(jù)類型有哪些? 一)原始(primitive:原始、基本)數(shù)據(jù)類型,也稱為原始值(primitive value),包括: 1.布爾值(Boolean),其字面值只有兩個,分別是true和false。 2.null,Null類型

    2024年02月05日
    瀏覽(18)
  • 深入探討Docker生態(tài)系統(tǒng),Docker Compose vs. Docker Swarm vs. Kubernetes:深入比較

    深入探討Docker生態(tài)系統(tǒng),Docker Compose vs. Docker Swarm vs. Kubernetes:深入比較

    ??個人主頁:程序員 小侯 ??CSDN新晉作者 ??歡迎 ??點贊?評論?收藏 ?收錄專欄:大數(shù)據(jù)系列 ?文章內(nèi)容:Docker生態(tài)系統(tǒng) ??希望作者的文章能對你有所幫助,有不足的地方請在評論區(qū)留言指正,大家一起學習交流!?? Docker已經(jīng)成為現(xiàn)代容器化應(yīng)用程序的事實標準,但

    2024年02月07日
    瀏覽(21)
  • 【排序算法】 計數(shù)排序(非比較排序)詳解!了解哈希思想!

    【排序算法】 計數(shù)排序(非比較排序)詳解!了解哈希思想!

    ?? 嶼小夏 : 個人主頁 ??個人專欄 : 算法—排序篇 ?? 莫道桑榆晚,為霞尚滿天! 什么是計數(shù)排序?計數(shù)排序的思想是什么?它是如何實現(xiàn)的? 本文會對計數(shù)排序進行由淺入深的探究,讓你徹底掌握計數(shù)排序! ? 計數(shù)排序又稱為鴿巢原理,是對哈希直接定址法的變形應(yīng)

    2024年02月06日
    瀏覽(25)
  • 深入淺出排序算法之計數(shù)排序

    深入淺出排序算法之計數(shù)排序

    目錄 1. 原理 2. 代碼實現(xiàn) 3. 性能分析 首先看一個題目,有n個數(shù),取值范圍是 0~n,寫出一個排序算法,要求時間復雜度和空間復雜度都是O(n)的。 為了達到這種效果,這一篇將會介紹一種 不基于比較的排序方法。 這種方法被稱為計數(shù)排序。 計數(shù)排序的思路是這樣的,對于每

    2024年02月06日
    瀏覽(19)
  • 關(guān)于VS2022使用EF生成實體模型報錯的問題:運行轉(zhuǎn)換:System.NullReferenceException:對象引用未設(shè)置為對象的示例。

    關(guān)于VS2022使用EF生成實體模型報錯的問題:運行轉(zhuǎn)換:System.NullReferenceException:對象引用未設(shè)置為對象的示例。

    起因: 之前版本vs2022生成EF模型一直沒有問題,在更新了最新的vs2022之后,版本號17.6+,出現(xiàn)此問題: 正在運行轉(zhuǎn)換:System.NullReferenceException:未將對象引用設(shè)置到對象的實例。 具體錯誤如下: 正在運行轉(zhuǎn)換: System.NullReferenceException: 未將對象引用設(shè)置到對象的實例。 在 Micro

    2024年02月08日
    瀏覽(35)
  • iOS——引用計數(shù)(一)

    iOS——引用計數(shù)(一)

    自動引用計數(shù)(ARC,Automatic Reference Counting)是指內(nèi)存管理中對引用采取自動計數(shù)的技術(shù)。 滿足以下要求后,我們的代碼就無需再次鍵入retain或者是release代碼了: 使用Xcode 4.2或以上版本 使用LLVM編譯器3.0或以上版本 編譯器選項中設(shè)置ARC為有效 在以上條件下編譯源代碼時,編

    2024年02月07日
    瀏覽(18)
  • C++引用計數(shù)

    C++引用計數(shù)

    引用計數(shù)(reference count)的核心思想是使用一個計數(shù)器來標識當前指針指向的對象被多少類的對象所使用(即記錄指針指向?qū)ο蟊灰玫拇螖?shù))。它允許有多個相同值的對象共享這個值的實現(xiàn)。引用計數(shù)的使用常有兩個目的: 簡化跟蹤堆中(也即C++中new出來的)的對象的過程

    2024年02月11日
    瀏覽(14)
  • RCU安全引用計數(shù)

    原文網(wǎng)址:https://lwn.net/Articles/93617 原文作者:Corbet 原文時間:2004年7月14日 內(nèi)核提供了一種用于實現(xiàn)引用計數(shù)的簡單機制kref;該機制是今年3月份完成的。kref機制的核心思想是,提供支持原子操作的計數(shù)器,用于對未決引用【outstanding references】進行計數(shù)。如果計數(shù)器數(shù)值為

    2024年02月11日
    瀏覽(24)
  • C++智能指針學習——小談引用計數(shù)

    C++智能指針學習——小談引用計數(shù)

    目錄 前言 控制塊簡介 共享控制塊 引用計數(shù)與弱引用計數(shù)創(chuàng)建過程 __shared_ptr __shared_count _Sp_counted_base 弱引用計數(shù)增加過程 再談共享控制塊 __weak_count 引用計數(shù)增加過程 弱引用計數(shù)的減少過程 弱引用計數(shù)減為0 引用計數(shù)的減少過程 引用計數(shù)減為0 參考文章 本文結(jié)合源碼討論

    2024年04月08日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包