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


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

MemTotal: 94348 КБ MemFree: 5784 КБ

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

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

9 89

9 ответов:

Внимание: этот ответ измеряет использование памяти / доступность устройства. Это не то, что доступно для вашего приложения. Чтобы измерить, что делает ваше приложение, и разрешено делать, используйте ответ разработчика android.


Android docs-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

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

P. S: нам нужно вычислить общую память только один раз. поэтому вызовите точку 1 только один раз в своем коде, а затем после этого вы можете повторно вызвать код точки 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 до этого достигает нуля.)

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

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

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;

}

другой способ (в настоящее время показывает 25 Мб бесплатно на моем G1):

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

философия управления памятью Linux - это "свободная память-это потерянная память".

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

гораздо более полезным руководством для свободной памяти в системе Linux является

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

ссылки:

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

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

Я посмотрел на дерево исходного кода Android.

внутри com.android.server.am.ActivityManagerService.java (внутренняя служба, выставленная android.приложение.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.ОС.

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

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