JVM实战调优系列之了解JVM的内存模型

31 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

JVM的内存模型

JVM的运行时数据区是一种规范,而JVM的内存模型是对规范的实现

模型

JVM内存模型.png

分区的目的

  • 如果不分区,虽然JVM对象的分配有着更大的内存,但是会引发垃圾回收扫描全部的JVM内存
  • 不分区,没有GC的复制移动,带来更多的内存碎片,或者带来整理内存碎片更大的开销
  • 实验显示:98%的对象,在一次GC就会被回收,所以划分old区和young区,所以youngGC的代价更小
  • 由于内存分配导致的内存空间的不连续性(内存碎片),会引发内存有空闲空间,但是无法分配,所以划分了Eden区和S区做内存整理,一次youngGC会扫描Eden和一个s0区,通过内存空间的交换,使得空间连续。

特殊的策略

悲观策略

  • 如果所有相同代的对象总和大于S区其中一个区域的一半,年龄大于该分代的对象,可以直接进入老年代。

    因为来回复制的成本太大,秒杀或者高并发,有可能使得同代年龄太多,直接进入old区,导致fullGC

  • 每次youngGC晋升的对象的平均大小大于老年代的剩余空间,提前判定,会产生fullGC。

  • youngGC之后,s区存活的对象大小大于old区剩余空间

内存担保

  • 分配的大对象,不够在young区存放,直接分配在old区。PretenureSizeThreshold控制对象大小阈值。

这个也容易造成FullGC。

比例

old : young = 2 : 1

eden : s0 : s1 = 8 : 1 : 1

这个比例是可以调整的,具体根据业务容忍停顿的程度进行调整。

对象的创建过程

对象创建过程.png

GC的相关叫法

  • 官方只有两种GC,partial GCFull GC即部分GC和全部GC
  • youngGC minor GC是回收Eden区和其中一个s区
  • old GC 回收的是old区的垃圾
  • full GC = young GC + old GC + MetaSpace GC

full GC的触发时机

  • 之前每次youngGC晋升对象的平均大小大于老年代剩余空间,基于历史水平的提前判定

  • young GC之后,s区的存活对象大小 大于 老年代剩余空间,基于晋升担保的悲观策略

  • MetaSpace空间不足

  • System.gc()

  • 老年代空间不足

方法区从堆内移到直接内存的考量

  • 1.7之前方法区使用的是堆内存,JVM内存,是优于堆分配的,因此JVM可用内存会更少
  • 1.8之后是放在直接内存,减少内存碎片,节省压缩的时间,并且减少内存溢出,进行动态扩容和自己想服务器申请内存
  • 方法区的GC会非常少