kvm垃圾收集-006

本文介绍kvm中垃圾收集中的sweep.sweep的意思是: 将垃圾对象清除(其实垃圾区域的对象还是存在的,但是由于没有对象引用,同时之后在分配对象时,会在这些区域分配,分配时会进行清零操作.因此,也就表现为实际清除了一样)。此处的代码如下:

static CHUNK
sweepTheHeap(long *maximumFreeSizeP)
{
    CHUNK firstFreeChunk = NULL;
    CHUNK newChunk;
    CHUNK* nextChunkPtr = &firstFreeChunk;
    bool_t done = FALSE;

    cell* scanner =  CurrentHeap; /* current object */
    cell* endScanPoint = CurrentHeapEnd;
    long maximumFreeSize = 0;
    long thisFreeSize;
    do {
        /* Skip over groups of live objects 1. 跳过存活的对象 */
        cell *lastLive;
        while (scanner < endScanPoint && ISKEPT(*scanner)) {
            *scanner &= ~MARKBIT; // 将标记位置0
            scanner += SIZE(*scanner) + HEADERSIZE;
        }
        lastLive = scanner;
        /* Skip over all the subsequent dead objects 2. 跳过所有的垃圾对象*/
        while (scanner < endScanPoint && !ISKEPT(*scanner)) {
#if INCLUDEDEBUGCODE
            if (tracememoryallocation && (TYPE(*scanner) != GCT_FREE)) {
                Log->freeObject((long)scanner,
                    (INSTANCE_CLASS)((OBJECT)(scanner + HEADERSIZE))->ofClass,
                    (long)SIZE(*scanner) + HEADERSIZE);
            }
#endif /* INCLUDEDEBUGCODE */
            scanner += SIZE(*scanner) + HEADERSIZE;
        }
        if (scanner == endScanPoint) {
            if (scanner == lastLive) {
                /* The memory ended precisely with a live object. 此时的情况是 内存中都是存活对象 */
                break;
            } else {
                done = TRUE;
            }
        }
        // 计算free 的大小
        thisFreeSize = (scanner - lastLive - 1);
        newChunk = (CHUNK)lastLive;
        newChunk->size = thisFreeSize << TYPEBITS;

        *nextChunkPtr = newChunk;
        nextChunkPtr = &newChunk->next;
        if (thisFreeSize > maximumFreeSize) {
            maximumFreeSize = thisFreeSize;
        }
    } while (!done);

    *nextChunkPtr = NULL;
    *maximumFreeSizeP = maximumFreeSize;
    return firstFreeChunk;
}

此处的代码比较简单.将垃圾对象所在的区域当做free 区.同时构建成free链表.另外此处还将存活对象的标记位置为0(以备下次gc时使用).

当sweep后,代码回到garbageCollectForReal方法.其代码如下:

 firstFreeChunk = sweepTheHeap(&maximumFreeSize);
#if ENABLE_HEAP_COMPACTION
    if (realSize > maximumFreeSize) {// 当heap 内最大的可用内存不满足要求时,需要进行压缩处理
        /* We need to compact the heap. */
        breakTableStruct currentTable;
        // 压缩
        cell* freeStart = compactTheHeap(&currentTable, firstFreeChunk);
        if (currentTable.length > 0) {
        	// 修改指针
            updateRootObjects(&currentTable);
            updateHeapObjects(&currentTable, freeStart);
        }
        
        // 压缩后,重新计算free 的大小.整理后, free 只有一块.
        if (freeStart < CurrentHeapEnd - 1) {
            firstFreeChunk = (CHUNK)freeStart;
            firstFreeChunk->size =
                (CurrentHeapEnd - freeStart - HEADERSIZE) << TYPEBITS;
            firstFreeChunk->next = NULL;
        } else {
            /* 
             * 没有空闲内存
             */
            firstFreeChunk = NULL;
        }
    }
#endif
    FirstFreeChunk = firstFreeChunk;

此时,如果sweep后最大的free chunk的大小不满足要求(realSize).则需要进行压缩.也就是将活动对象移动到一端.同时在移动的过程中要更新对象的引用(因为对象的位置变了)。同时, free chunk也就只有一个了(压缩的本来含义).

关于压缩的compactTheHeap, updateRootObjects等方法我们后续文章介绍…(这几个方法还是比较复杂的,就不在这里展开了)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值