关闭

JVM-典型的垃圾收集器

127人阅读 评论(0) 收藏 举报
分类:
从前面的博客知道,类实例化产生的对象在堆区中存储,而堆区不可能无限大,因此需要有垃圾收集器。JVM的垃圾收集器干两件事:
1 碎片整理:整理内存碎片
2 垃圾回收:以某种算法发现垃圾,并使用某种算法清除垃圾。


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

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





当对象创建的时候,首先被放到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会影响性能。
  • 大小: 38.4 KB
  • 大小: 6.8 KB
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:119966次
    • 积分:1429
    • 等级:
    • 排名:千里之外
    • 原创:137篇
    • 转载:10篇
    • 译文:0篇
    • 评论:27条
    最新评论