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


    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)
    
    
    • 1
    • 2
    • 3

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

    1. 使用map存储Activity的类与计数Map<Class,Count>
    StrictMode.java
    private static final HashMap<Class, Integer> sExpectedActivityInstanceCount = new HashMap<>();
    
    • 1
    • 2
    1. 在Activity启动阶段增加计数
    ActivityThread.java
    /**  Core implementation of activity launch. */
        private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
                StrictMode.incrementExpectedActivityCount(activity.getClass());
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    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);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    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);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    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));
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
  • 相关阅读:
    正则表达式 test()方法
    nodejs微信小程序 +python+PHP- 校园志愿者管理系统的设计与实现-计算机毕业设计推荐
    python sympy求多元函数的梯度、Hessian矩阵
    二、vue基础语法
    基于CentOS 7.9离线安装CM6.3.1和CDH6.3.2大数据平台
    MySQL 事务知识点盘点
    java的集合
    35岁程序员危机,有何破解之法
    zk中session的基本原理、create、set、delete命令的使用(重补早期学习记录)
    2023-IDEA插件推荐
  • 原文地址:https://blog.csdn.net/aa375809600/article/details/125420073