持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天,点击查看活动详情
面试官:JVM老年代的GC存在哪些问题?
频繁老年代gc问题
新生代gc一般问题不会太大,但是真正问题最大的地方,在于频繁触发老年代的GC。
对象进入老年代的几个条件:年龄太大了、动态年龄判断规则、新生代gc后存活对象太多无法放入Survivor中。
- 第一个,对象年龄太大了,这种对象一般很少,都是系统中确实需要长期存在的核心组件,他们一般不需要被回收掉,所以在新生代熬过默认15次垃圾回收之后就会进入老年代。
- 第二个,动态年龄判定规则,如果一次新生代gc过后,发现Survivor区域中的几个年龄的对象加起来超过了Survivor区域的50%,比如说年龄1+年龄2+年龄3的对象大小总和,超过了Survivor区域的50%,此时就会把年龄3以上的对象都放入老年代。
- 第三个,新生代垃圾回收过后,存活对象太多了,无法放入 Surviovr中,此时直接进入老年代。
其实上述条件中,第二个和第三个都是很关键的,通常如果新生代中的Survivor区域内存过小,就会导致上述第二个和第三个条件频繁发生,然后导致大量对象快速进入老年代,进而频繁触发老年代的gc。老年代gc通常来说都很耗费时间,无论是CMS垃圾回收器还是G1垃圾回收器,因为比如说CMS就要经历初始标记、并发标记、重新标记、并发清理、碎片整理几个环节,过程非常的复杂,G1同样也是如此。
通常来说,老年代gc至少比新生代gc慢10倍以上,比如新生代gc每次耗费200ms,其实对用户影响不大,但是老年代每次gc耗费2s,那可能就会导致老年代gc的时候用户发现页面上卡顿2s,影响就很大了。所以一旦因为jvm内存分配不合理,导致频繁进行老年代gc,比如说几分钟就有一次老年代gc,每次gc系统都停顿几秒钟,那简直对系统就是致命的打击。此时用户会发现页面上或者APP上经常性的出现点击按钮之后卡顿几秒钟。
面试官:JVM性能优化到底在优化什么?
其实说白了,系统真正最大的问题,就是因为内存分配、参数设置不合理,导致你的对象频繁的进入老年代,然后频繁触发老年代gc,导致系统频繁的每隔几分钟就要卡死几秒钟。
这就是所谓JVM的性能问题,也是所谓的JVM性能优化到底在优化什么东西!
名词解释
- Minor GC / Young GC:“新生代”也可以称之为“年轻代”,这两个名词是等价的。那么在年轻代中的Eden内存区域被占满之后,实际上就需要触发年轻代的gc,或者是新生代的gc。此时这个新生代gc,其实就是所谓的“Minor GC”,也可以称之为“Young GC”,这两个名词,说白了,就专门针对新生代的gc。
- Full GC:Full GC指的是针对新生代、老年代、永久代的全体内存空间的垃圾回收,所以称之为Full GC。从字面意思上也可以理解,“Full”就是整体的意思,所以就是对JVM进行一次整体的垃圾回收,把各个内存区域的垃圾都回收掉。但是说实话,不同的名词如何定义每个人都有自己的看法,有些人,平时有一定的习惯是把Full GC直接等价为Old GC的,也就是仅仅针对老年代的垃圾回收。但是如果从字面意义上来理解,建议把Full GC理解为针对JVM内所有内存区域的一次整体垃圾回收。
- Major GC:还有一个名词是所谓的Major GC,这个其实一般用的比较少,他也是一个非常容易混淆的概念。有些人把Major GC跟Old GC等价起来,认为他就是针对老年代的GC,也有人把Major GC和Full GC等价起来,认为他是针对JVM全体内存区域的GC。所以针对这个容易混淆的概念,建议少提。如果听到有人说这个Major GC的概念,可以问清楚,到底是想说Old GC呢?还是Full GC呢?
- Mixed GC:Mixed GC是G1中特有的概念,其实说白了,主要就是说在G1中,一旦老年代占据堆内存的45%了,就要触发Mixed GC,此时对年轻代和老年代都会进行回收。这个概念很好理解,只要知道是G1中特有的名词即可。