问题现象

(该文章,引自零号路的私人博客,本人在浏览框架的开发过程中,用该方式,规避了内存泄露的问题。)

在Android5.1系统中,会发现App存在 WebView 泄漏情况,还比较严重。并且只是发生在 Android 5.1 系统。

GC roots 如下:

每新打开一次这个WebViewActivity,就会发生就会发生一次改Webview实例无法释放,新增一个对象。

上图中的两个 AppSearchWebView实例,就是由于打开了两次导致。

问题分析

出现了这个问题分析起来还是比较简单的,根据这个引用关系,我们可以直观的看到是由于 Appsearch(extends Application)的 mComponentCallbacks 一直在强引用AWComponentCallbacks,导致无法释放。然后AWComponentCallbacks -> AWContents > AppSearchWebView。

通过分析代码发现关键在于 AwContents 这里的 AwComponentsCallbacks 为什么没有释放。

    @Override
    public void onAttachedToWindow() {
        if (isDestroyed()) return;
        if (mIsAttachedToWindow) {
            Log.w(TAG, "onAttachedToWindow called when already attached. Ignoring");
            return;
        }

		......

        mComponentCallbacks = new AwComponentCallbacks();
        mContext.registerComponentCallbacks(mComponentCallbacks);
    }

    @Override
    public void onDetachedFromWindow() {
        if (isDestroyed()) return;
        if (!mIsAttachedToWindow) {
            Log.w(TAG, "onDetachedFromWindow called when already detached. Ignoring");
            return;
        }
		......

        if (mComponentCallbacks != null) {
            mContext.unregisterComponentCallbacks(mComponentCallbacks);
            mComponentCallbacks = null;
        }

		......
    }

看这段代码看不出来什么问题,onAttach的时候 register,detach的时候 unregister, 不会存在问题。

但是为什么呢?

难道是由于 if (isDestroyed()) return 这条return引起的?

当调用 Webview.destroy() 后 这个判断 返回true。

我们看下哪里调用了 webview.destroy()

// source from WebViewActivity

@Override
protected void onDestroy() {
    super.onDestroy();

    if (mWebView != null) {
        mWebView.destroy();
    }
}

很多应用应该都是这么做的,包括系统浏览器,在Activity destroy的时候,调用 webview的destroy。并且一直工作的很好。

通过调试发现,确实是由于此调用导致的。onDestroy 发生在 onDetach 之前。

那为什么 android 5.1 之前的代码没有问题呢?

看下代码:

	// AwContents.java

    @Override
    public void onDetachedFromWindow() {
        if (!mIsAttachedToWindow) {
            Log.w(TAG, "onDetachedFromWindow called when already detached. Ignoring");
            return;
        }

		......

        if (mComponentCallbacks != null) {
            mContext.unregisterComponentCallbacks(mComponentCallbacks);
            mComponentCallbacks = null;
        }
		......
	}

相对于 5.1 的代码少了那句 if (isDestroyed()) return;

规避方法

  • 解决方案可以:在destroy之前,把webview 从 parent 中 remove 掉,同样可以提前detach。

      protected void onDestroy() {
          if (mWebView != null) {
              ((ViewGroup) mWebView.getParent()).removeView(mWebView);
              mWebView.destroy();
              mWebView = null;
          }
          super.onDestroy();
      }

Android5.1系统WebView内存泄漏场景的更多相关文章

  1. Android内存优化14 内存泄漏常见情况5 特殊对象造成的内存泄漏 WebView内存泄漏

    WebView造成内存泄露 关于WebView的内存泄露,因为WebView在加载网页后会长期占用内存而不能被释放,因此我们在Activity销毁后要调用它的destory()方法来销毁它以释放内存. ...

  2. 安卓android WebView Memory Leak WebView内存泄漏

    Android WebView Memory Leak WebView内存泄漏 在这次开发过程中,需要用到webview展示一些界面,但是加载的页面如果有很多图片就会发现内存占用暴涨,并且在退出该界面 ...

  3. Js中常见的内存泄漏场景

    常见的内存泄漏场景 内存泄漏Memory Leak是指程序中已动态分配的堆内存由于疏忽或错误等原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果.内存泄漏并非指内 ...

  4. js的内存泄漏场景、监控以及分析

    内存泄漏 Q:什么是内存泄漏? 字面上的意思,申请的内存没有及时回收掉,被泄漏了 Q:为什么会发生内存泄漏? 虽然前端有垃圾回收机制,但当某块无用的内存,却无法被垃圾回收机制认为是垃圾时,也就发生内存 ...

  5. Android WebView Memory Leak WebView内存泄漏

    在这次开发过程中,需要用到webview展示一些界面,但是加载的页面如果有很多图片就会发现内存占用暴涨,并且在退出该界面后,即使在包含该webview的Activity的destroy()方法中,使用 ...

  6. JVisualVM 模拟一次内存泄漏场景分析

    首先贴一段内存泄漏的代码并且执行.(内存泄漏:GC回收不掉的实例对象) package com.example.demo.memoryLeakDemo; import com.example.demo ...

  7. 系统剖析Android中的内存泄漏

    [转发]作为Android开发人员,我们或多或少都听说过内存泄漏.那么何为内存泄漏,Android中的内存泄漏又是什么样子的呢,本文将简单概括的进行一些总结. 关于内存泄露的定义,我可以理解成这样 没 ...

  8. 解决Android5.0以下Dialog引起的内存泄漏

    最近项目开发中,开发人员和测试人员均反应在android5.0以下手机上LeakCanary频繁监控到内存泄漏,如下图所示,但凡用到Dialog或DialogFragment地方均出现了内存泄漏. 如 ...

  9. Android开发之漫漫长途 番外篇——内存泄漏分析与解决

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

随机推荐

  1. Java中的最值

    Double.MAX_VALUE     等于 (2-2^(-52)) * 2^1023 约等于2^1024Double.MIN_VALUE      最小正非零值 2^(-1074)Long.MAX ...

  2. Java在已存在的pdf文件中生成文字和图片--基础

    自我总结,有什么不足之处请告知,感激不尽!下一次总结pdf模板映射生成报表(应对多变的pdf报表需求,数据提供和报表生成解耦). 目的:在给定的pdf模板上生成报表,就需要知道最基本的操作:文字添加, ...

  3. z3 巧解CTF逆向题

    z3 巧解逆向题 题目下载链接:http://reversing.kr/download.php?n=7 这次实验的题目为Reversing.kr网站中的一道题目. 题目要求: ReversingKr ...

  4. vue项目实战总结

    马上过年了,最近工作不太忙,再加上本人最近比较懒,毫无斗志,不愿学习新东西,或许是要过年的缘故(感觉像是在找接口). 就把前一段时间做过的vue项目,进行一次完整的总结. 这次算是详细总结,会从项目的 ...

  5. Android Studio 3.1 Beta 1发布,如何及时下载更新

    每次收到Android Studio更新提示,总是延迟一段时间才能下载的到或者更新成功.架梯子也不行.而且更新检测也是时断时续.Android Studio 3.0.1使用一段时间,多开几个工程.经常 ...

  6. BZOJ 4518: [Sdoi2016]征途 [斜率优化DP]

    4518: [Sdoi2016]征途 题意:\(n\le 3000\)个数分成m组,一组的和为一个数,求最小方差\(*m^2\) DP方程随便写\(f[i][j]=min\{f[k][j-1]+(s[ ...

  7. Google chrome浏览器中通过扩展调用本地应用程序以及和程序相互通讯(C++)

    最近项目用到浏览插件的开发,IE用到的是BHO,chrome打算做成扩展. 但是和ie有一点不同,chrome扩展是基于html+js+css开发的,那么就会有二个问题 1. 代码和算法等容易被别人复 ...

  8. 简述java中equals()方法和==的区别

    ==与equals的主要区别是: ==: ==常用于比较原生类型(基本数据类型):byte,short,char,int,long,float,double,boolean,比较的是他们的值. 若用= ...

  9. tcp_sync_server and tcp_sync_client

    #include <iostream> #include <fstream> #include <sstream> #include <boost/asio. ...

  10. 零基础2018如何系统地学习python?

    首先告诉你的是,零基础学习开始系统学习Python肯定难,Python的专业程度本身就不简单,学习这事本来就是一件非常煎熬的事情,人都不愿意学习,可是没办法,为了生存掌握一个技能,你必须学,如果你认真 ...