JVM对内存的管理主要体现在堆内存的管理上;在启动JVM时,可以设置JVM的内存大小及调整策略
JVM启动参数
-Xms:JVM的初始堆大小
-Xmx:JVM的最大堆大小
-Xss:线程栈大小
-Dname=value:JVM全局属性设置
......
注:当-Xms堆内存不足时,JVM会将堆内存大小调整至-Xmx;为-Xms与-Xmx设置相同值可避免不必要的内存调整,但一味地如此设置有时会造成资源的浪费
堆内存分布
堆内存分为新生代(Young)和老年代(Old),分区是为了有目的地选择GC算法
新生代被划分为三个区域:
Eden:基本上新诞生的Java对象都存储在该区域
From Survivor/To Survivor:经历GC后仍然存活,且未进入老年代的对象
Young:Old=1:2
Eden:From:To=8:1:1,可通过设置参数 -XX:SurvivorRatio=8(默认值为8) 修改比例
GC触发条件
通常新创建对象都会进入新生代中的Eden区域,但较大的对象会直接进入老年代,可通过设置参数 -XX:PretenureSizeThreshold 修改临界值
在新生代中,From区域与To区域只有一片会被使用,因为此处JVM采用复制GC算法
老年代未进行分区,所以采用的是GC算法为标记-清除算法或者标记 - 整理算法
Minor GC:
Eden区域空间不足时会产生一次Minor GC,垃圾回收器会在Eden和一片被使用的Survivor区域中进行清理,存活下来的对象会被复制到另一片Survivor区域中,随后清空Eden区域和原先被使用的Survivor区域。
存活的对象年龄加一,当年龄到达临界值时会进入老年代(默认是15),可通过设置参数 -XX:MaxTenuringThreshold 修改临界值。此外,当存在一个年龄的所有对象占用内存之和,大于Survivor区域的内存空间的一半时,大于等于该年龄的对象会被转移至老年代
Full GC:
Full GC会清理新生代、老年代、方法区
Full GC的触发条件:
1.调用System.gc()时
2.老年代空间不足时
为避免年代晋升失败:新生代历次转移至老年代的所有对象的大小合平均值,大于老年代余下的内存空间时,会直接进行Full GC,否则会进行Minor GC
发生年代晋升失败后:在上述情况下进行Minor GC时,发现Survivor区域不足以容纳存活的对象;尝试将溢出的对象转移至老年代后,又发现此次新生代转移至老年代的所有对象的大小合不仅大于历次转移的平均值,而且老年代余下的内存空间不足以容纳新生代转移来的对象时,会进行Full GC
3.方法区空间不足时