Как получить текущее использование памяти в Android?

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

MemTotal: 94348 kB MemFree: 5784 kB

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

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

Ответ 1

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

Ответ 2

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


Обычно вы хотите знать состояние кучи памяти, поскольку, если она использует слишком много памяти, вы получаете 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. (Из-за фрагментации памяти вы можете получить 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 хранит слишком много больших растровых изображений, но плохая новость заключается в том, что я не считаю возможным поймать такой случай во время выполнения.

Ответ 3

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

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;

}

Ответ 4

Еще один способ (показывая 25MB бесплатно на моем G1):

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

Ответ 5

Философия управления памятью 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 мегабайт буферов/кэшированной памяти можно выбросить, если память может быть более выгодно использована в других местах.

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

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

Ответ 6

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

ссылка:

Этот метод 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() стоит дорого, поэтому вы можете переместить его код в член класса.

Ответ 7

Я посмотрел на 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 + Cached in/proc/meminfo.

Примечания

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

Ответ 8

вы также можете использовать инструмент DDMS, который является частью SDK android. он помогает в распределении памяти java-кода и собственного кода c/С++.

Ответ 9

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;
}

Ответ 10

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 не используется?