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

  • 相关阅读:
    剑指 Offer 53
    Visual Studio Ultimate 2013
    手把手教你如何把java代码,打包成jar文件以及转换为exe可执行文件
    DirectX的Vertex Buffer顶点缓冲的理解和应用 Shader必知必会
    Qt5.2中的android环境搭建
    JavaScript的基础学习篇
    九月十月百度,迅雷,华为,阿里巴巴最新校招笔试面试三十题(10.18)
    十月下旬腾讯,网易游戏,百度迅雷校园招聘笔试题集锦(第271-330题)
    九月十月百度人搜,阿里巴巴,腾讯华为笔试面试八十题(第331-410题)
    十月上旬百度,阿里巴巴,迅雷搜狗最新面试七十题(第201-270题)
  • 原文地址:https://www.cnblogs.com/suiyilaile/p/15219181.html
Copyright © 2011-2022 走看看