NingG +

JVM 实践:浅析JVM中垃圾回收

Java内存分配和回收的机制概括的说,就是:分代分配,分代回收

Note:

分代策略,本质就是分级策略,同一类特征的堆内存对象(特征:对象存活时间),集中在一起,使用相同的垃圾回收策略,提升效率。

对象将根据存活的时间被分为:

新生代

新生代,被分为 3 个空间:

  1. Eden 区:新申请的对象,分配在 Eden 区
  2. Survivor 0 区:复制策略使用的复制区
  3. Survivor 1 区:复制策略使用的复制区

什么时候触发 Young GC?(Young GC,就是发生在新生代的 GC)

Young GC 的具体过程:

什么时候,对象进入老年代

详细说明:看下面

新生代(Young Generation):对象被创建时,内存的分配首先发生在新生代(大对象可以直接 被创建在老年代),大部分的对象在创建后很快就不再使用,因此很快变得不可达,于是被新生代的GC机制清理掉(IBM的研究表明,98%的对象都是很快消 亡的),这个GC机制被称为Minor GC或叫Young GC。新生代可以分为3个区域:Eden区和两个存活区(Survivor 0 、Survivor 1)。

  1. 绝大多数刚创建的对象会被分配在Eden区,其中的大多数对象很快就会消亡。Eden区是连续的内存空间,因此在其上分配内存极快;
  2. 当Eden区满的时候,执行Minor GC,将消亡的对象清理掉,并将剩余的对象复制到一个存活区Survivor0(此时,Survivor1是空白的,两个Survivor总有一个是空白的);
  3. 此后,每次Eden区满了,就执行一次Minor GC,并将剩余的对象都添加到Survivor0;
  4. 当Survivor0也满的时候,将其中仍然活着的对象直接复制到Survivor1,以后Eden区执行Minor GC后,就将剩余的对象添加Survivor1(此时,Survivor0是空白的)。
  5. 当两个存活区切换了几次(HotSpot虚拟机默认15次,用-XX:MaxTenuringThreshold控制,大于该值进入老年代)之后,仍然存活的对象(其实只有一小部分,比如,我们自己定义的对象),将被复制到老年代。

从上面的过程可以看出,Eden区是连续的空间,且Survivor总有一个为空。经过一次GC和复制,一个Survivor中保存着当前还活 着的对象,而Eden区和另一个Survivor区的内容都不再需要了,可以直接清空,到下一次GC时,两个Survivor的角色再互换。因此,这种方 式分配内存和清理内存的效率都极高,这种垃圾回收的方式就是著名的“停止-复制(Stop-and-copy)”清理法(将Eden区和一个Survivor中仍然存活的对象拷贝到另一个Survivor中),这不代表着停止复制清理法很高效,其实,它也只在这种情况下高效,如果在老年代采用停止复制,则挺悲剧的。

在Eden区,HotSpot虚拟机使用了两种技术来加快内存分配。分别是bump-the-pointerTLAB(Thread-Local Allocation Buffers) 线程本地分配缓存 ,这两种技术的做法分别是:

老年代

老年代(Old Generation):对象如果在新生代存活了足够长的时间而没有被清理掉(即在几次 Young GC后存活了下来),则会被复制到老年代,老年代的空间一般比新生代大,能存放更多的对象,在老年代上发生的GC次数也比新生代少。当老年代内存不足时, 将执行Major GC,也叫 Full GC。采用标记-整理算法。

什么时候触发 Full GC:老年代空间不足时,触发 Full GC,是发生在老年代的 GC

总之:Full GC 的时间,就是,有对象要进入老年代,但,老年代空间不足。

所以,

参考来源

Top