一、JVM内存的分代划分
首先我们要收集活跃数据的大小,例如JVM运行了一段时间,经过多次垃圾回收后程序稳定了,这时堆内存活的对象,就是活跃数据。
以活跃数据为基准,总堆空间的大小 = 活跃数据 的 3 ~ 4倍,新生代 = 1 ~ 1.5倍活跃数据的大小
老年代 = 2 ~ 3倍活跃数据的大小
元空间 = 在经过 Full GC后 永久代还有多少存活的对象,按照 存活对象的 1.2 ~ 1.5倍的大小设置
二、扩大新生代
MinorGC触发的条件是新生代内存占满的时候,扩大新生代可以扩大MinorGC的间隔。
一个对象在垃圾回收的时间 = 扫描 + 复制
如果扩大了GC的间隔,可能对象已经沦为垃圾,这时就不需要复制了,只需要扫描节省了一次复制的时间,但是扫描的时间增加了因为内存扩大了,即使扫描的时间增加了总体来说还是有很大概率减少垃圾回收的时间。
三、card table 卡表 帮助避免Minor GC扫描全堆
MinorGC为什么会扫描全堆?
当出现跨代引用的时候,老年代引用新生代,JVM会认为老年代的那个对象为GCROOT,所以一旦发生跨代引用,就需要扫描老年代看都有哪些GCROOT。
卡表的出现避免了扫描全堆
卡表相当于一个boolean类型的数组,卡表给老年代分区,每一张卡大小为512bit,当一个分区的对象出现跨带引用的时候,就会记录这块区域,当发生Minor GC发生时,只需要扫描卡表中标记的区域和新生代即可。