ReviewForJob——java虚拟机的垃圾回收策略(个人总结)
生活随笔
收集整理的這篇文章主要介紹了
ReviewForJob——java虚拟机的垃圾回收策略(个人总结)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
理解jvm的垃圾回收策略,需要解決以下3個問題
問題1:哪些內存需要回收? 問題2:什么時候進行回收? 問題3:怎樣來回收?
【解決問題1】哪些內存需要回收? jvm的內存區域有5大塊: 1)程序計數器:線程私有,用于記錄 當前線程所執行class 字節碼的行號計數器; 2)java 虛擬機棧:線程私有,指java 方法執行的 內存模型; 3)本地方法棧:線程私有,指java 本地方法執行的 內存模型; 4)java堆:線程公有,用于存儲所有對象實例 和 數組; 5)方法區:線程公有,用于存儲編譯后的 類信息(Class類),常量,靜態變量 和 即時編譯后的數據; 顯然,線程公有的內存區域需要回收,即 java堆 和 方法區; 看個荔枝:以可達性分析算法為荔枝,來介紹哪些內存需要回收? 其基本思想就是通過稱為“GC Root”的對象作為起點,點向下搜索,搜索所走過的路徑稱為引用鏈,但一個對象到GC Root沒有任何引用鏈相連的話,則證明對象是不可用的;(這時可以考慮通過 相交集和非相交集算法來實現) GC Roots的對象包括下面幾種(Objects): O1)虛擬機?;虮镜胤椒V幸玫膶ο?#xff1b; O2)方法區中常量或類靜態屬性引用的對象;
【解決問題2】什么時候進行回收? 顯然當 java堆或方法區的內存容量不足以滿足class字節碼運行時所需要的內存空間的時候,就需要進行內存回收(因為在運行期間,你不知道該字節碼文件需要多少內存,多大內存);
【解決問題3】怎樣來回收?這就不得不講 垃圾回收算法了。 寫在前面)java堆分為 老年代 和 新生代;對象首先分配在新生代Eden區中,當在新生代中經過若干次垃圾收集后,該對象如果還存在的話,就將其移入老年代進行存儲;
算法1)標記-清除算法(回收老年代):首先根據可達性分析標記處需要回收的對象;之后再統一回收所有被標記的對象; 缺點1:效率問題,標記和清除兩個效率都不高; 缺點2:空間問題,標記清除之后會留下大量的內存碎片 以至于可能導致以后分配較大對象時,因為無法找到足夠的連續內存而不得不提前觸發來一次垃圾收集動作;
算法2)復制算法(回收新生代):將jvm公共內存(主要是堆內存)劃分為容量相等的兩塊A 和 B,每次只使用其中一塊,如A 來進行運行時的內存分配;當塊A要使用完的時候,將塊A中的還存活的對象復制到 塊B上,然后一次性回收塊A中的使用空間。下一次就使用塊B 來進行運行時的內存分配了,而塊A的使用空間為零,即塊A的所有空間可用(復制垃圾回收算法主要解決的問題是: 內存碎片問題)。 缺點1:該算法的代價是將內存縮小了一半;內存利用率低;
算法3)復制算法變體算法(回收新生代):內存空間并不是像 算法2那樣 1:1 的分配,而是將內存分為 一塊 8個單位的稱為 Eden空間的內存, 兩塊 1個單位的稱為Survivor 空間的內存,記為A和B;每次只使用 Eden空間內存 和 其中一塊Survivor空間 如A的內存;當 上述內存空間要使用完的時候,就把 Eden空間和 Survivor A 空間的對象復制到 Survivor B空間中,然后再清除 Eden空間 和 Survivor A 空間中的內存;下次運行時內存分配區域是 Eden空間 和 Survivor A空間; 那如果 上述過程中 Survivor B 無法儲存 Eden 和 Survivor A 中的對象的時候,需要其他內存(老年代)進行分配擔保,即借用老年代的一部分內存空間來存儲 Eden 和 SurvivorA 中的對象數據。
算法4)標記整理算法(回收老年代):該算法類似于 標記清除算法,不同的是在清理階段,讓所有存活對象都向一端移動,然后直接清理內存邊界以外的內存
算法5)算法綜述——分代收集算法:要知道 java堆內存分為 新生代 和 老年代; 新生代:新生代中,每次垃圾收集時都發現有大批對象時區,只有少量存活,選用復制算法; 老年代:因為老年代中 對象存活率高,沒有額外空間對它進行分配擔保,就必須使用 “標記-清理” 或 標記整理算法 進行回收;
【2】Minor GC 和 Full/Major GC 1)Minor GC(新生代GC):因為 對象首先分配在 java堆新生代中的 Eden空間,如果Eden空間不夠用的話,就會進行一次 Minor GC; 2)Full/Major GC(老年代GC):大對象直接進入老年代(大對象就是需要大量連續內存空間的對象) 注意)Full/Major GC 比 Minor GC的速度至少慢10倍以上;所以能用Minor GC 解決問題 就不要用 Major GC;
【解決問題1】哪些內存需要回收? jvm的內存區域有5大塊: 1)程序計數器:線程私有,用于記錄 當前線程所執行class 字節碼的行號計數器; 2)java 虛擬機棧:線程私有,指java 方法執行的 內存模型; 3)本地方法棧:線程私有,指java 本地方法執行的 內存模型; 4)java堆:線程公有,用于存儲所有對象實例 和 數組; 5)方法區:線程公有,用于存儲編譯后的 類信息(Class類),常量,靜態變量 和 即時編譯后的數據; 顯然,線程公有的內存區域需要回收,即 java堆 和 方法區; 看個荔枝:以可達性分析算法為荔枝,來介紹哪些內存需要回收? 其基本思想就是通過稱為“GC Root”的對象作為起點,點向下搜索,搜索所走過的路徑稱為引用鏈,但一個對象到GC Root沒有任何引用鏈相連的話,則證明對象是不可用的;(這時可以考慮通過 相交集和非相交集算法來實現) GC Roots的對象包括下面幾種(Objects): O1)虛擬機?;虮镜胤椒V幸玫膶ο?#xff1b; O2)方法區中常量或類靜態屬性引用的對象;
【解決問題2】什么時候進行回收? 顯然當 java堆或方法區的內存容量不足以滿足class字節碼運行時所需要的內存空間的時候,就需要進行內存回收(因為在運行期間,你不知道該字節碼文件需要多少內存,多大內存);
【解決問題3】怎樣來回收?這就不得不講 垃圾回收算法了。 寫在前面)java堆分為 老年代 和 新生代;對象首先分配在新生代Eden區中,當在新生代中經過若干次垃圾收集后,該對象如果還存在的話,就將其移入老年代進行存儲;
算法1)標記-清除算法(回收老年代):首先根據可達性分析標記處需要回收的對象;之后再統一回收所有被標記的對象; 缺點1:效率問題,標記和清除兩個效率都不高; 缺點2:空間問題,標記清除之后會留下大量的內存碎片 以至于可能導致以后分配較大對象時,因為無法找到足夠的連續內存而不得不提前觸發來一次垃圾收集動作;
算法2)復制算法(回收新生代):將jvm公共內存(主要是堆內存)劃分為容量相等的兩塊A 和 B,每次只使用其中一塊,如A 來進行運行時的內存分配;當塊A要使用完的時候,將塊A中的還存活的對象復制到 塊B上,然后一次性回收塊A中的使用空間。下一次就使用塊B 來進行運行時的內存分配了,而塊A的使用空間為零,即塊A的所有空間可用(復制垃圾回收算法主要解決的問題是: 內存碎片問題)。 缺點1:該算法的代價是將內存縮小了一半;內存利用率低;
算法3)復制算法變體算法(回收新生代):內存空間并不是像 算法2那樣 1:1 的分配,而是將內存分為 一塊 8個單位的稱為 Eden空間的內存, 兩塊 1個單位的稱為Survivor 空間的內存,記為A和B;每次只使用 Eden空間內存 和 其中一塊Survivor空間 如A的內存;當 上述內存空間要使用完的時候,就把 Eden空間和 Survivor A 空間的對象復制到 Survivor B空間中,然后再清除 Eden空間 和 Survivor A 空間中的內存;下次運行時內存分配區域是 Eden空間 和 Survivor A空間; 那如果 上述過程中 Survivor B 無法儲存 Eden 和 Survivor A 中的對象的時候,需要其他內存(老年代)進行分配擔保,即借用老年代的一部分內存空間來存儲 Eden 和 SurvivorA 中的對象數據。
算法4)標記整理算法(回收老年代):該算法類似于 標記清除算法,不同的是在清理階段,讓所有存活對象都向一端移動,然后直接清理內存邊界以外的內存
算法5)算法綜述——分代收集算法:要知道 java堆內存分為 新生代 和 老年代; 新生代:新生代中,每次垃圾收集時都發現有大批對象時區,只有少量存活,選用復制算法; 老年代:因為老年代中 對象存活率高,沒有額外空間對它進行分配擔保,就必須使用 “標記-清理” 或 標記整理算法 進行回收;
【2】Minor GC 和 Full/Major GC 1)Minor GC(新生代GC):因為 對象首先分配在 java堆新生代中的 Eden空間,如果Eden空間不夠用的話,就會進行一次 Minor GC; 2)Full/Major GC(老年代GC):大對象直接進入老年代(大對象就是需要大量連續內存空間的對象) 注意)Full/Major GC 比 Minor GC的速度至少慢10倍以上;所以能用Minor GC 解決問題 就不要用 Major GC;
總結
以上是生活随笔為你收集整理的ReviewForJob——java虚拟机的垃圾回收策略(个人总结)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么用ps做出火焰效果(怎么用ps做出火
- 下一篇: 怎么磨皮保留质感(ps怎么磨皮保留质感)