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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java学习笔记-4 JVM垃圾回收(GC)

發布時間:2025/3/18 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java学习笔记-4 JVM垃圾回收(GC) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引言

jvm垃圾回收相關的問題是老生常談的問題了,相信大家都有所了解,這里再進行相關的探討,以加深理解。若文中有不正之言,望不吝指正。

本文將圍繞以下幾個點展開

1.為什么要進行垃圾回收

我們知道jvm的內存結構中,依賴內存是否可共享,將內存劃分為線程專享區和線程共享區,其中程序計數器、虛擬機棧、本地方法棧作為線程獨享的內存,生命周期跟線程相關,比如棧中的棧幀需要分配多少內存一般在類結構確定時就已經確定好了,線程結束時內存就跟著回收了,不需要我們過多的關心垃圾回收。但是作為線程共享的內存區域,堆和方法區,java new出來的對象大部分是在堆中分配的,而且只有在程序運行期間才能知道會創建出哪些對象,在這部分內存的分配和回收是我們關心的。其實歸根結底就是一句話,知道底層的jvm怎么進行垃圾回收的,對我們排查內存溢出和泄露的問題有很大幫助,而且對于提高程序的性能也有很大幫助。 復制代碼

2.哪些內存需要回收

判斷哪些內存需要回收有兩種經典的算法1.引用計數器法引用計數器法的實現是給對象添加一個引用計數器,當對象被引用時,計數器值就+1,對象引用失效時計數器值-1,當引用計數器值為0時,可認為對象無引用,此時可被回收。但是這個算法不能解決對象循環引用的問題,所以虛擬機并不是采用這種方式去判斷是否回收對象的。2.可達性分析算法可達性分析算法是將可作為GC Roots的對象作為起始點,展開搜索,搜索所經過的路徑,對一個對象到GC Roots 沒有任何引用,則意味著對象不可達,此時對象可被回收。 復制代碼

其中的GCRoots,其實就是一組必須活躍的引用,大致包括以下幾種

  • 虛擬機棧中引用的對象
  • 方法區中靜態屬性引用的變量
  • 方法區中常量引用的對象
  • 本地方法棧中引用的對象
  • 方法區垃圾回收:其實方法區中也是可以進行垃圾回收的,只是回收的性價比很低,就是說執行一次垃圾回收的動作并不能回收到很多的空間。但是滿足一定條件還是可以進行回收的,一般回收的是無用的類和廢棄常量。其中判斷常量是否廢棄,沒有引用即可;而判斷類無用需滿足 1.java堆中沒有任何該類的實例;2.加載該類的類加載器已被回收;3.該類的java.lang.Class對象沒有在任何地方被引用 ,不能通過反射獲取該類的方法。

    3.何時進行垃圾回收

    即觸發GC的時間,在新生代的Eden區滿了,會觸發新生代GC(MinorGC),經過多次觸發新生代GC存活下來的對象就會升級到老年代,升級到老年代的對象所需的內存大于老年代剩余的內存,則會觸發老年代GC(FullGC)。當程序調用System.gc()時也會觸發Full GC。 復制代碼

    4. 垃圾收集算法

    1. 標記清除算法見名知意,該算法分為兩個階段,標記和清除。如下圖所示,標記就是根據之前的GCRoots判斷對象是否還有引用可達。但是這個算法的缺點也很明顯,第一就是標記和清除效率都很低;第二就是這種算法會造成大量不連續的內存碎片的存在,當程序需要分配大的內存空間給對象的時候,很可能因為無法找到連續的大的內存空間,再一次觸發GC。圖如下: 復制代碼

    圖中對象b沒有引用,會被回收 圖中可以看出,回收后有大量不連續的內存空間。

    2.復制算法基于上一個算法,為了解決效率問題,引申出“復制”算法。基本思想就是將內存劃分為大小相等的兩塊,每次只使用其中的一塊,當一塊用完將整個活著的對象全部復制到另一個半區,此時不需要考慮內存碎片的問題,只需移動指針即可,簡單高效。但是需要浪費一半的內存。由于java堆內存對象存活的特點,大部分新生代中的對象存活時間都比較短,所以主流的虛擬機會將內存分為一塊較大的Eden區和兩塊較小的Survivor區,比例是8:1:1。每次分配對象到Eden區和一個Suivivor區,垃圾回收時將整個Eden區和剛才用到的Survivor區存活的對象一次性“復制”到未被使用的那個Survivor區,最后清理掉Eden區和之前的分配的Survivor區。但是并不能保證在將Eden去和Survivor區復制到另一個Survivor區的時候內存空間一定是充足的,此時需要依賴其它內存進行分配擔保。分配擔保策略指明,當Eden區和之前的Survivor區之存活的對象復制到另一塊Survivor區時,內存空間若不夠,則直接將內存分配到老年代。 復制代碼

    復制的時候只需移動相應的指針即可

    3.標記整理算法從上面的“復制”算法可以得知,當對象的存活率很高時,進行復制操作的時候效率將會變低。這時有人提出標記整理算法,標記過程較之前相同,只是后面不直接對對象進行清除,而是將存活的對象都向一邊移動,并更改對應的指針,然后清理掉右端以外的內存。但是這個算法效率也不高因為,因為包括了標記 + 移動,但是也解決了內存碎片的問題。 復制代碼

    4.分代收集算法

    其實就是上面算法的綜合。根據對象的存活周期,一般把java堆分為新生代和老生代。新生代中對象存活率較低,選用復制算法,只需付出少量存活對象的復制成本即可完成收集;老年代中對象存活率高,沒有額外的內控空間進行擔保,必須使用標記清除或者標記整理算法來進行垃圾回收。 復制代碼

    5.幾種垃圾收集器比較

    在進行比較之前先介紹下衡量的參數

  • 吞吐量: 所謂吞吐量就是 CPU 用于運行代碼的時間與 CPU 總消耗時間的比值,即吞吐量 = 運行用戶代碼時間 / (運行用戶代碼時間 + 垃圾收集時間)

  • 停頓時間 :jvm在運行垃圾回收時,需停頓用戶程序,這里指的是停頓用戶程序的時常

  • Serial收集器

    單線程的收集器,采用 復制算法,進行垃圾回收時需要將用戶的所有線程全部暫停直到垃圾回收動作的完成。交互體驗不是很好,但是在單核cpu或者虛擬機運行在client模式下,停頓時間可以控制到毫秒級,是可以接受。 復制代碼

    Serial Old收集器

    Serial Old是Serial的老年代版本,使用 標記整理算法 復制代碼

    ParNew收集器

    ParNew收集器采用復制算法,其實就是Serial收集器的多線程版本,是server模式下首選的新生代收集器。在多核cpu下有著比Serial更好的表現。 復制代碼

    Parallel Scavenge收集器

    采用復制算法,也是一個新生代的收集器。較于ParNew收集器,Parallel Scavenge收集器更多的目標是達到一個可控制的吞吐量。Parallel Scavenge收集器提供了兩個參數用于精確控制吞吐量,分別是控制最大垃圾收集 停頓時間的-XX:MaxGCPauseMillis參數以及直接設置吞吐量大小的-XX:GCTimeRatio參 數 復制代碼

    Parallel Old收集器

    Parallel Old收集器采用 標記整理算法 是ParallelScavenge收集器的老年代版本。在注重吞吐量以及cpu資源敏感的場合,都可以優先考慮Parallel Scavenge加Parallel Old收集器。 復制代碼

    CMS(Concurrent Mark Sweep)收集器

    采用標記清除算法,是一個老年代的并行收集器,是一個以獲取最短回收停頓時間為目標的處理器,具有高并發、低停頓的特點。包括四個過程:初始標記、并發標記、重新標記、并發清除。其中初始標記和重新標記都需要暫停用戶所有線程。 復制代碼

    但是這個收集器也有明顯的缺點, 1. 前面介紹過的標記清除算法講到會產生大量的內存碎片,很可能老年代空間有富余,但是新生代沒有足夠大的內存空間分配對象。CMS收集器提供了一個-XX:+UseCMSCompactAtFullCollection開 關參數(默認就是開啟的),用于在CMS收集器頂不住要進行FullGC時開啟內存碎片的合并 整理過程,內存整理的過程是無法并發的,空間碎片問題沒有了,但停頓時間不得不變長; 2.CMS收集器無法處理浮動垃圾(由于cms并發清理階段用戶線程還在運行,這段時間內出現的新的垃圾稱之為浮動垃圾) 3.cms對cpu的資源很敏感,雖然收集器是并發的,但是因為占用了一部分線程會導致應用程序變慢,總吞吐量降低。

    G1收集器

    G1收集器基于 標記整理算法 是面向服務端的,是面向新生代和老生代的收集器。收集過程主要包括:1.初始標記:標記GCRoots能關聯的對象; 2.并發標記:從GC Roots開始對對象進行可達性分析,找出存活的對象,耗時較久,可與用戶線程同時進行 3.最終標記:修正在并發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分標記記錄 4.篩選回收:首先對各個region的回收價值和成本進行排序,根據用戶所期望的停頓時間來制定回收計劃,優先處理最需要回收的。 復制代碼

    收集器參數總結

    引用

    《深入理解java虛擬機》 周志明

    轉載于:https://juejin.im/post/5b2efb4451882574cf66a837

    總結

    以上是生活随笔為你收集整理的java学习笔记-4 JVM垃圾回收(GC)的全部內容,希望文章能夠幫你解決所遇到的問題。

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