heap gc2

void dvmHeapScanMarkedObjects(void)

{

    GcMarkContext *ctx = &gDvm.gcHeap->markContext;

 

    assert(ctx->finger == NULL);

 

    /* The bitmaps currently have bits set for the root set.

     * Walk across the bitmaps and scan each object.

     */

    //ctx->bitmap用来标识是否可达

    //广度优先遍历所有对象是否可达

    dvmHeapBitmapScanWalk(ctx->bitmap, scanBitmapCallback, ctx);

 

    ctx->finger = (void *)ULONG_MAX;

 

    /* We've walked the mark bitmaps.  Scan anything that's

     * left on the mark stack.

     */

    processMarkStack(ctx);

}

 

void dvmHeapBitmapScanWalk(HeapBitmap *bitmap,

                           BitmapScanCallback *callback, void *arg)

{

    assert(bitmap != NULL);

    assert(bitmap->bits != NULL);

    assert(callback != NULL);

    uintptr_t end = HB_OFFSET_TO_INDEX(bitmap->max - bitmap->base);

    uintptr_t i;

    for (i = 0; i <= end; ++i) {

        unsigned long word = bitmap->bits[i];

        if (UNLIKELY(word != 0)) {

            unsigned long highBit = 1 << (HB_BITS_PER_WORD - 1);

                                                //找出实例基地址

            uintptr_t ptrBase = HB_INDEX_TO_OFFSET(i) + bitmap->base;

            void *finger = (void *)(HB_INDEX_TO_OFFSET(i + 1) + bitmap->base);

            while (word != 0) {

                                                                //最高位0的个数

                const int shift = CLZ(word);

                                                                //shift可能是object的个数

                                                                //难道bits里面存放的是每隔class对象的个数,借此找到对象的地址???

                                                                //object地址

                Object *obj = (Object *)(ptrBase + shift * HB_OBJECT_ALIGNMENT);

                (*callback)(obj, finger, arg);

                                                                //0操作

                word &= ~(highBit >> shift);

            }

            end = HB_OFFSET_TO_INDEX(bitmap->max - bitmap->base);

        }

    }

}

 

static void scanObject(const Object *obj, GcMarkContext *ctx)

{

    assert(obj != NULL);

    assert(obj->clazz != NULL);

    if (obj->clazz == gDvm.classJavaLangClass) {

        scanClassObject(obj, ctx);

    } else if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {

        scanArrayObject(obj, ctx);

    } else {

        scanDataObject(obj, ctx);

    }

}

static void scanClassObject(const Object *obj, GcMarkContext *ctx)

{

    assert(obj != NULL);

    assert(dvmIsClassObject(obj));

    assert(ctx != NULL);

    markObject((const Object *)obj->clazz, ctx);

    const ClassObject *asClass = (const ClassObject *)obj;

    if (IS_CLASS_FLAG_SET(asClass, CLASS_ISARRAY)) {

        markObject((const Object *)asClass->elementClass, ctx);

    }

    /* Do super and the interfaces contain Objects and not dex idx values? */

                //当前类的状态

    if (asClass->status > CLASS_IDX) {

        markObject((const Object *)asClass->super, ctx);

    }

    markObject((const Object *)asClass->classLoader, ctx);

                //扫描域和静态域

    scanFields(obj, ctx);

    scanStaticFields(asClass, ctx);

    if (asClass->status > CLASS_IDX) {

        scanInterfaces(asClass, ctx);

    }

}

static void scanDataObject(const Object *obj, GcMarkContext *ctx)

{

    assert(obj != NULL);

    assert(obj->clazz != NULL);

    assert(ctx != NULL);

    markObject((const Object *)obj->clazz, ctx);

                //扫描字段

    scanFields(obj, ctx);

                //如果是个引用

    if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISREFERENCE)) {

        delayReferenceReferent((Object *)obj, ctx);

    }

}

void dvmHeapProcessReferences(Object **softReferences, bool clearSoftRefs,

                              Object **weakReferences,

                              Object **finalizerReferences,

                              Object **phantomReferences)

{

    assert(softReferences != NULL);

    assert(weakReferences != NULL);

    assert(finalizerReferences != NULL);

    assert(phantomReferences != NULL);

    /*

     * Unless we are in the zygote or required to clear soft

     * references with white references, preserve some white

     * referents.

     */

    //部分时候会保存soft refs

    if (!gDvm.zygote && !clearSoftRefs) {

        preserveSomeSoftReferences(softReferences);

    }

    /*

     * Clear all remaining soft and weak references with white

     * referents.

     */

    //处理ref

    clearWhiteReferences(softReferences);

    clearWhiteReferences(weakReferences);

    /*

     * Preserve all white objects with finalize methods and schedule

     * them for finalization.

     */

    enqueueFinalizerReferences(finalizerReferences);

    /*

     * Clear all f-reachable soft and weak references with white

     * referents.

     */

    //Finalization改变了一些object的状态,重新处理soft refweak ref

    clearWhiteReferences(softReferences);

    clearWhiteReferences(weakReferences);

    /*

     * Clear all phantom references with white referents.

     */

    clearWhiteReferences(phantomReferences);

    /*

     * At this point all reference lists should be empty.

     */

}

static void clearWhiteReferences(Object **list)

{

    assert(list != NULL);

    GcMarkContext *ctx = &gDvm.gcHeap->markContext;

    size_t referentOffset = gDvm.offJavaLangRefReference_referent;

    while (*list != NULL) {

        Object *ref = dequeuePendingReference(list);

        Object *referent = dvmGetFieldObject(ref, referentOffset);

        if (referent != NULL && !isMarked(referent, ctx)) {

            /* Referent is white, clear it. */

            clearReference(ref);

                                                //soft ref队列,可用于检测soft ref是否被回收

            if (isEnqueuable(ref)) {

                enqueueReference(ref);

            }

        }

    }

    assert(*list == NULL);

}

Pending_next

//head--last  item1--head item2--head item3--head ...... last—head

void dvmHeapSweepSystemWeaks()

{

                //清空字符串池

    dvmGcDetachDeadInternedStrings(isUnmarkedObject);

                /*

                一个Dalvik虚拟机线程在执行JNI方法的时候,除了可能需要访问Java层的对象之外,

                还可能需要进行一些同步操作,也就是进行MonitorEnterMonitorExit操作。

                注意,MonitorEnterMonitorExitJava代码中的同步指令,用来实现synchronized代码块或者函数的。

                Dalvik虚拟机需要跟踪在JNI方法中所执行的MonitorEnter操作,

                也就是将被Monitor的对象添加到Monitor引用表中去,以便在JNI方法退出时,

                可以隐式地进行MonitorExit操作,避免出现不对称的MonitorEnterMonitorExit操作

                */

                //?

    dvmSweepMonitorList(&gDvm.monitorList, isUnmarkedObject);

                //清理jni中的弱引用

    sweepWeakJniGlobals();

}

void dvmHeapSweepUnmarkedObjects(bool isPartial, bool isConcurrent,

                                 size_t *numObjects, size_t *numBytes)

{

    uintptr_t base[HEAP_SOURCE_MAX_HEAP_COUNT];

    uintptr_t max[HEAP_SOURCE_MAX_HEAP_COUNT];

    SweepContext ctx;

    HeapBitmap *prevLive, *prevMark;

    size_t numHeaps, numSweepHeaps;

 

    numHeaps = dvmHeapSourceGetNumHeaps();

                //heap对象的basemaxcopy

    dvmHeapSourceGetRegions(base, max, numHeaps);

    if (isPartial) {

        assert((uintptr_t)gDvm.gcHeap->markContext.immuneLimit == base[0]);

        numSweepHeaps = 1;

    } else {

        numSweepHeaps = numHeaps;

    }

                //ctxobject的个数

    ctx.numObjects = ctx.numBytes = 0;

    ctx.isConcurrent = isConcurrent;

                //mark bitslive bits被交换过

                //此处又进行了第二次交换

    prevLive = dvmHeapSourceGetMarkBits();

    prevMark = dvmHeapSourceGetLiveBits();

    for (size_t i = 0; i < numSweepHeaps; ++i) {

        dvmHeapBitmapSweepWalk(prevLive, prevMark, base[i], max[i],

                               sweepBitmapCallback, &ctx);

    }

    *numObjects = ctx.numObjects;

    *numBytes = ctx.numBytes;

    if (gDvm.allocProf.enabled) {

        gDvm.allocProf.freeCount += ctx.numObjects;

        gDvm.allocProf.freeSize += ctx.numBytes;

    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值