在运行时设置JVM堆大小

64

有没有一种方法可以从运行中的Java程序中设置堆大小?


1
参考资料,这是热点的RFE:bugs.sun.com/bugdatabase/view_bug.do?bug_id=4408373 - Luke Quinane
7个回答

65

第一点。

如果你使用的应用程序具有非常不同的堆需求,那么你可以使用 -Xmx 设置你的最大堆大小,并调整 -XX:MaxHeapFreeRatio-XX:MinHeapFreeRatio,这样当堆缩小时(默认情况下会这样做),应用程序将不会卡住很多内存。

但是请注意,当应用程序实际使用的内存变化强烈且迅速时,这可能会导致性能问题 - 在这种情况下,与其将内存归还给操作系统,然后在一秒钟后再次索取,你最好让它保留所有内存。你也可能需要调整GC选项,以确保GC不会留下太多未声明的对象,当堆有大量空间增长时,GC往往会这样做,这会破坏希望堆大小调整到应用程序需求的目标。


-XX:MaxHeapFreeRatio 该参数的默认值为70。空闲比率是指堆中未分配空间占堆总大小的比例。如果空闲空间百分比超过默认值70%,JVM将减小堆的大小以允许操作系统使用内存。 - 027
这是可能的(我经常这样做),但问题在于内存使用量会大幅度上下波动。它不与实际的活动对象集成比例,只是连续创建大量对象就会导致堆爆炸。只有手动触发GC才能使其下降。因此,您基本上必须在实际RAM中保留最大数量。我们真的需要一种可以动态更改最大堆大小的选项。 - Stefan Reich

13

也被称为后背的巨大疼痛。如果你正在使用大量内存,最不希望的是将其全部释放,然后在另一个进程中重新加载它。当然,您无法保持旧进程足够长的时间来传输数据,因为您正在用2个进程独占更多的内存来完成传输。希望这次你猜对了,否则你需要重新开始做一遍。 - Basic

7

当你启动应用程序时,可以调整这些设置,但一旦JVM启动并运行,这些值就不能被更改。例如:

java -Xms32m -Xmx512m FooBar

将最小堆大小设置为32MB,最大堆大小设置为512MB。一旦设置了这些值,在运行程序时就无法更改。


2

大家普遍认为这是不可能的,但我们应该查看JVM源代码,看看如何进行人性化控制。如果能够让JVMTI代理在在线/运行时调整堆/永久代/老年代/新生代等大小,将非常方便。

这样做会有什么作用?它将允许代理根据性能或占用空间目标推断出大小调整,这在将JVM移入云端时非常重要。


5
这篇阅读起来更像是对JVM功能的请求,而不是答案... - ruakh

1

在启动时,您可以使用-mx选项(也称为-Xmx)。这是您可能需要的最大大小,在这种情况下,您不应将其设置为超过您将来可能需要的最大大小。

但是,一种解决方法是让main()检查最大大小,并在最大大小不符合要求时重新启动Java。即启动另一个Java程序并退出。


这假设您事先知道需要多少内存。对于流媒体等网络服务器/其他应用程序来说,这很好,但如果您正在分析数据(例如构建索引/查找趋势),则需要预先知道数据将是什么,这相当受限制。 - Basic
@Basic 你不需要知道你需要多少内存。-Xmx是JVM可以拥有的最大内存,即程序应该在使用更多内存之前崩溃并显示OutOfMemoryError。这个最大值通常基于你拥有的内存,而默认值是主内存的1/4。无论你将最大值设置为多少,JVM都不会为“hello world”程序使用大量内存。 - Peter Lawrey
1
假设您有一个进程,并提前为其分配了50 GB的内存,在运行过程中注意到有很多GC正在进行,可能56 GiB会更好,而且您不能轻易地重新启动程序而不进行大量的重新计算... - kap
@kap 所以最好将最大值设置为一个您宁愿程序失败而不是继续运行的级别。 - Peter Lawrey

0

我曾经问过自己同样的问题。与上面的答案不同,我可以做一些关于我的应用程序增加最大堆JVM大小的事情。如果应用程序是集群模式下的Web服务器,我可以启动一个具有更改的最小/最大堆大小的新实例,然后关闭初始实例。在GlassFish中,这应该特别简单,因为您可以将管理实例与nodeAgent(应用程序服务器集群实例)JVM分开。

由于许多JVM应用程序都是Web应用程序,我认为值得在此博客中保留。


-2

如果我理解你的问题正确,你正在尝试在运行时更改堆大小。我不认为这是可能的。使用-Xmx JVM选项在启动时设置堆大小。我还建议您仅在绝对需要时设置-Xms选项。此选项设置为JVM分配的初始头内存量。

您应该了解您的应用程序在内存方面的行为。明智地设置-Xmx的值。如果您的应用程序是某种服务器应用程序,则可以设置较高的值,否则请将您的选择与其他可能在客户端机器上运行的应用程序以及可用内存妥协。


2
明智地设置值...是的,这是一个好建议。但考虑这种情况——你正在观察你的应用程序接近堆最大值,而你却无能为力。是的,代码中存在泄漏问题...但首先我们需要在一天内保持运行,然后再解决问题。 - alsor.net
请注意,这可能是一个小程序或其他类型的应用程序,您无法控制VM启动设置。在这些情况下,这将是很好的选择。我认为主要问题是,如果您能够更改此设置,则可能会遇到与安全相关的内存问题。 - Alex Vaz

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