Как получить текущее использование памяти в Android? - PullRequest
97 голосов
/ 03 июля 2010

Я использовал / proc / meminfo и проанализировал команду response.Однако это показывает, что:

MemTotal: 94348 кБ MemFree: 5784 кБ

означает.это показывает, что есть только 5 МБ свободной памяти.Возможно ли это с Android Mobile?На моем мобильном телефоне установлено только 5-6 приложений, и никакие другие задачи не выполняются.но все же эта команда показывает, что свободной памяти очень мало.

Может кто-нибудь прояснить это?или есть ли другой способ получить использование памяти в Android?

Ответы [ 10 ]

160 голосов
/ 07 июля 2010

ВНИМАНИЕ: Этот ответ измеряет использование памяти / доступное УСТРОЙСТВА.Это НЕ то, что доступно для вашего приложения.* Чтобы определить, что делает ваше приложение и РАЗРЕШЕНО, Используйте ответ разработчика Android .


Документы Android - ActivityManager.MemoryInfo

  1. команда parse / proc / meminfo.Вы можете найти код ссылки здесь: Получить использование памяти в Android

  2. используйте приведенный ниже код и получите текущую оперативную память:

    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;
    

Объяснение числа 0x100000L

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

1024 * 1024     == 1048576
1048576         == 0x100000

Совершенно очевидно, что число используется для преобразования байтов в мегабайт

PS: нам нужно вычислить суммупамять только один раз.поэтому вызывайте точку 1 только один раз в своем коде, а затем после, вы можете повторно вызывать код точки 2.

70 голосов
/ 09 октября 2013

Это зависит от вашего определения, какой запрос памяти вы хотите получить.


Обычно вы хотите узнать состояние памяти кучи, так как, если она использует слишком много памяти, выполучить OOM и завершить работу приложения.

Для этого вы можете проверить следующие значения:

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

Чем больше переменная usedMemInMB приближается к maxHeapSizeInMB, тем ближе availHeapSizeInMB достигает нуля, чем ближе вы получаете ООМ.(Из-за фрагментации памяти вы можете получить OOM ДО того, как он достигнет нуля.)

Это также то, что показывает инструмент использования памяти DDMS.


Альтернативно, существует реальное использование ОЗУ, это то, сколько использует вся система - см. принятый ответ , чтобы вычислить это.


Обновление: поскольку Android O заставляет ваше приложение также использовать собственную оперативную память (по крайней мере для растровых изображений)хранилище, которое обычно является основной причиной огромного использования памяти), а не только куча, все изменилось, и вы получите меньше OOM (поскольку куча больше не содержит растровые изображения, проверьте здесь ), но вы все равно должны следить за использованием памяти, если вы подозреваете, что у вас есть утечки памяти.На Android O, если у вас есть утечки памяти, которые должны были вызвать OOM на более старых версиях, кажется, что он просто потерпит крах, и вы не сможете его перехватить.Вот как проверить использование памяти:

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

Но я считаю, что лучше всего использовать профилировщик среды IDE, который показывает данные в режиме реального времени с использованием графика.

Итак, хорошая новость для Android O состоит в том, что сбои намного сложнее из-за того, что OOM хранит слишком много больших растровых изображений, но плохая новость заключается в том, что я не думаю, что можно обнаружить такой случай во времяво время выполнения.

28 голосов
/ 30 октября 2012

Вот способ подсчета использования памяти запущенного в данный момент приложения :

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;

}
17 голосов
/ 03 июля 2010

Другой способ (в настоящее время на моем G1 отображается 25 МБ свободного места):

MemoryInfo mi = new MemoryInfo();
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
activityManager.getMemoryInfo(mi);
long availableMegs = mi.availMem / 1048576L;
12 голосов
/ 03 июля 2010

Философия управления памятью в Linux гласит: «Свободная память - пустая трата памяти».

Я предполагаю, что следующие две строки покажут, сколько памяти находится в «буферах» и сколько «кэшировано». Хотя между этими двумя понятиями есть разница (пожалуйста, не спрашивайте, что это за различие :) они оба примерно добавляют объем памяти, используемый для кэширования данных и метаданных файла.

Гораздо более полезным руководством по освобождению памяти в системе 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

Строка +/- buffers / cache: является магической линией, она сообщает, что я действительно получил около 589 мегабайт активной требуемой памяти процесса и около 5391 мегабайт «свободной» памяти, в том смысле, что 91 +374 мегабайта буферов / кэшированной памяти можно выбросить, если память будет более выгодно использоваться в других местах.

(Моя машина работала около трех часов, почти ничего не делая, кроме переполнения стека, поэтому у меня так много свободной памяти.)

Если Android не поставляется с free(1), вы можете сделать математику самостоятельно с файлом /proc/meminfo; Мне просто нравится формат вывода free(1). :)

6 голосов
/ 17 мая 2015

Я ссылаюсь на несколько работ.

справка:

Этот метод 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;
    }

Я знаю, что Pattern.compile () стоит дорого, поэтому вы можете переместить его код в класс.

3 голосов
/ 19 сентября 2013

Я посмотрел на Android Source Tree.

Внутри 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);
}

Внутри android.os. Process.java

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

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

Вызывает метод JNI из android_util_Process.cpp

Заключение

MemoryInfo.availMem = MemFree + Кэшируется в /proc/meminfo.

Примечания

Общая память добавлена ​​на уровне API 16.

1 голос
/ 15 марта 2013

Вы также можете использовать инструмент DDMS, который является частью Android SDK самостоятельно.это также помогает в распределении памяти для Java-кода и нативного кода C / C ++.

0 голосов
/ 17 апреля 2019
final long usedMemInMB=(runtime.totalMemory() - runtime.freeMemory()) / 1048576L;
final long maxHeapSizeInMB=runtime.maxMemory() / 1048576L;
final long availHeapSizeInMB = maxHeapSizeInMB - usedMemInMB;

Это странный код. Возвращает MaxMemory - (totalMemory - freeMemory). Если freeMemory равно 0, то код возвратит MaxMemory - totalMemory, так что он может быть больше или равен 0. Почему freeMemory не используется?

0 голосов
/ 15 сентября 2017
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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...