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内存。

  • 相关阅读:
    ABBYY FineReader 12如何识别包含非常规符号的文本
    如何使用ABBYY FineReader 12将JPEG文件转换成可编辑文本
    如何使用ABBYY FineReader 12将JPEG文件转换成Word文档
    ABBYY OCR技术教电脑阅读缅甸语(下)
    ABBYY OCR技术教电脑阅读缅甸语(上)
    ABBYY FineReader 12使用教程
    ABBYY FineReader Pro for Mac有哪些特性(下)
    ABBYY FineReader Pro for Mac有哪些特性(上)
    MyBatis foreach
    callback 回调函数
  • 原文地址:https://www.cnblogs.com/suiyilaile/p/15219181.html
Copyright © 2011-2022 走看看