共计 2000 个字符,预计需要花费 5 分钟才能阅读完成。
内存调配与回收策略
对象的内存调配,就是在堆上调配(也可能通过 JIT 编译后被拆散为标量类型并间接在栈上调配),对象次要调配在新生代的 Eden 区上,多数状况下可能间接调配在老年代,调配规定不固定,取决于以后应用的垃圾收集器组合以及相干的参数配置。
以下列举几条最广泛的内存调配规定,供大家学习。
对象优先在 Eden 调配
大多数状况下,对象在新生代 Eden 区中调配。当 Eden 区没有足够空间进行调配时,虚拟机将发动一次 Minor GC。
👇Minor GC vs Major GC/Full GC:
- Minor GC:回收新生代(包含 Eden 和 Survivor 区域),因为 Java 对象大多都具备朝生夕灭的个性,所以 Minor GC 十分频繁,个别回收速度也比拟快。
- Major GC / Full GC:回收老年代,呈现了 Major GC,常常会随同至多一次的 Minor GC,但这并非相对。Major GC 的速度个别会比 Minor GC 慢 10 倍 以上。
在 JVM 标准中,Major GC 和 Full GC 都没有一个正式的定义,所以有人也简略地认为 Major GC 清理老年代,而 Full GC 清理整个内存堆。
大对象间接进入老年代
大对象是指须要大量间断内存空间的 Java 对象,如很长的字符串或数据。
一个大对象可能存入 Eden 区的概率比拟小,产生调配担保的概率比拟大,而调配担保须要波及大量的复制,就会造成效率低下。
虚拟机提供了一个 -XX:PretenureSizeThreshold 参数,令大于这个设置值的对象间接在老年代调配,这样做的目标是防止在 Eden 区及两个 Survivor 区之间产生大量的内存复制。(还记得吗,新生代采纳复制算法回收垃圾)
长期存活的对象将进入老年代
JVM 给每个对象定义了一个对象年龄计数器。当新生代产生一次 Minor GC 后,存活下来的对象年龄 +1,当年龄超过肯定值时,就将超过该值的所有对象转移到老年代中去。
应用 -XXMaxTenuringThreshold
设置新生代的最大年龄,只有超过该参数的新生代对象都会被转移到老年代中去。
动静对象年龄断定
如果以后新生代的 Survivor 中,雷同年龄所有对象大小的总和大于 Survivor 空间的一半,年龄 >= 该年龄的对象就能够间接进入老年代,毋庸等到 MaxTenuringThreshold
中要求的年龄。
空间调配担保
JDK 6 Update 24 之前的规定是这样的:
在产生 Minor GC 之前,虚构机会先查看 老年代最大可用的间断空间是否大于新生代所有对象总空间,如果这个条件成立,Minor GC 能够确保是平安的;如果不成立,则虚构机会查看 HandlePromotionFailure
值是否设置为容许担保失败,如果是,那么会持续查看老年代最大可用的间断空间是否大于历次降职到老年代对象的均匀大小,如果大于,将尝试进行一次 Minor GC,只管这次 Minor GC 是有危险的;如果小于,或者 HandlePromotionFailure
设置不容许冒险,那此时也要改为进行一次 Full GC。
JDK 6 Update 24 之后的规定变为:
只有老年代的间断空间大于新生代对象总大小或者历次降职的均匀大小,就会进行 Minor GC,否则将进行 Full GC。
通过革除老年代中的废除数据来扩充老年代闲暇空间,以便给新生代作担保。
这个过程就是调配担保。
👇 总结一下有哪些状况可能会触发 JVM 进行 Full GC。
System.gc()
办法的调用
此办法的调用是倡议 JVM 进行 Full GC,留神这 只是倡议而非肯定,但在很多状况下它会触发 Full GC,从而减少 Full GC 的频率。通常状况下咱们只须要让虚拟机本人去治理内存即可,咱们能够通过 -XX:+ DisableExplicitGC 来禁止调用System.gc()
。- 老年代空间有余
老年代空间有余会触发 Full GC 操作,若进行该操作后空间仍然有余,则会抛出如下谬误:java.lang.OutOfMemoryError: Java heap space
- 永恒代空间有余
JVM 标准中运行时数据区域中的办法区,在 HotSpot 虚拟机中也称为永恒代(Permanet Generation),寄存一些类信息、常量、动态变量等数据,当零碎要加载的类、反射的类和调用的办法较多时,永恒代可能会被占满,会触发 Full GC。如果通过 Full GC 依然回收不了,那么 JVM 会抛出如下错误信息:java.lang.OutOfMemoryError: PermGen space
- CMS GC 时呈现
promotion failed
和concurrent mode failure
promotion failed,就是上文所说的担保失败,而 concurrent mode failure 是在执行 CMS GC 的过程中同时有对象要放入老年代,而此时老年代空间有余造成的。 - 统计失去的 Minor GC 降职到旧生代的均匀大小大于老年代的残余空间。
本文由 mdnice 多平台公布