午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

hotspot的垃圾回收策略,設(shè)置和調(diào)優(yōu)

 KongKong世界 2018-12-03

我們都知道JVM內(nèi)存由幾個(gè)部分組成 Java棧、程序計(jì)數(shù)器(ProgramCounter)寄存器、本地方法棧、堆、方法區(qū)、運(yùn)行常量池。

JVM垃圾回收僅僅針對(duì)公共內(nèi)存區(qū)域即:堆和方法區(qū)進(jìn)行。

本文主要討論兩點(diǎn),一是垃圾回收策略,二是調(diào)優(yōu)的方法。

一、垃圾回收機(jī)制

1.1 分代管理

將堆和方法區(qū)按照對(duì)象出現(xiàn)的不同時(shí)間進(jìn)行分代:

u  堆中會(huì)頻繁地創(chuàng)建對(duì)象,基于一種分代的思想,按照對(duì)象存活時(shí)間將堆劃分為新生代和舊生代兩部分,我們不能一次垃圾回收新生代存活的對(duì)象就放入舊生代,而是要經(jīng)過幾次GC后還存活的對(duì)象,我們才放入舊生代,所以我們又把新生代再次劃分為Eden區(qū)和兩個(gè)Survivor區(qū),讓對(duì)象創(chuàng)建在Eden區(qū),然后在兩個(gè)Survivor之間反復(fù)復(fù)制,最后仍然存活的對(duì)象才復(fù)制到舊生代中。

u  方法區(qū)存放的是常量、加載的字節(jié)碼文件信息等,信息相對(duì)穩(wěn)定。因?yàn)椴粫?huì)頻繁地創(chuàng)建對(duì)象,所以不需要分代,直接GC即可。

由此我們JVM垃圾回收要掃描的范圍是:

注:圖片來自網(wǎng)絡(luò)

新生代:

1.所有新對(duì)象創(chuàng)建發(fā)生在Eden區(qū),Eden區(qū)滿后觸發(fā)新生代上的minor GC,將Eden區(qū)和非空閑Survivor區(qū)存活對(duì)象復(fù)制到另一個(gè)空閑的Survivor區(qū)中。

2.永遠(yuǎn)保證一個(gè)Survivor是空的,新生代minor GC就是在兩個(gè)Survivor區(qū)之間相互復(fù)制存活對(duì)象,直到Survivor區(qū)滿為止。

舊生代:

1.Eden區(qū)滿后觸發(fā)minor GC將存活對(duì)象復(fù)制到Survivor區(qū),Survivor區(qū)滿后觸發(fā)minor GC將存活對(duì)象復(fù)制到舊生代。

2.經(jīng)過新生代的兩個(gè)Survivor之間多次復(fù)制,仍然存活下來的對(duì)象就是年齡相對(duì)比較老的,就可以放入到舊生代了,隨著時(shí)間推移,如果舊生代也滿了,將觸發(fā)Full GC,針對(duì)整個(gè)堆(有新生代、舊生代和持久代)進(jìn)行垃圾回收。

持久代:

持久代如果滿,將觸發(fā)Full GC

1.2 垃圾回收

要執(zhí)行g(shù)c關(guān)鍵在于兩點(diǎn),一是檢測(cè)出垃圾對(duì)象,二是釋放垃圾對(duì)象所占用的空間。

1.2.1 檢測(cè)垃圾對(duì)象

檢測(cè)出垃圾對(duì)象一般有兩種算法:

1、 引用計(jì)數(shù)法

2、 可達(dá)性分析

引用計(jì)數(shù)法因?yàn)闊o法檢測(cè)對(duì)象之間相互循環(huán)引用的問題,基本沒有被采用?,F(xiàn)在主流的語(yǔ)言的垃圾收集中檢測(cè)垃圾對(duì)象主要還是“可達(dá)性分析”方法,下面也主要介紹JVM可達(dá)性分析方法檢測(cè)垃圾對(duì)象。

“可達(dá)性分析”算法描述?

通過一系列的名為“GC Root”的對(duì)象作為起點(diǎn),從這些節(jié)點(diǎn)向下搜索,搜索所走過的路徑稱為引用鏈(Reference Chain),當(dāng)一個(gè)對(duì)象到GC Root沒有任何引用鏈相連時(shí),則該對(duì)象不可達(dá),該對(duì)象是不可使用的,垃圾收集器將回收其所占的內(nèi)存。所以JVM判斷對(duì)象需要存活的原則是:能夠被一個(gè)根對(duì)象到達(dá)的對(duì)象。

什么是能夠到達(dá)呢?

就是對(duì)象A中引用了對(duì)象B,那么就稱A到B可達(dá)。

GCRoot對(duì)象集合?

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

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

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

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

1.2.2 釋放空間

1、垃圾回收算法

前面已經(jīng)介紹了如何檢測(cè)出垃圾對(duì)象,在檢測(cè)出垃圾對(duì)象之后,需要按照特定的垃圾回收算法進(jìn)行內(nèi)存回收,常見的垃圾回收算法有:

u  復(fù)制(Copying)

u  標(biāo)記-清除(Mark-Sweep)

u  標(biāo)記-整理(Mark-Compact)

u  分代(Generational Collection),借助前面三種算法實(shí)現(xiàn)

這里就不一一詳述,感興趣可以自行百度。

2、垃圾收集器實(shí)現(xiàn)

上面算法都是理論性的東西,Java虛擬機(jī)規(guī)范沒有規(guī)定垃圾收集器具體如何實(shí)現(xiàn),因此不同廠商、不同版本虛擬機(jī)提供的垃圾收集器可能有所差異。下面列舉HotSpot(Sun JDK和Open JDK自帶)虛擬機(jī)提供的六種垃圾收集器實(shí)現(xiàn):

收集器名稱

應(yīng)用目標(biāo)

采用算法

引入版本

運(yùn)行方式

Serial

新生代

復(fù)制算法

Jdk1.3.1前

串行,單線程

ParNew

新生代

復(fù)制算法

 

并行,多線程

Parallel Scavenge

新生代

復(fù)制算法

Jdk1.4

并行,多線程

Serial Old

舊生代

標(biāo)記-整理

 

串行,單線程

Parallel Old

舊生代

標(biāo)記-整理

Jdk1.6

并行,多線程

CMS

舊生代

標(biāo)記-清除

Jdk1.5

并發(fā),多線程

并行(Parallel):多條垃圾收集線程并行工作,而用戶線程仍處于等待狀態(tài)。

并發(fā)(Concurrent):垃圾收集線程與用戶線程一段時(shí)間內(nèi)同時(shí)工作(不是并行,而是交替執(zhí)行)。

總結(jié):

1、兩個(gè)串行收集器、三個(gè)并行收集器、一個(gè)并發(fā)收集器。

2、ParNew收集器是Serial的多線程版本。

3、Serial Old收集器是Serial收集器的舊生代版本。

4、Parallel Scavenge收集器以吞吐量為目標(biāo),適合在后臺(tái)運(yùn)算而不需要太多交互的任務(wù)。

5、Parallel Old收集器是Parallel Scavenge的舊生代版本。

6、Parallel Scavenge收集器和Parallel Old收集器是名副其實(shí)的“吞吐量?jī)?yōu)先”組合。

7、除CMS外,其他收集器工作時(shí)都需要暫停其他所有線程,CMS是第一款真正意義上的并發(fā)(Concurrent)收集器,第一次實(shí)現(xiàn)了讓垃圾收 集器線程與 用戶線程同時(shí)工作,是一款以最短停頓時(shí)間為目標(biāo)的收集器,適合交互性較多的場(chǎng)景,這也是與Parallel Scavenge/Parallel Old吞吐量?jī)?yōu)先組合的區(qū)別。

8、新生代因?yàn)榛厥樟粝碌膶?duì)象少,所以采用標(biāo)記-復(fù)制法。

9、舊生代因?yàn)榛厥樟粝碌膶?duì)象多,所以采用標(biāo)記-清除/標(biāo)記-整理算法。

3、選擇所需垃圾收集器

虛擬機(jī)提供了參數(shù),以便用戶根據(jù)自己的需求設(shè)置所需的垃圾收集器:

JVM運(yùn)行參數(shù)

新生代

舊生代

-XX:+UseSerialGC(Client模式默認(rèn)值)

Serial

Serial Old

-XX:+UseParNewGC

ParNew

Serial Old

-XX:+UseConcMarkSweepGC

ParNew

CMS(Serial Old備用)

-XX:+UseParallelGC(Server模式默認(rèn)值)

Parallel Scavenge

Serial Old

-XX:+UseParallelOldGC

Parallel Scavenge

Parallel Old

二、性能調(diào)優(yōu)

2.1 性能調(diào)優(yōu)的目的

減少minor gc的頻率、以及full gc的次數(shù)。

2.2 性能調(diào)優(yōu)的手段

1.使用JDK提供的內(nèi)存查看工具,如JConsole和Java VisualVM

2.控制堆內(nèi)存各個(gè)部分所占的比例

3.采用合適的垃圾收集器

手段1:內(nèi)存查看工具和GC日志分析

n  -verbose.gc:顯示GC的操作內(nèi)容。打開它,可以顯示最忙和最空閑收集行為發(fā)生的時(shí)間、收集前后的內(nèi)存大小、收集需要的時(shí)間等。

n  -xx:+printGCdetails:詳細(xì)了解GC中的變化。

n  -XX:+PrintGCTimeStamps:了解這些垃圾收集發(fā)生的時(shí)間,自JVM啟動(dòng)以后以秒計(jì)量。

n  -xx:+PrintHeapAtGC:了解堆的更詳細(xì)的信息。

手段2:針對(duì)新生代和舊生代的比例

如果新生代太小,會(huì)導(dǎo)致頻繁GC,而且大對(duì)象對(duì)直接進(jìn)入舊生代引發(fā)full gc

如果新生代太大,會(huì)誘發(fā)舊生代full gc,而且新生代的gc耗時(shí)會(huì)延長(zhǎng)

建議新生代占整個(gè)堆1/3合適,相關(guān)JVM參數(shù)如下:

n  -Xms:初始堆大小

n  -Xmx:最大堆大小

n  - Xmn:新生代大小

n  -XX:PermSize=n:持久代最大值

n  -XX:MaxPermSize=n:持久代最大值

n  -XX:NewRatio=n:設(shè)置新生代和舊生代的比值。如:為3,表示新生代與舊生代比值為1:3,新生代占整個(gè)新生代舊生代和的1/4。

手段3:針對(duì)Eden和Survivor的比例

如果Eden太小,會(huì)導(dǎo)致頻繁GC

如果Eden太大,會(huì)導(dǎo)致大對(duì)象直接進(jìn)入舊生代,降低對(duì)象在新生代存活時(shí)間。

n  -XX:SurvivorRatio=n:新生代中Eden區(qū)與兩個(gè)Survivor區(qū)的比值。注意Survivor區(qū)有兩個(gè)。如:3,表示Eden:Survivor=3:2,一個(gè)Survivor區(qū)占整個(gè)年輕代的1/5

n  -XX:PretenureSizeThreshold:直接進(jìn)入舊生代中的對(duì)象大小,設(shè)置此值后,大于這個(gè)參數(shù)的對(duì)象將直接在舊生代中進(jìn)行內(nèi)存分配。

n  -XX:MaxTenuringThreshold:對(duì)象轉(zhuǎn)移到舊生代中的年齡,每個(gè)對(duì)象經(jīng)歷過一次新生代GC(Minor GC)后,年齡就加1,到超過設(shè)置的值后,對(duì)象轉(zhuǎn)移到舊生代。

手段4:采用正確的垃圾收集器

通過JVM參數(shù)設(shè)置所使用的垃圾收集器參考前面的介紹,這里關(guān)注其他一些設(shè)置。

并行收集器設(shè)置

n  -XX:ParallelGCThreads=n:設(shè)置并行收集器收集時(shí)并行收集線程數(shù)。

n  -XX:MaxGCPauseMillis=n:設(shè)置并行收集最大暫停時(shí)間,僅對(duì)ParallelScavenge生效。

n  -XX:GCTimeRatio=n:設(shè)置垃圾回收時(shí)間占程序運(yùn)行時(shí)間的百分比,僅對(duì)Parallel Scavenge生效。

并發(fā)收集器設(shè)置

n  -XX:CMSInitiatingOccupancyFraction:默認(rèn)設(shè)置下,CMS收集器在舊生代使用了68%的空間后就會(huì)被激活。此參數(shù)就是 設(shè)置舊生代空間被使用多少后觸發(fā)垃圾收集。注意要是CMS運(yùn)行期間預(yù)留的內(nèi)存無法滿足程序需要,就會(huì)出現(xiàn)concurrent mode failure,這時(shí)候就會(huì)啟用Serial Old收集器作為備用進(jìn)行舊生代的垃圾收集。

n  -XX:+UseCMSCompactAtFullCollection:空間碎片過多是標(biāo)記-清除算法的弊端,此參數(shù)設(shè)置在FULL GC后再進(jìn)行一個(gè)碎片整理過程

n  -XX:CMSFullGCsBeforeCompaction:設(shè)置在若干次垃圾收集之后再啟動(dòng)一次內(nèi)存碎片整理

三、實(shí)際項(xiàng)目配置

 

1、修改 tomcat\bin\Catalina.bat 文件
windows環(huán)境下:

 

在166行左右
rem Execute Java with the applicable properties ”以下每行
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%

在 %DEBUG_OPTS% 后面添加-Xms256m -Xmx512m

linux環(huán)境下:

打開在Tomcat的安裝目錄的bin文件的catalina.sh文件,進(jìn)入編輯狀態(tài).
在注釋后面加上如下腳本:
JAVA_OPTS='-Xms512m -Xmx1024m'
JAVA_OPTS="$JAVA_OPTS -server -XX:PermSize=64M -XX:MaxPermSize=256m"

其中 JAVA_OPTS='-Xms512m -Xmx1024m' 是設(shè)置Tomcat使用的內(nèi)存的大小.

-XX:PermSize=64M -XX:MaxPermSize=256m 指定類空間(用于加載類)的內(nèi)存大小 

 

保存后,重新以命令行的方式運(yùn)行 tomcat ,即可,然后通過最后面介紹的如何觀察tomcat現(xiàn)有內(nèi)存情況的方法進(jìn)行查看是否已經(jīng)變更成功。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多