Java如何在运行时动态增加Xmx的大小

7
我在我的机器上有一个jvm服务器,现在我想要两个apservers坐在同一台机器上,但是我希望备用服务器分配的内存量非常低,因为它是被动的。当主服务器(活动状态)崩溃时,我希望将更多的内存分配给我的备用服务器,而不必重新启动它(我已经让它们都有太多的xmx-请注意它们会在启动时消耗内存,我不能允许内存不足的可能性)。
所以我想要备用服务器-低xmx 一旦活动服务器崩溃,我希望我的备用服务器能够获得更多的xmx。
有没有办法实现这一点。 谢谢
4个回答

5
很遗憾,据我所知,在Sun提供的JVM中,这不是一个选项。
Xmx选项是指定最大内存的,它的作用是防止JVM消耗整个机器的空闲内存。如果你想将其设置得更高,就不需要JVM分配所有内存。为什么不将其设置为非常高的数字,并让JVM随着时间的推移逐渐增长呢?
为了确保您的JVM不会从太少的内存开始(创建很多暂停,因为它增加内存到所需的大小),请将Xms调整为您希望在启动时为JVM分配的大小。

我理解这一点,但是一旦我告诉JVM XMX = somevalue,那么在我的看法中,JVM就允许消耗它,我甚至不能让它有最小的可能需要它(请参见我的上一个评论)。 - Jas
4
在实践中,我发现 JVM 会使用你告诉它要使用的一切。即使你只有10MB的硬引用对象,如果你给它-Xmx100G,即使内存中几乎所有的对象都可以被收集,它也会使用100G的内存。这就是为什么他们让我们明确指定内存大小的原因——因为他们不知道如何管理内存,使其自动增长。 - Hakanai

3
短答案是,除非您特定的JVM允许在初始化后更改这些值,否则您不能(我认为HotSpot也是如此)。
然而,您可以通过不在运行时更改Xmx的方式来实现您的目标。例如,您可以使用较小的-Xms设置,但保持-Xmx相对较高。如果被动服务器在仍然作为备份提供服务时未使用太多内存/生成垃圾,则内存将保持接近Xms值。但是,一旦备份服务器接管,它将被允许根据需要扩展分配的内存,最多可扩展到Xmx值。
请参见适当的java (windows)java(*nix)(尽管在所有平台上,-Xms和-Xmx具有相同的一般含义)。

2
只要备用实例没有做任何事情(或者几乎没有做任何事情),您不需要调整Xmx,因为它应该保持接近您使用Xms设置的值,直到它开始执行真正的工作。
Xmx开关控制Java实例可以消耗的最大堆大小。Xms控制启动量。
如果您在备用实例上将Xms设置得很小,并将Xmx设置为程序所需的任何最大值,然后切换到备用实例(杀死常规实例),它应该能正常工作。
根据您可用的内存,可能需要实际停止/杀死常规Java进程,以便备用进程分配所有需要的堆空间,从初始较低堆大小向最大堆大小移动。

一旦我告诉JVM XMX=<somenum>,那么在我的观点中,我对此就没有任何控制权,并且我不能百分之百确定jvm不会使用这些内存。谁知道也许在一段时间后,jvm会决定它想要更多的内存-毕竟我无法控制它,即使只有1%的机会,我也不能允许jvm决定需要更多的内存-它在内部执行许多操作,也许它会决定需要更多的内存而不是我的应用程序需要更多,我的备用应用程序服务器有一些线程,它并不像一个完全冻结的应用程序... - Jas
因此,我的担心是,尽管我已经指定了高XMX,并且在某些时候它是备用的,但备用机器在某个时间点可能会使用到这个内存,只是因为JVM决定它需要它(也许它有一些我不知道的算法)。 - Jas
1
@Jason,你可以尝试使用特定的JVM进行测试。你可以运行一个外部监视器(参见hyperic.org,这是一个很好的开源监视器),它可以跟踪JVM内存使用情况和许多其他统计信息。Hyperic可以在备用JVM开始消耗更多内存时向你发出警报。 - Eric J.
您还可以使用“-XX:MaxHeapFreeRatio”来说服JVM将未使用的堆释放回操作系统。 - Piotr Findeisen

0

为了让JVM填满整个堆,您需要生成足够的对象以在年轻代收集之后幸存下来。这在轻负载的备用服务器上是不太可能的。

为了提高在年轻代中捕获所有垃圾的机会,请相应地配置年轻代堆:更大的大小,在对象老化之前有更多的代数。这是将备用服务器限制在年轻代和您在主服务器中所需的收集配置之间的折衷。

更新:新的G1收集器使用不同的配置选项。请查看http://www.oracle.com/technetwork/tutorials/tutorials-1876574.html以了解更多信息。对于您的情况最相关的选项是

-XX:InitiatingHeapOccupancyPercent=45 - 堆占用率达到此值时开始并发GC周期。G1根据整个堆的占用情况而不是其中一个代的情况来触发并发GC周期。值为0表示“进行常量GC周期”。默认值为45(即45%满或占用)。

换句话说,当当前堆(最小堆大小)使用了45%时,相当于年轻代收集将开始。您的轻负载服务器不应该离开最小堆大小(除非它生成相对寿命较长的对象,在这种情况下请参阅-XX:MaxTenuringThreshold)。

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