▼Androidメモ▼
メモリ

ヒープの種類
種類 Linuxヒープ アプリケーションヒープ(ネイティブヒープ+Javaヒープ)
説明 1つの端末に割り当てられるメモリ。

低メモリ状態になった時、
ActivityクラスのonLowMemory()メソッドが呼ばれる。
1つのアプリに割り当てるメモリ。
Linuxヒープをアプリ毎にアプリケーションヒープに振り分けて利用。

ネイティブヒープとJavaヒープ(Dalvikヒープ)に分けられ、
その合計がアプリケーションヒープの最大サイズを越えると

java.lang.OutOfMemoryErrorが投げられる。
種類 主な用途
ネイティブヒープ ビットマップ(Android 3.0以前)
Javaヒープ
(Dalvikヒープ)
クラス
オブジェクト
ビットマップ(Android 3.0
以降)
最大サイズ Galaxy Nexusで1GB。
Galaxy Nexusでは通常64MB、Large Heap256MB。

Large HeapはAndroid 3.0以降の機能で、
AndroidManifestに「android:largeHeap="true"」を追加。
取得方法
ActivityManager.MemoryInfo info=
new ActivityManager.MemoryInfo();
ActivityManager am=((ActivityManager)context.
getSystemService(Activity.ACTIVITY_SERVICE));
am.getMemoryInfo(info);

//Linuxヒープの空きサイズ
long linuxHeap=info.availMem;

//低メモリ状態かどうか
boolean lowMemory=info.lowMemory;
//低メモリ状態までの有効メモリ
long threshold=info.threshold;
//ネイティブヒープの利用サイズ
long nativeHeap=Debug.getNativeHeapAllocatedSize();


//Javaヒープの利用サイズと最大サイズ
Runtime runtime=Runtime.getRuntime();
long javaHeap=(runtime.totalMemory()-runtime.freeMemory()));
long maxJavaHeap=runtime.maxMemory();



EclipseでのJavaヒープの監視
Heapのカラム 説明 Runtimeクラス
Heap Size
Javaヒープの確保済みメモリのサイズ
必要に応じて確保され、最大値まで増える。
減ることはなく、
アプリがバックグラウンドの時に必要に応じてまるごと解放される。
runtime.totalMemory()
Allocated Javaヒープのメモリの利用サイズ runtime.totalMemory()-runtime.freeMemory()
フリー Javaヒープのフリーメモリの利用サイズ runtime.freeMemory()

ヒープ割当・解放のテストプログラム
HeapEx.java
package net.npaka.heapex;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Debug;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.LinearLayout;

//ヒープ割当・解放のテストプログラム
public class HeapEx extends Activity implements
View.OnClickListener {
private final static int WC=LinearLayout.LayoutParams.WRAP_CONTENT;

private ArrayList<Bitmap> bitmaps=new ArrayList<Bitmap>();
private ArrayList<Object> objects=new ArrayList<Object>();

//初期化
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
requestWindowFeature(Window.FEATURE_NO_TITLE);

//レイアウトの生成
LinearLayout layout=new LinearLayout(this);
layout.setBackgroundColor(Color.rgb(255,255,255));
layout.setOrientation(LinearLayout.VERTICAL);
setContentView(layout);

//ボタンの生成
layout.addView(makeButton("ビットマップ(1KB)の追加","bitmap"));
layout.addView(makeButton("バイト配列(1KB)の追加","data"));
layout.addView(makeButton("解放","release"));
layout.addView(makeButton("メモリ表示","memory"));
}

//ボタンの生成
private Button makeButton(String text,String tag) {
Button button=new Button(this);
button.setText(text);
button.setTag(tag);
button.setOnClickListener(this);
button.setLayoutParams(new LinearLayout.LayoutParams(WC,WC));
return button;
}

//ボタンクリック時に呼ばれる
public void onClick(View view) {
String tag=(String)view.getTag();
if (tag.equals("bitmap")) {
bitmaps.add(Bitmap.createBitmap(1024,1024/4,Bitmap.Config.ARGB_8888));
memory(this);
} else if (tag.equals("data")) {
objects.add(ByteBuffer.allocate(1024*1024));
memory(this);
} else if (tag.equals("release")) {
bitmaps=new ArrayList<Bitmap>();
objects=new ArrayList<Object>();
memory(this);
} else if (tag.equals("memory")) {
memory(this);
}
}

//メモリの出力
private void memory(Context context) {
android.util.Log.e("debug","--------------------");
android.util.Log.e("debug","ビットマップ,バイト配列>"+
bitmaps.size()+","+objects.size());
System.gc();

//Linuxヒープの空きサイズ
ActivityManager.MemoryInfo info=new ActivityManager.MemoryInfo();
ActivityManager am=((ActivityManager)context.
getSystemService(Activity.ACTIVITY_SERVICE));
am.getMemoryInfo(info);
long linuxHeap=info.availMem;
android.util.Log.e("debug","空きLinuxヒープ>"+
num2str(linuxHeap));

//アプリケーションヒープの利用サイズ
long nativeHeap=Debug.getNativeHeapAllocatedSize();
Runtime runtime=Runtime.getRuntime();
long javaHeap=runtime.totalMemory()-runtime.freeMemory();
long appHeap=nativeHeap+javaHeap;
android.util.Log.e("debug","アプリケーションヒープ(ネイティブ+Java)>"+
num2str(appHeap)+"("+num2str(nativeHeap)+"+"+num2str(javaHeap)+")");
}

//数値→文字列
private String num2str(long num) {
if (num<1024) return num+"B";
num/=1024;
if (num<1024) return num+"KB";
num/=1024;
return num+"MB";
}
}

メモリリークの注意点
アクティビティはContextとして利用し安いが、参照を長期間保持するとメモリリークの元。
アプリケーションオブジェクトを利用した方が良い。
「Hoge.this」→「Hoge.this.getApplication()」
[参考]Avoiding memory leaks

ストレージの種類
種類 内部ストレージ(システムメモリ) 外部ストレージ(ユーザーメモリ)
説明 本体のファイル保存領域。 外部SDカードのファイル保存領域。
最大サイズ GalaxyS2で2GB。
SDカードのサイズ。

adbコマンド
操作 書式 コマンド
メモリ簡易出力 adb shell procrank adb shell procrank

種類 説明
VSS(Virtual Set Size) 仮想メモリの消費量
RSS(Resident Set Size) 物理メモリの消費量
PSS(Proportional Set Size) プロセスのヒープ所有サイズ
USS(Unique Set Size) プロセスのヒープ利用サイズ
メモリ詳細出力 adb shell dumpsys meminfo パッケージ名 adb shell dumpsys meminfo net.npaka.helloworld

  native dalvik other total
size ネイティブヒープの
所有サイズ
Javaヒープの
所有サイズ
N/A アプリケーションヒープの所有サイズ
このサイズがアプリケーションヒープの
最大サイズを越えると
OutOfMemoryError発生
allocated ネイティブヒープの
利用サイズ
Javaヒープの
利用サイズ
N/A アプリケーションヒープの利用サイズ
 
内部ストレージ容量出力 adb shell df /data adb shell df /data


−戻る−