java - 调整大小时JVM元空间是否总是触发GC
问题描述
对于 Java 8 之后的 JVM
- 当元空间的大小 >
-XX:metaspaceSize
时,会触发一次 gc。 - 无论你如何配置
-XX:metaspaceSize
和-XX:maxMetaspaceSize
,元空间的初始大小在 64 位服务器上通常是一个固定值(20.8M)。 - 当接近当前容量时,JVM 会自动调整元空间的大小。
- 那么,如果
-XX:metaspaceSize
是20G,当前元空间大小为18M,需要分配大量新对象(约100M),JVM必须为这些新对象resize metaspace,JVM会在resize之前触发full GC吗?
解决方案
首先,“元空间的大小”是模棱两可的,因此没有上下文就毫无意义。至少有五个指标:reserved、committed、容量和已用内存,如本答案中所述,以及高水位线,也称为capacity_until_gc。
元空间不仅仅是一个连续的内存区域,因此它不会按照常识调整大小。相反,当分配发生时,上述一项或多项指标会发生变化。
- 在最快的路径上,从当前块中分配一个元数据块。
used
在这种情况下,内存会增加,仅此而已。 - 如果当前块中没有足够的空间,JVM 会搜索一个可能空闲的现有块。如果它成功重用块,则
capacity
增加。在此之前不会发生 GC。 - 如果没有空闲块,JVM 会尝试提交更多内存,除非新
committed
大小超过capacity_until_gc
. - 如果
capacity_until_gc
达到阈值,JVM 会触发 GC 循环。 - 如果 GC 没有释放足够的内存,则会增加高水位线,以便分配另一个虚拟空间。
在 GC 之后,根据以下 JVM 标志调整高水位标记值:
-XX:MinMetaspaceFreeRatio
(用于计算元空间容量中需要多少空闲空间来决定增加多少HWM);-XX:MaxMetaspaceFreeRatio
(用于在降低 HWM 之前决定元空间容量中需要多少可用空间);-XX:MinMetaspaceExpansion
(元空间的最小扩展,以字节为单位);-XX:MaxMetaspaceExpansion
(没有full GC的Metaspace的最大扩展)。
TL;DR这不是那么简单。JVM 绝对可以在不触发 GC 的情况下提交更多的 Metaspace 内存。但是,当达到 HWM 时,将触发 GC 并根据人体工程学策略重新计算 HWM。
推荐阅读
- c - TCC 是否允许创建静态库?
- ios - ios视图在情节提要中调整大小但在运行时不显示
- python - 检测图像的主要对象并去除背景
- swiftui - 有没有办法在 ZStack 中使用 Spacer() ?(斯威夫特用户界面)
- r - ggplot2:让 geom_abline() 为 facet_wrap() 的每个图绘制独立的斜率和截距
- javascript - 当点击文本输入时,使用 Javascript 的自动填充被删除,如何解决这个问题?
- python - 在 Pyspark 中对数据集进行联合分组
- python - Plotly:将等高线图更改为 3-d 曲面
- c# - 我怎么做DoSomething???方法一种通用方法?
- asp.net-core-webapi - .net core webapi启动时如何预加载数据?