JVM-典型的垃圾收集器

从前面的博客知道,类实例化产生的对象在堆区中存储,而堆区不可能无限大,因此需要有垃圾收集器。[color=red]JVM的垃圾收集器干两件事:
1 碎片整理:整理内存碎片
2 垃圾回收:以某种算法发现垃圾,并使用某种算法清除垃圾。[/color]

[color=red]JVM常见的垃圾发现算法包括引用计数和追踪[/color]。其中,[b]引用计数[/b]就是为每个对象维护一个数字,这个数字记录了当前对象被引用的次数。当这个数字变为0的时候,说明该对象可以被垃圾回收了。但是引用计数无法发现那些循环引用的垃圾对象,比如垃圾对象a和垃圾对象b,两者互相引用,这个时候,虽然他们都是垃圾,但由于引用计算都是1,因此无法被发现。
此时,可以使用[b]追踪算法[/b],JVM会维护一个从根节点开始的对象引用图,当需要垃圾收集的时候,会从根节点开始追踪。能追踪到的对象会被打上标记。当追踪结束的时候,还没有被标记的对象可以被回收。

下面介绍一个典型的分代垃圾收集算法:
在这种垃圾收集机制下,[b]jvm的堆区被分为young代,old代和永久代[/b]。这里主要讨论young代和old代。如图所示:(年轻代包括Eden,和Survivor0,survivor1)

[img]http://dl2.iteye.com/upload/attachment/0116/6279/13db50bb-1f28-30dc-955f-46ee2c7e0d07.png[/img]

[img]http://dl2.iteye.com/upload/attachment/0116/6281/aeedcec2-0920-364b-b59a-05bd5a32c2be.png[/img]

当对象创建的时候,首先被放到Eden中(很大的对象有可能直接到old中),随着不断有对象被放入,当Eden满的时候,就会发生一次minor gc.在垃圾回收之前,JVM会使用垃圾发现算法,发现那些活着的对象(young代中活着的对象很少),然后将他们复制到S0区(如果S0放不下,会放到old代中),接着将Eden清空。

当再有对象被创建的时候,会放到Eden区中(很大的对象有可能直接到old中),当Eden满的时候,会发生一次minor gc.在垃圾回收之前,JVM会找出Eden和S0中活着的对象,然后将他们复制到S1中(如果S1放不下,会放到old代中),接着清空Eden和S0.

当再有对象被创建的时候,会放到Eden区中(很大的对象有可能直接到old中),当Eden满的时候,会发生一次minor gc.在垃圾回收之前,JVM会找出Eden和S1中活着的对象,然后将他们复制到S0中(如果S0放不下,会放到old代中),接着清空Eden和S1.

大家会发现,S0和S1中总有一个是空着的。当一个对象经历了多次gc(达到一定的阈值)仍然活着的时候,JVM就会考虑把他们放到old代中去。

我们需要做的就是使JVM尽可能少的发生old代的full gc.适当的发生young代的minor gc.因为在young中活着的对象很少,在gc前需要复制的对象很少。而在old中活着的对象很多,在gc前需要复制的对象很多,因此full gc会影响性能。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值