JVM
2018-10-31 本文已影响0人
你比大笨钟还笨
一、JAVA虚拟机区分:
- 堆内存:年轻代(eden(对象优先分配在此处)、存活区)、老年代;
- 非堆内存:持久代,存放方法、动态的变量/常量、线程栈
二、分区目的
-
为什么要分为年轻代和老年代?
减少FGC的出现频率。 -
年轻代为什么要分为eden和存活区?
减少垃圾回收到老年代的速度。
三、YGC和FGC
-
YGC:只会在eden区满时触发YGC
eden区满时,触发YGC(垃圾回收),这时JVM会判断eden中的对象是否还有引用指向它,没有引用的回收掉,有引用的挪到存活区。
存活区:大小相等,位置互换。
第二次YGC时会把还在引用的对象挪到S1,然后判断S0里的对象是否已经引用完。如果引用完,则回收掉;若未引用完,则从S0挪到S1. -
FGC触发条件
- 老年代满了,会触发FullJC,这时触发FullJC是对整个堆内存(年轻代、老年代)和非堆内存(持久代)进行垃圾回收;
- 持久代(非堆内存)满了也会触发fullgc;
- 代码调用,人工执行system.gc runtime.cn 也会调用fullgc;
- 执行了悲观策略(基于一些框架的时候会触发悲观策略),例如 jmap -dump
- FGC可以关闭手动调用。
注:JVM调优时,尽量减少FGC的出现频率。因为FGC的时候会暂停线程引用,影响用户体验。YGC同
四、老年代
-
堆对象什么时候进入老年代?
- 长期存活的进入老年代:触发15次YGC还存活的对象,进入老年代;
- 大对象(存活区放不下)直接进入老年代。
-
老年代满了怎么办?
- 如果多次FGC后,FGC残留把老年代空间占满了,这时只能重启服务。
- 老年代满后会提示堆内存溢出。