有两个不同的内存限制。虚拟内存限制和物理内存限制。
虚拟内存
虚拟内存受可用地址空间的大小和布局限制。通常,最开始是可执行代码和静态数据以及过去增加堆的内容,而最后是内核保留的区域,然后是共享库和堆栈(在大多数平台上会减少)。这样就给堆和栈提供了可用的增长空间,而其他区域在进程启动时是已知的并已修复。
可用虚拟内存最初并未标记为可用,但在分配期间被标记为可用。尽管堆可以增长到所有可用内存,但是大多数系统不会自动增长堆栈。IIRC堆栈的默认限制在Linux上为8MiB,在Windows上为1MiB,并且可以在两个系统上更改。虚拟内存还包含任何内存映射文件和硬件。
不能(任意)自动增长堆栈的原因之一是,多线程程序需要为每个线程使用单独的堆栈,因此它们最终会互相干扰。
在32位平台上,虚拟内存总量为4GiB,Linux和Windows通常都为内核保留最后的1GiB,最多为您提供3GiB的地址空间。有一个特殊的Linux版本,它不保留任何东西给您完整的4GiB。这对于罕见的大型数据库很有用,因为最后一个1GiB节省了一天的时间,但是对于常规使用,由于额外的页表重新加载,它的速度稍慢一些。
在64位平台上,虚拟内存为64EiB,您无需考虑。
物理内存
物理内存通常仅在进程需要访问时才由操作系统分配。进程使用多少物理内存是非常模糊的数字,因为进程之间共享一些内存(代码,共享库和任何其他映射的文件),文件中的数据按需加载到内存中,而当内存不足时会被丢弃。可以交换“匿名”内存(没有文件支持的内存)。
在Linux上,当物理内存用尽时会发生什么情况取决于vm.overcommit_memory
系统设置。默认为过量使用。当您要求系统分配内存时,它会为您分配一些内存,但只会分配虚拟内存。当您实际访问内存时,它将尝试使用一些物理内存,丢弃可重新读取的数据或根据需要交换数据。如果发现它无法释放任何东西,它将简单地将进程从存在中移除(没有办法做出反应,因为这种反应可能需要更多的内存,并且会导致无限循环)。
这就是进程在Android(也是Linux)上死亡的方式。逻辑通过使用哪个逻辑从哪个进程中删除来进行了改进,该逻辑基于该进程正在执行的操作以及该进程的存在时间。比android进程简单地停止执行任何操作,而是坐在后台,当需要新的内存时,“内存不足杀手”将杀死它们。