▼Androidメモ▼
メモリ

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

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

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

java.lang.OutOfMemoryErrorが投げられる。
種類 主な用途
ネイティブヒープ ビットマップ
(※ハニカム以降ではJavaヒープ消費)
Javaヒープ
(Dalvikヒープ)
クラス
オブジェクト
最大サイズ Galaxy S2で700MB。
Galaxy S2で70MB。 MEDIAS N-06Cで30MB。

ハニカム以降ではAndroidManifestのandroid:largeHeap="true"で拡張可能。
GalaxyNexusで256MB
取得方法
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()));

//拡張ヒープサイズ(ハニカム以降)
ActivityManager am=((ActivityManager)
getSystemService(Activity.ACTIVITY_SERVICE));
int largeMemory=am.getLargeMemoryClass();
メモリ確保例 -
種類 コード
ネイティブヒープ Bitmap bmp=Bitmap.createBitmap(
1024,1024/4,Bitmap.Config.ARGB_8888);
ByteBuffer buf=ByteBuffer.allocateDirect(1024*1024);
(※ハニカム以降ではJavaヒープ消費)
Javaヒープ
(Dalvikヒープ)
ByteBuffer buf=ByteBuffer.allocate(1024*1024);



ヒープ割当・解放のテストプログラム
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("ネイティブヒープの負荷","nativeheap"));
layout.addView(makeButton("Javaヒープの負荷","javaheap"));
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("nativeheap")) {
bitmaps.add(Bitmap.createBitmap(1024,1024/4,Bitmap.Config.ARGB_8888));
memory(this);
} else if (tag.equals("javaheap")) {
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

apkの最大サイズ

明確な規定はないものの、ファイル保存領域の制限、マーケットの制限には注意する必要がある。
制限種別 サイズ 参考
ファイル保存領域の制限
(2.2以前は外部SDカードへのアプリ保存ができない)
Nexus Oneで512MB
HTC-03Aで192MB
-
Androidマーケットの制限 20MB程度? Androidのド肝
ドコモマーケットの制限 16MB 突然消失するかもしれないブログ



−戻る−