如何测量Android应用程序数据大小并识别存储泄漏?

如何测量Android应用程序数据大小并识别存储泄漏?,android,sqlite,caching,storage,Android,Sqlite,Caching,Storage,我制作了一个小的Android应用程序,并且已经使用了一段时间了。我注意到,在设置中,在我的应用程序特征的“数据”行上(我对分析“应用程序”行或“缓存”行上显示的数量不感兴趣),它显示了大约20MB,这对我来说似乎很重要。我担心该应用程序存在存储泄漏(即,它生成的数据永远不会被擦除) 我决定调查和测量可能占用这么多空间的东西。我在这个应用程序中使用了很多东西:SQLite DB、内部文件、外部文件、共享首选项(以及缓存文件,包括图片加载) 到目前为止,多亏了,我发现我的DB文件大约需要500 k

我制作了一个小的Android应用程序,并且已经使用了一段时间了。我注意到,在设置中,在我的应用程序特征的“数据”行上(我对分析“应用程序”行或“缓存”行上显示的数量不感兴趣),它显示了大约20MB,这对我来说似乎很重要。我担心该应用程序存在存储泄漏(即,它生成的数据永远不会被擦除)

我决定调查和测量可能占用这么多空间的东西。我在这个应用程序中使用了很多东西:SQLite DB、内部文件、外部文件、共享首选项(以及缓存文件,包括图片加载)

到目前为止,多亏了,我发现我的DB文件大约需要500 kB。通过递归扫描文件夹
getFilesDir()
中的文件和文件夹,我发现我在内部和应用程序私有外部文件中使用了10 kB的数据。我还没有分析共享首选项的大小,但我存储的键/值对不到20对

浏览文件夹
getCacheDirs()
我还发现Glide使用了大约3MB的缓存(接近Android设置应用程序的要求)

我的问题是,我错过了哪些线索来找到我找不到的这19.5 MB数据的位置?我是否忘记了某种可能占用空间的存储?而且,更一般地说,是否有工具来分析存储泄漏(即应用程序生成的可能永远不会被擦除的数据)?

您可以用于优化应用程序中的内存/大小问题。它显示应用程序中使用更多内存的部分。

在Android studio中运行你的应用程序,然后转到工具->Android->AndroidDeviceMonitor,运行你的场景,然后在设备监视器中单击下载你的应用程序。hprof文件,方法是按照下面我所附的图片进行下载

之后,您需要使用hprof-conv.exeinsidesdk->platform tools将Android studio.hprof文件转换为Eclipse Mat支持的.hprof文件 并在你的指令提示中遵循指令

F:\Android_Studio_SDK\platform-tools>hprof-conv "C:\Users\Bala\Desktop\your_AS_file.hprof" "C:\Users\Bala\Desktop\MAT_File_Name.hprof"
MAT-Tool中,转到文件->OpenHeapDump打开你的.hprof文件,它将按包、类、对象等显示你的应用程序内存利用率

了解MAT工具的一些参考链接


根据@James的建议,我开始探索不同的文件夹,在与同事讨论这个问题并尝试探索许多文件夹后,我最终发现大部分数据来自我以前的Webview的缓存。我正在公布我所有的调查结果,希望能有所帮助

当应用程序启动时,我执行了以下代码,从我的主要活动中调用了
analyseStorage(this)

public void analyseStorage(Context context) {
  File appBaseFolder = context.getFilesDir().getParentFile();
  long totalSize = browseFiles(appBaseFolder);
  Log.d(STORAGE_TAG, "App uses " + totalSize + " total bytes");
}

private long browseFiles(File dir) {
  long dirSize = 0;
  for (File f: dir.listFiles()) {
    dirSize += f.length();
    Log.d(STORAGE_TAG, dir.getAbsolutePath() + "/" + f.getName() + " uses " + f.length() + " bytes");
    if (f.isDirectory()) {
      dirSize += browseFiles(f);
    }
  }
  Log.d(STORAGE_TAG, dir.getAbsolutePath() + " uses " + dirSize + " bytes");
  return dirSize;
}
重要的是专门扫描与文件夹
/data/data/my.app.package/
匹配的
context.getFilesDir().getParentFile()

执行该代码后,我有以下日志:

D/storage﹕ /data/data/my.app.package/lib uses 0 bytes
D/storage﹕ /data/data/my.app.package/cache uses 3371773 bytes
D/storage﹕ /data/data/my.app.package/databases uses 483960 bytes
D/storage﹕ /data/data/my.app.package/shared_prefs uses 604 bytes
D/storage﹕ /data/data/my.app.package/app_webview uses 9139469 bytes
D/storage﹕ /data/data/my.app.package/files uses 7723 bytes
D/storage﹕ /data/data/my.app.package/app_ACRA-approved uses 0 bytes
D/storage﹕ /data/data/my.app.package/app_ACRA-unapproved uses 0 bytes
D/storage﹕ App uses 13003529 total bytes
我能看到的是:

  • 该缓存仅由Glide用于图片加载,占用3MB
  • SQLite数据库需要500kB
  • 共享首选项占用600B
  • 我以前拥有的所有网络视图的缓存仍然需要9MB
  • 其余的文件在
    文件
    和其他文件夹下,主要由ACRA用于缺陷跟踪,并占用10kB

最后,我终于发现我的大部分数据都进入了Webview缓存,实际上并没有显式存储为缓存。我删除了这些文件,实际上我的应用程序大小减少了20MB,甚至比上面列出的还要多。我现在知道了我的应用程序数据的数量级。

您可以使用类似Leak Canary的库自动检测应用程序中的所有内存泄漏:

您还可以在Android Studio中访问DDMS,无需编写任何代码即可获得应用程序中存储的更多信息。 然而,大多数泄漏都会被泄漏的金丝雀探测到


希望有帮助

没有存储泄漏

您没有将
odex
(dalvik)或
oat
(android运行时)文件计算在内。它们通常位于

/data/dalvik-cache/xxx.odex
/data/dalvik-cache/<target-architecture>/xxx.oat
/data/app/xxx.yyy.zzz.apk
如果设备没有根目录,则无法从adb外壳访问目录或文件

我认为在设置中显示的存储使用情况包括以下三个部分

/data/data/xxx.yyy.zzz
/data/app/xxx.yyy.zzz.apk
odex or oat file

因此,您在
/data/data/xxx.yyy.zzz
下计算的存储大小始终小于设置中的总大小。

是否使用adb@/data/…检查应用程序的默认数据路径?参考资料:@James谢谢,这些问题/答案很有用。/data//文件和/data//缓存分别由我已经检查过的getFilesDir()和getCacheDir()检索。但我将探索答案中列出的其他目录。我感谢您的努力,但我问的是数据存储,而不是内存。再次感谢您,但问题是关于存储,而不是内存泄漏。感谢您解释应用程序如何存储在设备上,但我的问题(我意识到它不清楚)与应用程序可执行文件的大小相比,更多的是由应用程序的使用生成的数据。我将更新我的问题,使之更清楚。