"Неизвестная" ( "Другая" ) утечка памяти в 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
для определенных производителей.