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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JVM虚拟机学习

發(fā)布時(shí)間:2024/1/17 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM虚拟机学习 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一:Java技術(shù)體系模塊圖

?

?

二:JVM內(nèi)存區(qū)域模型

?

1.方法區(qū)

?

也稱”永久代” 、“非堆”, ?它用于存儲(chǔ)虛擬機(jī)加載的類信息、常量、靜態(tài)變量、是各個(gè)線程共享的內(nèi)存區(qū)域。默認(rèn)最小值為16MB,最大值為64MB,可以通過-XX:PermSize 和 -XX:MaxPermSize 參數(shù)限制方法區(qū)的大小。

?

運(yùn)行時(shí)常量池:是方法區(qū)的一部分,Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項(xiàng)信息是常量池,用于存放編譯器生成的各種符號(hào)引用,這部分內(nèi)容將在類加載后放到方法區(qū)的運(yùn)行時(shí)常量池中。

?

2.虛擬機(jī)棧

?

描述的是Java 方法執(zhí)行的內(nèi)存模型:每個(gè)方法被執(zhí)行的時(shí)候 都會(huì)創(chuàng)建一個(gè)“棧幀”用于存儲(chǔ)局部變量表(包括參數(shù))、操作棧、方法出口等信息。每個(gè)方法被調(diào)用到執(zhí)行完的過程,就對(duì)應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中從入棧到出棧的過程。聲明周期與線程相同,是線程私有的。

?

局部變量表存放了編譯器可知的各種基本數(shù)據(jù)類型(boolean、byte、char、short、int、float、long、double)、對(duì)象引用(引用指針,并非對(duì)象本身),其中64位長度的long和double類型的數(shù)據(jù)會(huì)占用2個(gè)局部變量的空間,其余數(shù)據(jù)類型只占1個(gè)。局部變量表所需的內(nèi)存空間在編譯期間完成分配,當(dāng)進(jìn)入一個(gè)方法時(shí),這個(gè)方法需要在棧幀中分配多大的局部變量是完全確定的,在運(yùn)行期間棧幀不會(huì)改變局部變量表的大小空間。

?

3.本地方法棧

?

與虛擬機(jī)?;绢愃?#xff0c;區(qū)別在于虛擬機(jī)棧為虛擬機(jī)執(zhí)行的java方法服務(wù),而本地方法棧則是為Native方法服務(wù)。

?

4.堆

?

也叫做java 堆、GC堆是java虛擬機(jī)所管理的內(nèi)存中最大的一塊內(nèi)存區(qū)域,也是被各個(gè)線程共享的內(nèi)存區(qū)域,在JVM啟動(dòng)時(shí)創(chuàng)建。該內(nèi)存區(qū)域存放了對(duì)象實(shí)例及數(shù)組(所有new的對(duì)象)。其大小通過-Xms(最小值)和-Xmx(最大值)參數(shù)設(shè)置,-Xms為JVM啟動(dòng)時(shí)申請(qǐng)的最小內(nèi)存,默認(rèn)為操作系統(tǒng)物理內(nèi)存的1/64但小于1G,-Xmx為JVM可申請(qǐng)的最大內(nèi)存,默認(rèn)為物理內(nèi)存的1/4但小于1G,默認(rèn)當(dāng)空余堆內(nèi)存小于40%時(shí),JVM會(huì)增大Heap到-Xmx指定的大小,可通過-XX:MinHeapFreeRation=來指定這個(gè)比列;當(dāng)空余堆內(nèi)存大于70%時(shí),JVM會(huì)減小heap的大小到-Xms指定的大小,可通過XX:MaxHeapFreeRation=來指定這個(gè)比列,對(duì)于運(yùn)行系統(tǒng),為避免在運(yùn)行時(shí)頻繁調(diào)整Heap的大小,通常-Xms與-Xmx的值設(shè)成一樣。

?

由于現(xiàn)在收集器都是采用分代收集算法,堆被劃分為新生代和老年代。新生代主要存儲(chǔ)新創(chuàng)建的對(duì)象和尚未進(jìn)入老年代的對(duì)象。老年代存儲(chǔ)經(jīng)過多次新生代GC(Minor GC)任然存活的對(duì)象。

?

新生代:

?

程序新創(chuàng)建的對(duì)象都是從新生代分配內(nèi)存,新生代由Eden Space和兩塊相同大小的Survivor Space(通常又稱S0和S1或From和To)構(gòu)成,可通過-Xmn參數(shù)來指定新生代的大小,也可以通過-XX:SurvivorRation來調(diào)整Eden Space及Survivor Space的大小。

?

老年代:

?

用于存放經(jīng)過多次新生代GC任然存活的對(duì)象,例如緩存對(duì)象,新建的對(duì)象也有可能直接進(jìn)入老年代,主要有兩種情況:①.大對(duì)象,可通過啟動(dòng)參數(shù)設(shè)置-XX:PretenureSizeThreshold=1024(單位為字節(jié),默認(rèn)為0)來代表超過多大時(shí)就不在新生代分配,而是直接在老年代分配。②.大的數(shù)組對(duì)象,切數(shù)組中無引用外部對(duì)象。

?

老年代所占的內(nèi)存大小為-Xmx對(duì)應(yīng)的值減去-Xmn對(duì)應(yīng)的值。

?

?

5.程序計(jì)數(shù)器

?

是最小的一塊內(nèi)存區(qū)域,它的作用是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器,在虛擬機(jī)的模型里,字節(jié)碼解釋器工作時(shí)就是通過改變這個(gè)計(jì)數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令,分支、循環(huán)、異常處理、線程恢復(fù)等基礎(chǔ)功能都需要依賴計(jì)數(shù)器完成。

?

三:直接內(nèi)存

?

直接內(nèi)存并不是虛擬機(jī)內(nèi)存的一部分,也不是Java虛擬機(jī)規(guī)范中定義的內(nèi)存區(qū)域。jdk1.4中新加入的NIO,引入了通道與緩沖區(qū)的IO方式,它可以調(diào)用Native方法直接分配堆外內(nèi)存,這個(gè)堆外內(nèi)存就是本機(jī)內(nèi)存,不會(huì)影響到堆內(nèi)存的大小。

?

?

跟蹤收集器

?

跟蹤收集器采用的為集中式的管理方式,全局記錄對(duì)象之間的引用狀態(tài),執(zhí)行時(shí)從一些列GC ?Roots的對(duì)象做為起點(diǎn),從這些節(jié)點(diǎn)向下開始進(jìn)行搜索所有的引用鏈,當(dāng)一個(gè)對(duì)象到GC ?Roots 沒有任何引用鏈時(shí),則證明此對(duì)象是不可用的。

?

下圖中,對(duì)象Object6、Object7、Object8雖然互相引用,但他們的GC Roots是不可到達(dá)的,所以它們將會(huì)被判定為是可回收的對(duì)象。

?

?

可作為GC Roots 的對(duì)象包括:

?

  • 虛擬機(jī)棧(棧幀中的本地變量表)中的引用對(duì)象。

  • 方法區(qū)中的類靜態(tài)屬性引用的對(duì)象

  • 方法區(qū)中的常量引用的對(duì)象

  • 本地方法棧中JNI的引用對(duì)象。

?

主要有復(fù)制、標(biāo)記清除、標(biāo)記壓縮三種實(shí)現(xiàn)算法。

?

1. 標(biāo)記 – 清除算法?

?

標(biāo)記清除算法是最基礎(chǔ)的收集算法,其他收集算法都是基于這種思想。標(biāo)記清除算法分為“標(biāo)記”和“清除”兩個(gè)階段:首先標(biāo)記出需要回收的對(duì)象,標(biāo)記完成之后統(tǒng)一清除對(duì)象。

?

它的主要缺點(diǎn):

?

①.標(biāo)記和清除過程效率不高

?

②.標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片。

?

?

2. 復(fù)制算法

?

它將可用內(nèi)存容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)這一塊用完之后,就將還存活的對(duì)象復(fù)制到另外一塊上面,然后在把已使用過的內(nèi)存空間一次清理掉。這樣使得每次都是對(duì)其中的一塊進(jìn)行內(nèi)存回收,不會(huì)產(chǎn)生碎片等情況,只要移動(dòng)堆訂的指針,按順序分配內(nèi)存即可,實(shí)現(xiàn)簡單,運(yùn)行高效。

?

主要缺點(diǎn):

?

內(nèi)存縮小為原來的一半。

?

?

3. 標(biāo)記 ?- 整理算法

?

標(biāo)記操作和“標(biāo)記-清除”算法一致,后續(xù)操作不只是直接清理對(duì)象,而是在清理無用對(duì)象完成后讓所有存活的對(duì)象都向一端移動(dòng),并更新引用其對(duì)象的指針。

?

主要缺點(diǎn):

?

在標(biāo)記-清除的基礎(chǔ)上還需進(jìn)行對(duì)象的移動(dòng),成本相對(duì)較高,好處則是不會(huì)產(chǎn)生內(nèi)存碎片。

?

?

引用計(jì)數(shù)收集器

?

引用計(jì)數(shù)收集器采用的是分散式管理方式,通過計(jì)數(shù)器記錄對(duì)象是否被引用。當(dāng)計(jì)數(shù)器為0時(shí)說明此對(duì)象不在被使用,可以被回收。

?

主要缺點(diǎn):

?

循環(huán)引用的場景下無法實(shí)現(xiàn)回收,例如下面的圖中,ObjectC和ObjectB相互引用,那么ObjectA即便釋放了對(duì)ObjectC、ObjectB的引用,也無法回收。sunJDK在實(shí)現(xiàn)GC時(shí)未采用這種方式。

?

?

垃圾收集器

HotSpot JVM收集器

? ? ? ? ? ? ? 上面有7中收集器,分為兩塊,上面為新生代收集器,下面是老年代收集器。如果兩個(gè)收集器之間存在連線,就說明它們可以搭配使用。

Serial(串行GC)收集器

Serial收集器是一個(gè)新生代收集器,單線程執(zhí)行,使用復(fù)制算法。它在進(jìn)行垃圾收集時(shí),必須暫停其他所有的工作線程(用戶線程)。是Jvm client模式下默認(rèn)的新生代收集器。對(duì)于限定單個(gè)CPU的環(huán)境來說,Serial收集器由于沒有線程交互的開銷,專心做垃圾收集自然可以獲得最高的單線程收集效率。

ParNew(并行GC)收集器

ParNew收集器其實(shí)就是serial收集器的多線程版本,除了使用多條線程進(jìn)行垃圾收集之外,其余行為與Serial收集器一樣。

Parallel Scavenge(并行回收GC)收集器

Parallel Scavenge收集器也是一個(gè)新生代收集器,它也是使用復(fù)制算法的收集器,又是并行多線程收集器。parallel Scavenge收集器的特點(diǎn)是它的關(guān)注點(diǎn)與其他收集器不同,CMS等收集器的關(guān)注點(diǎn)是盡可能地縮短垃圾收集時(shí)用戶線程的停頓時(shí)間,而parallel Scavenge收集器的目標(biāo)則是達(dá)到一個(gè)可控制的吞吐量。吞吐量= 程序運(yùn)行時(shí)間/(程序運(yùn)行時(shí)間 + 垃圾收集時(shí)間),虛擬機(jī)總共運(yùn)行了100分鐘。其中垃圾收集花掉1分鐘,那吞吐量就是99%。

Serial Old(串行GC)收集器

Serial Old是Serial收集器的老年代版本,它同樣使用一個(gè)單線程執(zhí)行收集,使用“標(biāo)記-整理”算法。主要使用在Client模式下的虛擬機(jī)。

Parallel Old(并行GC)收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多線程和“標(biāo)記-整理”算法。

CMS(并發(fā)GC)收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器。CMS收集器是基于“標(biāo)記-清除”算法實(shí)現(xiàn)的,整個(gè)收集過程大致分為4個(gè)步驟: ①.初始標(biāo)記(CMS initial mark) ②.并發(fā)標(biāo)記(CMS concurrenr mark) ③.重新標(biāo)記(CMS remark) ④.并發(fā)清除(CMS concurrent sweep) 其中初始標(biāo)記、重新標(biāo)記這兩個(gè)步驟任然需要停頓其他用戶線程。初始標(biāo)記僅僅只是標(biāo)記出GC ROOTS能直接關(guān)聯(lián)到的對(duì)象,速度很快,并發(fā)標(biāo)記階段是進(jìn)行GC ROOTS 根搜索算法階段,會(huì)判定對(duì)象是否存活。而重新標(biāo)記階段則是為了修正并發(fā)標(biāo)記期間,因用戶程序繼續(xù)運(yùn)行而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄,這個(gè)階段的停頓時(shí)間會(huì)被初始標(biāo)記階段稍長,但比并發(fā)標(biāo)記階段要短。 由于整個(gè)過程中耗時(shí)最長的并發(fā)標(biāo)記和并發(fā)清除過程中,收集器線程都可以與用戶線程一起工作,所以整體來說,CMS收集器的內(nèi)存回收過程是與用戶線程一起并發(fā)執(zhí)行的。 CMS收集器的優(yōu)點(diǎn):并發(fā)收集、低停頓,但是CMS還遠(yuǎn)遠(yuǎn)達(dá)不到完美,器主要有三個(gè)顯著缺點(diǎn): CMS收集器對(duì)CPU資源非常敏感。在并發(fā)階段,雖然不會(huì)導(dǎo)致用戶線程停頓,但是會(huì)占用CPU資源而導(dǎo)致引用程序變慢,總吞吐量下降。CMS默認(rèn)啟動(dòng)的回收線程數(shù)是:(CPU數(shù)量+3) / 4。 CMS收集器無法處理浮動(dòng)垃圾,可能出現(xiàn)“Concurrent Mode Failure“,失敗后而導(dǎo)致另一次Full ?GC的產(chǎn)生。由于CMS并發(fā)清理階段用戶線程還在運(yùn)行,伴隨程序的運(yùn)行自熱會(huì)有新的垃圾不斷產(chǎn)生,這一部分垃圾出現(xiàn)在標(biāo)記過程之后,CMS無法在本次收集中處理它們,只好留待下一次GC時(shí)將其清理掉。這一部分垃圾稱為“浮動(dòng)垃圾”。也是由于在垃圾收集階段用戶線程還需要運(yùn)行, 即需要預(yù)留足夠的內(nèi)存空間給用戶線程使用,因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全被填滿了再進(jìn)行收集,需要預(yù)留一部分內(nèi)存空間提供并發(fā)收集時(shí)的程序運(yùn)作使用。在默認(rèn)設(shè)置下,CMS收集器在老年代使用了68%的空間時(shí)就會(huì)被激活,也可以通過參數(shù)-XX:CMSInitiatingOccupancyFraction的值來提供觸發(fā)百分比,以降低內(nèi)存回收次數(shù)提高性能。要是CMS運(yùn)行期間預(yù)留的內(nèi)存無法滿足程序其他線程需要,就會(huì)出現(xiàn)“Concurrent Mode Failure”失敗,這時(shí)候虛擬機(jī)將啟動(dòng)后備預(yù)案:臨時(shí)啟用Serial Old收集器來重新進(jìn)行老年代的垃圾收集,這樣停頓時(shí)間就很長了。所以說參數(shù)-XX:CMSInitiatingOccupancyFraction設(shè)置的過高將會(huì)很容易導(dǎo)致“Concurrent Mode Failure”失敗,性能反而降低。 最后一個(gè)缺點(diǎn),CMS是基于“標(biāo)記-清除”算法實(shí)現(xiàn)的收集器,使用“標(biāo)記-清除”算法收集后,會(huì)產(chǎn)生大量碎片??臻g碎片太多時(shí),將會(huì)給對(duì)象分配帶來很多麻煩,比如說大對(duì)象,內(nèi)存空間找不到連續(xù)的空間來分配不得不提前觸發(fā)一次Full ?GC。為了解決這個(gè)問題,CMS收集器提供了一個(gè)-XX:UseCMSCompactAtFullCollection開關(guān)參數(shù),用于在Full ?GC之后增加一個(gè)碎片整理過程,還可通過-XX:CMSFullGCBeforeCompaction參數(shù)設(shè)置執(zhí)行多少次不壓縮的Full ?GC之后,跟著來一次碎片整理過程。

G1收集器

G1(Garbage First)收集器是JDK1.7提供的一個(gè)新收集器,G1收集器基于“標(biāo)記-整理”算法實(shí)現(xiàn),也就是說不會(huì)產(chǎn)生內(nèi)存碎片。還有一個(gè)特點(diǎn)之前的收集器進(jìn)行收集的范圍都是整個(gè)新生代或老年代,而G1將整個(gè)Java堆(包括新生代,老年代)。

垃圾收集器參數(shù)總結(jié)

-XX:+<option> 啟用選項(xiàng) -XX:-<option> 不啟用選項(xiàng) -XX:<option>=<number>? -XX:<option>=<string>

?

參數(shù)描述

-XX:+UseSerialGC

Jvm運(yùn)行在Client模式下的默認(rèn)值,打開此開關(guān)后,使用Serial + Serial Old的收集器組合進(jìn)行內(nèi)存回收
-XX:+UseParNewGC打開此開關(guān)后,使用ParNew + Serial Old的收集器進(jìn)行垃圾回收
-XX:+UseConcMarkSweepGC使用ParNew + CMS + ?Serial Old的收集器組合進(jìn)行內(nèi)存回收,Serial Old作為CMS出現(xiàn)“Concurrent Mode Failure”失敗后的后備收集器使用。
-XX:+UseParallelGCJvm運(yùn)行在Server模式下的默認(rèn)值,打開此開關(guān)后,使用Parallel Scavenge +??Serial Old的收集器組合進(jìn)行回收
-XX:+UseParallelOldGC使用Parallel Scavenge +??Parallel?Old的收集器組合進(jìn)行回收
-XX:SurvivorRatio新生代中Eden區(qū)域與Survivor區(qū)域的容量比值,默認(rèn)為8,代表Eden:Subrvivor = 8:1
-XX:PretenureSizeThreshold直接晉升到老年代對(duì)象的大小,設(shè)置這個(gè)參數(shù)后,大于這個(gè)參數(shù)的對(duì)象將直接在老年代分配
-XX:MaxTenuringThreshold晉升到老年代的對(duì)象年齡,每次Minor GC之后,年齡就加1,當(dāng)超過這個(gè)參數(shù)的值時(shí)進(jìn)入老年代
-XX:UseAdaptiveSizePolicy動(dòng)態(tài)調(diào)整java堆中各個(gè)區(qū)域的大小以及進(jìn)入老年代的年齡
-XX:+HandlePromotionFailure是否允許新生代收集擔(dān)保,進(jìn)行一次minor gc后, 另一塊Survivor空間不足時(shí),將直接會(huì)在老年代中保留
-XX:ParallelGCThreads設(shè)置并行GC進(jìn)行內(nèi)存回收的線程數(shù)
-XX:GCTimeRatioGC時(shí)間占總時(shí)間的比列,默認(rèn)值為99,即允許1%的GC時(shí)間,僅在使用Parallel Scavenge 收集器時(shí)有效
-XX:MaxGCPauseMillis設(shè)置GC的最大停頓時(shí)間,在Parallel Scavenge 收集器下有效
-XX:CMSInitiatingOccupancyFraction設(shè)置CMS收集器在老年代空間被使用多少后出發(fā)垃圾收集,默認(rèn)值為68%,僅在CMS收集器時(shí)有效,-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSCompactAtFullCollection由于CMS收集器會(huì)產(chǎn)生碎片,此參數(shù)設(shè)置在垃圾收集器后是否需要一次內(nèi)存碎片整理過程,僅在CMS收集器時(shí)有效
-XX:+CMSFullGCBeforeCompaction設(shè)置CMS收集器在進(jìn)行若干次垃圾收集后再進(jìn)行一次內(nèi)存碎片整理過程,通常與UseCMSCompactAtFullCollection參數(shù)一起使用
-XX:+UseFastAccessorMethods原始類型優(yōu)化
-XX:+DisableExplicitGC是否關(guān)閉手動(dòng)System.gc
-XX:+CMSParallelRemarkEnabled降低標(biāo)記停頓
-XX:LargePageSizeInBytes內(nèi)存頁的大小不可設(shè)置過大,會(huì)影響Perm的大小,-XX:LargePageSizeInBytes=128m

?

?

Client、Server模式默認(rèn)GC

?

?新生代GC方式老年代和持久GC方式

Client

Serial 串行GCSerial Old?串行GC
ServerParallel Scavenge ?并行回收GCParallel Old 并行GC

?

Sun/Oracle?JDK GC組合方式

?

?新生代GC方式老年代和持久GC方式

-XX:+UseSerialGC

Serial 串行GCSerial Old?串行GC
-XX:+UseParallelGCParallel Scavenge ?并行回收GCSerial Old??并行GC
-XX:+UseConcMarkSweepGCParNew?并行GCCMS 并發(fā)GC? 當(dāng)出現(xiàn)“Concurrent Mode Failure”時(shí) 采用Serial Old?串行GC
-XX:+UseParNewGCParNew?并行GCSerial Old?串行GC
-XX:+UseParallelOldGCParallel Scavenge ?并行回收GCParallel Old 并行GC
-XX:+UseConcMarkSweepGC -XX:+UseParNewGCSerial 串行GCCMS 并發(fā)GC? 當(dāng)出現(xiàn)“Concurrent Mode Failure”時(shí) 采用Serial Old?串行GC

轉(zhuǎn)載于:https://www.cnblogs.com/xxh520/p/6422213.html

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的JVM虚拟机学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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