1. ホーム
  2. android

[解決済み] Androidのアプリケーションヒープサイズを検出する

2022-06-28 16:24:23

質問

Android アプリで利用可能なアプリケーション ヒープ サイズをプログラムで検出するにはどうすればよいですか?

SDK の後のバージョンでは、これを行う関数があると聞きました。いずれにせよ、1.5 以上で動作する解決策を探しています。

どのように解決するのですか?

アプリケーション ヒープ サイズが利用可能です」という表現には、2 つの考え方があります。

  1. ハード エラーが発生する前に、私のアプリはどれだけのヒープを使用できるでしょうか。 また

  2. ヒープ量 が必要です。 を使用する必要がありますか?

それぞれ判断する方法があります。

上記の項目1について maxMemory()

を呼び出すことができます (例えば、メインのアクティビティで onCreate() メソッドで)次のように呼び出すことができます。

Runtime rt = Runtime.getRuntime();
long maxMemory = rt.maxMemory();
Log.v("onCreate", "maxMemory:" + Long.toString(maxMemory));

このメソッドでは、合計で何個の バイト であるか、また、アプリのヒープが を許可します。 を使用することができます。

上記項目2について getMemoryClass()

であり、以下のように呼び出すことができる。

ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass();
Log.v("onCreate", "memoryClass:" + Integer.toString(memoryClass));

このメソッドでは、おおよそ メガバイト のヒープを知ることができます。 に繰り返し押し込まれることなく、現在のデバイスの限界と他のアプリが実行する権利を適切に尊重したいのであれば、アプリは を使用する必要があります。 onStop() / onResume() のサイクルが、あなたの象のようなアプリが Android のジャグジーで入浴している間に、無造作にメモリからフラッシュされるのです。

私が知る限り、この区別は明確に文書化されていませんが、私はこの仮説を 5 つの異なる Android デバイスでテストし (以下を参照)、これが正しい解釈であることを自分自身で納得のいくまで確認しました。

純正バージョンの Android の場合 maxMemory() で示されるのと同じ数のメガバイトを返すのが普通です。 getMemoryClass() (で示されるのと同じ数(つまり、後者の値のおよそ100万倍)のメガバイトを返します。

私が知る限り、2 つの方法が分岐する唯一の状況は、CyanogenMod などの Android バージョンを実行している root 化されたデバイスで、ユーザーが手動で 選択 この場合、ユーザーは各アプリに対して許容されるヒープ サイズを手動で選択できます。 たとえば、CM では、このオプションは [CyanogenMod設定] / [パフォーマンス] / [VM ヒープ サイズ] の下に表示されます。

注意: この値を手動で設定すると、お使いのデバイスの通常よりも小さい値を選択した場合、特にシステムを混乱させる可能性があることに注意してください。

によって返される値を示す私のテスト結果は次のとおりです。 maxMemory()getMemoryClass() を、CyanogenMod を実行している 4 つの異なるデバイスで、それぞれ 2 つの異なる (手動で設定された) ヒープ値を使用しています。

  • G1:
    • VM Heap Size を 16MB に設定した場合。
      • maxMemory: 16777216
      • getMemoryClass: 16
    • VM Heap Sizeを24MBに設定した場合。
      • maxMemory: 25165824
      • getMemoryClass: 16
  • Moto Droidです。
    • VM ヒープ サイズを 24MB に設定した場合。
      • maxMemory: 25165824
      • getMemoryClass: 24
    • VM Heap Sizeを16MBに設定した場合。
      • maxMemory: 16777216
      • getMemoryClass: 24
  • ネクサス・ワン
    • VM ヒープ サイズを 32MB に設定した場合。
      • maxMemory 33554432
      • getMemoryClass: 32
    • VMヒープサイズを24MBに設定した場合。
      • maxMemory: 25165824
      • getMemoryClass: 32
  • ビューソニックGTab:
    • VM ヒープ サイズを 32 に設定した場合。
      • maxMemory 33554432
      • getMemoryClass: 32
    • VM Heap Sizeを64に設定した場合。
      • maxMemory: 67108864
      • getMemoryClass: 32

上記に加え、Ice Cream Sandwich を実行している Novo7 Paladin タブレットでテストを行いました。 これは、OS 全体を置き換えたり、特にヒープ サイズを手動で調整できるようなインターフェイスを提供したりしない、簡単なプロセスによってタブレットをルート化したことを除いて、本質的に ICS の純正バージョンでした。

その端末の場合、以下のような結果になりました。

  • Novo7
    • maxMemory: 62914560
    • getMemoryClass: 60

また、(下のコメントでKishoreによると)。

  • HTC One X
    • maxMemory: 67108864
    • getMemoryClass: 64

そして(akauppiさんのコメントにあるように)。

  • サムスン電子のギャラクシー コア プラス
    • maxMemory。(コメントで指定されていません)
    • getMemoryClassです。48
    • largeMemoryClass: 128

cmcromanceさんからのコメントにつきまして。

  • Galaxy S3 (Jelly Bean) の大きなヒープ
    • maxMemory: 268435456
    • getMemoryClass: 64

そして、(tencentのコメントにより)。

  • LG Nexus 5 (4.4.3) の通常版
    • maxMemory: 201326592
    • getMemoryClass: 192
  • LG Nexus 5 (4.4.3) のラージヒープ
    • maxMemory 536870912
    • getMemoryClass。192
  • ギャラクシーネクサス (4.3) 通常版
    • maxMemory: 100663296
    • getMemoryClass: 96
  • Galaxy Nexus (4.3) の大きなヒープ
    • maxMemory: 268435456
    • getMemoryClass: 96
  • ギャラクシー S4 プレイストア版 (4.4.2) の通常版
    • maxMemory: 201326592
    • getMemoryClass: 192
  • ギャラクシー S4 プレイストア版 (4.4.2) 大容量ヒープ
    • maxMemory 536870912
    • getMemoryClass。192

その他のデバイス

  • Huawei Nexus 6P (6.0.1) 通常版
    • maxMemory: 201326592
    • getMemoryClass: 192

私は、Honeycomb から利用できる特別な android:largeHeap="true" というマニフェスト オプションを使用してこれら 2 つの方法をテストしていませんが、cmcromance と tencent のおかげで、上で報告したようにいくつかのサンプル largeHeap 値を入手することができました。

私の 期待

(これは上記の largeHeap の数値によってサポートされているようです) は、このオプションが rooted OS を介してヒープを手動で設定するのと同様の効果を持つこと、すなわち、このオプションによって maxMemory() の値を上げる一方で getMemoryClass() を残しています。getLargeMemoryClass() という別のメソッドがあり、largeHeap 設定を使用するアプリに許容されるメモリ量を示します。 getLargeMemoryClass() のドキュメントでは、"ほとんどのアプリケーションはこの量のメモリを必要とせず、代わりに getMemoryClass() の制限値を維持する必要がある、と述べられています。

私の推測が正しければ、このオプションを使用すると、root 化した OS でヒープを増やしたユーザーが使用できる領域を使用するのと同じ利点 (と危険性) があります (つまり、アプリケーションが追加のメモリを使用すると、ユーザーが同時に実行している他のアプリケーションとうまく動作しなくなる可能性があります)。

メモリ クラスは明らかに 8 MB の倍数である必要はないことに注意してください。

上記からわかることは getMemoryClass() の結果は、与えられたデバイス/OSの構成に対して不変であるのに対し、maxMemory()の値はヒープがユーザーによって異なるように設定されたときに変化することがわかります。

私自身の実際の経験では、G1 (メモリ クラスが 16) で、ヒープ サイズとして 24MB を手動で選択すると、メモリ使用量が 20MB (おそらく 24MB まで行けると思いますが、私はこれを試していません) に向かってドリフトすることを許可されても、エラーなしで実行することができます。 しかし、他の同じような大きさのアプリは、私のアプリが豚になった結果、メモリからフラッシュされるかもしれません。 また、逆に 私の はメモリからフラッシュされるかもしれません。

で指定されたメモリ量を超えることはできないわけです。 maxMemory() . また を試してみてください。 で指定された範囲内にとどまるように getMemoryClass() . 他のすべてが失敗した場合、そのようなデバイスの機能を、メモリを節約する方法で制限することが 1 つの方法かもしれません。

で指定されたメガバイトの数を超える予定がある場合は、最後に getMemoryClass() に指定されたメガバイト数を超える予定がある場合、私のアドバイスは、アプリの状態の保存と復元に長い時間と労力を費やすことです。 onStop() / onResume() のサイクルが発生します。

私の場合、パフォーマンスの理由から、アプリを 2.2 以降を実行しているデバイスに限定しており、それは、私のアプリを実行しているほとんどすべてのデバイスが 24 以上の memoryClass を持つことを意味します。 したがって、最大 20MB のヒープを占有するように設計でき、ユーザーが同時に実行する可能性のある他のアプリとうまく動作することにかなり自信を持てます。

しかし、古いデバイス (例: G1) に Android の 2.2 以上のバージョンをロードしているルート ユーザーが常に少数存在します。 このような構成に遭遇した場合、理想的には、メモリ使用量を削減する必要がありますが、たとえ maxMemory() が 16MB よりもはるかに大きいメモリを使用できることを告げている場合でも、メモリの使用を抑えるのが理想的です。 getMemoryClass() はあなたに べきである をターゲットにする必要があります。 そして、アプリがその予算内に収まることを確実に保証できないのであれば、せめて onStop() / onResume() はシームレスに動作します。

getMemoryClass() は、上記の Diane Hackborn (hackbod) が示すように、API レベル 5 (Android 2.0) までしか利用できないため、彼女が助言するように、以前のバージョンの OS を実行しているデバイスの物理ハードウェアは、16 MB 以下のヒープ領域を占有するアプリを最適にサポートするよう設計されていると考えてよいでしょう。

これに対して maxMemory() は、ドキュメントによると、APIレベル1まで遡って利用可能です。 maxMemory() は、2.0 より前のバージョンでは、おそらく 16MB の値を返しますが、私は を実行します。 で、ユーザーは 12MB という低いヒープ値を選択できることを確認しました。 maxMemory() の値をテストし続けることをお勧めします。たとえ 2.0 より前の OS のバージョンであっても。 万が一、この値が 16MB よりもさらに低く設定されている場合は、実行を拒否する必要があるかもしれません。 maxMemory() は許可されていることを示しています。