Java `Android中未知的“(`Other`)内存泄漏?
Android Studio内存探查器报告Java `Android中未知的“(`Other`)内存泄漏?,java,android,memory-leaks,Java,Android,Memory Leaks,Android Studio内存探查器报告其他类别中的分配 根据:其他:系统不确定如何分类的应用程序使用的内存 如果我们深入研究,可以在运行时使用 Android Studio内存分析器中的Others与Debug.MemoryInfo类中的summary.private other相对应。该参数报告为: public int getSummaryPrivateOther() { return getTotalPrivateClean() +
其他
类别中的分配
根据:其他:系统不确定如何分类的应用程序使用的内存
如果我们深入研究,可以在运行时使用
Android Studio内存分析器中的Others
与Debug.MemoryInfo
类中的summary.private other
相对应。该参数报告为:
public int getSummaryPrivateOther() {
return getTotalPrivateClean()
+ getTotalPrivateDirty()
- getSummaryJavaHeap()
- getSummaryNativeHeap()
- getSummaryCode()
- getSummaryStack()
- getSummaryGraphics();
}
哪种内存分配最终属于该类别?它显然不是Java、本机、代码、堆栈和图形
如果我的应用程序(代码库非常大,因此我无法真正确定导致它的特定代码)消耗了大量的其他内存,那么是否存在导致这种消耗的特定源/模式
编辑1
我能够部分回答第一部分我自己的问题:
哪种内存分配最终属于该类别?它是
显然不是Java、本机、代码、堆栈和图形
RAM信息也可以使用adb shell dumpsys meminfo来检索,通常如下所示:
通过实验,我可以看出,未知
很可能包含在私有其他
中。这就引出了下一个问题:未知
?根据:
系统无法分类为其中一个的任何RAM页
其他更具体的项目。目前,它主要包含本机代码
分配,收集时工具无法识别分配
这些数据是由于地址空间布局随机化(ASLR)造成的。像
Dalvik堆,未知的Pss总数考虑与共享
合子,和私人肮脏是未知的RAM专用于您的应用程序
看起来还是本地分配。可识别的本机分配以本机
类别结束,但是,由于ASLR,其数据不再可识别的本机分配似乎以未知
结束
然而,主要问题仍然存在:
如果我的应用程序(有非常大的代码库,所以我不能真的锁定点)
导致它的特定代码)会消耗大量的其他
内存
是否存在导致此类消费的特定来源/模式?我在寻找答案,比如挂线、打开游标、网络视图等等
经过数小时的研究,我终于找到了一种导致高未知
内存消耗的常见模式:WebView
启用Javascript
以下示例代码将导致在HTC One API 19上消耗约100mb的未知内存,在三星Galaxy Note 4(API23)上消耗约120mb的内存,在三星Galaxy S8(API-24)上消耗约94mb的内存:
输出:
现在,它提出了一系列后续问题,这些问题超出了这一特定问题的范围:
操作系统是否故意在dumpsys meminfo
中的Unknown
下报告WebView内存,还是它是一个bug?如果它是一个bug,它是否特定于某些操作系统和API级别?如果是故意的,那么使用4-5个活动的WebView
s将使应用程序崩溃,并留下非常混乱的痕迹
对于使用javascript的现代典型网页来说,如此高的内存消耗是正常的,还是存在由某些javascript代码触发的错误?实验上,像http://stackoverflow.com/
占用23mb
。与任何新闻网站一样,用户体验更丰富的页面将占用高达120mb-130mb的空间
TLDR:WebView
启用Javascript
是一种常见的使用案例,它会导致某些制造商消耗大量未知
内存。
更新2018-07-23:与本次调查直接相关的chromium bug tracker存在一个未决问题:
TL;DR:只有某些版本的WebView(>52)会导致高内存消耗,而旧版本的WebView则可以。原因不明。感谢您的调查,这是一个有趣的发现!
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
}
while sleep 1; do adb shell dumpsys meminfo com.dkarmazi.memoryleakerapp | grep Unknown; done