如何以编程方式找到我的Android应用程序上使用的内存?
我希望有一种方法可以做到。另外,我也该如何获得手机的空闲内存?
请注意,现代操作系统(如Linux)上的内存使用是一个极其复杂且难以理解的领域。实际上,你正确解释任何数字的机会非常低。(几乎每当我与其他工程师一起查看内存使用量数字时,对于它们的实际含义总会进行长时间的讨论,这只会导致模糊的结论。)
注意:我们现在有更多有关管理应用程序内存的文档,其中涵盖了许多内容,并且是有关Android状态的最新信息。
第一件事可能是阅读本文的最后部分,该部分讨论了如何在Android上管理内存:
从Android 2.0开始更改服务API
现在ActivityManager.getMemoryInfo()
是我们用于查看整体内存使用情况的最高级别的API。这主要是为了帮助应用程序评估系统将如何接近没有更多内存供后台进程使用,因此需要开始杀死所需的进程(如服务)。对于纯Java应用程序,这应该没有多大用处,因为Java堆限制在某种程度上避免了一个应用程序能够使系统承受这一压力。
进入较低级别,你可以使用Debug API获得有关内存使用情况的原始内核级别信息:android.os.Debug.MemoryInfo
请注意,从2.0开始,还有一个API ActivityManager.getProcessMemoryInfo
来获取有关另一个进程的此信息:ActivityManager.getProcessMemoryInfo(int [])
这将返回具有所有以下数据的低级MemoryInfo结构:
/** The proportional set size for dalvik. */
public int dalvikPss;
/** The private dirty pages used by dalvik. */
public int dalvikPrivateDirty;
/** The shared dirty pages used by dalvik. */
public int dalvikSharedDirty;
/** The proportional set size for the native heap. */
public int nativePss;
/** The private dirty pages used by the native heap. */
public int nativePrivateDirty;
/** The shared dirty pages used by the native heap. */
public int nativeSharedDirty;
/** The proportional set size for everything else. */
public int otherPss;
/** The private dirty pages used by everything else. */
public int otherPrivateDirty;
/** The shared dirty pages used by everything else. */
public int otherSharedDirty;
但是关于,和之间的区别是什么Pss
,现在好了。PrivateDirtySharedDirty
实际上,Android
(通常是Linux
系统)中的许多内存在多个进程之间共享。因此,一个进程使用多少内存确实不清楚。在将页面调度到磁盘的基础上再加上磁盘(更不用说我们在Android上不使用的交换)了,这甚至还不清楚。
因此,如果你要获取实际映射到每个进程中的所有物理RAM
,并将所有进程相加,那么最终结果可能会比实际总RAM大得多。
该Pss
数字是内核计算的考虑内存共享的度量标准-基本上,一个进程中RAM的每个页面都是按也使用该页面的其他进程数的比例来缩放的。这样,你可以(理论上)将所有进程的pss
相加,以查看它们正在使用的总RAM
,并比较各个进程之间的pss
,以大致了解它们的相对权重。
另一个有趣的指标是PrivateDirty
,它基本上是进程内无法分页到磁盘(不由磁盘上的相同数据支持)并且不与任何其他进程共享的RAM量。另一种看待这种情况的方式是,当该进程消失时,RAM将可供系统使用(并且可能很快被包含在缓存和其他用途中)。
这差不多就是SDK API。但是,作为设备开发人员,你可以做更多的事情。
使用adb
,你可以获得许多有关正在运行的系统的内存使用情况的信息。常见的命令adb shell dumpsys meminfo
是吐出有关每个Java进程的内存使用信息的信息,其中包含上述信息以及其他各种信息。你还可以添加单个进程的名称或pid来查看,例如,adb shell dumpsys meminfo system
给我系统进程:
** MEMINFO in pid 890 [system] **
native dalvik other total
size: 10940 7047 N/A 17987
allocated: 8943 5516 N/A 14459
free: 336 1531 N/A 1867
(Pss): 4585 9282 11916 25783
(shared dirty): 2184 3596 916 6696
(priv dirty): 4504 5956 7456 17916
Objects
Views: 149 ViewRoots: 4
AppContexts: 13 Activities: 0
Assets: 4 AssetManagers: 4
Local Binders: 141 Proxy Binders: 158
Death Recipients: 49
OpenSSL Sockets: 0
SQL
heap: 205 dbFiles: 0
numPagers: 0 inactivePageKB: 0
activePageKB: 0
顶部是主要部分,其中size是特定堆的地址空间中的总大小,allocated是堆认为具有的实际分配的kb,free是堆可用于其他分配的剩余kb,并且pss与priv dirty相同如前所述,专门针对与每个堆相关的页面。
如果只想查看所有进程的内存使用情况,则可以使用命令adb shell procrank。在同一系统上的输出如下所示:
PID Vss Rss Pss Uss cmdline
890 84456K 48668K 25850K 21284K system_server
1231 50748K 39088K 17587K 13792K com.android.launcher2
947 34488K 28528K 10834K 9308K com.android.wallpaper
987 26964K 26956K 8751K
7308K 24308s 24com google.google.com .android.phone
948 23020K 23016K 5864K 4748K com.android.inputmethod.latin
888 25728K 25724K 5774K 3668K zygote
977 24100K 24096K 5667K 4340K android.process.acore
...
59 336K 332K 99K 92K / system / bin /
installed 60 396K 392K 93K 84K / system / bin / keystore
51 280K 276K 74K 68K / system / bin / servicemanager
54 256K 252K 69K 64K / system / bin / debuggerd
这里的Vss
和Rss
列基本上是噪音(这些是进程的直接地址空间和RAM使用情况,如果你将各个进程之间的RAM使用情况相加,则会得到非常高的数字)。
Pss
正如我们之前所见,并且Uss
是Priv Dirty
。
在此需要注意的有趣事情:Pss
与Uss
我们在中看到的内容略有不同(或略有不同)meminfo。这是为什么?好procrank
使用的内核机制与收集数据的机制不同meminfo,它们给出的结果略有不同。这是为什么?老实说我没头绪。我相信procrank
可能是更准确的……但是,实际上,这就是要说的:“获取一粒盐得到的任何存储信息;通常是非常大的一粒。”
最后,该命令adb shell cat /proc/meminfo提供了系统整体内存使用情况的摘要。这里有很多数据,只有前几个值得讨论(剩下的几个人很少理解,而我对这几个人的问题经常会引起相互矛盾的解释):
MemTotal: 395144 kB
MemFree: 184936 kB
Buffers: 880 kB
Cached: 84104 kB
SwapCached: 0 kB
MemTotal 是内核和用户空间可用的内存总量(通常少于设备的实际物理RAM,因为无线电,DMA缓冲区等需要一些RAM)。
MemFree 是根本不使用的RAM数量。你在这里看到的数字很高;通常在Android系统上只有几MB,因为我们尝试使用可用内存来保持进程运行
Cached 是用于文件系统缓存和其他此类事物的RAM。典型的系统将需要大约20MB的内存,以避免陷入不良的分页状态。针对特定系统对Android内存不足杀手进行了调整,以确保在后台进程被缓存RAM占用过多而导致这种分页之前,后台进程被杀死。
问题内容: 您如何衡量Linux中应用程序或进程的内存使用情况? 从了解Linux上的内存使用的博客文章中可以看出,这不是用于此目的的准确工具。 为什么是“错” 根据您的看法,它不会报告进程的实际内存使用情况。它的真正作用是显示 如果 每个进程 是唯一运行的进程 , 则 每个进程将占用多少实际内存。当然,一台典型的Linux机器在任何给定时间都运行着几十个进程,这意味着报告的VSZ和RSS编号几乎
问题内容: 在Android应用中实施应用内结算似乎非常复杂。我该怎么办?SDK中的示例应用程序只有一个Activity,对于像我这样的具有多个Activity的应用程序来说,这过于简化了。 问题答案: 好吧,我将尝试解释我的经历。我不认为自己是专家,但是几天我都伤透了脑筋。 对于初学者来说,我很难理解示例和应用程序的工作流程。我认为从一个简单的示例开始应该会更好,但是将代码分成几小段并且不知道是
如何配置我的应用程序引擎应用程序的内存(RAM)使用情况?我试图解决与超过实例内存限制相关的错误。我尝试过这些东西,到目前为止,它们不起作用或者不能提供我需要的东西。 Appstats。这不提供内存使用的详细信息 以上任何一点我都错了吗?在这个问题上,评分最高的答案(不是公认的答案)表示没有办法监控App Engine上的内存使用情况。那不可能是真的。可以吗? 编辑 我可以确认GAE mini p
我们的Android应用程序有很多不同的设置。我们想简化它,只保持可见的最常用的和隐藏其他在一些高级模式。为了做到这一点,我们需要知道我们的用户主要使用的设置是什么。所以我们需要找到一种方法来获得应用程序使用的统计数据。 该应用程序包含谷歌分析(GA),所以自然而然的选择是使用GA。然而,GA似乎更适合跟踪事件,而不是应用程序中的恒定设置。换句话说,使用遗传算法,我们可以很容易地跟踪用户何时更改一
问题内容: 我意识到之前在SO上已经问过类似的问题,但是让我准确描述一下我需要做的事情: 我有一组运行命令行Java应用程序的测试,我想向它们添加内存配置文件。我看到的一个选择是将代码(可能使用第三方工具/库)添加到应用程序中,以提供内存快照。另一种选择是使用第三方工具为我管理/安装我的应用程序和JVM(理想情况下不需要我更改代码)。我在想类似Valgrind的东西,但是对于Java。如果可能的话
我有一个问题,为什么非常简单的Spring Boot应用程序分配100 MB内存?如何减少内存使用? 1) https://start.spring.io/生成带有“Spring Web Starter”依赖项的演示程序 2) Dockerfile pom.xml 类 1) 记忆测试1 Docker build-f Dockerfile-t demo. docker run-p 8080:8080