日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 详解(JVM) 垃圾回收机制原理

發布時間:2023/12/10 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 详解(JVM) 垃圾回收机制原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、什么是垃圾。

二、如何判斷垃圾。

三、垃圾回收。

一、什么是垃圾。

? ? ? ? 首先我們要搞懂什么是垃圾。

? ? ? ? 在 JVM 的眼中,垃圾就是指那些在堆中存在的,已經“死亡”的對象。而對于“死亡”的定義,我們可以簡單的將其理解為“不可能再被任何途徑使用的對象”。(通俗的的講就是在堆中創建的對象不會再次被使用)。

二、如何判斷垃圾。

? ? ? ? 垃圾判斷算法:引用判斷法,可達性分析法。

? ? ? ? 引用判斷法:

????????在這種算法中,假設堆中每個對象(不是引用)都有一個引用計數器。當一個對象被創建并且初始化賦值后,該對象的計數器的值就設置為 1,每當有一個地方引用它時,計數器的值就加 1,例如將對象 b 賦值給對象 a,那么 b 被引用,則將 b 引用對象的計數器累加 1。

反之,當引用失效時,例如一個對象的某個引用超過了生命周期(出作用域后)或者被設置為一個新值時,則之前被引用的對象的計數器的值就減 1。而那些引用計數為 0 的對象,就可以稱之為垃圾,可以被收集。

特別地,當一個對象被當做垃圾收集時,它引用的任何對象的計數器的值都減 1。

優點:引用計數法實現起來比較簡單,對程序不被長時間打斷的實時環境比較有利。
缺點:需要額外的空間來存儲計數器,難以檢測出對象之間的循環引用。

????????可達性分析法:

????????可達性分析法也被稱之為根搜索法,可達性是指,如果一個對象會被至少一個在程序中的變量通過直接或間接的方式被其他可達的對象引用,則稱該對象就是可達的。更準確的說,一個對象只有滿足下述兩個條件之一,就會被判斷為可達的:

????????對象是屬于根集中的對象
????????對象被一個可達的對象引用
在這里,我們引出了一個專有名詞,即根集,其是指正在執行的 Java 程序可以訪問的引用變量(注意,不是對象)的集合,程序可以使用引用變量訪問對象的屬性和調用對象的方法。在 JVM 中,會將以下對象標記為根集中的對象,具體包括:

????????虛擬機棧(棧幀中的本地變量表)中引用的對象
????????方法區中的常量引用的對象
????????方法區中的類靜態屬性引用的對象
????????本地方法棧中 JNI(Native 方法)的引用對象
????????活躍線程(已啟動且未停止的 Java 線程)
????????根集中的對象稱之為GC Roots,也就是根對象。可達性分析法的基本思路是:將一系列的根對象作為起始點,從這些節點開始向下搜索,搜索所走過的路徑稱為引用鏈,如果一個對象到根對象沒有任何引用鏈相連,那么這個對象就不是可達的,也稱之為不可達對象。

????????

????????如上圖所示,形象的展示了可達對象與不可達對象的示例,其中灰色的對象都是不可達對象,表示可以被垃圾收集的對象。在可達性分析法中,對象有兩種狀態,那么是可達的、要么是不可達的,在判斷一個對象的可達性的時候,就需要對對象進行標記。

優點:可以解決循環引用的問題,不需要占用額外的空間
缺點:多線程場景下,其他線程可能會更新已經訪問過的對象的引用

? ? ? ? 引用(Java中的四種引用類型):

????????強引用(Strong Reference):如Object obj = new Object(),這類引用是 Java 程序中最普遍的。只要強引用還存在,垃圾收集器就永遠不會回收掉被引用的對象。
????????軟引用(Soft Reference):它用來描述一些可能還有用,但并非必須的對象。在系統內存不夠用時,這類引用關聯的對象將被垃圾收集器回收。JDK1.2 之后提供了SoftReference類來實現軟引用。
????????弱引用(Weak Reference):它也是用來描述非必須對象的,但它的強度比軟引用更弱些,被弱引用關聯的對象只能生存到下一次垃圾收集發生之前。當垃圾收集器工作時,無論當前內存是否足夠,都會回收掉只被弱引用關聯的對象。在 JDK1.2 之后,提供了WeakReference類來實現弱引用。
????????虛引用(Phantom Reference):也稱為幻引用,最弱的一種引用關系,完全不會對其生存時間構成影響,也無法通過虛引用來取得一個對象實例。為一個對象設置虛引用關聯的唯一目的是希望能在這個對象被收集器回收時收到一個系統通知。JDK1.2 之后提供了PhantomReference類來實現虛引用。

三、垃圾回收。

? ? ? ?垃圾回收算法:標記-清除算法、標記-整理算法、復制算法、分代收集算法。

????????標記-清除算法:

????????標記-清除(Tracing Collector)算法是最基礎的收集算法,為了解決引用計數法的問題而提出。它使用了根集的概念,它分為“標記”和“清除”兩個階段:首先標記出所需回收的對象,在標記完成后統一回收掉所有被標記的對象,它的標記過程其實就是前面的可達性分析法中判定垃圾對象的標記過程。

優點:不需要進行對象的移動,并且僅對不存活的對象進行處理,在存活對象比較多的情況下極為高效。
缺點:標記和清除過程的效率都不高,這種方法需要使用一個空閑列表來記錄所有的空閑區域以及大小,對空閑列表的管理會增加分配對象時的工作量;標記清除后會產生大量不連續的內存碎片,雖然空閑區域的大小是足夠的,但卻可能沒有一個單一區域能夠滿足這次分配所需的大小,因此本次分配還是會失敗,不得不觸發另一次垃圾收集動作。

????????標記-整理算法:

????????標記-整理(Compacting Collector)算法標記的過程與“標記-清除”算法中的標記過程一樣,但對標記后出的垃圾對象的處理情況有所不同,它不是直接對可回收對象進行清理,而是讓所有的對象都向一端移動,然后直接清理掉端邊界以外的內存。在基于“標記-整理”算法的收集器的實現中,一般增加句柄和句柄表。

優點:經過整理之后,新對象的分配只需要通過指針碰撞便能完成,比較簡單;使用這種方法,空閑區域的位置是始終可知的,也不會再有碎片的問題了。
缺點:GC 暫停的時間會增長,因為你需要將所有的對象都拷貝到一個新的地方,還得更新它們的引用地址。

? ? ? ? 復制算法:

????????復制(Copying Collector)算法的提出是為了克服句柄的開銷和解決堆碎片的垃圾回收。它將內存按容量分為大小相等的兩塊,每次只使用其中的一塊(對象面),當這一塊的內存用完了,就將還存活著的對象復制到另外一塊內存上面(空閑面),然后再把已使用過的內存空間一次清理掉。

復制算法比較適合于新生代(短生存期的對象),在老年代(長生存期的對象)中,對象存活率比較高,如果執行較多的復制操作,效率將會變低,所以老年代一般會選用其他算法,如“標記-整理”算法。一種典型的基于復制算法的垃圾回收是stop-and-copy算法,它將堆分成對象區和空閑區,在對象區與空閑區的切換過程中,程序暫停執行。

優點:標記階段和復制階段可以同時進行;每次只對一塊內存進行回收,運行高效;只需移動棧頂指針,按順序分配內存即可,實現簡單;內存回收時不用考慮內存碎片的出現。
缺點:需要一塊能容納下所有存活對象的額外的內存空間。因此,可一次性分配的最大內存縮小了一半。

????????分代收集算法:

分代收集(Generational Collector)算法的將堆內存劃分為新生代、老年代和永久代。新生代又被進一步劃分為 Eden 和 Survivor 區,其中 Survivor 由 FromSpace(Survivor0)和 ToSpace(Survivor1)組成。所有通過new創建的對象的內存都在堆中分配,其大小可以通過-Xmx和-Xms來控制。分代收集,是基于這樣一個事實:不同的對象的生命周期是不一樣的。因此,可以將不同生命周期的對象分代,不同的代采取不同的回收算法進行垃圾回收,以便提高回收效率。

????????新生代:目的是回收那些生命周期短的對象,主要存放新產生的對象。新生代按照8:1:1分為eden區、survivor0、survivor1,大部分對象在eden區中生成,當eden滿時,將存活的對象復制到survivor0,然后清空eden,當eden、survivor0都滿了時,將這兩個區中存活的對象復制到survivor1,然后清空eden、survivor0,當著三個區都滿了時則把存貨對象復制到老年代,如果老年代也滿了則觸發FullGC。新生代的全回收叫MinorGC,MinorGC發生頻率比較高,不一定等到新生代滿了時才進行。

????????老年代:存放對象生命周期較長,且內存大概是新生代的兩倍,老年代存活對象生命周期長,因此MajorGC發生頻率較低。

????????永久代:主要存放靜態文件,如Java類,方法等。永久帶對垃圾回收基本沒有影響,當應用動態生成或者調用一些類的時候,例如反射、動態代理CGLib等bytecode框架時需要永久帶來保存新生成的類。

小結:

????????在新生代中,每次垃圾收集時都有大批對象死去,只有少量存活,那就選用復制算法。只需要付出少量存活對象的復制成本就可以完成收集。
老年代中因為對象存活率高、沒有額外空間對他進行分配擔保,就必須用標記-清除或者標記-整理。
????????由于永久代經常會內存不夠用或者發生內存泄露,JDK1.8開始廢棄了永久代,取而代之的是元空間(直接存在內存中可自定義大小),主要存放類的元數據。

? ? ? ??

總結

以上是生活随笔為你收集整理的Java 详解(JVM) 垃圾回收机制原理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。