メモリ確保に関して

2,437 views
Skip to first unread message

peach

unread,
Mar 30, 2011, 11:20:40 AM3/30/11
to 日本Androidの会
いつもお世話になっております。
メモリ確保に関して不明な点があるので質問させてください。

具体的には、Nativeコード内でのメモリ確保に関してなのですが、
どのような領域から確保されるのでしょうか?

DalvikVMには、DalvikHeapとNativeHeapがあるようですが、
この二つのヒープの違いと使われ方がわかりません。
出来れば、管理のされ方(アプリ毎にあるのか)や
メモリの制限(上限・メモリが不足した場合はどうなるのか)なども知りたいです。

詳しい方いらっしゃいましたら、ご教授お願い致します。

ohisamallc

unread,
Mar 30, 2011, 6:40:08 PM3/30/11
to android-g...@googlegroups.com
山形のohisamaです。
がんばろう東北。

自分も、調査中です。
調査のため、ツールを作ってます。
Another availMem
 タスクキラーです。
Another System Info
 メモリーの領域毎使用を表示します。ついでにopenglも
調査方法は、アプリの起動前後のメモリの使用量を
確認します。
アプリは、タスクキラーで消さないとメモリに残ります。
アプリ起動にメモリ足りないと、バックのアプリが
消されます。(この辺りは、タスクキラーで見れる)
nativeからは、7mbは使えました。
たぶん10mb辺りが限界かと。
すいません上記、有料です。

> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送られ

> います。
> このグループに投稿するには、android-g...@googlegroups.com にメール

> 送信してください。
> このグループから退会するには、
> android-group-j...@googlegroups.com にメールを送信してくださ

> 。
> 詳細については、http://groups.google.com/group/android-group-japan?hl=ja

> らこのグループにアクセスしてください。
>
>
>

大垣憲俊

unread,
May 29, 2011, 1:19:07 PM5/29/11
to 日本Androidの会
大垣です。

> > 具体的には、Nativeコード内でのメモリ確保に関してなのですが、
> > どのような領域から確保されるのでしょうか?
> > DalvikVMには、DalvikHeapとNativeHeapがあるようですが、
> > この二つのヒープの違いと使われ方がわかりません。
> > 出来れば、管理のされ方(アプリ毎にあるのか)や
> > メモリの制限(上限・メモリが不足した場合はどうなるのか)なども知りたいです。

同じような質問と回答を見つけました。

http://groups.google.com/group/android-platform/browse_thread/thread/769e86b14881ca74/5154f0b9fc6b5fff?lnk=gst&q=heap#5154f0b9fc6b5fff


すみませんが、めんどうなので訳さずに、一部引用します。

Maximum dvm heap size limits external heap and gc heap.
Because of external heap plus gc heap can't exceed dvm max heap size.

When we use a user defined JNI native method.
and JNI native method use a native heap using malloc().
In this case, native heap usage is not tracked by dvm.
These means native heap usage could exceed dvm max heap size.

As of Honeycomb bitamps are allocated on the DVM heap.

たろサ

unread,
May 29, 2011, 4:26:52 PM5/29/11
to android-g...@googlegroups.com
 こんにちは、たろサです。

 私の理解なので、間違っていたら、どなたか訂正お願いします。

 NativeコードもDalvikVMが確保するメモリも同じheap(bionic libc管理)から
確保していると理解しています。

 ただし、DalvikVMから確保できるheapの量は規定されていると理解していま
す。なので、DalvikVMの規定heap量を超えてなくても、bionic libcにメモリを
もらいに行ったときに、heapが足りないと、エラーになって確保できませんし、
heapに余裕があっても、アプリの規定heap量を超えてメモリを確保しようとして
も、エラーになって確保できない。と理解しています。

 DalvikVMの方は、中でメモリリークしないように作っているとは思いますが、
Nativeコードはちゃんと開放しないとメモリリークすると思います。

--
山本三七男 (Minao Yamamoto) ---------------- ハンドル:たろサ -----
E-Mail: taro...@gmail.com

たろサ

unread,
May 29, 2011, 5:24:05 PM5/29/11
to android-g...@googlegroups.com
 たろサです。

 便乗質問なのですが、mallocとfreeのinternal callは、dlmallocにdefineさ
れていると思っていたのですが、

bionic/libc/bionic/dlmalloc.cのinternal callのdefineの部分を、
下記のように書き換えてみたところ、internal_mallocとinternal_freeがdefine
していないとエラーで怒られました。
---
#if ONLY_MSPACES
//#define internal_malloc(m, b) mspace_malloc(m, b)
//#define internal_free(m, mem) mspace_free(m,mem);
#else /* ONLY_MSPACES */
#if MSPACES
//#define internal_malloc(m, b) (m == gm)? dlmalloc(b) :
mspace_malloc(m, b)
//#define internal_free(m, mem) if (m == gm) dlfree(mem); else
mspace_free(m,mem);
#else /* MSPACES */
#define internal_malloc(m, b) dlmalloc(b)
#define internal_free(m, mem) dlfree(mem)
#endif /* MSPACES */
#endif /* ONLY_MSPACES */
---

 あれ?と思って、下記のように変更してmakeしても、internal_mallocと
internal_freeがdefineしていないとエラーで怒られました。
---
#if ONLY_MSPACES
#define internal_malloc(m, b) mspace_malloc(m, b)
#define internal_free(m, mem) mspace_free(m,mem);
#else /* ONLY_MSPACES */
#if MSPACES
//#define internal_malloc(m, b) (m == gm)? dlmalloc(b) :
mspace_malloc(m, b)
//#define internal_free(m, mem) if (m == gm) dlfree(mem); else
mspace_free(m,mem);
#else /* MSPACES */
//#define internal_malloc(m, b) dlmalloc(b)
//#define internal_free(m, mem) dlfree(mem)
#endif /* MSPACES */
#endif /* ONLY_MSPACES */
---

 おやおや?と思って、下記のように変更してmakeすると、通りました。
---
#if ONLY_MSPACES
#define internal_malloc(m, b) mspace_malloc(m, b)
#define internal_free(m, mem) mspace_free(m,mem);
#else /* ONLY_MSPACES */
#if MSPACES
//#define internal_malloc(m, b) (m == gm)? dlmalloc(b) :
mspace_malloc(m, b)
//#define internal_free(m, mem) if (m == gm) dlfree(mem); else
mspace_free(m,mem);
#else /* MSPACES */
#define internal_malloc(m, b) dlmalloc(b)
#define internal_free(m, mem) dlfree(mem)
#endif /* MSPACES */
#endif /* ONLY_MSPACES */
---

 原因がいまいちよく分からないのですが、internal_mallocは、dlmallocを
使っているのでしょうか、それとも、mspace_mallocを使っているのでしょうか。

 もしかしたら、dalvikVMのmakeの際にはmspace_mallocを使って、libcのmake
にdlmallocを使っているなんて、そんなことは無いですよね。

 どなたか、教えてください。makeしたソースは2.2.2_r1です。

 よろしくお願いします。

たろサ

unread,
May 30, 2011, 1:37:38 AM5/30/11
to android-g...@googlegroups.com
 こんにちは、たろサです。

 自己解決です。
 結論から言うと、HeapSource.cでは、internal callは、mspace_が呼ばれて、
それ以外は、dlmalloc, dlfreeが呼ばれるということでした。

 ソースを追っかけてみると、mspace.hに、下記のように定義されていました。
---
#define MSPACES 1
#define ONLY_MSPACES 1
#include "../../../../bionic/libc/bionic/dlmalloc.h"
---
 mspace.hは、HeapSource.cでincludeされているので、HeapSource.cをコンパ
イルするときは、dlmalloc.hで、下記のところで、internal_mallocは、
mspace_mallocと定義されてコンパイルされるようです。


---
#if ONLY_MSPACES
#define internal_malloc(m, b) mspace_malloc(m, b)
#define internal_free(m, mem) mspace_free(m,mem);
#else /* ONLY_MSPACES */

...
---

 mspace.hをincludeしていない場合は、dlmalloc.c中の下記のところで、
ONLY_MSPACESもMSPACESも、0になるようです。
---
#ifndef ONLY_MSPACES
#define ONLY_MSPACES 0
#endif /* ONLY_MSPACES */
#ifndef MSPACES
#if ONLY_MSPACES
#define MSPACES 1
#else /* ONLY_MSPACES */
#define MSPACES 0
#endif /* ONLY_MSPACES */
#endif /* MSPACES */
---

 それで、その後にある#ifのところで、
---


#define internal_malloc(m, b) dlmalloc(b)
#define internal_free(m, mem) dlfree(mem)

---
が定義されることになります。

 2.2.2_r1だと、ONLY_MSPACESが0で、MSPACESが1という#defineが無いので、下
記の定義は通らないようです。
---


#define internal_malloc(m, b)\
(m == gm)? dlmalloc(b) : mspace_malloc(m, b)

#define internal_free(m, mem)\
if (m == gm) dlfree(mem); else mspace_free(m,mem);

---

 すいません、お騒がせしました。Android難しいよー。

大垣憲俊

unread,
May 30, 2011, 5:28:11 AM5/30/11
to 日本Androidの会
たろサさん

大垣です。

> >  もしかしたら、dalvikVMのmakeの際にはmspace_mallocを使って、
> >  libcのmakeにdlmallocを使っているなんて、そんなことは無いですよね。


MSPACEとは何ぞや? bionic/libc/bionic/dlmalloc.cから引用。


MSPACES default: 0 (false)
If true, compile in support for independent allocation spaces.
This is only supported if HAVE_MMAP is true.

ONLY_MSPACES default: 0 (false)
If true, only compile in mspace versions, not regular versions.

HAVE_MMAP default: 1 (true)
True if this system supports mmap or an emulation of it. If so, and
HAVE_MORECORE is not true, MMAP is used for all system
allocation. If set and HAVE_MORECORE is true as well, MMAP is
primarily used to directly allocate very large blocks. It is also
used as a backup strategy in cases where MORECORE fails to provide
space from system. Note: A single call to MUNMAP is assumed to be
able to unmap memory that may have be allocated using multiple calls
to MMAP, so long as they are adjacent.

tarosa

unread,
Jun 12, 2011, 1:21:55 PM6/12/11
to android-g...@googlegroups.com
 たろサです。

 すっかり、時間が経ってしまいましたが、ソースを追いかけて、やっと、メモリの使われ方について理解しました(したつもりです)。ソースは2.2.2_r1です。

 Nativeコードからmallocするときは、dlmalloc()が呼ばれるので、カーネルが管理するグローバルなメモリから確保されます(malloc_state _gm_を見に行く)。

 DalvikVMは、Zygote()からforkされてアプリが起動するときに、最大heap領域をmmap()によって確保し、アプリは、以後、mmap()からメモリを確保します。forkされるたびにmmap()が確保されるので、アプリ毎に別々のheap領域(mmap())を持つことになります。ただし、Zygote()の基本モジュールはmmap()内で同じ物理アドレスにマッピングされています。

 また、同時にもう1つ別にmmap()が確保されており、これはメモリを割り当てた箇所を別に管理するobjectBitmapという管理テーブル用に確保されています。

 ここで、1つわかったことが、javaの中のライブラリで、JNIからNativeのプログラムが呼ばれている場合、Javaコードといえども、Nativeで作られているため、dlmalloc()でカーネルから直接メモリを確保しているということです。

 ここら辺を抑えておけば、メモリ管理を理解するのが早いのかもしれません。
 linuxの知識が無かったので、理解するのにすごく時間が掛かってしまいました。

 1つ不思議なのは、mspace.cのmspace create_contiguous_mspace_with_name()で、
---
fd = ashmem_create_region(buf, max_capacity);
base = mmap(NULL, max_capacity, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
close(fd);
---
 のように、mmap()を確保したとたんに、close(fd)しているところです。これはこういうものなのでしょうか???

 次は、2.3.3に挑戦かな。DalvikVM内のthread処理がどう変っているのかという興味ですね。

ちなみに、少し読んだのですが、2.3.3はHeapSourceからHeapは2こしか取られなくなっています(Heap heaps[2]ですね)。それで、Heap構造体内にHeapBitmapを持っている必要が無くなったらしく、HeapSourceの方に出してきて、mmap()でliveBitsとmarkBitsと2つのHeapBitmapを確保していますね。こっちの方がスッキリしますね。

 どうも、お騒がせしました。どなたか、上の疑問が分かれば、教えてください。
 よろしくお願いします。

(2011/03/31 0:20), peach wrote:

--

山本三七男 (Minao Yamamoto) ---------------- ハンドル:たろサ -----

Androidで簡単にプログラミングできるLuarida無料公開中。よろしくね!
http://d.hatena.ne.jp/tarosay/

yoshiyuki kanno

unread,
Jun 12, 2011, 7:42:38 PM6/12/11
to android-g...@googlegroups.com
菅野です。

ファイルディスクリプタをcloseしても、仮想アドレス空間にマップされた領域は
munmapされるまで有効です。
なので不要なリソースは即削除しているのでしょう。
詳細はmmapのmapページを参照してみてください。

2011年6月13日2:21 tarosa <taro...@gmail.com>:

yoshiyuki kanno

unread,
Jun 12, 2011, 7:43:59 PM6/12/11
to android-g...@googlegroups.com
>詳細はmmapのmapページを参照してみてください。
すいません。manページの誤りです。。。

2011年6月13日8:42 yoshiyuki kanno <neko...@gmail.com>:

tarosa

unread,
Jun 12, 2011, 11:13:55 PM6/12/11
to android-g...@googlegroups.com
 菅野様、

 たろサです。

> ファイルディスクリプタをcloseしても、仮想アドレス空間にマップされた領域は
> munmapされるまで有効です。

 manで確認しました。しっかり書いていました。
 ありがとうございます。


(2011/06/13 8:42), yoshiyuki kanno wrote:
> 菅野です。
>
> ファイルディスクリプタをcloseしても、仮想アドレス空間にマップされた領域は
> munmapされるまで有効です。
> なので不要なリソースは即削除しているのでしょう。
> 詳細はmmapのmapページを参照してみてください。
>

> 2011年6月13日2:21 tarosa <taro...@gmail.com <mailto:taro...@gmail.com>>:

> <mailto:android-g...@googlegroups.com> にメールを送信してくだ
> さい。
> このグループから退会するには、android-group-
> japan+un...@googlegroups.com
> <mailto:android-group-japan%2Bunsu...@googlegroups.com> にメール
> を送信してください。
> 詳細については、http://groups.google.com/group/android-group-
> japan?hl=ja からこのグループにアクセスしてください。


>
>
> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送ら
> れています。
> このグループに投稿するには、android-g...@googlegroups.com にメー
> ルを送信してください。
> このグループから退会するには、android-group-

> japan+un...@googlegroups.com にメールを送信してください。
> 詳細については、http://groups.google.com/group/android-group-japan?hl=ja
> からこのグループにアクセスしてください。

--

Reply all
Reply to author
Forward
0 new messages