Home » Android » java – `Unknown` (`Other`) memory leak in Android?

java – `Unknown` (`Other`) memory leak in Android?

Posted by: admin May 14, 2020 Leave a comment

Questions:

Android Studio Memory Profiler reports allocations in Others category.

enter image description here

According to https://developer.android.com/studio/profile/memory-profiler.html: Other: Memory used by your app that the system isn’t sure how to categorize.

If we dig deeper, similar memory footprint information can be retrieved at runtime using https://developer.android.com/reference/android/os/Debug.MemoryInfo.html#getMemoryStat(java.lang.String)

It looks like Others in Android Studio Memory Profiler corresponds to summary.private-other in Debug.MemoryInfo class. That parameter is reported as:

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

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

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?

Edit 1
I was able to partially answer the first part my own question:

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

RAM info can also be retrieved using adb shell dumpsys meminfo <your proc name> and typically looks like:

enter image description here

Experimentally, I can see that Unknown is most likely included into Private Other. Which raises the next question: what is Unknown? According to 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.

It looks like it’s still native allocations. Identifiable Native allocations end up in Native category, however, Native allocations whose data is no longer identifiable due to ASLR seem to end up in Unknown.

The main question however still holds:

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.

How to&Answers:

After many hours of research, I’ve finally found one common pattern that leads to high Unknown memory consumption: WebView with enabled Javascript.

The following sample code will lead to consuming about 100mb of unknown memory on HTC One API 19 and about 120mb on Samsung Galaxy Note 4 (API23) and about 94mb on 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
    }

The following command will output Unknown memory in kb category every second):

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

Output:

enter image description here

Now it raises a series of follow up questions which go beyond this particular issue:

  1. Does OS report WebView memory under Unknown in dumpsys meminfo on purpose or it’s a bug? If it’s a bug, is it specific to certain OS and API levels? If it is on purpose, then having 4-5 active WebViews will crash the app with very confusing traces.
  2. Is such high memory consumption for a modern typical webpage with javascript normal or there is also a bug that is triggered by certain javascript code? Experimentally, simpler sites like http://stackoverflow.com/ take 23mb. Pages with a richer user experience, like any news website, will take up to 120mb-130mb.

TLDR: WebView with enabled Javascript is one common use case that leads to consuming a lot of unknown memory on certain manufacturers.

Update 2018-07-23: There is an open issue on chromium bug tracker which is directly connected to this investigation: https://bugs.chromium.org/p/chromium/issues/detail?id=819901

TL;DR: only certain versions of WebView (>52) will cause high memory consumption while older WebViews are fine. The reason remains unknown.