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

歡迎訪問 生活随笔!

生活随笔

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

java

深入理解Java虚拟机 第2版 周志明著(三)

發(fā)布時間:2023/12/8 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解Java虚拟机 第2版 周志明著(三) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

第3章 垃圾收集器與內(nèi)存分配策略


3.1 如何判定對象是“活著”或者“死去”?

  • 引用計數(shù)法:給對象中添加一個引用計數(shù)器,每當有一個地方引用它時,計數(shù)器就加1,當引用失效時,計數(shù)器值就減1,任何時刻計數(shù)器為0的對象就是不在被使用的對象。
    缺點:很難解決循環(huán)引用問題。

  • 可達性分析算法:通過一系列的稱為"GC Roots"的對象作為起始點,從這些節(jié)點開始向下搜索,搜索所走過的路徑稱為引用鏈,當一個對象到GC Roots沒有任何引用鏈相連時,這個對象就是不可用的。
    可作為GC Roots的對象有:
    1.虛擬機棧(棧幀中的本地變量表)中引用的對象。
    2.方法區(qū)中類靜態(tài)變量屬性引用的對象。
    3.方法區(qū)中常量引用的對象。

3.2 引用
Java中引用的定義:如果reference類型的數(shù)據(jù)中存儲的數(shù)值代表的是另外一塊內(nèi)存的起始地址,就稱這塊內(nèi)存代表著一個引用。
在定義之下對象只有被引用或者沒有被引用兩種狀態(tài),但是我們希望有一些中間態(tài)的對象,當空間足夠的時候保留在內(nèi)存中,如果內(nèi)存空間在進行垃圾收集后還是非常緊張的話可以拋棄這些對象。所以Java中才有了,強引用,軟引用,弱引用,虛引用。

3.3 垃圾收集算法

  • 標記 - 清除:
    首先標記出所有需要回收的對象,標記完成后統(tǒng)一回收所有被標記的對象。
    缺點:效率低,會產(chǎn)生大量不連續(xù)的內(nèi)存碎片,可能會導致需要分配較大對象時,無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)一次GC。
  • 復制算法:
    將可用內(nèi)存的容量劃分為大小相等的兩塊,每次只用其中一塊,當這一塊的內(nèi)存用完了,就將還活著的對象復制到另外一塊上,然后再把使用過的這塊清空。
    缺點:內(nèi)存縮減為原來的一半。
    大部分虛擬機都是用這種算法,但是內(nèi)存比例是按照8:1:1來分配的。即將內(nèi)存分為較大的Eden空間,和兩塊較小的From Survivor和To Survivor空間,每次使用Eden和From Survivor。當回收時,將Eden和From Survivor中還存活的對象一次性的復制到To Survivor中,最后清理掉Eden和From Survivor。當To Survivor內(nèi)存空間不夠用來收集存活的對象時,需要依賴老年代進行分配擔保。
  • 標記 - 整理(一般針對老年代):
    首先標記出所有需要回收的對象,然后讓所有存活的對象都向一端移動,然后直接清理掉邊界以外的內(nèi)存。
  • 分代收集算法(主流):
    把Java堆分為新生代和老年代,這樣就可以根據(jù)各個年代的特點采用最適當?shù)氖占惴ā?/li>

    3.4 垃圾收集器

  • Serial收集器
    單線程收集器,它在進行垃圾收集時必須暫停其他所有的工作線程,直到它收集結(jié)束。它是虛擬機運行在Client模式下的默認新生代收集器。
    算法:復制算法

  • ParNew收集器
    就是Serial收集器的多線程版本,目前只有它可以和CMS收集器配合工作。單CPU的環(huán)境中效果一定不會有Serial收集器效果好,雙CPU也不一定能保證。但是CPU越多效果越好。默認開啟的收集線程數(shù)與CPU數(shù)量相同。
    算法:復制算法

  • Parallel Scavenge收集器
    新生代的收集器,又是并行的多線程收集器,特點是它的關(guān)注點與其他的收集器不同,其他的收集器的關(guān)注點是盡可能的縮短垃圾收集時間用戶線程的停頓時間。而Parallel Scavenge收集器的目標則是達到一個可控制的吞吐量。吞吐量是CPU用戶運行代碼的時間與CPU總消耗時間的比值。公式:
    吞吐量 = 運行用戶代碼時間 / (運行用戶代碼時間 + 垃圾收集時間)
    Parallel Scavenge收集器與ParNew還有一個重要區(qū)別就是Parallel Scavenge收集器可以設(shè)置自適應(yīng)的調(diào)節(jié)策略。Parallel Scavenge收集器架構(gòu)中是有收集器來進行老年代收集的,但是這個收集器的實現(xiàn)和Serial Old非常接近

  • Serial Old收集器
    Serial Old是Serial收集器的老年代版本,同樣是單線程收集器,這個收集器的主要意義在于給Client模式下的虛擬機使用,一般作為CMS收集器的后備預(yù)案。
    算法:標記 - 整理

  • Parallel Old收集器
    Parallel Old是Parallel Scavenge收集器的老年代版本。在注重吞吐量以及CPU資源敏感的場合,都可以優(yōu)先考慮Parallel Scavenge收集器加Parallel Old收集器的組合。
    算法:標記 - 整理

  • CMS收集器
    老年代收集器,CMS收集器是一種以獲取最短回收停頓時間為目標的收集器。優(yōu)點,并發(fā)收集,低停頓。
    算法:標記 - 清除
    運作過程分為:初始標記,并發(fā)標記,重新標記,并發(fā)清除4個步驟。其中初始標記和重新標記這兩個步驟仍然需要Stop The World。
    初始標記:僅僅只是標記一下GC Roots能直接關(guān)聯(lián)到的對象,速度很快、
    并發(fā)標記:就是進行CG Roots Tracing(找引用鏈)的過程。
    重新標記:是為了修正并發(fā)標記期間因用戶程序繼續(xù)運作而導致標記產(chǎn)生變動的那一部分對象的標記記錄。這個階段的停頓時間一般會比初始標記的時間長,但是遠低于并發(fā)標記的時間。
    并發(fā)清除:回收垃圾。
    缺點:1.雖然不會導致用戶線程停頓,但會因為占用了一部分線程導致應(yīng)用程序變慢,總吞吐量降低。2.CMS無法處理浮動垃圾(并發(fā)清除中用戶線程還在運行,也就還會有新的垃圾出現(xiàn),這一部分垃圾沒有被標記過,無法在當次收集中處理掉,這一部分垃圾稱為浮動垃圾)。正是因為清除的時候用戶線程還在運行,所以需要預(yù)留一部分空間給用戶線程在這期間產(chǎn)生的垃圾使用,如果預(yù)留的空間不夠用,虛擬就就會臨時啟用Serial Old收集器來重新進行老年代的垃圾收集,停頓時間就很長了。3.由于算法實現(xiàn)的原因會產(chǎn)生大量的空間碎片。

  • G1收集器
    面向服務(wù)端的收集器,優(yōu)點:并行與并發(fā),分代收集,空間整合,可預(yù)測停頓。它將整個java堆劃分為多個大小相等的獨立的區(qū)域(Region),新生代和老年代不再是物理隔離,他們都是一部分Region(不需要連續(xù))的集合。
    運作過程分為:初始標記,并發(fā)標記,最終標記,篩選回收4個步驟。

    3.5 內(nèi)存分配
    1.對象優(yōu)先在Eden分配(當Eden沒有足夠空間時,虛擬機發(fā)起一次Minor GC)。
    2.大對象直接進入老年代。
    3.長期存活的對象進入老年代(默認年齡15)。
    4.如果在Survivor空間中相同年齡所有對象大小的總和大于Survivor空間的一半,年齡大于或者等于該年齡的對象可以直接進入老年代。
    5.空間分配擔保:在發(fā)生Minor GC之前,虛擬機會檢查老年代最大可用的連續(xù)空間是否大于新生代所有對象總空間,如果大于,那Minor GC安全。如果小于,接著查看HandlePromotionFailure的值是否允許失敗,如果設(shè)置允許失敗,會檢查老年代最大可用的連續(xù)空間是否大于歷次晉升到老年代對象的平均大小,如果大于,嘗試進行一次Minor GC。如果小于或者HandlePromotionFailure的值設(shè)置不允許,那這時需要進行一次Full GC。

  • 總結(jié)

    以上是生活随笔為你收集整理的深入理解Java虚拟机 第2版 周志明著(三)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。