java - Android 中的 `Unknown` ( `Other` ) 内存泄漏?

标签 java android memory-leaks

Android Studio Memory Profiler 在 Others 中报告分配情况类别。

enter image description here

根据 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类(class)。该参数报告为:

public int getSummaryPrivateOther() {
            return getTotalPrivateClean()
              + getTotalPrivateDirty()
              - getSummaryJavaHeap()
              - getSummaryNativeHeap()
              - getSummaryCode()
              - getSummaryStack()
              - getSummaryGraphics();
        }

哪种内存分配最终属于该类别?显然不是Java、Native、Code、Stack和Graphics。

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

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

Which kind of memory allocations end up in that category? It is obviously not Java, Native, Code, Stack and Graphics.

RAM 信息也可以使用 adb shell dumpsys meminfo <your proc name> 检索通常看起来像:

enter image description here

通过实验,我可以看到 Unknown很可能包含在 Private Other 中.这就引出了下一个问题:什么是 Unknown ?根据https://developer.android.com/studio/command-line/dumpsys.html#meminfo :

Any RAM pages that the system could not classify into one of the other more specific items. Currently, this contains mostly native allocations, which cannot be identified by the tool when collecting this data due to Address Space Layout Randomization (ASLR). Like the Dalvik heap, the Pss Total for Unknown takes into account sharing with Zygote, and Private Dirty is unknown RAM dedicated to only your app.

看起来它仍然是 native 分配。可识别的 native 分配最终在 Native 中然而,由于 ASLR 的原因,其数据不再可识别的 native 分配似乎最终出现在 Unknown 中。 .

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

If my app (with enormously large codebase so I can't really pin point a certain code that causes it) consumes a lot of Other memory, is there a certain source/pattern that leads to such consumption? I'm looking for answers such as hanging threads, open cursors, webviews and etc.

最佳答案

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

以下示例代码将导致在 HTC One API 19 上消耗大约 100mbunknown 内存,在 Samsung Galaxy Note 4 上消耗大约 120mb (API23) 和大约 94mb 在 Samsung Galaxy S8 (API-24) 上:

    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
    }

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

while sleep 1; do adb shell dumpsys meminfo com.dkarmazi.memoryleakerapp | grep Unknown; done

输出:

enter image description here

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

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

TLDR:启用JavascriptWebView 是一种常见用例,会导致某些制造商消耗大量未知 内存.

2018-07-23 更新:chromium bug tracker 上有一个 Unresolved 问题,与此调查直接相关:https://bugs.chromium.org/p/chromium/issues/detail?id=819901

TL;DR:只有某些版本的 WebView (>52) 会导致高内存消耗,而较旧的 WebView 没问题。原因仍然未知。

关于java - Android 中的 `Unknown` ( `Other` ) 内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47839681/

相关文章:

Java:使用等于覆盖从列表中删除对象

Android Mosby MVI 绑定(bind)到演示者中的服务

C++ 是内存泄漏吗?指向在另一个函数中动态分配的数组的指针

java - 如何设置 Java 数组长度

java - 如何根据可用的可见空间调整特定组件的大小?

android - 在 xamarin 中使用交错网格

java - Android 中动态删除选项卡

ios - 潜在的内存泄漏 - 收到内存警告

c++ - 内存泄漏预防 C++(我是对还是错?)

java - 正则表达式获取一个或两个分隔符之间的字符串