全網(wǎng)最硬核 JVM 內(nèi)存解析 - 4.Java 堆內(nèi)存大小的確認(rèn)

個人創(chuàng)作公約:本人聲明創(chuàng)作的所有文章皆為自己原創(chuàng),如果有參考任何文章的地方,會標(biāo)注出來,如果有疏漏,歡迎大家批判。如果大家發(fā)現(xiàn)網(wǎng)上有抄襲本文章的,歡迎舉報,并且積極向這個?github 倉庫?提交 issue,謝謝支持~
另外,本文為了避免抄襲,會在不影響閱讀的情況下,在文章的隨機位置放入對于抄襲和洗稿的人的“親切”的問候。如果是正常讀者看到,筆者在這里說聲對不起,。如果被抄襲狗或者洗稿狗看到了,希望你能夠好好反思,不要再抄襲了,謝謝。
今天又是干貨滿滿的一天,這是全網(wǎng)最硬核 JVM 解析系列第四篇,往期精彩:
全網(wǎng)最硬核 TLAB 解析
全網(wǎng)最硬核 Java 隨機數(shù)解析
全網(wǎng)最硬核 Java 新內(nèi)存模型解析
本篇是關(guān)于 JVM 內(nèi)存的詳細(xì)分析。網(wǎng)上有很多關(guān)于 JVM 內(nèi)存結(jié)構(gòu)的分析以及圖片,但是由于不是一手的資料亦或是人云亦云導(dǎo)致有很錯誤,造成了很多誤解;并且,這里可能最容易混淆的是一邊是 JVM Specification 的定義,一邊是 Hotspot JVM 的實際實現(xiàn),有時候人們一些部分說的是 JVM Specification,一部分說的是 Hotspot 實現(xiàn),給人一種割裂感與誤解。本篇主要從 Hotspot 實現(xiàn)出發(fā),以 Linux x86 環(huán)境為主,緊密貼合 JVM 源碼并且輔以各種 JVM 工具驗證幫助大家理解 JVM 內(nèi)存的結(jié)構(gòu)。但是,本篇僅限于對于這些內(nèi)存的用途,使用限制,相關(guān)參數(shù)的分析,有些地方可能比較深入,有些地方可能需要結(jié)合本身用這塊內(nèi)存涉及的 JVM 模塊去說,會放在另一系列文章詳細(xì)描述。最后,洗稿抄襲狗不得 house
本篇全篇目錄(以及涉及的 JVM 參數(shù)):
從 Native Memory Tracking 說起(全網(wǎng)最硬核 JVM 內(nèi)存解析 - 1.從 Native Memory Tracking 說起開始)
Native Memory Tracking 的開啟
Native Memory Tracking 的使用(涉及 JVM 參數(shù):
NativeMemoryTracking
)Native Memory Tracking 的 summary 信息每部分含義
Native Memory Tracking 的 summary 信息的持續(xù)監(jiān)控
為何 Native Memory Tracking 中申請的內(nèi)存分為 reserved 和 committed
JVM 內(nèi)存申請與使用流程(全網(wǎng)最硬核 JVM 內(nèi)存解析 - 2.JVM 內(nèi)存申請與使用流程開始)
Linux 大頁分配方式 - Huge Translation Lookaside Buffer Page (hugetlbfs)
Linux 大頁分配方式 - Transparent Huge Pages (THP)
JVM 大頁分配相關(guān)參數(shù)與機制(涉及 JVM 參數(shù):
UseLargePages
,UseHugeTLBFS
,UseSHM
,UseTransparentHugePages
,LargePageSizeInBytes
)JVM commit 的內(nèi)存與實際占用內(nèi)存的差異
Linux 下內(nèi)存管理模型簡述
JVM commit 的內(nèi)存與實際占用內(nèi)存的差異
大頁分配 UseLargePages(全網(wǎng)最硬核 JVM 內(nèi)存解析 - 3.大頁分配 UseLargePages開始)
Java 堆內(nèi)存相關(guān)設(shè)計(全網(wǎng)最硬核 JVM 內(nèi)存解析 - 4.Java 堆內(nèi)存大小的確認(rèn)開始)
驗證?
32-bit
?壓縮指針模式驗證?
Zero based
?壓縮指針模式驗證?
Non-zero disjoint
?壓縮指針模式驗證?
Non-zero based
?壓縮指針模式壓縮對象指針存在的意義(涉及 JVM 參數(shù):
ObjectAlignmentInBytes
)壓縮對象指針與壓縮類指針的關(guān)系演進(jìn)(涉及 JVM 參數(shù):
UseCompressedOops
,UseCompressedClassPointers
)壓縮對象指針的不同模式與尋址優(yōu)化機制(涉及 JVM 參數(shù):
ObjectAlignmentInBytes
,HeapBaseMinAddress
)通用初始化與擴展流程
直接指定三個指標(biāo)的方式(涉及 JVM 參數(shù):
MaxHeapSize
,MinHeapSize
,InitialHeapSize
,Xmx
,Xms
)不手動指定三個指標(biāo)的情況下,這三個指標(biāo)(MinHeapSize,MaxHeapSize,InitialHeapSize)是如何計算的
壓縮對象指針相關(guān)機制(涉及 JVM 參數(shù):
UseCompressedOops
)(全網(wǎng)最硬核 JVM 內(nèi)存解析 - 5.壓縮對象指針相關(guān)機制開始)為何預(yù)留第 0 頁,壓縮對象指針 null 判斷擦除的實現(xiàn)(涉及 JVM 參數(shù):
HeapBaseMinAddress
)結(jié)合壓縮對象指針與前面提到的堆內(nèi)存限制的初始化的關(guān)系(涉及 JVM 參數(shù):
HeapBaseMinAddress
,ObjectAlignmentInBytes
,MinHeapSize
,MaxHeapSize
,InitialHeapSize
)使用 jol + jhsdb + JVM 日志查看壓縮對象指針與 Java 堆驗證我們前面的結(jié)論
堆大小的動態(tài)伸縮(涉及 JVM 參數(shù):
MinHeapFreeRatio
,MaxHeapFreeRatio
,MinHeapDeltaBytes
)(全網(wǎng)最硬核 JVM 內(nèi)存解析 - 6.其他 Java 堆內(nèi)存相關(guān)的特殊機制開始)適用于長期運行并且盡量將所有可用內(nèi)存被堆使用的 JVM 參數(shù) AggressiveHeap
JVM 參數(shù) AlwaysPreTouch 的作用
JVM 參數(shù) UseContainerSupport - JVM 如何感知到容器內(nèi)存限制
JVM 參數(shù) SoftMaxHeapSize - 用于平滑遷移更耗內(nèi)存的 GC 使用
JVM 元空間設(shè)計(全網(wǎng)最硬核 JVM 內(nèi)存解析 - 7.元空間存儲的元數(shù)據(jù)開始)
jcmd <pid> VM.metaspace
?元空間說明元空間相關(guān) JVM 日志
元空間 JFR 事件詳解
jdk.MetaspaceSummary
?元空間定時統(tǒng)計事件jdk.MetaspaceAllocationFailure
?元空間分配失敗事件jdk.MetaspaceOOM
?元空間 OOM 事件jdk.MetaspaceGCThreshold
?元空間 GC 閾值變化事件jdk.MetaspaceChunkFreeListSummary
?元空間 Chunk FreeList 統(tǒng)計事件CommitLimiter
?的限制元空間可以 commit 的內(nèi)存大小以及限制元空間占用達(dá)到多少就開始嘗試 GC每次 GC 之后,也會嘗試重新計算?
_capacity_until_GC
首先類加載器 1 需要分配 1023 字節(jié)大小的內(nèi)存,屬于類空間
然后類加載器 1 還需要分配 1023 字節(jié)大小的內(nèi)存,屬于類空間
然后類加載器 1 需要分配 264 KB 大小的內(nèi)存,屬于類空間
然后類加載器 1 需要分配 2 MB 大小的內(nèi)存,屬于類空間
然后類加載器 1 需要分配 128KB 大小的內(nèi)存,屬于類空間
新來一個類加載器 2,需要分配 1023 Bytes 大小的內(nèi)存,屬于類空間
然后類加載器 1 被 GC 回收掉
然后類加載器 2 需要分配 1 MB 大小的內(nèi)存,屬于類空間
元空間的整體配置以及相關(guān)參數(shù)(涉及 JVM 參數(shù):
MetaspaceSize
,MaxMetaspaceSize
,MinMetaspaceExpansion
,MaxMetaspaceExpansion
,MaxMetaspaceFreeRatio
,MinMetaspaceFreeRatio
,UseCompressedClassPointers
,CompressedClassSpaceSize
,CompressedClassSpaceBaseAddress
,MetaspaceReclaimPolicy
)元空間上下文?
MetaspaceContext
虛擬內(nèi)存空間節(jié)點列表?
VirtualSpaceList
虛擬內(nèi)存空間節(jié)點?
VirtualSpaceNode
?與?CompressedClassSpaceSize
MetaChunk
類加載的入口?
SystemDictionary
?與保留所有?ClassLoaderData
?的?ClassLoaderDataGraph
每個類加載器私有的?
ClassLoaderData
?以及?ClassLoaderMetaspace
管理正在使用的?
MetaChunk
?的?MetaspaceArena
元空間內(nèi)存分配流程(全網(wǎng)最硬核 JVM 內(nèi)存解析 - 9.元空間內(nèi)存分配流程開始)
ClassLoaderData
?回收ChunkHeaderPool
?池化?MetaChunk
?對象ChunkManager
?管理空閑的?MetaChunk
類加載器到?
MetaSpaceArena
?的流程從?
MetaChunkArena
?普通分配 - 整體流程從?
MetaChunkArena
?普通分配 -?FreeBlocks
?回收老的?current chunk
?與用于后續(xù)分配的流程從?
MetaChunkArena
?普通分配 - 嘗試從?FreeBlocks
?分配從?
MetaChunkArena
?普通分配 - 嘗試擴容?current chunk
從?
MetaChunkArena
?普通分配 - 從?ChunkManager
?分配新的?MetaChunk
從?
MetaChunkArena
?普通分配 - 從?ChunkManager
?分配新的?MetaChunk
?- 從?VirtualSpaceList
?申請新的?RootMetaChunk
從?
MetaChunkArena
?普通分配 - 從?ChunkManager
?分配新的?MetaChunk
?- 將?RootMetaChunk
?切割成為需要的?MetaChunk
MetaChunk
?回收 - 不同情況下,?MetaChunk
?如何放入?FreeChunkListVector
什么時候用到元空間,以及釋放時機
元空間保存什么
什么是元數(shù)據(jù),為什么需要元數(shù)據(jù)
什么時候用到元空間,元空間保存什么
元空間的核心概念與設(shè)計(全網(wǎng)最硬核 JVM 內(nèi)存解析 - 8.元空間的核心概念與設(shè)計開始)
元空間分配與回收流程舉例(全網(wǎng)最硬核 JVM 內(nèi)存解析 - 10.元空間分配與回收流程舉例開始)
元空間大小限制與動態(tài)伸縮(全網(wǎng)最硬核 JVM 內(nèi)存解析 - 11.元空間分配與回收流程舉例開始)
jcmd VM.metaspace
?元空間說明、元空間相關(guān) JVM 日志以及元空間 JFR 事件詳解(全網(wǎng)最硬核 JVM 內(nèi)存解析 - 12.元空間各種監(jiān)控手段開始)JVM 線程內(nèi)存設(shè)計(重點研究 Java 線程)(全網(wǎng)最硬核 JVM 內(nèi)存解析 - 13.JVM 線程內(nèi)存設(shè)計開始)
解釋執(zhí)行與編譯執(zhí)行時候的判斷(x86為例)
一個 Java 線程 Xss 最小能指定多大
JVM 中有哪幾種線程,對應(yīng)線程棧相關(guān)的參數(shù)是什么(涉及 JVM 參數(shù):
ThreadStackSize
,VMThreadStackSize
,CompilerThreadStackSize
,StackYellowPages
,StackRedPages
,StackShadowPages
,StackReservedPages
,RestrictReservedStack
)Java 線程棧內(nèi)存的結(jié)構(gòu)
Java 線程如何拋出的 StackOverflowError
3. Java 堆內(nèi)存相關(guān)設(shè)計
3.1. 通用初始化與擴展流程
目前最新的 JVM,主要根據(jù)三個指標(biāo)初始化堆以及擴展或縮小堆:
最大堆大小
最小堆大小
初始堆大小
不同的 GC 情況下,初始化以及擴展的流程可能在某些細(xì)節(jié)不太一樣,但是,大體的思路都是:
初始化階段,reserve?最大堆大小,并且 commit?初始堆大小
在某些 GC 的某些階段,根據(jù)上次 GC 的數(shù)據(jù),動態(tài)擴展或者縮小堆大小,擴展就是 commit 更多,縮小就是 uncommit 一部分內(nèi)存。但是,堆大小不會小于最小堆大小,也不會大于最大堆大小
3.2. 直接指定三個指標(biāo)(MinHeapSize,MaxHeapSize,InitialHeapSize)的方式
這三個指標(biāo),直接對應(yīng)的 JVM 參數(shù)是:
最大堆大小:
MaxHeapSize
,如果沒有指定的話會有默認(rèn)預(yù)設(shè)值用于指導(dǎo) JVM 計算這些指標(biāo)的大小,下一章節(jié)會詳細(xì)分析,預(yù)設(shè)值為 125MB 左右(96M*13/10)最小堆大小:
MinHeapSize
,默認(rèn)為 0,0 代表讓 JVM 自己計算,下一章節(jié)會詳細(xì)分析初始堆大小:
InitialHeapSize
,默認(rèn)為 0,0 代表讓 JVM 自己計算,下一章節(jié)會詳細(xì)分析
對應(yīng)源碼是:https://github.com/openjdk/jdk/blob/jdk-21+3/src/hotspot/share/gc/shared/gc_globals.hpp
:
#define ScaleForWordSize(x) align_down((x) * 13 / 10, HeapWordSize)
product(size_t, MaxHeapSize, ScaleForWordSize(96*M), ? ? ? ? ? ? ? ?\
?"Maximum heap size (in bytes)") ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
?constraint(MaxHeapSizeConstraintFunc,AfterErgo) ? ? ? ? ? ? ? ? ? \
product(size_t, MinHeapSize, 0, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
?"Minimum heap size (in bytes); zero means use ergonomics") ? ? ? ?\
?constraint(MinHeapSizeConstraintFunc,AfterErgo) ? ? ? ? ? ? ? ? ? \
product(size_t, InitialHeapSize, 0, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
?"Initial heap size (in bytes); zero means use ergonomics") ? ? ? ?\
?constraint(InitialHeapSizeConstraintFunc,AfterErgo) ? ? ? ? ? ? ? \
我們可以通過類似于?-XX:MaxHeapSize=1G
?這種啟動參數(shù)對這三個指標(biāo)進(jìn)行設(shè)置,但是,我們經(jīng)??吹降目赡苁?Xmx
?以及?Xms
?這兩個參數(shù)設(shè)置這三個指標(biāo),這兩個參數(shù)分別對應(yīng):
Xmx
:對應(yīng)?最大堆大小?等價于?MaxHeapSize
Xms
:相當(dāng)于同時設(shè)置最小堆大小?MinHeapSize
?和初始堆大小?InitialHeapSize
對應(yīng)的 JVM 源碼是:https://github.com/openjdk/jdk/blob/jdk-21+3/src/hotspot/share/runtime/arguments.cpp
:
//如果設(shè)置了 Xms
else if (match_option(option, "-Xms", &tail)) {
?julong size = 0;
?//解析 Xms 大小
?ArgsRange errcode = parse_memory_size(tail, &size, 0);
?if (errcode != arg_in_range) {
? ?jio_fprintf(defaultStream::error_stream(),
? ? ? ? ? ? ? ?"Invalid initial heap size: %s\n", option->optionString);
? ?describe_range_error(errcode);
? ?return JNI_EINVAL;
?}
?//將解析的值設(shè)置到 MinHeapSize
?if (FLAG_SET_CMDLINE(MinHeapSize, (size_t)size) != JVMFlag::SUCCESS) {
? ?return JNI_EINVAL;
?}
?//將解析的值設(shè)置到 InitialHeapSize
?if (FLAG_SET_CMDLINE(InitialHeapSize, (size_t)size) != JVMFlag::SUCCESS) {
? ?return JNI_EINVAL;
?}
//如果設(shè)置了 Xmx
} else if (match_option(option, "-Xmx", &tail) || match_option(option, "-XX:MaxHeapSize=", &tail)) {
?julong long_max_heap_size = 0;
?//解析 Xmx 大小
?ArgsRange errcode = parse_memory_size(tail, &long_max_heap_size, 1);
?if (errcode != arg_in_range) {
? ?jio_fprintf(defaultStream::error_stream(),
? ? ? ? ? ? ? ?"Invalid maximum heap size: %s\n", option->optionString);
? ?describe_range_error(errcode);
? ?return JNI_EINVAL;
?}
?//將解析的值設(shè)置到 MaxHeapSize
?if (FLAG_SET_CMDLINE(MaxHeapSize, (size_t)long_max_heap_size) != JVMFlag::SUCCESS) {
? ?return JNI_EINVAL;
?}
}
最后提一句,JVM 啟動參數(shù),同一個參數(shù)可以多次出現(xiàn),但是只有最后一個會生效,例如:
java -XX:MaxHeapSize=8G -XX:MaxHeapSize=4G -XX:MaxHeapSize=8M -version
這個命令啟動的 JVM MaxHeapSize 為 8MB。由于前面提到 Xmx 與 MaxHeapSize 是等價的,所以這么寫也是可以的(雖然最后 MaxHeapSize 還是 8MB):
java -Xmx=8G -XX:MaxHeapSize=4G -XX:MaxHeapSize=8M -version
3.3. 不手動指定三個指標(biāo)的情況下,這三個指標(biāo)(MinHeapSize,MaxHeapSize,InitialHeapSize)是如何計算的
上一章節(jié)我們提到我們可以手動指定這三個參數(shù),如果不指定呢?JVM 會怎么計算這三個指標(biāo)的大???首先,當(dāng)然,JVM 會讀取?JVM 可用內(nèi)存:首先 JVM 需要知道自己可用多少內(nèi)存,我們稱為可用內(nèi)存。由此引入第一個 JVM 參數(shù),MaxRAM
,這個參數(shù)是用來明確指定 JVM 進(jìn)程可用內(nèi)存大小的,如果沒有指定,JVM 會自己讀取系統(tǒng)可用內(nèi)存。這個可用內(nèi)存用來指導(dǎo) JVM 限制最大堆內(nèi)存。后面我們會看到很多 JVM 參數(shù)與這個可用內(nèi)存相關(guān)。
前面我們還提到了,就算沒有指定?MaxHeapSize
?或者?Xmx
,MaxHeapSize
?也有自己預(yù)設(shè)的一個參考值。源碼中這個預(yù)設(shè)參考值為 125MB 左右(96M*13/10
)。但是一般最后不會以這個參考值為準(zhǔn),JVM 初始化的時候會有很復(fù)雜的計算計算出合適的值。比如你可以在你的電腦上執(zhí)行下下面的命令,可以看到類似下面的輸出:
> ?java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version|grep MaxHeapSize
? size_t MaxHeapSize ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?= 1572864000 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?{product} {ergonomic}
? size_t SoftMaxHeapSize ? ? ? ? ? ? ? ? ? ? ? ? ?= 1572864000 ? ? ? ? ? ? ? ? ? ? ? ? ? ? {manageable} {ergonomic}
openjdk version "17.0.2" 2022-01-18 LTS
OpenJDK Runtime Environment Corretto-17.0.2.8.1 (build 17.0.2+8-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.2.8.1 (build 17.0.2+8-LTS, mixed mode, sharing)
可以看到?MaxHeapSize
?的大小,以及它的值是通過 ergonomic 決定的。也就是非人工指定而是 JVM 自己算出來的。
上面提到的那個 125MB 左右的初始參考值,一般用于 JVM 計算。我們接下來就會分析這個計算流程,首先是最大堆內(nèi)存 MaxHeapSize 的計算流程:

流程中涉及了以下幾個參數(shù),還有一些已經(jīng)過期的參數(shù),會被轉(zhuǎn)換成未過期的參數(shù):
MinRAMPercentage
:注意不要被名字迷惑,這個參數(shù)是在可用內(nèi)存比較小的時候生效,即最大堆內(nèi)存占用為可用內(nèi)存的這個參數(shù)指定的百分比,默認(rèn)為 50,即 50%MaxRAMPercentage
:注意不要被名字迷惑,這個參數(shù)是在可用內(nèi)存比較大的時候生效,即最大堆內(nèi)存占用為可用內(nèi)存的這個參數(shù)指定的百分比,默認(rèn)為 25,即 25%ErgoHeapSizeLimit
:通過自動計算,計算出的最大堆內(nèi)存大小不超過這個參數(shù)指定的大小,默認(rèn)為 0 即不限制MinRAMFraction
: 已過期,如果配置了會轉(zhuǎn)化為?MinRAMPercentage
?換算關(guān)系是:MinRAMPercentage
?= 100.0 /?MinRAMFraction
,默認(rèn)是 2MaxRAMFraction
: 已過期,如果配置了會轉(zhuǎn)化為?MaxRAMPercentage
?換算關(guān)系是:MaxRAMPercentage
?= 100.0 /?MaxRAMFraction
,默認(rèn)是 4
對應(yīng)的源碼是:https://github.com/openjdk/jdk/blob/jdk-21+3/src/hotspot/share/gc/shared/gc_globals.hpp
:
product(double, MinRAMPercentage, 50.0, ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
?"Minimum percentage of real memory used for maximum heap" ? ? ? ? \
?"size on systems with small physical memory size") ? ? ? ? ? ? ? ?\
?range(0.0, 100.0) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
product(double, MaxRAMPercentage, 25.0, ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
?"Maximum percentage of real memory used for maximum heap size") ? \
?range(0.0, 100.0) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
product(size_t, ErgoHeapSizeLimit, 0, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
?"Maximum ergonomically set heap size (in bytes); zero means use " \
?"MaxRAM * MaxRAMPercentage / 100") ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\
?range(0, max_uintx) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
product(uintx, MinRAMFraction, 2, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
?"Minimum fraction (1/n) of real memory used for maximum heap " ? ?\
?"size on systems with small physical memory size. " ? ? ? ? ? ? ? \
?"Deprecated, use MinRAMPercentage instead") ? ? ? ? ? ? ? ? ? ? ? \
?range(1, max_uintx) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
product(uintx, MaxRAMFraction, 4, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
?"Maximum fraction (1/n) of real memory used for maximum heap " ? ?\
?"size. " ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\
?"Deprecated, use MaxRAMPercentage instead") ? ? ? ? ? ? ? ? ? ? ? \
?range(1, max_uintx) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
然后如果我們也沒有設(shè)置?MinHeapSize
?以及?InitialHeapSize
,也會經(jīng)過下面的計算過程計算出來:

流程中涉及了以下幾個參數(shù),還有一些已經(jīng)過期的參數(shù),會被轉(zhuǎn)換成未過期的參數(shù):
NewSize
:初始新生代大小,預(yù)設(shè)值為 1.3MB 左右(1*13/10
)OldSize
:老年代大小,預(yù)設(shè)值為 5.2 MB 左右(4*13/10
)InitialRAMPercentage
:初始堆內(nèi)存為可用內(nèi)存的這個參數(shù)指定的百分比,默認(rèn)為 1.5625,即 1.5625%InitialRAMFraction
: 已過期,如果配置了會轉(zhuǎn)化為?InitialRAMPercentage
?換算關(guān)系是:InitialRAMPercentage
?= 100.0 /?InitialRAMFraction
對應(yīng)的源碼是:https://github.com/openjdk/jdk/blob/jdk-21+3/src/hotspot/share/gc/shared/gc_globals.hpp
:
product(size_t, NewSize, ScaleForWordSize(1*M), ? ? ? ? ? ? ? ? ? ? \
?"Initial new generation size (in bytes)") ? ? ? ? ? ? ? ? ? ? ? ? \
?constraint(NewSizeConstraintFunc,AfterErgo) ? ? ? ? ? ? ? ? ? ? ? \
product(size_t, OldSize, ScaleForWordSize(4*M), ? ? ? ? ? ? ? ? ? ? \
?"Initial tenured generation size (in bytes)") ? ? ? ? ? ? ? ? ? ? \
?range(0, max_uintx) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
product(double, InitialRAMPercentage, 1.5625, ? ? ? ? ? ? ? ? ? ? ? \
?"Percentage of real memory used for initial heap size") ? ? ? ? ? \
?range(0.0, 100.0) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
product(uintx, InitialRAMFraction, 64, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\
?"Fraction (1/n) of real memory used for initial heap size. " ? ? ?\
?"Deprecated, use InitialRAMPercentage instead") ? ? ? ? ? ? ? ? ? \
?range(1, max_uintx) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
微信搜索“干貨滿滿張哈希”關(guān)注公眾號,加作者微信,每日一刷,輕松提升技術(shù),斬獲各種offer
我會經(jīng)常發(fā)一些很好的各種框架的官方社區(qū)的新聞視頻資料并加上個人翻譯字幕到如下地址(也包括上面的公眾號),歡迎關(guān)注:
知乎:https://www.zhihu.com/people/zhxhash