Java虚拟机中的年轻代、老年代、永久代图解版

常见名词:年轻代、老年代、永久代、Minor GC、Full GC(也称Major GC)

Java堆内存图:

Java虚拟机中的年轻代、老年代、永久代图解版_第1张图片

 Java虚拟机中的年轻代、老年代、永久代图解版_第2张图片

堆内存分配:

  • 年轻代
    • Eden区
    • Survivor区
      • From(S0)
      • To(S1)
  • 老年代

年轻代

        java新生成的对象几乎都会存放在新生代的Eden区中(如果对象的占用内存较大则直接分配至老年代中),当Eden区内存不够的时候就会触发MinorGC(Survivor满不会引发MinorGC,而是将对象移动到老年代中)。

        在Minor GC开始的时候,对象只会存在于Eden区和Survivor from区,Survivor to区是空的。

        Minor GC操作后,Eden区如果仍然存活(判断的标准是被引用了,通过GC root进行可达性判断)的对象,将会被移到Survivor To区。而From区中,对象在Survivor区中每熬过一次Minor GC,年龄就会+1岁,当年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置,默认是15)的对象会被移动到年老代中,否则对象会被复制到“To”区。经过这次GC后,Eden区和From区已经被清空。

        “From”区和“To”区互换角色,原Survivor To成为下一次GC时的Survivor From区, 总之,GC后,都会保证Survivor To区是空的。

奇怪为什么有 From和To,2块区域?

        这就要说到新生代Minor GC的算法了:标记-复制算法

        把内存区域分为两块,每次使用一块,GC的时候把一块中的内容移动到另一块中,原始内存中的对象就可以被回收了,

优点:避免内存碎片。        

老年代

        Full GC 是发生在老年代的垃圾收集动作,所采用的是标记-清除算法

        现实的生活中,老年代的人通常会比新生代的人 “早死”。堆内存中的老年代(Old)不同于这个,老年代里面的对象几乎个个都是在 Survivor 区域中熬过来的,它们是不会那么容易就 “死掉” 了的。因此,Full GC 发生的次数不会有 Minor GC 那么频繁,并且做一次 Full GC 要比进行一次 Minor GC 的时间更长。 另外,标记-清除算法收集垃圾的时候会产生许多的内存碎片 ( 即不连续的内存空间 ),此后需要为较大的对象分配内存空间时,若无法找到足够的连续的内存空间,就会提前触发一次 GC 的收集动作。

你可能感兴趣的:(#,GC,java)