jvm 中一次完整的 GC 流程是怎样的,对象如何晋升到老年代,说说你知道的几种主要的jvm 参数。
对象诞生即新生代->eden,在进行minor gc过程中,如果依旧存活,移动到from,变成Survivor,进行标记代数,如此检查一定次数后,晋升为老年代,
堆内存GC
JVM(采用分代回收的策略),用较高的频率对年轻的对象(young generation)进行YGC,而对老对象(tenured generation)较少(tenured generation 满了后才进行)进行Full GC。这样就不需要每次GC都将内存中所有对象都检查一遍。
非堆内存不GC
GC不会在主程序运行期对PermGen Space进行清理,所以如果你的应用中有很多CLASS(特别是动态生成类,当然permgen space存放的内容不仅限于类)的话,就很可能出现PermGen Space错误。
内存申请、对象衰老过程
一、内存申请过程
- JVM会试图为相关Java对象在Eden中初始化一块内存区域;
- 当Eden空间足够时,内存申请结束。否则到下一步;
- JVM试图释放在Eden中所有不活跃的对象(minor collection),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区;
- Survivor区被用来作为Eden及old的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区;
- 当old区空间不够时,JVM会在old区进行major collection;
- 完全垃圾收集后,若Survivor及old区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现"Out of memory错误";
并行收集会阻塞用户线程,所以一般常用并发垃圾回收,CMS G1
Full gc通常比Young gc慢10倍
ParNew + CMS 配合使用
Parallel Scavenge 达到一个可控制的吞吐量
CMS会占用一部分CPU资源,会导致吞吐量降低
会临时启用Serail Old收集器,导致另外一次Full GC的产生
GC停顿过长
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ParNew 回收器也是独占式的回收器,在收集过程中,应用程序会全部暂停。但是由于并行回收器使用多线程进行垃圾回收,因此在并发能力比较强的CPU上,它产生的停顿时间要短于串行回收器。在单CPU或者并发能力较弱的系统中,并行回收器的效果不会比串行回收器好。
并行线程默认值
CPU核数<=8:CPU核数?(3+CUP核数*5)/8