網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
目錄
- 檢測(cè)垃圾
- 引用計(jì)數(shù)算法
- 可達(dá)性分析算法
- 回收垃圾
- 標(biāo)記清除算法
- 復(fù)制算法
- 標(biāo)記整理算法
- 分代算法
Java運(yùn)行時(shí)內(nèi)存中的程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧這三部分區(qū)域其生命周期與相關(guān)線程有關(guān),隨線程而生,隨線程而滅。而程序計(jì)數(shù)器就是一個(gè)單純存地址的整數(shù)也不需要關(guān)心,因此我們GC(垃圾回收)的主要目標(biāo)就是堆(堆中存放著幾乎所有實(shí)例對(duì)象)!
檢測(cè)垃圾
一個(gè)對(duì)象,如果后續(xù)不再被使用且沒(méi)有引用指向它,就可以認(rèn)為是垃圾。
有以下方法可知對(duì)象是否有引用指向:
引用計(jì)數(shù)算法
在主流的JVM中沒(méi)有選用引用計(jì)數(shù)法來(lái)管理內(nèi)存,最主要的原因就是引用計(jì)數(shù)法無(wú)法解決對(duì)象的循環(huán)引用問(wèn)題 Python,PHP采取了引用計(jì)數(shù)算法。
給對(duì)象增加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它時(shí),計(jì)數(shù)器就+1;當(dāng)引用失效時(shí),計(jì)數(shù)器就-1;任何時(shí)刻計(jì)數(shù)器為0的對(duì)象就是不能再被使用的,即可被回收。
Test test1 = new Test();
Test test2 = test1;
Test test3 = test1;
Test test4 = test1;
此算法存在兩個(gè)缺陷:
- 浪費(fèi)內(nèi)存空間
- 存在循環(huán)引用的情況
用一個(gè)例子來(lái)解釋一下循環(huán)引用的問(wèn)題:
class Test {
public Test test;
}
Test test1 = new Test();
Test test2 = new Test();
test1.test=test2;
test2.test=test1;
此時(shí)test1與test2 銷毀了,兩個(gè)對(duì)象的引用計(jì)數(shù)分別減一。
此時(shí)這兩個(gè)對(duì)象的引用計(jì)數(shù)不為0,不能作為垃圾且無(wú)法使用,陷入了一個(gè)邏輯上的循環(huán)。
可達(dá)性分析算法
通過(guò)一系列稱為"GC Roots"的對(duì)象作為起始點(diǎn),從這些節(jié)點(diǎn)開(kāi)始向下搜索,搜索走過(guò)的路徑稱之為"引用鏈",當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何的引用鏈相連時(shí)(從GC Roots到這個(gè)對(duì)象不可達(dá))時(shí),證明此對(duì)象是不可用的。
在java中,可作為GC Roots(垃圾回收根對(duì)象)的對(duì)象有以下幾種:
- 棧上的局部變量
- 常量池中引用的對(duì)象
- 方法區(qū)中類靜態(tài)屬性引用的對(duì)象
只有從GC Roots對(duì)象開(kāi)始,通過(guò)引用鏈可達(dá)的對(duì)象才被認(rèn)為是存活的,而無(wú)法通過(guò)引用鏈訪問(wèn)的對(duì)象則會(huì)被判定為垃圾,并進(jìn)行回收。
缺點(diǎn):
- 遍歷開(kāi)銷:可達(dá)性分析算法需要遍歷整個(gè)對(duì)象圖以確定每個(gè)對(duì)象的可達(dá)性。對(duì)于大型堆和復(fù)雜的引用關(guān)系,遍歷開(kāi)銷可能非常大,特別是在全局垃圾回收中。這可能會(huì)導(dǎo)致垃圾回收的性能下降。
- 延遲回收:可達(dá)性分析算法需要遍歷整個(gè)對(duì)象圖,從GC Roots開(kāi)始,逐個(gè)檢查每個(gè)對(duì)象的引用關(guān)系。這個(gè)過(guò)程可能需要消耗大量的時(shí)間,且在垃圾回收期間,應(yīng)用程序的執(zhí)行會(huì)被暫停(STW - Stop-The-World)。因此,可達(dá)性分析算法可能導(dǎo)致較高的延遲,影響程序的響應(yīng)性能。
回收垃圾
標(biāo)記清除算法
算法分為"標(biāo)記"和"清除"兩個(gè)階段 : 首先標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象。
回收前:
回收后:
不足:
- 標(biāo)記和清除這兩個(gè)過(guò)程的效率都不高。
- 標(biāo)記清除后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,空間碎片太多可能會(huì)導(dǎo)致以后在程序運(yùn)行中需要分配較大對(duì)象時(shí),無(wú)法找到足夠連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集。
復(fù)制算法
"復(fù)制"算法是為了解決"標(biāo)記-清理"的效率問(wèn)題。它將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。
簡(jiǎn)單來(lái)說(shuō)復(fù)制算法就是把不是垃圾的對(duì)象拷貝到未使用的那一邊,然后再統(tǒng)一釋放剛才使用過(guò)的那一塊區(qū)域。
缺點(diǎn):
- 內(nèi)存利用率比較低。
- 如果當(dāng)前區(qū)域的大部分對(duì)象都需要保留垃圾很少,那么此時(shí)的復(fù)制成本就比較高。
標(biāo)記整理算法
標(biāo)記整理算法的基本流程:
-
標(biāo)記:從根對(duì)象開(kāi)始,通過(guò)可達(dá)性分析算法,標(biāo)記所有從根對(duì)象可達(dá)的存活對(duì)象。標(biāo)記過(guò)程中,通常使用標(biāo)記位(標(biāo)記狀態(tài))來(lái)標(biāo)記對(duì)象是否為存活對(duì)象。
-
整理:將所有存活對(duì)象移到堆的一端,緊湊排列,以便釋放出連續(xù)的一段內(nèi)存空間。在移動(dòng)存活對(duì)象時(shí),需要更新對(duì)這些對(duì)象的引用,確保引用指向移動(dòng)后的新位置。
-
更新引用:在堆中,遍歷所有存活對(duì)象的引用,將其指向新的位置。這是為了避免懸掛指針(引用指向被移動(dòng)或已回收的對(duì)象)的問(wèn)題。
-
釋放未標(biāo)記的對(duì)象:在整理后的堆中,所有沒(méi)有被標(biāo)記的對(duì)象都可以被認(rèn)為是垃圾對(duì)象,可以直接被回收。
優(yōu)點(diǎn):解決了內(nèi)存碎片問(wèn)題。
缺點(diǎn):搬運(yùn)復(fù)制開(kāi)銷比較大。
分代算法
分代算法主要基于一種觀察:大部分對(duì)象的生命周期都比較短暫。根據(jù)這個(gè)觀察,分代算法將堆內(nèi)存劃分為不同的代(Generation),每一代中對(duì)象的生命周期不同,并且根據(jù)對(duì)象的生命周期將不同的垃圾回收策略應(yīng)用于不同的代中。
一般來(lái)說(shuō),分代堆內(nèi)存被劃分為年輕代(Young Generation)和老年代(Old Generation)兩個(gè)主要部分
年輕代:
年輕代是存放新創(chuàng)建的對(duì)象的地方,大部分對(duì)象在創(chuàng)建后很快就變?yōu)槔鴮?duì)象。年輕代通常進(jìn)一步分為Eden區(qū)和兩個(gè)Survivor區(qū)。新創(chuàng)建的對(duì)象首先放入Eden區(qū),當(dāng)Eden區(qū)滿時(shí),不會(huì)被回收的對(duì)象會(huì)被轉(zhuǎn)移到一個(gè)Survivor區(qū)。當(dāng)一個(gè)Survivor區(qū)滿時(shí),其中的存活對(duì)象會(huì)被復(fù)制到另一個(gè)Survivor區(qū)或者老年代。經(jīng)過(guò)多次垃圾回收后依然存活的對(duì)象將晉升到老年代。
年輕代通常采用復(fù)制算法(Copying)作為垃圾回收策略,因?yàn)樾聞?chuàng)建的對(duì)象的生命周期短暫,復(fù)制算法可以更好地利用對(duì)象的特點(diǎn)。
老年代:
老年代是存放存活時(shí)間較長(zhǎng)的對(duì)象的地方,老年代的對(duì)象生命周期較長(zhǎng),垃圾回收頻率相對(duì)較低。對(duì)于老年代的垃圾回收,可以采用標(biāo)記-清除(Mark-Sweep)或者標(biāo)記-整理(Mark-Compact)等算法。
分代算法通過(guò)區(qū)分不同代的對(duì)象,針對(duì)不同代采取不同的垃圾回收策略,可以提高垃圾回收效率和系統(tǒng)性能。年輕代的頻繁垃圾回收可以快速回收新創(chuàng)建對(duì)象,老年代的較少回收可以減少全局垃圾回收的引發(fā),提高應(yīng)用程序的響應(yīng)性。這種分代垃圾回收策略在大多數(shù)的垃圾收集器中都有應(yīng)用。
原文鏈接:https://blog.csdn.net/st200112266/article/details/131728218
- 上一篇:沒(méi)有了
- 下一篇:沒(méi)有了
相關(guān)推薦
- 2022-08-31 在.Net?Framework應(yīng)用中請(qǐng)求HTTP2站點(diǎn)的問(wèn)題解析_實(shí)用技巧
- 2022-11-23 iOS開(kāi)發(fā)學(xué)習(xí)?ViewController使用示例詳解_IOS
- 2023-12-23 npm install 下載成功,npm run serve 運(yùn)行失敗
- 2022-04-08 pytorch?plt.savefig()的用法及保存路徑_python
- 2022-07-23 SpringBoot分頁(yè)查詢
- 2022-07-31 pycharm終端解釋器與Python解釋器配置_python
- 2022-09-18 go?mock?server的簡(jiǎn)易實(shí)現(xiàn)示例_Golang
- 2022-05-24 Pytho的HTTP交互httpx包模塊使用詳解_python
- 欄目分類
-
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支