• 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
  • 相关阅读:
    Python Opencv实践 - 霍夫圆检测(Hough Circles)
    第21章_瑞萨MCU零基础入门系列教程之事件链接控制器ELC
    math标准库的一些函数介绍
    PlanetScale云数据库
    设计模式 --- 适配器模式 Adapter Pattern
    菜鸟学Kubernetes(K8s)系列——(三)关于Service、Ingress
    VisualStudio 制作Dynamic Link Library动态链接库文件
    短视频矩阵系统,短视频矩阵源码技术
    uniapp小程序与webview通信
    STM32CubeMX配置-RTC周期唤醒
  • 原文地址:https://blog.csdn.net/aa375809600/article/details/125420073