HiC*_*123 24 java memory jvm memory-management out-of-memory
我正在研究真正了解内存分配在JVM中的工作原理.我正在编写一个应用程序,其中我将失去内存:堆空间异常.
我知道我可以将诸如Xms和Xmx之类的VM参数传递给JVM为正在运行的进程分配的堆空间.这是问题的一种可能的解决方案,或者我可以检查我的代码是否存在内存泄漏并解决问题.
我的问题是:
1)JVM如何为自己实际分配内存?这与操作系统如何将可用内存传递给JVM有何关系?或者更一般地说,任何进程的内存分配实际上如何工作?
2)虚拟内存如何发挥作用?假设您有一个具有32GB物理内存的系统,并且您将所有32GB分配给您的Java进程.假设您的进程实际上消耗了所有32GB的内存,我们如何强制使用虚拟内存而不是运行到OOM异常?
谢谢.
Pet*_*rey 23
JVM如何为自己实际分配内存?
对于堆,它分配一个大的最大内存的连续区域.最初这是虚拟存储器,但是随着时间的推移,它在OS的控制下成为所使用部分的真实存储器
这与操作系统如何将可用内存传递给JVM有何关系?
JVM不知道操作系统中的空闲内存.
或者更一般地说,任何进程的内存分配实际上如何工作?
一般来说,它使用malloc和free.
虚拟内存如何发挥作用?
最初分配虚拟内存,这将变为使用的实际内存.这对任何过程都是正常的.
假设您有一个具有32GB物理内存的系统,并且您将所有32GB分配给您的Java进程.
你不能.操作系统需要一些内存,并有内存用于其他目的.即使在JVM中,堆也只是所用内存的一部分.如果你有32 GB的内存我建议最大24 GB.
假设你的进程实际上消耗了所有32GB的内存,
假设你有48 GB,并启动一个使用32 GB主内存的进程.
我们如何强制使用虚拟内存而不是运行到OOM异常?
该应用程序从一开始就使用虚拟内存.您不能使堆太大,因为如果它开始交换您的机器(不仅仅是您的应用程序)将变得无法使用.
通过使用off heap memory,您可以使用比物理更多的内存.但是,托管内存必须位于物理内存中,因此如果需要32 GB堆,请购买64 GB主内存.
想要分配内存的JVM(或任何进程)将调用C运行时' malloc '函数.此函数维护C运行时的堆内存.反过来,它从操作系统内核获取内存 - 用于此的函数取决于平台; 在Linux中它可以使用brk或sbrk系统调用.
一旦JVM获得了内存,它就会管理内存本身,将其中的一部分分配给正在运行的程序创建的各种对象.
虚拟内存完全由操作系统内核处理.内核管理物理内存页面到各种进程的地址空间的映射; 如果物理内存少于系统中所有进程所需的内存,则OS内核会将其中一些内容交换到磁盘.
您不能(也不需要)强制进程使用虚拟内存.它对您的流程是透明的.
如果您遇到"内存不足"错误,原因很可能是:
正在超出JVM限制.这些由您在问题中声明的各种命令行参数和/或属性控制
操作系统可能已用尽交换空间(或者没有配置任何交换空间开始).或者某些操作系统甚至不支持虚拟内存,在这种情况下,您的实际内存已用完.
大多数操作系统都有管理员限制进程占用的内存量的工具 - 例如,在Linux中使用setrlimit系统调用和/或ulimit shell命令,这两者都设置了内核将遵守的限制.如果进程请求的内存多于限制允许的内存,则尝试将失败(通常会导致内存不足消息).