Android中的"未知"("其他")内存泄漏?

dka*_*azi 11 java android memory-leaks

Android Studio Memory Profiler报告Others类别中的分配.

在此输入图像描述

根据https://developer.android.com/studio/profile/memory-profiler.html:其他:您的应用程序使用的内存,系统不确定如何分类.

如果我们深入挖掘,可以使用https://developer.android.com/reference/android/os/Debug.MemoryInfo.html#getMemoryStat(java.lang.String)在运行时检索类似的内存占用信息.

它看起来像Others在Android Studio Memory Profiler中对应summary.private-otherDebug.MemoryInfo类.该参数报告为:

public int getSummaryPrivateOther() {
            return getTotalPrivateClean()
              + getTotalPrivateDirty()
              - getSummaryJavaHeap()
              - getSummaryNativeHeap()
              - getSummaryCode()
              - getSummaryStack()
              - getSummaryGraphics();
        }
Run Code Online (Sandbox Code Playgroud)

哪种内存分配最终会出现在该类别中?它显然不是Java,Native,Code,Stack和Graphics.

如果我的应用程序(具有非常大的代码库,所以我无法确定某个导致它的特定代码)消耗大量Other内存,是否有某种源/模式导致这种消费?

编辑1 我能够部分回答第一部分我自己的问题:

哪种内存分配最终会出现在该类别中?它显然不是Java,Native,Code,Stack和Graphics.

也可以使用以下内容检索RAM信息adb shell dumpsys meminfo <your proc name>,通常如下所示:

在此输入图像描述

在实验上,我可以看到Unknown最有可能包括在内 Private Other.这提出了下一个问题:什么是Unknown?根据https://developer.android.com/studio/command-line/dumpsys.html#meminfo:

系统无法将任何RAM页面分类为其他更具体的项目之一.目前,这主要包含本机分配,由于地址空间布局随机化(ASLR),该工具在收集此数据时无法识别.就像Dalvik堆一样,Pss Total for Unknown考虑了与Zygote的共享,而Private Dirty是专门用于你的app的未知RAM.

它看起来仍然是原生分配.可识别的本机分配最终Native归类,但是,由于ASLR而无法识别其数据的本机分配似乎最终会出现Unknown.

然而,主要问题仍然存在:

如果我的应用程序(具有非常大的代码库,所以我无法确定某个导致它的特定代码)消耗大量Other内存,是否有某种源/模式导致这种消费?我正在寻找悬挂线程,打开游标,webviews等答案.

dka*_*azi 5

经过几个小时的研究,我终于找到了一种导致高Unknown内存消耗的常见模式:WebView启用Javascript.

以下示例代码将导致在 HTC One API 19 上消耗约100mb100内存,在 Samsung Galaxy Note 4 (API23) 上消耗约 20% 内存,在 Samsung Galaxy S8 (API-24) 上消耗约 10% 内存:unknown120mb94mb

    val webView1 = findViewById<WebView>(R.id.webview_1)
    webView1.settings.javaScriptEnabled = true
    webView1.webViewClient = WebViewClient()
    findViewById<Button>(R.id.load_webview_1).setOnClickListener {
        webView1.loadUrl("http://www.nbcsports.com/") // can be any arbitrary URL
    }
Run Code Online (Sandbox Code Playgroud)

以下命令将Unknown每秒输出 kb 类别的内存):

while sleep 1; do adb shell dumpsys meminfo com.dkarmazi.memoryleakerapp | grep Unknown; done
Run Code Online (Sandbox Code Playgroud)

输出:

在此输入图像描述

现在它提出了一系列超出这个特定问题的后续问题:

  1. 操作系统是否故意报告 WebView 内存不足Unknowndumpsys meminfo或者这是一个错误?如果这是一个错误,它是否特定于某些操作系统和 API 级别?如果是故意的,那么有 4-5 个 activeWebView就会使应用程序崩溃,并留下非常混乱的痕迹。
  2. 对于带有 javascript 的现代典型网页来说,如此高的内存消耗是正常的还是存在由某些 javascript 代码触发的错误?实验上,更简单的网站,如http://stackoverflow.com/take 23mb。与任何新闻网站一样,具有更丰富用户体验的页面将占用120mb-130mb.

TLDR:WebView启用是一种常见用例,会导致某些制造商Javascript消耗大量内存。unknown

2018 年 7 月 23 日更新:Chromium Bug Tracker 上有一个未解决的问题,该问题与本次调查直接相关:https://bugs.chromium.org/p/chromium/issues/detail ?id=819901

TL;DR:只有某些版本的 WebView (>52) 会导致高内存消耗,而较旧的 WebView 则没问题。原因尚不清楚。