"Неизвестная" ( "Другая" ) утечка памяти в Android?

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-other в классе Debug.MemoryInfo. Этот параметр отображается как:

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

Какие распределения памяти попадают в эту категорию? Это, очевидно, не 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:

Любые страницы ОЗУ, которые система не могла классифицировать в одну из другие более конкретные предметы. В настоящее время это содержит в основном распределения, которые не могут быть идентифицированы инструментом при сборе эти данные из-за рандомизации макета адресного пространства (ASLR). Как Далвикская куча, Pss Total for Unknown учитывает совместное использование с Zygote и Private Dirty - это неизвестная оперативная память, предназначенная только для вашего приложения.

Похоже, что он все еще является родным распределением. Однако идентифицируемые собственные распределения заканчиваются в категории Native. Родные распределения, данные которых больше не идентифицируются из-за ASLR, похоже, заканчиваются на Unknown.

Основной вопрос, тем не менее, сохраняется:

Если мое приложение (с чрезвычайно большой базой кода, поэтому я не могу точно указать точку определенный код, который его вызывает) потребляет много памяти Other, является существует определенный источник/образец, который приводит к такому потреблению? Я ищу ответы, такие как зависание потоков, открытые курсоры, веб-просмотры и т.д.

Ответ 1

После многих часов исследований я наконец нашел один общий шаблон, который приводит к высокому потреблению памяти Unknown: WebView с включенным Javascript.

Следующий пример кода приведет к потреблению около 100mb памяти Unknown на HTC One API 19 и около 120mb на Samsung Galaxy Note 4 (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
    }

Следующая команда будет выводить Unknown память в категории kb каждую секунду):

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

Вывод:

введите описание изображения здесь

Теперь он поднимает ряд последующих вопросов, выходящих за рамки этой конкретной проблемы:

  • Указывает ли ОС на WebView память под Unknown в dumpsys meminfo с целью или это ошибка? Если это ошибка, она специфична для определенных уровней ОС и API? Если это специально, то с 4-5 активных WebView приведет к сбою приложения с очень запутанными трассами.
  • Является ли такое высокое потребление памяти для современной типичной веб-страницы с нормальным javascript или есть ошибка, вызванная определенным кодом javascript? Экспериментально более простые сайты, такие как http://stackoverflow.com/, принимают 23mb. Страницы с более богатым пользовательским интерфейсом, как и любой новостной сайт, занимают до 120mb-130mb.

TL;DR: WebView с включенным Javascript - один из распространенных вариантов использования, который приводит к потреблению большого количества памяти Unknown для определенных производителей.