【Java 虚拟机原理】垃圾回收算法 ( Java 虚拟机内存分区 | 垃圾回收机制 | 引用计数器算法 | 引用计数循环引用弊端 )
文章目錄
- 一、Java 虛擬機內存分區
- 二、垃圾回收機制
- 三、引用計數器算法 ( 無法解決循環引用問題 )
一、Java 虛擬機內存分區
Java 虛擬機內存分區 :
-
所有線程共有的內存區域 : 堆 , 方法區 ( 元空間 ) ;
- 方法區 : 存放 靜態變量 , 常量 , class 編譯后的代碼數據 , 永久代對象數據 ( 很少 GC , 永久代的 GC 就是卸載常量池及類型 ) ;
- 堆 : 存放 創建的 對象實例 , 所有線程共享這個區域 , 堆是 垃圾回收的重點管理區域 ; 有 年輕代 , 老年代 空間 ;
- 年輕代 : 占整個 堆內存的 13\cfrac{1}{3}31? 的空間 ;
- Eden 區 : 占 年輕代的 80%80\%80% 空間 ;
- Survivor 區 : 占年輕代的 20%20\%20% 空間 ;
- From : 占 年輕代的 10%10\%10% 空間 ;
- To : 占 年輕代的 10%10\%10% 空間 ;
- 老年代 : 占整個 堆內存的 23\cfrac{2}{3}32? 空間 ; 老年代又稱為永生代 , 只要程序沒有 OOM 崩潰 , 這些 對象都是永生的 ; 比較大的對象直接放入老年代 ;
- 年輕代 : 占整個 堆內存的 13\cfrac{1}{3}31? 的空間 ;
-
線程私有的內存區域 : 線程棧 , 本地方法棧 , 程序計數器 ; 每個線程都會分配上述 3 個內存區域 ;
- 虛擬機棧 ( 線程棧 ) : 主要管理 " 棧幀 " , 棧幀 在 線程棧 中也是 后入先出 的 ; 每個棧幀都包含 局部變量表 , 操作數棧 , 動態鏈接 , 方法出口 , 這四個數據 ;
- 動態鏈接 : 每個 " 棧幀 " 都包含一個引用 , 是該引用指向 運行時 , 該 棧幀 對應方法 的引用 ;
- 局部變量表 : 存放 方法中的 局部變量 ;
- 操作數棧 : 存放方法執行中的 操作數 , 一般是 0,1,20,1 , 20,1,2 個數值 , 很少有其它情況 ;
- 方法出口 : 記錄本方法執行完畢后該執行的下一行 JVM 指令 ;
- 本地方法棧 : 記錄 JNI 執行的棧 ;
- 程序計數器 : 記錄線程執行到哪一行的 JVM 指令 ;
- 虛擬機棧 ( 線程棧 ) : 主要管理 " 棧幀 " , 棧幀 在 線程棧 中也是 后入先出 的 ; 每個棧幀都包含 局部變量表 , 操作數棧 , 動態鏈接 , 方法出口 , 這四個數據 ;
二、垃圾回收機制
Java 中 不需要 手動回收 對象內存 , 由 Java 虛擬機 自動執行 ;
- 好處 : 開發相對簡單 ;
- 壞處 : 不能直接操作內存 ;
C 語言中 , 自己 malloc 手動申請了內存 , 必須使用 free 手動釋放內存 ;
垃圾回收 的目標 是 垃圾對象 , 主要針對 堆內存 中的空間進行 ;
垃圾對象 的判斷標準 : 沒有任何作用的 被廢棄的 對象 , 即 一個對象 沒有任何引用 指向它 ;
三、引用計數器算法 ( 無法解決循環引用問題 )
引用計數器算法 判定 垃圾對象 : 使用引用計數算法 , 判定一個對象是否是垃圾對象 ;
為 對象 分配 引用計數器 , 當 有一個引用指向它時 , 引用計數器 +1+ 1+1 , 如果有 333 個引用指向該對象時 , 引用計數器值為 333 , 如果某個引用失效 , 則 引用計數器 ?1- 1?1 , 如果對象的全部引用失效 , 則對象的引用計數器值為 000 , 此時該對象就是 垃圾對象 , 需要被回收 ;
目前成熟的 Java 虛擬機 沒有使用 引用計數器 算法 , 因為 如果 兩個對象 僅僅是 互相引用 , 這兩個對象的引用計數器 都是 111 , 但是這兩個對象與其余對象沒有任何聯系 , 這樣就導致了 這兩個對象所占用的內存 , 永久泄漏了 ;
引用計數器算法 無解解決 循環引用的問題 , 如果有 222 個及以上的對象循環引用 , 與程序隔絕 , 造成內存泄漏 , 無法解決 ;
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的【Java 虚拟机原理】垃圾回收算法 ( Java 虚拟机内存分区 | 垃圾回收机制 | 引用计数器算法 | 引用计数循环引用弊端 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Java 虚拟机原理】堆区 | Jav
- 下一篇: 【Java 虚拟机原理】垃圾回收算法 (