Android NDK:Dalvik堆和本地堆 - 如何区分两者

16
我知道在Android平台中有Dalvik(JVM)堆和本地堆。Dalvik GC不处理本地堆。但我不确定它们是如何工作的,我的意思是Android OS如何将它们分开?
可能情况1:由单独的内存硬件组成(我不太相信)。
可能情况2:Android OS有固定的内存量用于两种堆。
可能情况3:当必要时,Android OS需要将一部分Dalvik内存堆分配为本地堆,因此本地堆和Dalvik堆的大小是灵活的。
哪一个是真实的或者我没有提到的其他可能性?
3个回答

10
本地堆由“dlmalloc()”管理,它使用“mmap()”和标准调用(例如“sbrk()”)的组合来分配内存。管理的(“Dalvik”)堆大多是用“mmap()”分配的一个大块。这一切都在Linux内核之上运行,因此如果你理解Linux内存管理,那么你已经知道底层部分如何工作了。
您可以阅读更多关于Dalvik如何从托管堆返回空页面到操作系统的信息,在此帖子中。 编辑: 关于Android内存管理的信息的规范帖子是这个。我不认为它直接回答了您的问题,但它有很多好的信息和链接到信息丰富的网站。

2
我对Linux内存管理或Android操作系统的底层部分并不是很了解。你有没有任何介绍它们的链接? - Keith Mak
1
我没有可以推荐的网站。在某种程度上,你从哪里开始取决于你对malloc/sbrk/mmap、虚拟内存以及需要多精确的答案有多少了解。要得到非常精确的答案,您需要阅读代码并理解它。对于不太精确的答案,我可以说,“堆是分开的,Dalvik堆大小受限制,本地堆没有固定限制;Dalvik堆容量是每个进程而不是每个设备的”。 - fadden
1
你说本地堆没有限制,那么当需要更多的内存空间时,本地堆是否会使用dalvik内存? - Keith Mak
1
不,如果您请求太多,您只会耗尽内存。 - fadden
我知道,但当需要更多的本地内存时,原始堆是否会使用分配给dalvik堆的内存空间? - Keith Mak

3

这已经是你的第二个案例了

有两个不同的堆(heap),一个是为运行时Art(之前是DalvikVM)准备的,另一个是为本地(native)程序准备的。

您可以通过在proc文件系统的maps伪文件上执行cat来轻松看到这两个不同的区域。

请考虑以下输出:

2a028000-2a029000 rw-p 00000000 00:00 0          [heap]
b6400000-b6c00000 rw-p 00000000 00:00 0          [anon:libc_malloc]

在上面的例子中,第一个仅有一个页面长度的区域由ART Runtime管理。同时支持dlmallocrosalloc,但ART使用rosalloc,因为它更快。与@fadden所说的相反(至少对于棒棒糖),这个区域由sbrk管理。它向上增长。
第二个区域有2048个页面长度,是native heap。它由库使用,这是Android上libc的实现。同时支持dlmallocjemalloc,使用哪一个取决于设备。我没有找到扩展该堆的调用方法,但我想mmap应该足够了。它向下增长,朝向runtime堆。

“cat on the maps pseudo-file of the proc filesystem” 的意思是“在 proc 文件系统的伪文件上执行 cat 命令”。完整命令是 cat /proc/meminfo 吗? - IgorGanapolsky
使用命令 cat /proc/<pid>/maps(将 <pid> 替换为 self 可以获得您要运行的 cat 命令的 maps 文件)。 - Paschalis
似乎[堆]VMA并未由ART运行时管理,而fadden所说的ART运行时使用大量内存的说法确实是正确的。 - lirui

3
由于Android是开源的,您可以自己查看源代码。看起来它调用create_mspace_with_base()。我不确定它具体做了什么,但根据这篇文章, 它将内存映射到/dev/zero
因此,它确实使用了“单独的”堆。它直接分配自己的内存页面并自己管理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接