JVM源码分析之MetaspaceSize和MaxMetaspaceSize的区别

JVM加载类的时候,须要记录类的元数据,这些数据会保存在一个单独的内存区域内,在Java 7里,这个空间被称为永久代(Permgen),在Java 8里,使用元空间(Metaspace)代替了永久代。永久代和元空间保存的数据并不彻底同样,永久代中还保存另外一些与类的元数据无关的杂项。java

如咱们以前的一篇文章016:字符串对象在JVM中是如何存放的中说的,在Java 7里将字符串常量从永久代移动到了堆区域,可是永久代并无彻底改造完成。直到Java 8,永久代的改造才算彻底搞定,在元空间中保存的数据比永久代中纯粹不少,就是类的元数据,这些信息只对编译期或JVM的运行时有用。面试

理论学习

使用Java 8之后,关于元空间的JVM参数有两个:-XX:MetaspaceSize=N-XX:MaxMetaspaceSize=N,对于64位JVM来讲,元空间的默认初始大小是20.75MB,默认的元空间的最大值是无限。MaxMetaspaceSize用于设置metaspace区域的最大值,这个值能够经过mxbean中的MemoryPoolBean获取到,若是这个参数没有设置,那么就是经过mxbean拿到的最大值是-1,表示无穷大。后端

因为调整元空间的大小须要Full GC,这是很是昂贵的操做,若是应用在启动的时候发生大量Full GC,一般都是因为永久代或元空间发生了大小调整,基于这种状况,通常建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成同样的值,并设置得比初始值要大,对于8G物理内存的机器来讲,通常我会将这两个值都设置为256M(PS:读者能够根据本身的实际状况再调整)。源码分析

源码分析

MetaspaceSize表示metaspace首次使用不够而触发FGC的阈值,只对触发起做用,缘由是:垃圾搜集器内部是根据变量_capacity_until_GC来判断metaspace区域是否达到阈值的,初始化代码以下所示:学习

void MetaspaceGC::initialize() {
  // Set the high-water mark to MaxMetapaceSize during VM initializaton since
  // we can't do a GC during initialization.
  _capacity_until_GC = MaxMetaspaceSize;
}复制代码

GC收集器会在发生对metaspace的回收会,会计算新的capacityuntil_GC值,之后发生FGC就跟MetaspaceSize没有关系了。屏幕快照 2018-10-16 下午6.39.08.png优化

若是不设置MetaspaceSize,则默认的capacityuntil_GC为20M左右,具体代码以下:![屏幕快照 2018-10-16 下午6.46.27.png](https://user-gold-cdn.xitu.io/2019/10/4/16d97024b10550ee?w=1240&h=301&f=png&s=195510)***本号专一于后端技术、JVM问题排查和优化、Java面试题、我的成长和自我管理等主题,为读者提供一线开发者的工做和成长经验,期待你能在这里有所收获。javaaduspa

相关文章
相关标签/搜索