03.Java 内存分配策略
Java 内存分配策略

新生代和老年代的
GC 操作
- 新生代
GC 操作:Minor GC
- 发生的非常频繁,速度较块。
- 老年代
GC 操作:Full GC / Major GC
- 经常伴随着至少一次的
Minor GC ;- 速度一般比
Minor GC 慢上10 倍以上。
优先在Eden 区分配
Eden 空间不够将会触发一次Minor GC ;- 虚拟机参数:
-Xmx
:Java 堆的最大值;-Xms
:Java 堆的最小值;-Xmn
:新生代大小;-XX:SurvivorRatio=8
:Eden 区/ Survivor 区= 8 : 1
大对象直接进入老年代
- 大对象定义: 需要大量连续内存空间的
Java 对象。例如那种很长的字符串或者数组。 - 设置对象直接进入老年代大小限制:
-XX:PretenureSizeThreshold
:单位是字节;- 只对
Serial 和ParNew 两款收集器有效。
- 只对
- 目的: 因为新生代采用的是复制算法收集垃圾,大对象直接进入老年代可以避免在
Eden 区和Survivor 区发生大量的内存复制。
长期存活的对象将进入老年代
- 固定对象年龄判定: 虚拟机给每个对象定义一个年龄计数器,对象每在
Survivor 中熬过一次Minor GC ,年龄+1 ,达到-XX:MaxTenuringThreshold
设定值后,会被晋升到老年代,-XX:MaxTenuringThreshold
默认为15 ; - 动态对象年龄判定:
Survivor 中有相同年龄的对象的空间总和大于Survivor 空间的一半,那么,年龄大于或等于该年龄的对象直接晋升到老年代。
空间分配担保
我们知道,新生代采用的是复制算法清理内存,每一次
这么做有一个前提,就是老年代得装得下这么多对象。可是在一次
- 发生
Minor GC 前,虚拟机先检查老年代的最大可用连续空间是否大于新生代所有对象的总空间;- 如果大于,
Minor GC 一定是安全的; - 如果小于,虚拟机会查看
HandlePromotionFailure 参数,看看是否允许担保失败;- 允许失败:尝试着进行一次
Minor GC ; - 不允许失败:进行一次
Full GC ;
- 允许失败:尝试着进行一次
- 如果大于,
- 不过
JDK 6 Update 24 后,HandlePromotionFailure 参数就没有用了,规则变为只要老年代的连续空间大于新生代对象总大小或者历次晋升的平均大小就会进行Minor GC ,否则将进行Full GC 。
Metaspace 元空间与PermGen 永久代
移除
PermGen 内存经常会溢出,引发恼人的java.lang.OutOfMemoryError: PermGen ,因此JVM 的开发者希望这一块内存可以更灵活地被管理,不要再经常出现这样的OOM ;- 移除
PermGen 可以促进HotSpot JVM 与JRockit VM 的融合,因为JRockit 没有永久代。
移除
- 方法区:移至
Metaspace ; - 字符串常量:移至
Java Heap 。
-XX:MetaspaceSize
:分配给类元数据空间(以字节计)的初始大小,为估计值。MetaspaceSize 的值设置的过大会延长垃圾回收时间。垃圾回收过后,引起下一次垃圾回收的类元数据空间的大小可能会变大。-XX:MaxMetaspaceSize
:分配给类元数据空间的最大值,超过此值就会触发Full GC ,取决于系统内存的大小。JVM 会动态地改变此值。-XX:MinMetaspaceFreeRatio
:一次GC 以后,为了避免增加元数据空间的大小,空闲的类元数据的容量的最小比例,不够就会导致垃圾回收。-XX:MaxMetaspaceFreeRatio
:一次GC 以后,为了避免增加元数据空间的大小,空闲的类元数据的容量的最大比例,不够就会导致垃圾回收。