StrictMode分析Activity泄漏-StrictMode原理(3)

本文深入探讨了StrictMode如何检测Activity的内存泄漏,通过引用计数法来监控Activity的生命周期。在启动和销毁Activity时调整计数,并在发现实例数量超过预期时触发泄漏检查。通过对实例计数的增加和减少实现,以及GC后的引用计数验证,确保Activity的正确管理,防止内存泄漏的发生。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

3. Activity的泄漏

StrictMode对于Activity的泄漏检测也是有的。

泄漏的日志:

 D/StrictMode: StrictMode policy violation: android.os.strictmode.InstanceCountViolation: class com.ifreedomer.strictmode.activity.TestLeakedActivity; instances=3; limit=1
        at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)

StrictMode的activity泄漏检测,用的是引用计数法,大致思路分为三步:

  1. 使用map存储Activity的类与计数Map<Class,Count>
StrictMode.java
private static final HashMap<Class, Integer> sExpectedActivityInstanceCount = new HashMap<>();
  1. 在Activity启动阶段增加计数
ActivityThread.java
/**  Core implementation of activity launch. */
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
            StrictMode.incrementExpectedActivityCount(activity.getClass());
        }
  1. 在Activity的回收阶段减少计数
ActivityThread.java
/** Core implementation of activity destroy call. */
    void performDestroyActivity(ActivityClientRecord r, boolean finishing,
            int configChanges, boolean getNonConfigInstance, String reason) {
        StrictMode.decrementExpectedActivityCount(activityClass);
    }

3.1 增加计数实现

  1. 是否开启了检测开关
  2. 是否有计数,如果有+1
  3. 放回map
    public static void incrementExpectedActivityCount(Class klass) {
        if (klass == null) {
            return;
        }

        synchronized (StrictMode.class) {
            if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
                return;
            }

            // Use the instance count from InstanceTracker as initial value.
            Integer expected = sExpectedActivityInstanceCount.get(klass);
            Integer newExpected =
                    expected == null ? InstanceTracker.getInstanceCount(klass) + 1 : expected + 1;
            sExpectedActivityInstanceCount.put(klass, newExpected);
        }
    }

3.2 减少计数实现

  1. 是否开启了检测开关
  2. 是否有计数,如果有-1
  3. GC
  4. 重新寻找是否有引用,有几个引用
  5. 引用大于计数,则认为有泄漏
    public static void decrementExpectedActivityCount(Class klass) {
        if (klass == null) {
            return;
        }

        final int limit;
        synchronized (StrictMode.class) {
            if ((sVmPolicy.mask & DETECT_VM_ACTIVITY_LEAKS) == 0) {
                return;
            }

            Integer expected = sExpectedActivityInstanceCount.get(klass);
            int newExpected = (expected == null || expected == 0) ? 0 : expected - 1;
            if (newExpected == 0) {
                sExpectedActivityInstanceCount.remove(klass);
            } else {
                sExpectedActivityInstanceCount.put(klass, newExpected);
            }

            // Note: adding 1 here to give some breathing room during
            // orientation changes.  (shouldn't be necessary, though?)
            limit = newExpected + 1;
        }

        // Quick check.
        int actual = InstanceTracker.getInstanceCount(klass);
        if (actual <= limit) {
            return;
        }

        System.gc();
        System.runFinalization();
        System.gc();
				//计算有几个引用
        long instances = VMDebug.countInstancesOfClass(klass, false);
        if (instances > limit) {
            onVmPolicyViolation(new InstanceCountViolation(klass, instances, limit));
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值