内容来着《Java 程序员面试笔试宝典 第2版》
因为fullGC是用来清理整个堆空间—包括年轻代和永久代的,所以fullGC会造成很大的系统资源开销。因此,通常需要尽量避免fullGC操作。
下面介绍几种常见的fullGC产生的原因以及避免的方法。
(1)调用System.gc()方法会触发fullGC
因此,在编码的时候尽量避免调用这个方法。
(2)老年代(Old Generation)空间不足
由于老年代主要用来存储从年轻代转入的对象、大对象和大数组,因此,为了避免触发fullGC,应尽量做到让对象在Minor GC阶段被回收、不要创建过大的对象及数组。由于在Minor GC时,只有Survivor区放不下的对象才会被放入老年代,而此时只有老年代也放不下才会触发fullGC,因此,另外一种避免fullGC的方法如下所示:根据实际情况增大Survivor区、老年代空间或调低触发并发GC(并发垃圾回收)的比率。
(3)永久代(Permanent Generation)满永久代主要存放class相关的信息,当永久代满的时候,也会触发fullGC。为了避免这种情况的发生,可以增大永久代的空间(例如-XX:MaxPermSize=16m:设置永久代大小为16M)。为了避免Perm区满引起的fullGC,也可以开启CMS回收永久代选项(开启的选项为:-XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled)。CMS利用和应用程序线程并发的垃圾回收线程来进行垃圾回收操作。
需要注意的是,Java8中已经移除了永久代,新加了一个称为元数据区的native内存区,所以,大部分类的元数据都在本地内存中分配。