在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

阿里:每天100w次登陸請求, 8G內存該如何設置JVM參數?

jf_ro2CN3Fa ? 來源:千淘萬漉 ? 2023-03-13 09:44 ? 次閱讀

每天100w次登陸請求, 8G 內存該如何設置JVM參數

    • Step1:新系統上線如何規劃容量?
    • Step2:該如何進行垃圾回收器的選擇?
    • Step3:如何對各個分區的比例、大小進行規劃
    • step4:棧內存大小多少比較合適?
    • step5:對象年齡應該為多少才移動到老年代比較合適?
    • step6:多大的對象,可以直接到老年代比較合適?
    • step7:垃圾回收器CMS老年代的參數優化
    • step8:配置OOM時候的內存dump文件和GC日志
    • 調優總結
  • 什么是ZGC?
  • 如何選擇垃圾收集器?
  • Hotspot為什么使用元空間替換了永久代?
  • 什么是Stop The World ? 什么是OopMap?什么是安全點?
d29eff8c-c02f-11ed-bfe3-dac502259ad0.jpg

在阿里云技術面終面的時候被問到這么一個問題:假設一個每天100w次登陸請求的平臺,一個服務節點 8G 內存,該如何設置JVM參數?

下面以面試題的形式給大家梳理出來,做到一箭雙雕:

  • 既供大家實操參考
  • 又供大家面試參考

大家要學習的,除了 JVM 配置方案 之外,是其 分析問題的思路、思考問題的視角。這些思路和視角,能幫助大家走更遠、更遠。

接下來,進入正題。

每天100w次登陸請求, 8G 內存該如何設置JVM參數?

每天100w次登陸請求, 8G 內存該如何設置JVM參數,大概可以分為以下8個步驟

Step1:新系統上線如何規劃容量?

1.套路總結

任何新的業務系統在上線以前都需要去估算服務器配置和JVM的內存參數,這個容量與資源規劃并不僅僅是系統架構師的隨意估算的,需要根據系統所在業務場景去估算,推斷出來一個系統運行模型,評估JVM性能和GC頻率等等指標。以下是我結合大牛經驗以及自身實踐來總結出來的一個建模步驟:

  • 計算業務系統每秒鐘創建的對象會佔用多大的內存空間,然后計算集群下的每個系統每秒的內存佔用空間(對象創建速度)
  • 設置一個機器配置,估算新生代的空間,比較不同新生代大小之下,多久觸發一次MinorGC。
  • 為了避免頻繁GC,就可以重新估算需要多少機器配置,部署多少臺機器,給JVM多大內存空間,新生代多大空間。
  • 根據這套配置,基本可以推算出整個系統的運行模型,每秒創建多少對象,1s以后成為垃圾,系統運行多久新生代會觸發一次GC,頻率多高。

2.套路實戰——以登錄系統為例

有些同學看到這些步驟還是發憷,說的好像是那么回事,一到實際項目中到底怎麼做我還是不知道!

光說不練假把式,以登錄系統為例模擬一下推演過程:

  • 假設每天100w次登陸請求,登陸峰值在早上,預估峰值時期每秒100次登陸請求。
  • 假設部署3臺服務器,每臺機器每秒處理30次登陸請求,假設一個登陸請求需要處理1秒鐘,JVM新生代里每秒就要生成30個登陸對象,1s之后請求完畢這些對象成為了垃圾。
  • 一個登陸請求對象假設20個字段,一個對象估算500字節,30個登陸佔用大約15kb,考慮到RPC和DB操作,網絡通信、寫庫、寫緩存一頓操作下來,可以擴大到20-50倍,大約1s產生幾百k-1M數據。
  • 假設2C4G機器部署,分配2G堆內存,新生代則只有幾百M,按照1s1M的垃圾產生速度,幾百秒就會觸發一次MinorGC了。
  • 假設4C8G機器部署,分配4G堆內存,新生代分配2G,如此需要幾個小時才會觸發一次MinorGC。

所以,可以粗略的推斷出來一個每天100w次請求的登錄系統,按照4C8G的3實例集群配置,分配4G堆內存、2G新生代的JVM,可以保障系統的一個正常負載。

基本上把一個新系統的資源評估了出來,所以搭建新系統要每個實例需要多少容量多少配置,集群配置多少個實例等等這些,并不是拍拍腦袋和胸脯就可以決定的下來的。

Step2:該如何進行垃圾回收器的選擇?

吞吐量還是響應時間

首先引入兩個概念:吞吐量和低延遲

吞吐量 = CPU在用戶應用程序運行的時間 / (CPU在用戶應用程序運行的時間 + CPU垃圾回收的時間)

響應時間 = 平均每次的GC的耗時

通常,吞吐優先還是響應優先這個在JVM中是一個兩難之選。

堆內存增大,gc一次能處理的數量變大,吞吐量大;但是gc一次的時間會變長,導致后面排隊的線程等待時間變長;相反,如果堆內存小,gc一次時間短,排隊等待的線程等待時間變短,延遲減少,但一次請求的數量變小(并不絕對符合)。

無法同時兼顧,是吞吐優先還是響應優先,這是一個需要權衡的問題。

垃圾回收器設計上的考量

  • JVM在GC時不允許一邊垃圾回收,一邊還創建新對象(就像不能一邊打掃衛生,還在一邊扔垃圾)。
  • JVM需要一段Stop the world的暫停時間,而STW會造成系統短暫停頓不能處理任何請求;
  • 新生代收集頻率高,性能優先,常用復制算法;老年代頻次低,空間敏感,避免復制方式。
  • 所有垃圾回收器的涉及目標都是要讓GC頻率更少,時間更短,減少GC對系統影響!

CMS和G1

目前主流的垃圾回收器配置是新生代采用ParNew,老年代采用CMS組合的方式,或者是完全采用G1回收器,

從未來的趨勢來看,G1是官方維護和更為推崇的垃圾回收器。

d2b1306c-c02f-11ed-bfe3-dac502259ad0.jpg

業務系統:

  • 延遲敏感的推薦CMS;
  • 大內存服務,要求高吞吐的,采用G1回收器!

CMS垃圾回收器的工作機制

CMS主要是針對老年代的回收器,老年代是標記-清除,默認會在一次FullGC算法后做整理算法,清理內存碎片。

CMS GC 描述 Stop the world 速度
1.開始標記 初始標記僅標記GCRoots能直接關聯到的對象,速度很快 Yes 很快
2.并發標記 并發標記階段就是進行GCRoots Tracing的過程 No
3.重新標記 重新標記階段則是為了修正并發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分對象的標記記錄。 Yes 很快
4.垃圾回收 并發清理垃圾對象(標記清除算法) No
  • 優點:并發收集、主打“低延時” 。在最耗時的兩個階段都沒有發生STW,而需要STW的階段都以很快速度完成。
  • 缺點:1、消耗CPU;2、浮動垃圾;3、內存碎片
  • 適用場景:重視服務器響應速度,要求系統停頓時間最短。

總之:

業務系統,延遲敏感的推薦CMS;

大內存服務,要求高吞吐的,采用G1回收器!

Step3:如何對各個分區的比例、大小進行規劃

一般的思路為:

首先,JVM最重要最核心的參數是去評估內存和分配,第一步需要指定堆內存的大小,這個是系統上線必須要做的,-Xms 初始堆大小,-Xmx 最大堆大小,后臺Java服務中一般都指定為系統內存的一半,過大會佔用服務器的系統資源,過小則無法發揮JVM的最佳性能。

其次,需要指定-Xmn新生代的大小,這個參數非常關鍵,靈活度很大,雖然sun官方推薦為3/8大小,但是要根據業務場景來定,針對于無狀態或者輕狀態服務(現在最常見的業務系統如Web應用)來說,一般新生代甚至可以給到堆內存的3/4大小;關注公z號:碼猿技術專欄,回復關鍵詞:1111 獲取阿里內部java性能調優手冊!而對于有狀態服務(常見如IM服務、網關接入層等系統)新生代可以按照默認比例1/3來設置。服務有狀態,則意味著會有更多的本地緩存和會話狀態信息常駐內存,應為要給老年代設置更大的空間來存放這些對象。

最后,是設置-Xss棧內存大小,設置單個線程棧大小,默認值和JDK版本、系統有關,一般默認512~1024kb。一個后臺服務如果常駐線程有幾百個,那麼棧內存這邊也會佔用了幾百M的大小。

JVM參數 描述 默認 推薦
-Xms Java堆內存的大小 OS內存64/1 OS內存一半
-Xmx Java堆內存的最大大小 OS內存4/1 OS內存一半
-Xmn Java堆內存中的新生代大小,扣除新生代剩下的就是老年代的內存大小了 跌認堆的1/3 sun推薦3/8
-Xss 每個線程的棧內存大小 和idk有關 sun

對于8G內存,一般分配一半的最大內存就可以了,因為機器本上還要占用一定內存,一般是分配4G內存給JVM,

引入性能壓測環節,測試同學對登錄接口壓至1s內60M的對象生成速度,采用ParNew+CMS的組合回收器,

正常的JVM參數配置如下:

-Xms3072M-Xmx3072M-Xss1M-XX:MetaspaceSize=256M-XX:MaxMetaspaceSize=256M-XX:SurvivorRatio=8

這樣設置可能會由于動態對象年齡判斷原則 導致頻繁full gc。為啥呢?

壓測過程中,短時間(比如20S后)Eden區就滿了,此時再運行的時候對象已經無法分配,會觸發MinorGC,

假設在這次GC后S1裝入100M,馬上過20S又會觸發一次MinorGC,多出來的100M存活對象+S1區的100M已經無法順利放入到S2區,此時就會觸發JVM的動態年齡機制,將一批100M左右的對象推到老年代保存,持續運行一段時間,系統可能一個小時候內就會觸發一次FullGC。

按照默認81的比例來分配時, survivor區只有 1G的 10%左右,也就是幾十到100M,

如果 每次minor GC垃圾回收過后進入survivor對象很多,并且survivor對象大小很快超過 Survivor 的 50% , 那么會觸發動態年齡判定規則,讓部分對象進入老年代.

而一個GC過程中,可能部分WEB請求未處理完畢, 幾十兆對象,進入survivor的概率,是非常大的,甚至是一定會發生的.

如何解決這個問題呢?為了讓對象盡可能的在新生代的eden區和survivor區, 盡可能的讓survivor區內存多一點,達到200兆左右,

于是我們可以更新下JVM參數設置:

-Xms3072M-Xmx3072M-Xmn2048M-Xss1M-XX:MetaspaceSize=256M-XX:MaxMetaspaceSize=256M-XX:SurvivorRatio=8

說明:
‐Xmn2048M‐XX:SurvivorRatio=8
年輕代大小2g,eden與survivor的比例為8:1:1,也就是1.6g:0.2g:0.2g
d2ca57b8-c02f-11ed-bfe3-dac502259ad0.jpg

survivor達到200m,如果幾十兆對象到底survivor, survivor 也不一定超過 50%

這樣可以防止每次垃圾回收過后,survivor對象太早超過 50% ,

這樣就降低了因為對象動態年齡判斷原則導致的對象頻繁進入老年代的問題,

什么是JVM動態年齡判斷規則呢?

對象進入老年代的動態年齡判斷規則 (動態晉升年齡計算閾值):Minor GC 時,Survivor 中年齡 1 到 N 的對象大小超過 Survivor 的 50% 時,則將大于等于年齡 N 的對象放入老年代。

核心的優化策略是:是讓短期存活的對象盡量都留在survivor里,不要進入老年代,這樣在minor gc的時候這些對象都會被回收,不會進到老年代從而導致full gc

應該如何去評估新生代內存和分配合適?

這里特別說一下,JVM最重要最核心的參數是去評估內存和分配,

第一步需要指定堆內存的大小,這個是系統上線必須要做的,-Xms 初始堆大小,-Xmx 最大堆大小,

后臺Java服務中一般都指定為系統內存的一半,過大會佔用服務器的系統資源,過小則無法發揮JVM的最佳性能。

其次需要指定-Xmn新生代的大小,這個參數非常關鍵,靈活度很大,雖然sun官方推薦為3/8大小,但是要根據業務場景來定:

  • 針對于無狀態或者輕狀態服務(現在最常見的業務系統如Web應用)來說,一般新生代甚至可以給到堆內存的3/4大小;
  • 而對于有狀態服務(常見如IM服務、網關接入層等系統)新生代可以按照默認比例1/3來設置。

服務有狀態,則意味著會有更多的本地緩存和會話狀態信息常駐內存,應為要給老年代設置更大的空間來存放這些對象。

step4:棧內存大小多少比較合適?

-Xss棧內存大小,設置單個線程棧大小,默認值和JDK版本、系統有關,一般默認512~1024kb。一個后臺服務如果常駐線程有幾百個,那麼棧內存這邊也會佔用了幾百M的大小。

step5:對象年齡應該為多少才移動到老年代比較合適?

假設一次minor gc要間隔二三十秒,并且,大多數對象一般在幾秒內就會變為垃圾,

如果對象這么長時間都沒被回收,比如2分鐘沒有回收,可以認為這些對象是會存活的比較長的對象,從而移動到老年代,而不是繼續一直占用survivor區空間。

所以,可以將默認的15歲改小一點,比如改為5,

那么意味著對象要經過5次minor gc才會進入老年代,整個時間也有一兩分鐘了(5*30s= 150s),和幾秒的時間相比,對象已經存活了足夠長時間了。

所以:可以適當調整JVM參數如下:

‐Xms3072M‐Xmx3072M‐Xmn2048M‐Xss1M‐XX:MetaspaceSize=256M‐XX:MaxMetaspaceSize=256M‐XX:SurvivorRatio=8‐XX:MaxTenuringThreshold=5

step6:多大的對象,可以直接到老年代比較合適?

對于多大的對象直接進入老年代(參數-XX:PretenureSizeThreshold),一般可以結合自己系統看下有沒有什么大對象 生成,預估下大對象的大小,一般來說設置為1M就差不多了,很少有超過1M的大對象,

所以:可以適當調整JVM參數如下:

‐Xms3072M‐Xmx3072M‐Xmn2048M‐Xss1M‐XX:MetaspaceSize=256M‐XX:MaxMetaspaceSize=256M‐XX:SurvivorRatio=8‐XX:MaxTenuringThreshold=5‐XX:PretenureSizeThreshold=1M

step7:垃圾回收器CMS老年代的參數優化

JDK8默認的垃圾回收器是-XX:+UseParallelGC(年輕代)和-XX:+UseParallelOldGC(老年代),

如果內存較大(超過4個G,只是經驗 值),還是建議使用G1.

這里是4G以內,又是主打“低延時” 的業務系統,可以使用下面的組合:

ParNew+CMS(-XX:+UseParNewGC-XX:+UseConcMarkSweepGC)

新生代的采用ParNew回收器,工作流程就是經典復制算法,在三塊區中進行流轉回收,只不過采用多線程并行的方式加快了MinorGC速度。

老生代的采用CMS。再去優化老年代參數 :比如老年代默認在標記清除以后會做整理,還可以在CMS的增加GC頻次還是增加GC時長上做些取舍,

如下是響應優先的參數調優:

XX:CMSInitiatingOccupancyFraction=70

設定CMS在對內存占用率達到70%的時候開始GC(因為CMS會有浮動垃圾,所以一般都較早啟動GC)

XX:+UseCMSInitiatinpOccupancyOnly

和上面搭配使用,否則只生效一次

-XX:+AlwaysPreTouch

強制操作系統把內存真正分配給IVM,而不是用時才分配。

綜上,只要年輕代參數設置合理,老年代CMS的參數設置基本都可以用默認值,如下所示:

‐Xms3072M‐Xmx3072M‐Xmn2048M‐Xss1M‐XX:MetaspaceSize=256M‐XX:MaxMetaspaceSize=256M‐XX:SurvivorRatio=8‐XX:MaxTenuringThreshold=5‐XX:PretenureSizeThreshold=1M‐XX:+UseParNewGC‐XX:+UseConcMarkSweepGC‐XX:CMSInitiatingOccupancyFraction=70‐XX:+UseCMSInitiatingOccupancyOnly‐XX:+AlwaysPreTouch

參數解釋

1.‐Xms3072M ‐Xmx3072M 最小最大堆設置為3g,最大最小設置為一致防止內存抖動

2.‐Xss1M 線程棧1m

3.‐Xmn2048M ‐XX:SurvivorRatio=8 年輕代大小2g,eden與survivor的比例為81,也就是1.6g0.2g

4.-XX:MaxTenuringThreshold=5 年齡為5進入老年代 5.‐XX:PretenureSizeThreshold=1M 大于1m的大對象直接在老年代生成

6.‐XX:+UseParNewGC ‐XX:+UseConcMarkSweepGC 使用ParNew+cms垃圾回收器組合

7.‐XX:CMSInitiatingOccupancyFraction=70 老年代中對象達到這個比例后觸發fullgc

8.‐XX:+UseCMSInitiatinpOccupancyOnly 老年代中對象達到這個比例后觸發fullgc,每次

9.‐XX:+AlwaysPreTouch 強制操作系統把內存真正分配給IVM,而不是用時才分配。

step8:配置OOM時候的內存dump文件和GC日志

額外增加了GC日志打印、OOM自動dump等配置內容,幫助進行問題排查

-XX:+HeapDumpOnOutOfMemoryError

在Out Of Memory,JVM快死掉的時候,輸出Heap Dump到指定文件。

不然開發很多時候還真不知道怎么重現錯誤。

路徑只指向目錄,JVM會保持文件名的唯一性,叫java_pid${pid}.hprof。

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=${LOGDIR}/

因為如果指向特定的文件,而文件已存在,反而不能寫入。

輸出4G的HeapDump,會導致IO性能問題,在普通硬盤上,會造成20秒以上的硬盤IO跑滿,

需要注意一下,但在容器環境下,這個也會影響同一宿主機上的其他容器。

GC的日志的輸出也很重要:

-Xloggc:/dev/xxx/gc.log
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails

GC的日志實際上對系統性能影響不大,打日志對排查GC問題很重要。

一份通用的JVM參數模板

一般來說,大企業或者架構師團隊,都會為項目的業務系統定制一份較為通用的JVM參數模板,但是許多小企業和團隊可能就疏于這一塊的設計,如果老板某一天突然讓你負責定制一個新系統的JVM參數,你上網去搜大量的JVM調優文章或博客,結果發現都是零零散散的、不成體系的JVM參數講解,根本下不了手,這個時候你就需要一份較為通用的JVM參數模板了,不能保證性能最佳,但是至少能讓JVM這一層是穩定可控的,

在這里給大家總結了一份模板:

基于4C8G系統的ParNew+CMS回收器模板(響應優先),新生代大小根據業務靈活調整!

-Xms4g
-Xmx4g
-Xmn2g
-Xss1m
-XX:SurvivorRatio=8
-XX:MaxTenuringThreshold=10
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSInitiatingOccupancyOnly
-XX:+AlwaysPreTouch
-XX:+HeapDumpOnOutOfMemoryError
-verbose:gc
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-Xloggc:gc.log

如果是GC的吞吐優先,推薦使用G1,基于8C16G系統的G1回收器模板:

G1收集器自身已經有一套預測和調整機制了,因此我們首先的選擇是相信它,

即調整-XX:MaxGCPauseMillis=N參數,這也符合G1的目的——讓GC調優盡量簡單!

同時也不要自己顯式設置新生代的大小(用-Xmn或-XX:NewRatio參數),

如果人為干預新生代的大小,會導致目標時間這個參數失效。

-Xms8g
-Xmx8g
-Xss1m
-XX:+UseG1GC
-XX:MaxGCPauseMillis=150
-XX:InitiatingHeapOccupancyPercent=40
-XX:+HeapDumpOnOutOfMemoryError
-verbose:gc
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-Xloggc:gc.log
G1參數 描述 默認值
XX:MaxGCPauseMillis=N 最大GC停頓時間。柔性目標,JVM滿足90%,不保證100%。 200
-XX:nitiatingHeapOccupancyPercent=n 當整個堆的空間使用百分比超過這個值時,就會融發MixGC 45

針對-XX:MaxGCPauseMillis來說,參數的設置帶有明顯的傾向性:調低↓:延遲更低,但MinorGC頻繁,MixGC回收老年代區減少,增大Full GC的風險。調高↑:單次回收更多的對象,但系統整體響應時間也會被拉長。

針對InitiatingHeapOccupancyPercent來說,調參大小的效果也不一樣:調低↓:更早觸發MixGC,浪費cpu。調高↑:堆積過多代回收region,增大FullGC的風險。

調優總結

系統在上線前的綜合調優思路:

1、業務預估:根據預期的并發量、平均每個任務的內存需求大小,然后評估需要幾臺機器來承載,每臺機器需要什么樣的配置。

2、容量預估:根據系統的任務處理速度,然后合理分配Eden、Surivior區大小,老年代的內存大小。

3、回收器選型:響應優先的系統,建議采用ParNew+CMS回收器;吞吐優先、多核大內存(heap size≥8G)服務,建議采用G1回收器。

4、優化思路:讓短命對象在MinorGC階段就被回收(同時回收后的存活對象

5、到目前為止,總結到的調優的過程主要基于上線前的測試驗證階段,所以我們盡量在上線之前,就將機器的JVM參數設置到最優!

JVM調優只是一個手段,但并不一定所有問題都可以通過JVM進行調優解決,大多數的Java應用不需要進行JVM優化,我們可以遵循以下的一些原則:

  • 上線之前,應先考慮將機器的JVM參數設置到最優;
  • 減少創建對象的數量(代碼層面);
  • 減少使用全局變量和大對象(代碼層面);
  • 優先架構調優和代碼調優,JVM優化是不得已的手段(代碼、架構層面);
  • 分析GC情況優化代碼比優化JVM參數更好(代碼層面);

通過以上原則,我們發現,其實最有效的優化手段是架構和代碼層面的優化,而JVM優化則是最后不得已的手段,也可以說是對服務器配置的最后一次“壓榨”。

基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

  • 項目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 視頻教程:https://doc.iocoder.cn/video/

什么是ZGC?

ZGC (Z Garbage Collector)是一款由Oracle公司研發的,以低延遲為首要目標的一款垃圾收集器。

它是基于動態Region內存布局,(暫時)不設年齡分代,使用了讀屏障、染色指針和內存多重映射等技術來實現可并發的標記-整理算法的收集器。

在 JDK 11 新加入,還在實驗階段,

主要特點是:回收TB級內存(最大4T),停頓時間不超過10ms。

優點:低停頓,高吞吐量, ZGC 收集過程中額外耗費的內存小

缺點:浮動垃圾

目前使用的非常少,真正普及還是需要寫時間的。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

  • 項目地址:https://github.com/YunaiV/yudao-cloud
  • 視頻教程:https://doc.iocoder.cn/video/

如何選擇垃圾收集器?

在真實場景中應該如何去選擇呢,下面給出幾種建議,希望對你有幫助:

1、如果你的堆大小不是很大(比如 100MB ),選擇串行收集器一般是效率最高的。參數:-XX:+UseSerialGC

2、如果你的應用運行在單核的機器上,或者你的虛擬機核數只有 單核,選擇串行收集器依然是合適的,這時候啟用一些并行收集器沒有任何收益。參數:-XX:+UseSerialGC

3、如果你的應用是“吞吐量”優先的,并且對較長時間的停頓沒有什么特別的要求。選擇并行收集器是比較好的。參數:-XX:+UseParallelGC

4、如果你的應用對響應時間要求較高,想要較少的停頓。甚至 1 秒的停頓都會引起大量的請求失敗,那么選擇 G1 、 ZGC 、 CMS 都是合理的。雖然這些收集器的 GC 停頓通常都比較短,但它需要一些額外的資源去處理這些工作,通常吞吐量會低一些。參數:-XX:+UseConcMarkSweepGC-XX:+UseG1GC-XX:+UseZGC 等。從上面這些出發點來看,我們平常的 Web 服務器,都是對響應性要求非常高的。

選擇性其實就集中在 CMS、G1、ZGC 上。而對于某些定時任務,使用并行收集器,是一個比較好的選擇。

Hotspot為什么使用元空間替換了永久代?

什么是元空間?什么是永久代?為什么用元空間代替永久代?

我們先回顧一下方法區 吧,看看虛擬機運行時數據內存圖,如下:

d2dfdb9c-c02f-11ed-bfe3-dac502259ad0.jpg

方法區和堆一樣,是各個線程共享的內存區域,它用于存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯后的代碼等數據。

什么是永久代?它和方法區有什么關系呢?

如果在HotSpot虛擬機上開發、部署,很多程序員都把方法區稱作永久代。

可以說方法區是規范,永久代是Hotspot針對該規范進行的實現。

在Java7及以前的版本,方法區都是永久代實現的。

什么是元空間?它和方法區有什么關系呢?

對于Java8,HotSpots取消了永久代,取而代之的是元空間(Metaspace)。

換句話說,就是方法區還是在的,只是實現變了,從永久代變為元空間了。

為什么使用元空間替換了永久代?

永久代的方法區,和堆使用的物理內存是連續的。

d2ee07e4-c02f-11ed-bfe3-dac502259ad0.jpg

永久代 是通過以下這兩個參數配置大小的~

  • -XX:PremSize:設置永久代的初始大小
  • -XX:MaxPermSize: 設置永久代的最大值,默認是64M

對于永久代 ,如果動態生成很多class的話,就很可能出現java.lang.OutOfMemoryError:PermGen space錯誤 ,因為永久代空間配置有限嘛。最典型的場景是,在web開發比較多jsp頁面的時候。

JDK8之后,方法區存在于元空間(Metaspace)。

物理內存不再與堆連續,而是直接存在于本地內存中,理論上機器內存有多大,元空間就有多大

d3049450-c02f-11ed-bfe3-dac502259ad0.jpg

可以通過以下的參數來設置元空間的大小:

  • -XX:MetaspaceSize,初始空間大小,達到該值就會觸發垃圾收集進行類型卸載,同時GC會對該值進行調整:如果釋放了大量的空間,就適當降低該值;如果釋放了很少的空間,那么在不超過MaxMetaspaceSize時,適當提高該值。
  • -XX:MaxMetaspaceSize,最大空間,默認是沒有限制的。
  • -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空間容量的百分比,減少為分配空間所導致的垃圾收集
  • -XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空間容量的百分比,減少為釋放空間所導致的垃圾收集

所以,為什么使用元空間替換永久代?

表面上看是為了避免OOM異常。

因為通常使用PermSize和MaxPermSize設置永久代的大小就決定了永久代的上限,但是不是總能知道應該設置為多大合適, 如果使用默認值很容易遇到OOM錯誤。

當使用元空間時,可以加載多少類的元數據就不再由MaxPermSize控制, 而由系統的實際可用空間來控制啦。

什么是Stop The World ? 什么是OopMap?什么是安全點?

進行垃圾回收的過程中,會涉及對象的移動。

為了保證對象引用更新的正確性,必須暫停所有的用戶線程,像這樣的停頓,虛擬機設計者形象描述為Stop The World 。也簡稱為STW。

在HotSpot中,有個數據結構(映射表)稱為OopMap

一旦類加載動作完成的時候,HotSpot就會把對象內什么偏移量上是什么類型的數據計算出來,記錄到OopMap。

在即時編譯過程中,也會在特定的位置 生成 OopMap,記錄下棧上和寄存器里哪些位置是引用。

這些特定的位置主要在:

1.循環的末尾(非 counted 循環)

2.方法臨返回前 / 調用方法的call指令后

3.可能拋異常的位置

這些位置就叫作安全點(safepoint)。

用戶程序執行時并非在代碼指令流的任意位置都能夠在停頓下來開始垃圾收集,而是必須是執行到安全點才能夠暫停。

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內存
    +關注

    關注

    8

    文章

    3064

    瀏覽量

    74382
  • JVM
    JVM
    +關注

    關注

    0

    文章

    158

    瀏覽量

    12270
  • 收集器
    +關注

    關注

    0

    文章

    30

    瀏覽量

    3194

原文標題:阿里:每天100w次登陸請求, 8G 內存該如何設置JVM參數?

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    容器JVM內存配置最佳實踐

    Killer)機制,此時系統會終止內存占用較多的進程以保證系統的正常運行。特別是在容器環境下,不合理的JVM參數設置會導致各種異常現象產生,例如應用堆大小還未到達JVM
    發表于 06-20 09:45 ?940次閱讀
    容器<b class='flag-5'>JVM</b><b class='flag-5'>內存</b>配置最佳實踐

    我想請問下 手機可以登陸 網站嗎

    我想請問下 手機可以登陸 網站嗎、我用手機找到論壇了 但是登陸時出現的問題
    發表于 05-28 20:14

    100W擴音機電路

    100W擴音機電路
    發表于 10-19 14:27 ?5897次閱讀

    100W逆變電源電路

    100W逆變電源電路原理圖
    發表于 11-03 19:18 ?1650次閱讀
    <b class='flag-5'>100W</b>逆變電源電路

    100W RMS的放大器電路 (100W rms ampli

    100W RMS的放大器電路 (100W rms amplifier) Circuit Description: This is a 100 watt basic power amp that was designed t
    發表于 12-23 18:04 ?3379次閱讀
    <b class='flag-5'>100W</b> RMS的放大器電路 (<b class='flag-5'>100W</b> rms ampli

    傳iPhone8將一破保守的傳統采用8G超速內存

    隨著6G內存智能手機在市場上廣泛出現,今年我們將更加普遍地看到8G內存的智能設備。據最新消息,三星Galaxy S8 將是首個采用
    發表于 01-13 09:08 ?964次閱讀

    Fitomodule 100W項目開源

    電子發燒友網站提供《Fitomodule 100W項目開源.zip》資料免費下載
    發表于 08-22 16:14 ?14次下載
    Fitomodule <b class='flag-5'>100W</b>項目開源

    在4G內存的機器上,申請8G內存會怎么樣?

    這篇文章其實之前發過,但是最近有位讀者跟我反饋,我文章中的實驗在 64 位操作系統、2 G 物理內存的場景,申請 8G 內存是沒問題的,而他也是這個環境,為什么他就無法申請成功呢?
    的頭像 發表于 01-31 16:41 ?992次閱讀

    jvm內存溢出如何定位解決

    在Java應用程序中,JVM(Java虛擬機)內存溢出是指Java應用程序試圖分配的內存超過了JVM所允許的最大內存大小,導致程序無法正常執
    的頭像 發表于 12-05 11:05 ?1383次閱讀

    jvm調優參數

    和類元數據等方面的參數設置。下面我們將詳細介紹這些參數以及如何進行優化。 首先,堆內存JVM中用于存放對象實例的內存區域。通過調整堆
    的頭像 發表于 12-05 11:29 ?702次閱讀

    jvm參數設置jvm調優

    JVM(Java虛擬機)參數設置和調優對于提高Java應用程序的性能和穩定性非常重要。在本文中,我們將詳細介紹JVM參數
    的頭像 發表于 12-05 11:36 ?1699次閱讀

    jvm配置metaspace最大值的參數

    內存限制):參數用于設置JVM堆的最大大小。在JVM啟動時,可以使用以下命令來配置Metas
    的頭像 發表于 12-05 14:21 ?2316次閱讀

    weblogic jvm參數配置

    ,讓我們來了解一些常用的JVM參數: -Xms 和 -Xmx參數:這些參數分別用于設置Java虛擬機的初始堆大小和最大堆大小。-Xms
    的頭像 發表于 12-05 14:31 ?1541次閱讀

    weblogic設置jvm內存大小

    WebLogic是一種Java EE應用服務器,用于構建和部署企業級Java應用程序。在配置WebLogic服務器時,設置JVM內存大小非常重要,這可以提高應用程序的性能和可靠性。本文將詳細介紹
    的頭像 發表于 12-05 14:44 ?3152次閱讀

    eclipse設置jvm內存大小

    Eclipse是一個功能強大的集成開發環境(IDE),常用于Java開發。為了保證Eclipse的性能和穩定性,我們可以根據需要來設置JVM內存大小。本文將詳細介紹如何在Eclipse中設置
    的頭像 發表于 12-06 11:43 ?1965次閱讀
    主站蜘蛛池模板: 伊在线视频 | 午夜视频免费国产在线 | 亚洲欧美一区二区三区在线播放 | 91大神大战高跟丝袜美女 | cijilu刺激 国产免费的 | 中国特级毛片 | 亚洲国产人久久久成人精品网站 | 九九久久国产精品大片 | 国产一区二区在线不卡 | 91精品国产免费久久久久久青草 | 亚洲欧美日本视频 | 日韩第十页 | 91伊人网 | 911精品国产91久久久久 | 高清一区二区三区 | 男女午夜特黄毛片免费 | 亚洲第一在线视频 | 亚欧乱色束缚一区二区三区 | 久久精品re | 99久久婷婷免费国产综合精品 | 成人五级毛片免费播放 | 色倩网站 | 国产人免费人成免费视频 | 国产男人搡女人免费视频 | 国产高清一级视频在线观看 | 波多野结衣在线免费视频 | 国产精品色片 | 8天堂资源在线 | 影音先锋ady69色资源网站 | 五月婷婷在线观看视频 | 一级毛片真人免费观看 | 午夜美女久久久久爽久久 | 亚洲免费在线看 | 国产乱人视频免费播放 | 久久精品亚洲精品国产欧美 | 黄页网站在线 | 六月婷婷啪啪 | 两性色午夜视频免费老司机 | 日本黄色免费大片 | 中出丰满大乳中文字幕 | 欧美ggg666|