为什么Java不支持自动堆扩展?

7
为什么Java不像.NET CLR那样在达到操作系统所强制的进程内存限制之前扩展堆大小?
这是JVM开发者制定的政策,还是.NET CLR架构优于JVM架构的一个优势?换句话说,如果Oracle工程师想要为JVM实现自动堆扩展,他们能做到吗?
编辑:我真的认为这是Java的一个糟糕的设计选择。将Xmx设置得尽可能高(例如100 GB!)是不安全的。如果用户需要在更大的数据上运行我的代码,他可以在可用RAM更多的系统上运行它。为什么我作为开发人员需要设置程序的最大可用内存?我不知道数据的大小!!!
2个回答

7
JVM需要时增加堆大小,但不会占用全部内存,因为它必须在启动时进行预分配,并且您可能希望将一些内存用于其他事情,比如线程堆栈、共享库和离堆内存等。如果将最大堆大小设置得足够大或使用离堆内存,则可以扩展堆大小,但默认情况下不会这样做。原因之一是堆内存必须在主存储器中,并且不能进行交换,否则会导致机器性能下降甚至崩溃。JVM的一个关键特点是它平台无关,因此它有自己的控制。如果JVM运行在进程空间的极限处,很可能会阻止机器工作(因为过度交换)。至于.NET是否避免了这种情况,我并不知道。关于自动堆扩展的实现,Oracle的工程师已经完成了,只是允许它使用过多的内存并不明智。

为什么?有什么区别呢?在C程序中,可以进行交换而不会导致[等等]被终止...这与其他程序不同。 - undefined
@Clonkex 最新的垃圾回收器理论上可以将内存释放回操作系统。然而,在实践中,它们似乎并不经常这样做。 - undefined
那跟交换内存有什么关系呢?这就是我困惑的地方。无论是在C还是C#中分配内存,它仍然可以进行分页,而分页的速度无论如何都会很慢。(但我远非专家,很乐意被证明是错误的。) - undefined

3

作为开发者,决定为Java进程允许多少堆内存是您的决策。这取决于各种因素,例如项目设计、运行平台等。

我们可以设置堆大小属性。

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size
-Xss<size>        set java thread stack size

正如您所看到的,我们设置了初始堆大小,如果后来 JVM 发现需要更多空间,则可以将堆大小增加到最大指定限制。实际上,这个大小在进行垃圾回收时可能会发生变化(不是强制性的)。我曾经在类似的基础上发布了问题,您可以参考一下。因此,堆大小的增加/减少是由 JVM 完成的。开发人员只需要根据自己的需求指定限制即可。


是的,但人们并不能总是猜测代码需要多少内存。而且,将Xmx设置得尽可能高(例如100 GB!)并不安全。如果用户需要在更大的数据上运行我的代码,他可能会提供更多的RAM。作为开发人员,我为什么要设置程序的最大可用内存?我不知道正在处理的数据有多大。 - Ali
如果您不知道正在处理的数据有多大,那么这是您的设计缺陷。在产品交付给客户之前,会进行边缘情况测试(SDLC的一部分)。您会问:“作为开发人员,我应该设置程序的最大可用内存吗?”因为您必须告诉客户(并记录)这是程序可以承受的最大负载(或者通常是根据客户要求而定,但我们仍然知道估计值)。 - Aniket Thakur
例如,如果您正在为Android制作一些基于文本的应用程序,并且数据超过了您设置的最大内存(如果未设置,则设置了一些默认值,顺便说一句,如果您正在制作客户端产品,则这不是良好的编程实践),那么该应用程序将简单地崩溃(显然您不希望发生这种情况)。相反,如果您有估计值,可以向用户发出关于负载增加的警告。 - Aniket Thakur
我同意,但只是在某种程度上!我认为JVM的行为在大多数情况下都是可以接受的,例如在通常的Web应用程序或Android游戏中。然而,在某些应用程序中,使用最大内存大小是不可避免的。例如,如果您开发科学计算工具、视频处理库或数据挖掘应用程序,用户可能希望程序根据正在解析的数据使用最大可用RAM!不可能指望程序员定义所需的最大内存! - Ali
假设您正在编写一个视频转换软件,当用户尝试转换非常大的文件时,以下哪些错误在您看来更容易被接受:“文件太大无法适应内存”,还是“文件太大无法保留在JVM堆大小中!”。我相信第二个只是一个玩笑! - Ali
对于Java堆来说,它是内存。你向用户展示的内容应该让他们感到有意义(例如在你提供的例子中文件太大)。即使我有3GB的空闲RAM,由于视频转换软件有1GB的限制,所以对于1GB的文件仍然很可能出现错误。 - Aniket Thakur

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