-Xms 和 -Xmx 标志是否保留计算机的资源?



我知道JVM进程的-Xms标志是允许JVM进程使用特定数量的内存来初始化其进程。关于 Java 应用程序的性能,通常建议在启动应用程序时将相同的值设置为-Xms-Xmx,例如-Xms2048M -Xmx2048M.

我很好奇-Xms-Xmx标志是否意味着 JVM 进程为特定的内存量预留以防止同一台机器中的其他进程使用它。

这是对的吗?

Xmx只保留虚拟地址空间。Xms实际上分配(提交)它,但不一定预先错误。

操作系统对分配的响应方式各不相同。

Windows确实允许您保留非常大的地址空间块(Xmx),但不允许过度使用(Xms)。限制由掉期 + 实物定义。例外情况是大页面(需要使用组策略设置启用),这将通过物理 ram 对其进行限制。

Linux 行为比较复杂,它取决于传递给 mmap syscall 的vm.overcommit_memory和相关 sysctls 以及各种标志,这在一定程度上可以通过 JVM 配置标志来控制。行为范围可以从 a) Xms 可以超过总 ram + 交换到 b) Xmx 由可用的物理 ram 限制。

简短回答:取决于操作系统,尽管它在所有流行的操作系统中绝对是 NO。

我将在这里以 Linux 的内存分配术语为例。

-Xms 和 -Xmx 指定 JVM 堆的最小和最大大小。这些大小反映了虚拟内存分配,可以随时物理映射到 RAM 中的页面,称为进程的驻留大小。

当 JVM 启动时,它将分配 -Xms 的虚拟内存量。一旦在堆上动态创建更多对象,就可以将其映射到驻留内存(物理内存)。此操作不需要 JVM 从操作系统请求任何新的分配,但会增加您的 RAM 利用率,因为这些虚拟页面现在实际上也将具有相应的物理内存分配。但是,一旦您的进程在 RAM 上消耗其所有 Xms 分配后尝试在堆上创建更多对象,它就必须向操作系统请求操作系统提供更多虚拟内存,这些虚拟内存也可能/可能不会在以后映射到物理内存,具体取决于您需要它的时间。此限制是您的 -Xmx 分配。

请注意,这一切都是可能的,因为 linux 中的内存是共享的。因此,即使一个进程事先分配了内存,它得到的只是虚拟内存,它只是一个可寻址的连续虚构分配,根据需求,可能会也可能不会映射到真实的物理页面。阅读此答案,了解内存管理在流行操作系统中的工作原理。这里有一个关于 Linux 内存管理如何工作的非常详细(略微过时但非常有用)的信息。

另请注意,这些标志仅影响堆大小。您将看到的驻留内存大小将大于当前的 JVM 堆大小。更具体地说,JVM消耗的内存等于其堆大小加上直接内存,后者反映了来自方法堆栈,本机缓冲区分配等的内容。

JVM 进程是否为特定的内存量进行了预留?

是的,JVM 在开始时保留Xms指定的内存,并且最多可以保留Xmx但保留不必在物理内存中,也可以在交换中。JVM 页面将根据需要交换入和换出内存。


为什么建议对 Xms 和 Xmx 具有相同的值?

注意:对于计算机专用于单个应用程序(或者没有很多应用程序争用系统资源)的生产系统,通常建议设置XmsXmx。这并不能概括它到处都是好的。

避免堆大小:

JVM 最初从Xms值指定的堆大小开始。当堆由于应用程序分配对象而耗尽时。JVM 开始增加堆。每次 JVM 增加堆大小时,它都必须要求操作系统提供额外的内存。这是一项耗时的操作,会导致 gc 暂停时间增加,并反过来增加请求的响应时间。

从长远来看,应用程序行为:

尽管我不能一概而论,但从长远来看,许多应用程序最终会增长到最大堆值。这是从最大内存开始的另一个原因,而不是随着时间的推移增加堆并创建不必要的堆大小调整开销。这就像要求应用程序在开始时占用内存本身,最终会占用内存。

指导性案例数量:

从较小的堆大小开始会导致更频繁地进行垃圾回收。堆大小越大,发生的 gc 数就越少,因为有更多的内存可用于对象分配。但是,必须注意的是,增加堆大小会增加 gc 暂停时间。仅当垃圾回收已正确调整并且暂停时间不会随着堆大小的增加而显著增加时,这才具有优势。

这样做的另一个原因是服务器通常具有大量内存,那么为什么不使用可用的资源呢?

最新更新