JVM之垃圾回收过程

JVM之垃圾回收过程

 

为什么要垃圾回收

 

      前面谈到过,JVM中的设计是操作和数据分离,临时变量和操作运算在栈中运行,对象和数组存储在堆中,当栈运行完就会释放消耗的内存,但是堆不知道什么时候运行完,所以对象就会一直堆在那里越堆越多,直至内存被耗尽,幸好Java提供垃圾回收机制,将程序员从内存释放中解放出来,集中精力在业务开发上。

 

 

 

启动垃圾回收

 

System.gc() 和 Runtime.gc() 会向JVM发送GC的请求,但JVM不能保证一定会执行GC,因为一般GC的执行,都是因为内存不足引起的。

扫描二维码关注公众号,回复: 524570 查看本文章

 

 

 

垃圾回收的过程



 

  1. Eden:当对象创建后,会被存储在新生代的Eden区中
  2. Survivor(S0):当Eden满了,就会进行一个Minor GC,将存活的对象复制到S0,然后清空Eden
  3. Survivor(S1):当再次放生Minor GC时,就会对Edon和S0一起进行垃圾回收,将存活的对象复制到S1,然后清空Eden和S0
  4. 年轻代垃圾回收就是上面的三步,不断地复制清除
  5. 老年代:在年轻代中进行垃圾回收存活的对象有一个岁数,垃圾回收一次就会加一,默认值是15,当到达临界年龄,对象就会被复制到老年代
  6. 当老年代的被占满,无法再进入对象时,就会进行一次Full GC,这个垃圾回收的时间比较长

注意:大对象、大数组会直接晋升到老年代

   

 

 

GC触发的条件

 

  • Minor GC触发条件:大多数情况下,空间会在Eden进行分配。如果Eden没有足够空间,就会发起一次Minor GC
  • Full GC触发条件:同理,当老年代没有足够的空间时,进行一次Full GC(Full GC = Minor GC + Major GC)

实际上,GC的触发条件要更复杂:

 

在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象的总空间。如果大于则进行Minor GC,否则看HandlePromotionFailure设置是否允许担保失败(不允许则直接Full GC)。如果允许,会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于则尝试进行Minor GC(如果失败也会触发Full GC),如果小于则直接进行Full GC

 

 

 

哪些情况下会出现Full GC

 

  • 老年代空间不足,由于大对象,大数组可能会直接把老年代挤爆,所以减少使用大对象、大数组
  • 永久代空间满了,有加载的类、反射的类,调用的方法太多,导致永久代满了,所以要适当增大永久代
  • 新生代垃圾回收后,晋升到老年代的大小大于老年代的剩余空间
  • 设置Full GC的周期时间,如果是并行的话,设置MaxGCPauseMillis。

猜你喜欢

转载自youyu4.iteye.com/blog/2353904