一篇文章了解GC----jvm中Minor GC和Full GC/Major GC以及jdk1.8中默认GC

简述Java内存分配与回收策略以及Minor GC和Major GC

  • 对象优先在堆的Eden区分配
  • 大对象直接进入老年代
  • 长期存活的对象将直接进入老年代

  当Eden区没有足够的空间进行分配时,虚拟机会执行一次Minor GC。Minor GC通常发生在新生代的Eden区,在这个区的对象生存期短,往往发生GC的频率较高,回收速度比较快。Full GC/Major GC发生在老年代,一般情况下,触发老年代GC的时候不会触发Minor GC,但是通过配置,可以在Full GC前执行一次Minor GC,这可以可以加快老年代的回收速度。对于jdk8之前,垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。jdk8已经移除了永久代,新加了元数据区。

垃圾收集方法有哪些

  标记-清除:这是垃圾收集算法中最基础的,根据名字就可以知道,它的思想就是标记哪些对象需要回收,然后统一回收。这种方法很简单,但是会有两个主要问题:
1:效率不高,标记和清除的效率都很低。
2:会产生大量不连续的内存碎片,导致以后程序在分配较大的对象时,由于没有充足的连续内存而提前触发一次GC操作。

  复制算法:为了解决效率问题,复制算法将可用内存按容量划分为相等的两部分,然后每次只使用其中的一块,当一块内存用完时,就将还存活的对象复制到第二块内存上,然后一次性清除完第一块内存,再将第二块上的对象复制到第一块。但是这种方式,内存的代价太高,每次都要浪费一半的内存。于是将该算法进行了改进,内存区域不再是按照1:1去划分,而是将内存划分为8:1:1三部分,较大那份内存叫Eden区,如果Eden区满了,那就将对象复制到第二块内存区上,然后清除Eden区,如果此时对象存活的太多,以至于Survivor不够时,会将这些对象通过分配担保机制复制到老年代中。

  标记-整理:该算法主要是为了解决标记-清除产生大量内存碎片的问题。当对象存活率较高时,也解决了复制算法的效率问题。它的不同之处就是在清理对象的时候将可回收对象移动到一端,然后清除掉端边界以外的对象,这样就不会产生内存碎片了。

  分代收集:现在的虚拟机垃圾收集大多采用这种方式,它根据对象的生存周期,将堆分为新生代和老年代。在新生代中,由于对象生存期短,每次回收都会有大量对象死去,那么这时就采用复制算法。老年代里的对象存活率较高,没有额外的空间进行分配担保。

JDK8默认收集器

jdk8默认是UseParallelGC,UseParallelGC 表示Parallel Scavenge+ Serial Old。

总结

  survivor设置2个内存区是为了解决内存碎片化的问题。至于为什么不整三个,应该是不想让每个survivor区过小。survivor满了不会引起Minor GC,只有Eden区满了才会。有意思的是,survivor中的对象每熬过一次Minor GC,它的年龄就会加一岁。我们可以通过设置这个年龄,来决定它什么时候进入老年代。jdk8只有新生代和老年代,永生代移除。

猜你喜欢

转载自blog.csdn.net/qq_39753008/article/details/107862995