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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

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

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

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


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

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

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

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

3.3 垃圾收集算法

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

    3.4 垃圾收集器

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

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

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

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

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

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

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

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

  • 總結(jié)

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

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