亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java基礎之垃圾回收機制詳解

 更新時間:2021年04月28日 11:12:40   作者:洛白雙雙  
這篇文章主要介紹了Java基礎之垃圾回收機制詳解,文中有非常詳細的代碼示例,對正在學習java基礎的小伙伴們有非常好的幫助,需要的朋友可以參考下

一、GC的作用

進行內存管理

C語言中的內存,申請內存之后需要手動釋放;一旦忘記釋放,就會發(fā)生內存泄漏!

而Java語言中,申請內存后會由GC來釋放內存空間,無需手動釋放

GC雖然代替了手動釋放的操作,但是它也有局限性:

  •  需要消耗更多的資源;
  • 沒有手動釋放那么及時;
  • STW(Stop The World)會影響程序的執(zhí)行效率

二、GC主要回收哪些內存

(1)堆:主要回收堆中的內存

(2)方法區(qū):需要回收

(3)棧(包括本地方法棧和JVM虛擬機棧):不需要回收,棧上的內存什么時候釋放是明確的(線程結束,棧上的內存也就被釋放了;對應的某個棧幀銷毀[某個方法執(zhí)行完畢],也會導致對應的局部變量被釋放)

(4)程序計數器:不需要被回收

GC回收內存的基本單位:對象

GC回收對象的基本思路

(1)標記:判斷當前對象的生死,對象不再被使用為死,則需要回收,反之不需要被回收;

標記的方法:

  • 引用計數法

記錄當前這個對象是否有引用指向,有則引用計數加1,如果當前這個對象的引用指向了其他新的對象,則引用計數減1,當引用計數為0的時候,我們認為這個對象需要被回收!

缺點:無法解決循環(huán)引用問題

下面用一段偽代碼來演示一下循環(huán)引用問題:

class Test{
Test t = null;
}
Test a = new Test();
Test b = new Test();
a.t = b;
b.t = a;
a = null;
b = null;

我們發(fā)現(xiàn),在上述代碼中已經沒有辦法使用對象a和對象b了,但是它們的引用計數不為1.想使用對象a,就得找到對象a的引用,但是對象a的引用又在對象b當中。想使用對象b,就得找到對象b 的引用,但是對象b的引用又在對象a當中。

在這里插入圖片描述

  • 可達性分析:

代碼中的對象具有一定的關聯(lián)關系,這樣錯綜復雜的關系,構成了一個"有向圖"??蛇_性分析也就是遍歷這個對象關系的“有向圖”。如果某個對象可以被遍歷到,那么它就是可達的(非垃圾),那么就是不可達的(是垃圾)

那么可達性分析從哪里開始呢?

a)針對每個線程的每個棧幀的局部變量表(線程有很多,每個線程棧幀也有很多,每個棧幀也會有很多個變量);

b)常量池中引用的對象;

c)方法區(qū)中靜態(tài)變量引用的對象;

因為遍歷的起點不止一個,而是很多個起點,因此把這些起點也稱之為GCRoot

  • 回收方法區(qū)對象的規(guī)則:

a)該類的所有實例已經被回收;

b)加載類的ClassLoader也已經被回收了;

c)該類對象沒有在代碼中使用了

同時具備以上三個條件,就認為該類對象是可以被回收的

回收的方法:

  • 標記-清除【適合老年代】

在這里插入圖片描述

通過上面的圖,我們可以發(fā)現(xiàn),兩個空閑區(qū)被其他的對象分隔開了。一旦需要一個比較大的空間,就會申請失敗。

標記-清除法的優(yōu)缺點:

優(yōu)點:簡單高效

缺點:會出現(xiàn)內存碎片

  • 標記-復制【適合新生代】

在這里插入圖片描述

優(yōu)點:解決了內存碎片問題,保證回收之后不會存在碎片(回收后使用的對象之間是連續(xù)的,空余內存之間也是連續(xù)的)

缺點:需要一塊額外的空間,如果生存的對象較多就比較難低效

  • 標記-整理【適合老年代】

在這里插入圖片描述

優(yōu)點:沒有內存碎片問題,也不需要額外的空間

缺點:類似于順序表的刪除操作,效率不是很高

三、分代回收

按照對象的年齡,將堆內存分為:新生代(伊甸區(qū)和生存區(qū))、老年代

對象的年齡不是直接使用時間來記錄,而是使用對象活過GC輪次來記錄(GC是按照一定周期來運行)

在這里插入圖片描述

一個對象的一生:

(1)對象誕生于新生代的伊甸區(qū)。新產生的對象的內存就是新生代中的內存

(2)第一輪GC掃描伊甸區(qū)之后,就會把大量的對象回收掉。少數沒有被回收的對象,就會通過標記-復制算法進入到生存區(qū)

(3)少數進入生存區(qū)的對象,再次被GC掃描(對這些對象進行可達性分析)。如果發(fā)現(xiàn)該對象已經不可達,也就被銷毀了。沒有被銷毀的對象,再次通過標記-復制算法,把它拷貝到另一個生存區(qū)。

(4)對象在兩個生存區(qū)中經過若干次拷貝,如果還沒有被回收,那么就說明這些個對象存活時間比較久,就拷貝到老年代

(5)老年代的對象也是要經過GC掃描的。由于老年代的對象生存時間比較長。因此掃描周期要比新生代的周期要長

相關術語:

  • Partical GC:只進行一部分內存區(qū)域的GC
  • Full GC:針對整個內存區(qū)域進行GC
  • Minor GC:針對新生代內存的GC,執(zhí)行頻繁,速度較快
  • Major GC:針對老年代的GC,沒那么頻繁。速度較慢,通常由Minor GC 觸發(fā)

四、垃圾回收器

在這里插入圖片描述

垃圾回收器做的兩件事情:標記(可達性分析)+回收(標記清除,標記復制,標記整理)

  • Serial收集器(給新生代使用,串行回收)【存在STW】

在這里插入圖片描述

采用復制算法,單線程進行標記和回收

  • ParNew收集器(新生代收集器,多線程GC)

在這里插入圖片描述

采用復制算法,多線程進行標記和回收

  • Parallel scavenge收集器(新生代收集器,并行GC)

設計初衷是為了縮短STW時間,以犧牲吞吐量和新生代空間作為代價。

相當于承諾用戶,在一定時間內就會完成一次GC。

  • Serial Old收集器(老年代收集器,串行GC)

在這里插入圖片描述

  • Parallel old收集器(老年代收集器,并行GC)

在這里插入圖片描述

使用多線程完成標記整理,效率更高,消耗的CPU資源更多

  • CMS垃圾回收器(老年代收集器,并行GC,采用多線程標記清除算法)

a)初始標記【STW】
只是把和GCRoot相關的對象標記出來,涉及STW
b)并發(fā)標記
執(zhí)行整個標記遍歷的過程(從GCRoot開始,把能訪問的對象都遍歷)
不需要暫停用戶線程

消耗的時間相對比較久,但是可以和用戶線程并發(fā)

注意:當進行并發(fā)標記的時候,當用戶線程也在執(zhí)行,可能導致某個對象,剛剛標記的時候不是垃圾,代碼執(zhí)行后,就成了垃圾

c)重新標記(CMS remark)【STW】
修正誤差

d)并發(fā)清除
多線程的方式將剛剛的垃圾對象都清除釋放掉,可以和應用程序并發(fā)執(zhí)行

優(yōu)點:能夠讓STW時間盡量短
缺點:有內存碎片; GC操作和應用程序并發(fā)進行,消耗CPU資源多;

  • G1回收器(Java11開始默認使用)

既可以回收新生代,也可以回收老年代

在這里插入圖片描述

每個矩形稱為一個region
E表示伊甸區(qū)
S表示生存區(qū)
T表示老年代
H表示存放大對象的區(qū)域
以region為單位進行回收,回收粒度更精細
針對新生區(qū)的region同樣適用復制算法
針對老年代的回收類似于CMS
a)初始標記【STW】:只去找和GRoot直接相連的對象
b)并發(fā)標記:和應用程序并發(fā)執(zhí)行,進行可達性分析,遍歷所有對象。如果發(fā)現(xiàn)某個老年代region中已經沒有存活對象,就直接回收
c)最終標記:修正第二步產生的誤差
d)篩選回收:挑選出對象存活率低的region進行回收

五、總結

在這里插入圖片描述

到此這篇關于Java基礎之垃圾回收機制詳解的文章就介紹到這了,更多相關Java垃圾回收機制內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java實現(xiàn)解數獨的小程序

    Java實現(xiàn)解數獨的小程序

    最近在學習Java,然后上個月迷上了九宮格數獨,玩了幾天,覺得實在有趣,就想著能不能用編程來解決,于是就自己寫了個,還真解決了。下面這篇文章就給大家主要介紹了Java實現(xiàn)解數獨的小程序,需要的朋友可以參考借鑒。
    2017-01-01
  • Java Netty實現(xiàn)心跳機制過程解析

    Java Netty實現(xiàn)心跳機制過程解析

    這篇文章主要介紹了Java Netty實現(xiàn)心跳機制過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • Springboot整合quartz實現(xiàn)多個定時任務實例

    Springboot整合quartz實現(xiàn)多個定時任務實例

    這篇文章主要介紹了Springboot整合quartz實現(xiàn)多個定時任務代碼實例,Quartz?是一款功能強大的開源任務調度框架,幾乎可以集成到任何?Java?應用程序中,Quartz?可用于創(chuàng)建簡單或復雜的任務調度,用以執(zhí)行數以萬計的任務,需要的朋友可以參考下
    2023-08-08
  • 手把手教你實現(xiàn)Java第三方應用登錄

    手把手教你實現(xiàn)Java第三方應用登錄

    本文主要介紹了手把手教你實現(xiàn)Java第三方應用登錄,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Java中的OkHttp使用教程

    Java中的OkHttp使用教程

    OkHttp是目前非?;鸬木W絡庫,OKHttp與HttpClient類似,也是一個Http客戶端,提供了對?HTTP/2?和?SPDY?的支持,并提供了連接池,GZIP?壓縮和?HTTP?響應緩存功能,本文重點給大家介紹Java?OkHttp使用,感興趣的朋友一起看看吧
    2022-04-04
  • 詳解mybatis 批量更新數據兩種方法效率對比

    詳解mybatis 批量更新數據兩種方法效率對比

    這篇文章主要介紹了詳解mybatis 批量更新數據兩種方法效率對比,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-02-02
  • Java中零拷貝和深拷貝的原理及實現(xiàn)探究(代碼示例)

    Java中零拷貝和深拷貝的原理及實現(xiàn)探究(代碼示例)

    深拷貝和零拷貝是兩個在 Java 中廣泛使用的概念,它們分別用于對象復制和數據傳輸優(yōu)化,下面將詳細介紹這兩個概念的原理,并給出相應的 Java 代碼示例,感興趣的朋友一起看看吧
    2023-12-12
  • 詳解SpringBoot的三種緩存技術(Spring Cache、Layering Cache 框架、Alibaba JetCache 框架)

    詳解SpringBoot的三種緩存技術(Spring Cache、Layering Cache 框架、Alibaba J

    這篇文章主要介紹了SpringBoot的三種緩存技術,幫助大家更好的理解和學習springboot框架,感興趣的朋友可以了解下
    2020-10-10
  • 通過實例了解Java jdk和jre的區(qū)別

    通過實例了解Java jdk和jre的區(qū)別

    這篇文章主要介紹了通過實例了解Java jdk和jre的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-05-05
  • Java調用Pytorch實現(xiàn)以圖搜圖功能

    Java調用Pytorch實現(xiàn)以圖搜圖功能

    這篇文章主要為大家詳細介紹了Java如何調用Pytorch實現(xiàn)以圖搜圖功能,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的小伙伴可以了解一下
    2023-06-06

最新評論