zoukankan      html  css  js  c++  java
  • 内存泄露之LeakCanary原理简析

    1 监听Activity,Fragment生命周期

    在Android中,当一个Activity走完onDestroy生命周期后,说明该页面已经被销毁了,应该被系统GC回收。

    通过Application.registerActivityLifecycleCallbacks()方法注册Activity生命周期的监听,每当一个Activity页面销毁时候,获取到这个Activity去检测这个Activity是否真的被系统GC。

    2 监听是否GC回收

    在一个Activity执行完onDestroy()之后,将它放入WeakReference中,然后将这个WeakReference类型的Activity对象与ReferenceQueque关联。

    1. 检测该Activity是否系统回收,从弱引用队列ReferenceQueque分析关联对象,如果找到对象,说明已回收,未发生内存泄露。移除相应key。
    2. 如果未被回收,在ReferenceQueque中找不到关联对象,此时手动进行gc。
    3. 再次判断ReferenceQueque能否找到关联对象,若找不到,则发生内存泄露
    Retryable.Result ensureGone(final KeyedWeakReference reference, final long watchStartNanoTime) {
        long gcStartNanoTime = System.nanoTime();
        long watchDurationMs = NANOSECONDS.toMillis(gcStartNanoTime - watchStartNanoTime);
    
        removeWeaklyReachableReferences();
    
        if (debuggerControl.isDebuggerAttached()) {
          // The debugger can create false leaks.
          return RETRY;
        }
        if (gone(reference)) {
          return DONE;
        }
        gcTrigger.runGc();
        removeWeaklyReachableReferences();
        if (!gone(reference)) {
            long startDumpHeap = System.nanoTime();
            long gcDurationMs = NANOSECONDS.toMillis(startDumpHeap - gcStartNanoTime);
    
            File heapDumpFile = heapDumper.dumpHeap();
            if (heapDumpFile == RETRY_LATER) {
                // Could not dump the heap.
                return RETRY;
            }
            long heapDumpDurationMs = NANOSECONDS.toMillis(System.nanoTime() - startDumpHeap);
            heapdumpListener.analyze(
                new HeapDump(heapDumpFile, reference.key, reference.name, excludedRefs, watchDurationMs,
                gcDurationMs, heapDumpDurationMs));
        }
        return DONE;
    }
    
    private void removeWeaklyReachableReferences() {
        // WeakReferences are enqueued as soon as the object to which they point to becomes weakly
        // reachable. This is before finalization or garbage collection has actually happened.
        KeyedWeakReference ref;
        while ((ref = (KeyedWeakReference) queue.poll()) != null) {
            retainedKeys.remove(ref.key);
        }
    }
    
    private boolean gone(KeyedWeakReference reference) {
        return !this.retainedKeys.contains(reference.key);
    }

    知识点1:gc之后,jvm会回收弱引用的对象,即回收WeakReference类型的Activity对象,防止内存泄露

    知识点2:被回收的WeakReference类型的Activity对象,会被添加到ReferenceQueque中

    知识点3:软引用的对象,调用gc,只有在内存不足时,jvm才会回收

    3 分析泄露

    最后用HAHA这个开源库去分析dump之后的heap内存。

  • 相关阅读:
    node
    github
    [模块] pdf转图片-pdf2image
    python 15 自定义模块 随机数 时间模块
    python 14 装饰器
    python 13 内置函数II 匿名函数 闭包
    python 12 生成器 列表推导式 内置函数I
    python 11 函数名 迭代器
    python 10 形参角度 名称空间 加载顺序
    python 09 函数参数初识
  • 原文地址:https://www.cnblogs.com/suiyilaile/p/15219181.html
Copyright © 2011-2022 走看看