如何以编程方式查找Android应用程序上使用的内存?

我希望有办法做到这一点。此外,我如何获得手机的空闲内存?


当前回答

哈克堡是堆栈溢出的最佳答案之一。它揭示了一个非常晦涩的主题。这对我帮助很大。

另一个非常有用的资源是这段必看的视频:Google I/O 2011:Android应用程序的内存管理


更新:

Process Stats是一项发现应用程序如何管理内存的服务,Dianne Hackborn在博客文章《Process Stats:了解应用程序如何使用RAM》中对此进行了解释:

其他回答

这是一项正在进行的工作,但我不明白:

ActivityManager activityManager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);

Log.i(TAG, " memoryInfo.availMem " + memoryInfo.availMem + "\n" );
Log.i(TAG, " memoryInfo.lowMemory " + memoryInfo.lowMemory + "\n" );
Log.i(TAG, " memoryInfo.threshold " + memoryInfo.threshold + "\n" );

List<RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();

Map<Integer, String> pidMap = new TreeMap<Integer, String>();
for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses)
{
    pidMap.put(runningAppProcessInfo.pid, runningAppProcessInfo.processName);
}

Collection<Integer> keys = pidMap.keySet();

for(int key : keys)
{
    int pids[] = new int[1];
    pids[0] = key;
    android.os.Debug.MemoryInfo[] memoryInfoArray = activityManager.getProcessMemoryInfo(pids);
    for(android.os.Debug.MemoryInfo pidMemoryInfo: memoryInfoArray)
    {
        Log.i(TAG, String.format("** MEMINFO in pid %d [%s] **\n",pids[0],pidMap.get(pids[0])));
        Log.i(TAG, " pidMemoryInfo.getTotalPrivateDirty(): " + pidMemoryInfo.getTotalPrivateDirty() + "\n");
        Log.i(TAG, " pidMemoryInfo.getTotalPss(): " + pidMemoryInfo.getTotalPss() + "\n");
        Log.i(TAG, " pidMemoryInfo.getTotalSharedDirty(): " + pidMemoryInfo.getTotalSharedDirty() + "\n");
    }
}

为什么PID没有映射到activityManager.getProcessMemoryInfo()中的结果?很明显,你想让结果数据变得有意义,那么为什么谷歌会让结果之间的关联变得如此困难呢?如果我想处理整个内存使用情况,当前系统甚至无法正常工作,因为返回的结果是一个android.os.Debug.MemoryInfo对象数组,但这些对象都没有告诉你它们与哪些pid相关。如果只传入所有pid的数组,则无法理解结果。据我所知,一次传递多个pid是没有意义的,如果是这样,为什么要使activityManager.getProcessMemoryInfo()只接受一个int数组?

哈克堡是堆栈溢出的最佳答案之一。它揭示了一个非常晦涩的主题。这对我帮助很大。

另一个非常有用的资源是这段必看的视频:Google I/O 2011:Android应用程序的内存管理


更新:

Process Stats是一项发现应用程序如何管理内存的服务,Dianne Hackborn在博客文章《Process Stats:了解应用程序如何使用RAM》中对此进行了解释:

Android Studio 0.8.10+推出了一个非常有用的工具,叫做内存监视器。

它的好处:

在图形中显示可用和已使用的内存,以及垃圾收集随着时间的推移。快速测试应用程序速度是否可能与过多的垃圾收集事件相关。快速测试应用程序崩溃是否与内存不足有关。

图1。在Android内存监视器上强制GC(垃圾收集)事件

通过使用它,您可以获得有关应用程序RAM实时消耗的大量有用信息。

我们发现,获取当前进程总内存的所有标准方法都存在一些问题。

Runtime.getRuntime().totalMemory():仅返回JVM内存ActivityManager.getMemoryInfo()、Process.getFreeMemory()以及基于/proc/meminfo的任何其他内容-返回所有组合进程的内存信息(例如android_util_Process.cpp)Debug.getNativeHeapAllocatedSize()-使用mallinfo(),它只返回malloc()和相关函数执行的内存分配信息(请参阅android_os_Debug.cpp)Debug.getMemoryInfo()-完成了任务,但速度太慢。在Nexus 6上,单次通话大约需要200毫秒。性能开销使得这个函数对我们来说毫无用处,因为我们经常调用它,并且每次调用都非常明显(请参见android_os_Debug.cpp)ActivityManager.getProcessMemoryInfo(int[])-在内部调用Debug.getMemoryInformation()(请参阅ActivityManagerService.java)

最后,我们使用了以下代码:

const long pageSize = 4 * 1024; //`sysconf(_SC_PAGESIZE)`
string stats = File.ReadAllText("/proc/self/statm");
var statsArr = stats.Split(new [] {' ', '\t', '\n'}, 3);

if( statsArr.Length < 2 )
    throw new Exception("Parsing error of /proc/self/statm: " + stats);

return long.Parse(statsArr[1]) * pageSize;

它返回VmRSS度量。你可以在这里找到更多关于它的细节:一、二和三。


P.S.我注意到,如果性能不是关键要求,主题仍然缺少一个实际而简单的代码片段,说明如何估计进程的私有内存使用:

Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
Debug.getMemoryInfo(memInfo);
long res = memInfo.getTotalPrivateDirty();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) 
    res += memInfo.getTotalPrivateClean(); 

return res * 1024L;

我在阅读答案时感到困惑,所以我决定阅读文档。好的,我们来做:

本机堆内存使用情况

您可以使用Debug对象获取设备的本机堆内存大小:

long nativeTotal = Debug.getNativeHeapSize();
long nativeFree = Debug.getNativeHeapFreeSize();
long nativeAllocated = Debug.getNativeHeapAllocatedSize();
long nativeUsed = nativeTotal - nativeFree;

注意:nativeUsed和nativeAllocated具有相同的值。

运行时内存使用

使用应用程序的运行时对象的内存使用情况。每个应用程序都有一个运行时对象来访问其接口:

Runtime runtime = Runtime.getRuntime();
long runtimeMax = runtime.maxMemory();
long runtimeTotal = runtime.totalMemory();
long runtimeFree = runtime.freeMemory();
long runtimeUsed = runtimeTotal - runtimeFree;

系统内存使用

您可以使用ActivityManager.MemoryInfo对象获取系统的内存使用情况:

ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
long systemTotal = memoryInfo.totalMem;
long systemFree = memoryInfo.availMem;
long systemUsed = systemTotal - systemFree;

过程内存使用

读取系统内存使用情况的另一种方法是在linux中解析/proc/meminfo文件的内容。

RandomAccessFile reader = new RandomAccessFile("/proc/meminfo", "r");
Pattern pattern = Pattern.compile("(\\d+)");
Matcher totalMatcher = pattern.matcher(reader.readLine());
totalMatcher.find();
long procTotal = Long.parseLong(totalMatcher.group(1)) * 1024L; // KB to B
Matcher freeMatcher = pattern.matcher(reader.readLine());
freeMatcher.find();
long procFree = Long.parseLong(freeMatcher.group(1)) * 1024L; // KB to B
long procUsed = procTotal - procFree;

好吧,我还是很困惑。但这是所有可以获得内存使用率的方法。记录它们以调试应用程序!!!

我还为他们每个人提供了一个链接,以阅读他们的用法和信息。