Java JVM:垃圾回收问题

包括:

一. 垃圾回收基本概念

二. GC日志


一. 垃圾回收基本概念

        垃圾回收也就是GC。那么GC 在什么时候,对什么东西,做了什么事情

1.1 在什么时候

        首先需要知道,GC又分为minor GC 和 Full Gc。Java 堆内存分为新生代和老年代,新生代中又分为1个Eden区域 和两个 Survivor区域,当Eden区域内存不足的时候,就会触发minor GC,当老年代内存不足的时候,就会触发Full GC。但是,具体到什么时刻执行,这个是由系统来进行决定,是无法预测的。


1.2 对什么东西

        主要根据可达性分析算法,如果一个对象不可达,那么就是可以回收的;如果一个对象可达,那么这个对象就不可以回收。对于可达性分析算法,它是通过一系列称为“GC Roots” 的对象作为起始点,当一个对象到 GC Roots 没有任何引用链相接的时候,那么这个对象就是不可达,就可以被回收。如下图1:

Java JVM:垃圾回收问题_第1张图片

图1

       这个GC Root 对象可以是一些静态的对象,Java方法的local变量或参数, native 方法引用的对象,活着的线程。


1.3 做了什么事情

       主要做了清理对象,整理内存的工作。Java堆分为新生代和老年代,采用了不同的回收方式。例如新生代采用了复制算法,老年代采用了标记整理法。在新生代中,分为一个Eden 区域和两个Survivor区域,真正使用的是一个Eden区域和一个Survivor区域,GC的时候,会把存活的对象放入到另外一个Survivor区域中,然后再把这个Eden区域和Survivor区域清除。那么对于老年代,采用的是标记整理法,首先标记出存活的对象,然后再移动到一端。这样也有利于减少内存碎片。


二. GC日志

Java JVM:垃圾回收问题_第2张图片
图3

Java JVM:垃圾回收问题_第3张图片

图4


Full GC 信息与 Minor GC 的信息是相似的,这里就不一个一个的画出来了。
       从 Full GC 信息可知,新生代可用的内存大小约为 18M,则新生代实际分配得到的内存空间约为 20M(为什么是 20M? 请继续看下面…)。老年代分得的内存大小约为 42M,堆的可用内存的大小约为 60M。可以计算出: 18432K ( 新生代可用空间 ) + 42112K ( 老年代空间 ) = 60544K ( 堆的可用空间 )
       新生代约占堆大小的 1/3,老年代约占堆大小的 2/3。也可以看出,GC 对新生代的回收比较乐观,而对老年代以及方法区的回收并不明显或者说不及新生代。并且在这里 Full GC 耗时是 Minor GC 的 22.89 倍。
 


总结:

  1. 主要回收场所:JVM方法区,JVM方法栈。
  2. 回收方式: 新生代(复制算法),老年代(标记整理法)。
  3. 根据Young / Old 判断是新生代还是老年代的 GC,然后就是给出 Young / Old ,整个堆内存 GC 前后的大小。 


参考:一个面试官对面试问题的分析

你可能感兴趣的:(Java,JVM,GCRoots,垃圾回收,GC日志)