我知道JVM进程的-Xms
标志是允许JVM进程使用特定数量的内存来初始化其进程。关于Java应用程序的性能,通常建议在启动应用程序时为-Xms
和-Xmx
设置相同的值,如-Xms2048M -Xmx2048M
。
我很好奇-Xms
和-Xmx
标志是否表示JVM进程预留了特定的内存量,以防止同一台机器中的其他进程使用它。 / p>
这是对的吗?
答案 0 :(得分:7)
Xmx
仅保留虚拟地址空间。
Xms
实际上是分配(提交)它,但不一定是预先故障。
操作系统对分配的响应方式各不相同。
Windows允许您保留非常大的地址空间块(Xmx),但不允许过度使用(Xms)。限制由swap + physical定义。例外是大页面(需要使用组策略设置启用),这将通过物理ram限制它。
Linux行为更复杂,它取决于vm.overcommit_memory
和相关的sysctls以及传递给mmap系统调用的各种标志,这在某种程度上可以由JVM配置标志控制。行为的范围可以从a)Xms可以超过总ram + swap到b)Xmx受可用物理ram的限制。
答案 1 :(得分:2)
JVM进程是否预留了特定的内存量?
是的,JVM在开始时保留Xms
指定的内存,并且可能保留最多Xmx
但预留不需要在物理内存中,也可以在交换中。根据需要,JVM页面将进出内存。
为什么建议Xms和Xmx具有相同的值?
注意:对于生产系统,通常建议设置Xms
和Xmx
,其中计算机专用于单个应用程序(或者没有多少应用程序竞争系统资源)。这并不能说明它到处都是好的。
避免堆大小:
JVM最初以Xms
值指定的堆大小开始。当堆由于应用程序分配对象而耗尽时。 JVM开始增加堆。每次JVM增加堆大小时,它都必须向操作系统询问额外的内存。这是一项耗时的操作,会导致gc暂停时间增加,并导致请求的响应时间缩短。
应用行为从长远来看:
即使我无法概括,但从长远来看,许多应用程序最终会增长到最大堆值。这是开始使用最大内存而不是随着时间的推移增加堆并创建堆调整大小的不必要开销的另一个原因。这就像要求应用程序在开始时占用内存最终将占用内存。
GC的数量::
从较小的堆大小开始会导致更频繁的垃圾回收。较大的堆大小会减少发生的gcs数量,因为更多内存可用于对象分配。但是必须注意,增加的堆大小会增加gc的暂停时间。仅当您的垃圾收集已正确调整且暂停时间不会随堆大小的增加而显着增加时,这才是一个优势。
这样做的另一个原因是服务器通常会带有大量内存,那么为什么不使用可用的资源呢?
答案 2 :(得分:2)
简短的回答:取决于操作系统,尽管它在所有流行的操作系统中绝对是NO。
我将在这里以Linux的内存分配术语为例。
-Xms和-Xmx指定JVM堆的最小和最大大小。这些大小反映了VIRTUAL MEMORY分配,可以随时物理映射到RAM中的页面,称为进程的RESIDENT SIZE。
当JVM启动时,它将分配-Xms的虚拟内存量。一旦在堆上动态创建更多对象,就可以将其映射到驻留内存(物理内存)。此操作不需要JVM请求来自操作系统的任何新分配,但会增加RAM利用率,因为这些虚拟页面现在实际上也具有相应的物理内存分配。但是,一旦您的进程尝试在RAM上消耗其所有Xms分配后在堆上创建更多对象,它就必须从操作系统请求操作系统获取更多虚拟内存,以后可能/也可能不会映射到物理内存,具体取决于何时你需要它。这个限制是你的-Xmx分配。
请注意,这是可能的,因为Linux中的内存是共享的。因此,即使进程事先分配了内存,它所获得的是虚拟内存,它只是一个可寻址的连续虚构分配,可能会也可能不会根据需求映射到真实的物理页面。阅读this answer,了解内存管理在常用操作系统中的工作原理。 Here是关于Linux内存管理如何工作的非常详细(稍微过时但非常有用)的信息。
另请注意,这些标志仅影响堆大小。您将看到的驻留内存大小将大于当前JVM堆大小。更具体地说,JVM消耗的内存等于其HEAP SIZE和DIRECT MEMORY,它反映了来自方法堆栈,本机缓冲区分配等的内容。