如何在android中获取当前的内存使用情况?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3170691/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:01:51  来源:igfitidea点击:

How to get current memory usage in android?

androidmemory-management

提问by Badal

I have used /proc/meminfo and parsed command response.however it result shows that :

我使用了 /proc/meminfo 并解析了命令响应。但是结果显示:

MemTotal: 94348 kB MemFree: 5784 kB

MemTotal:94348 kB MemFree:5784 kB

means. it shows there is only 5MB free memory. Is it possible with android mobile? There is only 5-6 application installed on my mobile and no other task is running. but still this command shows there is very little free memory.

方法。它显示只有 5MB 可用内存。安卓手机可以吗?我的手机上只安装了 5-6 个应用程序,没有其他任务正在运行。但是这个命令仍然显示可用内存很少。

Can somebody clarify this? or is there any other way of getting memory usage in android?

有人可以澄清这一点吗?或者有没有其他方法可以在android中获取内存使用情况?

回答by Badal

CAUTION: This answer measures memory usage/available of the DEVICE. This is NOT what is available to your app. To measure what your APP is doing, and is PERMITTED to do, Use android developer's answer.

注意:此答案衡量设备的内存使用情况/可用情况。这不是您的应用程序可用的内容。要衡量您的 APP 正在做什么以及允许做什么,请使用 android developer's answer



Android docs - ActivityManager.MemoryInfo

Android 文档 - ActivityManager.MemoryInfo

  1. parse /proc/meminfo command. You can find reference code here: Get Memory Usage in Android

  2. use below code and get current RAM:

    MemoryInfo mi = new MemoryInfo();
    ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    activityManager.getMemoryInfo(mi);
    double availableMegs = mi.availMem / 0x100000L;
    
    //Percentage can be calculated for API 16+
    double percentAvail = mi.availMem / (double)mi.totalMem * 100.0;
    
  1. 解析 /proc/meminfo 命令。您可以在此处找到参考代码:Get Memory Usage in Android

  2. 使用以下代码并获取当前 RAM:

    MemoryInfo mi = new MemoryInfo();
    ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    activityManager.getMemoryInfo(mi);
    double availableMegs = mi.availMem / 0x100000L;
    
    //Percentage can be calculated for API 16+
    double percentAvail = mi.availMem / (double)mi.totalMem * 100.0;
    

Explanation of the number 0x100000L

数字 0x100000L 的解释

1024 bytes      == 1 Kibibyte 
1024 Kibibyte   == 1 Mebibyte

1024 * 1024     == 1048576
1048576         == 0x100000

It's quite obvious that the number is used to convert from bytes to mebibyte

很明显,该数字用于从字节转换为兆字节

P.S: we need to calculate total memory only once. so call point 1 only once in your code and then after, you can call code of point 2 repetitively.

PS:我们只需要计算一次总内存。所以在你的代码中只调用点 1 一次,然后你可以重复调用点 2 的代码。

回答by android developer

It depends on your definition of what memory query you wish to get.

这取决于您对希望获得的内存查询的定义。



Usually, you'd like to know the status of the heap memory, since if it uses too much memory, you get OOM and crash the app.

通常,您想知道堆内存的状态,因为如果它使用太多内存,您会出现 OOM 并使应用程序崩溃。

For this, you can check the next values:

为此,您可以检查下一个值:

final Runtime runtime = Runtime.getRuntime();
final long usedMemInMB=(runtime.totalMemory() - runtime.freeMemory()) / 1048576L;
final long maxHeapSizeInMB=runtime.maxMemory() / 1048576L;
final long availHeapSizeInMB = maxHeapSizeInMB - usedMemInMB;

The more the "usedMemInMB" variable gets close to "maxHeapSizeInMB", the closer availHeapSizeInMBgets to zero, the closer you get OOM. (Due to memory fragmentation, you may get OOM BEFORE this reaches zero.)

“usedMemInMB”变量越接近“maxHeapSizeInMB”,越接近于availHeapSizeInMB零,越接近 OOM。(由于内存碎片,您可能会在达到零之前出现 OOM。)

That's also what the DDMS tool of memory usage shows.

这也是内存使用的 DDMS 工具显示的内容。



Alternatively, there is the real RAM usage, which is how much the entire system uses - see accepted answerto calculate that.

或者,还有实际的 RAM 使用量,即整个系统使用了多少 - 请参阅已接受的答案来计算。



Update: since Android O makes your app also use the native RAM (at least for Bitmaps storage, which is usually the main reason for huge memory usage), and not just the heap, things have changed, and you get less OOM (because the heap doesn't contain bitmaps anymore,check here), but you should still keep an eye on memory use if you suspect you have memory leaks. On Android O, if you have memory leaks that should have caused OOM on older versions, it seems it will just crash without you being able to catch it. Here's how to check for memory usage:

更新:由于 Android O 使您的应用程序也使用本机 RAM(至少对于位图存储,这通常是大量内存使用的主要原因),而不仅仅是堆,事情发生了变化,您的 OOM 减少了(因为堆不再包含位图,请在此处查看),但如果您怀疑存在内存泄漏,您仍应注意内存使用情况。在 Android O 上,如果您的内存泄漏应该在旧版本上导致 OOM,那么它似乎会崩溃而您无法捕捉到它。以下是检查内存使用情况的方法:

val nativeHeapSize = Debug.getNativeHeapSize()
val nativeHeapFreeSize = Debug.getNativeHeapFreeSize()
val usedMemInBytes = nativeHeapSize - nativeHeapFreeSize
val usedMemInPercentage = usedMemInBytes * 100 / nativeHeapSize

But I believe it might be best to use the profiler of the IDE, which shows the data in real time, using a graph.

但我认为最好使用 IDE 的分析器,它使用图形实时显示数据。

So the good news on Android O is that it's much harder to get crashes due to OOM of storing too many large bitmaps, but the bad news is that I don't think it's possible to catch such a case during runtime.

因此,Android O 上的好消息是,由于存储太多大位图的 OOM,导致崩溃要困难得多,但坏消息是我认为在运行时不可能捕捉到这种情况。



EDIT: seems Debug.getNativeHeapSize()changes over time, as it shows you the total max memory for your app. So those functions are used only for the profiler, to show how much your app is using.

编辑:似乎Debug.getNativeHeapSize()随着时间的推移而变化,因为它显示了您的应用程序的总最大内存。所以这些函数仅用于分析器,以显示您的应用程序使用了多少。

If you want to get the real total and available native RAM , use this:

如果您想获得真实的总和可用本机 RAM,请使用以下命令:

val memoryInfo = ActivityManager.MemoryInfo()
(getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).getMemoryInfo(memoryInfo)
val nativeHeapSize = memoryInfo.totalMem
val nativeHeapFreeSize = memoryInfo.availMem
val usedMemInBytes = nativeHeapSize - nativeHeapFreeSize
val usedMemInPercentage = usedMemInBytes * 100 / nativeHeapSize
Log.d("AppLog", "total:${Formatter.formatFileSize(this, nativeHeapSize)} " +
        "free:${Formatter.formatFileSize(this, nativeHeapFreeSize)} " +
        "used:${Formatter.formatFileSize(this, usedMemInBytes)} ($usedMemInPercentage%)")

回答by Sharmilee

Here is a way to calculate memory usage of currently running application:

这是一种计算当前正在运行的应用程序的内存使用情况的方法

public static long getUsedMemorySize() {

    long freeSize = 0L;
    long totalSize = 0L;
    long usedSize = -1L;
    try {
        Runtime info = Runtime.getRuntime();
        freeSize = info.freeMemory();
        totalSize = info.totalMemory();
        usedSize = totalSize - freeSize;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return usedSize;

}

回答by yanchenko

Another way (currently showing 25MB free on my G1):

另一种方式(目前在我的 G1 上显示 25MB 可用空间):

MemoryInfo mi = new MemoryInfo();
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
activityManager.getMemoryInfo(mi);
long availableMegs = mi.availMem / 1048576L;

回答by sarnold

Linux's memory management philosophy is "Free memory is wasted memory".

Linux 的内存管理理念是“空闲内存就是浪费内存”。

I assume that the next two lines will show how much memory is in "Buffers" and how much is "Cached". While there is a difference between the two (please don't ask what that difference is :) they both roughly add up to the amount of memory used to cache file data and metadata.

我假设接下来的两行将显示“缓冲区”中有多少内存以及“缓存”中有多少内存。虽然两者之间存在差异(请不要问差异是什么:)它们都大致加起来用于缓存文件数据和元数据的内存量。

A far more useful guide to free memory on a Linux system is the free(1)command; on my desktop, it reports information like this:

在 Linux 系统上释放内存的一个更有用的指南是free(1)命令;在我的桌面上,它报告如下信息:

$ free -m
             total       used       free     shared    buffers     cached
Mem:          5980       1055       4924          0         91        374
-/+ buffers/cache:        589       5391
Swap:         6347          0       6347

The +/- buffers/cache: line is the magic line, it reports that I've really got around 589 megs of actively required process memory, and around 5391 megs of 'free' memory, in the sense that the 91+374 megabytes of buffers/cached memory can be thrown away if the memory could be more profitably used elsewhere.

+/- buffers/cache: 行是一条神奇的线,它报告说我真的有大约 589 兆的主动需要的进程内存和大约 5391 兆的“空闲”内存,从 91+374 兆字节的意义上说如果可以在其他地方更有利地使用内存,则可以丢弃缓冲区/缓存内存。

(My machine has been up for about three hours, doing nearly nothing but stackoverflow, which is why I have so much free memory.)

(我的机器已经启动了大约三个小时,除了 stackoverflow 之外几乎什么都不做,这就是我有这么多空闲内存的原因。)

If Android doesn't ship with free(1), you can do the math yourself with the /proc/meminfofile; I just like the free(1)output format. :)

如果 Android 没有附带free(1),您可以自己使用该/proc/meminfo文件进行数学计算;我只是喜欢free(1)输出格式。:)

回答by Hogun

I refer few writings.

我参考了很少的著作。

reference:

参考:

This getMemorySize() method is returned MemorySize that has total and free memory size.
I don't believe this code perfectly.
This code is testing on LG G3 cat.6 (v5.0.1)

此 getMemorySize() 方法返回具有总内存和可用内存大小的 MemorySize。
我不完全相信这段代码。
此代码正在 LG G3 cat.6 (v5.0.1) 上测试

    private MemorySize getMemorySize() {
        final Pattern PATTERN = Pattern.compile("([a-zA-Z]+):\s*(\d+)");

        MemorySize result = new MemorySize();
        String line;
        try {
            RandomAccessFile reader = new RandomAccessFile("/proc/meminfo", "r");
            while ((line = reader.readLine()) != null) {
                Matcher m = PATTERN.matcher(line);
                if (m.find()) {
                    String name = m.group(1);
                    String size = m.group(2);

                    if (name.equalsIgnoreCase("MemTotal")) {
                        result.total = Long.parseLong(size);
                    } else if (name.equalsIgnoreCase("MemFree") || name.equalsIgnoreCase("Buffers") ||
                            name.equalsIgnoreCase("Cached") || name.equalsIgnoreCase("SwapFree")) {
                        result.free += Long.parseLong(size);
                    }
                }
            }
            reader.close();

            result.total *= 1024;
            result.free *= 1024;
        } catch (IOException e) {
            e.printStackTrace();
        }

        return result;
    }

    private static class MemorySize {
        public long total = 0;
        public long free = 0;
    }

I know that Pattern.compile() is expensive cost so You may move its code to class member.

我知道 Pattern.compile() 成本很高,因此您可以将其代码移至类成员。

回答by ragazenta

I looked at Android Source Tree.

我查看了 Android 源代码树。

Inside com.android.server.am.ActivityManagerService.java(internal service exposed by android.app.ActivityManager).

在 com.android.server.am 里面。ActivityManagerService.java(由android.app。暴露的内部服务ActivityManager)。

public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
    final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
    final long hiddenAppMem = mProcessList.getMemLevel(ProcessList.HIDDEN_APP_MIN_ADJ);
    outInfo.availMem = Process.getFreeMemory();
    outInfo.totalMem = Process.getTotalMemory();
    outInfo.threshold = homeAppMem;
    outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((hiddenAppMem-homeAppMem)/2));
    outInfo.hiddenAppThreshold = hiddenAppMem;
    outInfo.secondaryServerThreshold = mProcessList.getMemLevel(
            ProcessList.SERVICE_ADJ);
    outInfo.visibleAppThreshold = mProcessList.getMemLevel(
            ProcessList.VISIBLE_APP_ADJ);
    outInfo.foregroundAppThreshold = mProcessList.getMemLevel(
            ProcessList.FOREGROUND_APP_ADJ);
}

Inside android.os.Process.java

在android.os里面。进程.java

/** @hide */
public static final native long getFreeMemory();

/** @hide */
public static final native long getTotalMemory();

It calls JNI method from android_util_Process.cpp

它从android_util_Process.cpp调用 JNI 方法

Conclusion

结论

MemoryInfo.availMem = MemFree + Cached in /proc/meminfo.

MemoryInfo.availMem = MemFree + 缓存在 /proc/meminfo 中。

Notes

笔记

Total Memory is added in API level 16.

在 API 级别 16 中添加了总内存。

回答by vsmph

you can also use DDMS tool which is part of android SDK it self. it helps in getting memory allocations of java code and native c/c++ code as well.

您还可以使用 DDMS 工具,它是 android SDK 的一部分。它也有助于获取 java 代码和本机 c/c++ 代码的内存分配。

回答by iMobaio

public static boolean isAppInLowMemory(Context context) {
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
    activityManager.getMemoryInfo(memoryInfo);

    return memoryInfo.lowMemory;
}

回答by Andrey

final long usedMemInMB=(runtime.totalMemory() - runtime.freeMemory()) / 1048576L;
final long maxHeapSizeInMB=runtime.maxMemory() / 1048576L;
final long availHeapSizeInMB = maxHeapSizeInMB - usedMemInMB;

It is a strange code. It return MaxMemory - (totalMemory - freeMemory). If freeMemory equals 0, then the code will return MaxMemory - totalMemory, so it can more or equals 0. Why freeMemory not used?

这是一个奇怪的代码。它返回 MaxMemory - (totalMemory - freeMemory)。如果 freeMemory 等于 0,那么代码将返回 MaxMemory - totalMemory,因此它可以大于或等于 0。为什么不使用 freeMemory?