Androidで現在のメモリ使用量を取得するにはどうすればよいですか?


108

/ proc / meminfoを使用してコマンド応答を解析しましたが、結果は次のことを示しています:

MemTotal:94348 kB MemFree:5784 kB

手段。5MBの空きメモリしかないことを示しています。Androidモバイルで可能ですか?私の携帯にインストールされているアプリケーションは5〜6しかなく、他のタスクは実行されていません。それでも、このコマンドは空きメモリがほとんどないことを示しています。

誰かがこれを明確にできますか?またはアンドロイドでメモリ使用量を取得する他の方法はありますか?


2
デバイスごと、またはアプリごとの空きメモリを確認しようとしていますか?アプリごとの場合は、ヒープa-laで計算する必要がありますDebug.getNativeHeapFreeSize()
IgorGanapolsky

1
/ proc / meminfoを使用して(RAM内の)空きメモリを計算するには、MemFreeBuffersCached、およびSwapCachedの集計を取得する必要があります。Androidによって提供されるこの目的のためのAPIがあり、API 16およびワードで動作します。古いAPIをターゲットにしている場合は、Meminfoが役立ちます。
AB

回答:


174

注意:この回答は、デバイスのメモリ使用量/使用可能量を測定します。これは、アプリで利用できるものではありません。アプリの動作を測定し、許可されている場合は、Android開発者の回答を使用します


Androidドキュメント-ActivityManager.MemoryInfo

  1. parse / proc / meminfoコマンド。ここで参照コードを見つけることができます: 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;

番号0x100000Lの説明

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

1024 * 1024     == 1048576
1048576         == 0x100000

数値がバイトからメビバイトへの変換に使用されていることは明らかです

PS:合計メモリを計算する必要があるのは1回だけです。したがって、コードでポイント1を1回だけ呼び出してから、ポイント2のコードを繰り返し呼び出すことができます。


メモリサイズを確認したいのですが、MemoryInfoとは何ですか?
ピラバ

PIraba、そのandroid APIクラス。ここでdeveloper.android.com/reference/android/app/…を確認してください。
Badal

@SanjayJoshiこれは、availMem変数にメモリがバイト単位で含まれているためです。1024バイトは1キロバイトに相当し、1024キロバイトは1メガバイトに相当します。したがって、1024 * 1024は1048576に等しい
Rolf

2
上記の2倍に変換します。それ以外の場合、percentAvailは0になります
blueether '28年

1
@Rolfツ申し訳ありませんが、1024バイトは1キビバイトに相当し、1024キビバイトは1ミビバイトです。KiloとMegaは10進数の接頭辞です。1000バイト= 1キロバイト。これも答えで間違って説明されています。
JacksOnF1re 2017年

88

取得したいメモリクエリの定義によって異なります。


通常、ヒープメモリの状態を知りたいと思います。メモリが多すぎると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ツールが示すものでもあります。


または、実際のRAM使用量があります。これは、システム全体が使用する量です。これを計算するには、承認された回答を参照してください。


更新:Android OはアプリにネイティブRAM(少なくともビットマップストレージ用であり、これは通常、大量のメモリ使用量の主な理由です)を使用するため、ヒープだけでなく、物事が変更され、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が原因でクラッシュするのがはるかに難しいことですが、悪いニュースは、実行時にそのようなケースをキャッチすることは不可能だということです。


編集:Debug.getNativeHeapSize()それはあなたのアプリの合計最大メモリを示すので、時間とともに変化するようです。したがって、これらの関数は、アプリが使用している量を示すために、プロファイラーにのみ使用されます。

実際の合計および使用可能なネイティブ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%)")

ワオ。とてもシンプルでありながら本当です!
2016

実際のメモリ使用量とは何ですか?この場合、usedMemInMBはアプリの実際のメモリ使用量ではありませんか?このコードを使用すると、使用量が50 MBのように表示されますが、電話の設定に移動してメモリ使用量を表示すると、アプリで100 MBと表示されます。なぜこの違いがあるのですか?
batmaci

1
@batmaciヒープメモリは、アプリの合計メモリ使用量の一部にすぎません。ネイティブのメモリ使用量もあり、通常はWebページ、ゲーム、およびいくつかの重い目的に使用されます。通常、アプリはヒープメモリのみを調べる必要があります。これは、デバイスRAMと比較してかなり低いためです。ヒープメモリに達すると、アプリはクラッシュします(十分な空きRAMがある場合でも)。
Androidデベロッパー

これは完璧なコードスニペットであり、OOMのチェックに非常に役立ちます。
aolphn

@AlphaOFありがとうございます。AndroidOでは状況が変わりました。状況に合わせて回答を更新しました。
Android開発者

29

現在実行中のアプリケーションのメモリ使用量を計算する方法は次のとおりです

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
これは単純なアプローチですが、ドキュメントで説明されているように、RuntimeクラスのfreeMemory()メソッドは、現在のプログラムまたはアプリケーションで使用可能なメモリを返します。使用中は注意してください。
Aksel Fatih 2013

2
@ピーター-はい、それは質問されたものとは異なる質問に答えるという点で「間違っています」。一方、このアプリの開発者が通常知っている必要があります何のために「右」である:めったにデバイス上のメモリの全体的な状態が何であるかを問題にしない-ユーザーがアプリケーションの多くを実行した場合、OSがなければならないのほとんどを利用しますそのメモリ-そうでなければ、それは非効率的です。OSは、受け入れられた答えが何を与えるかを知る必要があり、最近使用されていないアプリをいつ殺し始めるかを知る必要があります。しかし、アプリプログラマーは、この答え(およびandroid開発者の同様の答え)が何を伝えているかを、runtime.maxMemoryと比較して知る必要があります。
ToolmakerSteve 2017

このソリューションは、ランタイムによってアプリに公開されたメモリでのみ機能します。これは、OPが必要とするシステムメモリ全体についての洞察を与えません。
AB

多くのデバイス(Xiaomiなど)ではRuntime.freeMemory()0をRuntime.totalMemory()返し、現在割り当てられているメモリのみを返します。
アルテム

17

別の方法(現在、私のG1で25MBの空き容量を示しています):

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

こんにちはアレックス、あなたの助けをありがとう!もう1つ質問。このコードは、使用可能なRAMを提供します。合計RAMも表示したい。どうすれば入手できますか?
Badal

@Badal私はそのためのJava APIを知りません。/ proc / meminfoの解析に固執します。
yanchenko 2010

12

Linuxのメモリ管理の考え方は、「空きメモリは無駄なメモリである」です。

次の2行は、「バッファ」内のメモリと「キャッシュ」内のメモリの量を示していると思います。2つには違いがありますが(その違いについては尋ねないでください:)どちらも、ファイルデータとメタデータのキャッシュに使用されるメモリの量とほぼ同じになります。

Linuxシステムでメモリを解放するためのはるかに役立つガイドは、free(1)コマンドです。私のデスクトップでは、次のような情報が報告されます。

$無料-m
             キャッシュされた使用済みの空き共有バッファの合計
メモリ:5980 1055 4924 0 91 374
-/ +バッファ/キャッシュ:589 5391
スワップ:6347 0 6347

+/- buffers / cache:行は魔法の行です。91+ 374メガバイトという意味で、実際に必要なプロセスメモリは約589 MB、「空き」メモリは約5391 MBあると報告されていますメモリが他の場所でより有益に使用できる場合、バッファ/キャッシュされたメモリは破棄されます。

(私のマシンは約3時間稼働しており、stackoverflow以外はほとんど何もしていません。そのため、私には多くの空きメモリがあります。)

Androidがに同梱されていない場合はfree(1)/proc/meminfoファイルを使用して自分で計算できます。私はfree(1)出力形式が好きです。:)


1
@イゴール、あなたはcat /proc/meminfo代わりにしたいでしょう。それははるかに詳しいのですが、MemFreeBuffers、そしてCachedおそらく最も重要な行です。
サルノルド2013

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()は高コストであることを知っているので、そのコードをクラスメンバーに移動できます。


3

Androidソースツリーを確認しました。

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();

android_util_Process.cppからJNIメソッドを呼び出します

結論

MemoryInfo.availMem = MemFree + / proc / meminfoにキャッシュされます。

ノート

合計メモリはAPIレベル16で追加されます。


1

Android SDKの一部であるDDMSツールを使用することもできます。これは、Javaコードとネイティブのc / c ++コードのメモリ割り当ての取得にも役立ちます。


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

0
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

アプリのメモリ使用量を確認する別の方法を次に示します。

adb shell dumpsys meminfo <com.package.name> -d

出力例:

Applications Memory Usage (kB):
Uptime: 2896577 Realtime: 2896577

** MEMINFO in pid 2094 [com.package.name] **
                   Pss  Private  Private  Swapped     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap     3472     3444        0        0     5348     4605      102
  Dalvik Heap     2349     2188        0        0     4640     4486      154
 Dalvik Other     1560     1392        0        0
        Stack      772      772        0        0
    Other dev        4        0        4        0
     .so mmap     2749     1040     1220        0
    .jar mmap        1        0        0        0
    .apk mmap      218        0       32        0
    .ttf mmap       38        0        4        0
    .dex mmap     3161       80     2564        0
   Other mmap        9        4        0        0
      Unknown       76       76        0        0
        TOTAL    14409     8996     3824        0     9988     9091      256

 Objects
               Views:       30         ViewRootImpl:        2
         AppContexts:        4           Activities:        2
              Assets:        2        AssetManagers:        2
       Local Binders:       17        Proxy Binders:       21
    Death Recipients:        7
     OpenSSL Sockets:        0

 SQL
         MEMORY_USED:        0
  PAGECACHE_OVERFLOW:        0          MALLOC_SIZE:        0

全体的なメモリ使用量:

adb shell dumpsys meminfo

https://developer.android.com/studio/command-line/dumpsys#meminfo

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.