Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Java堆的最大大小是固定的?_Java_Garbage Collection_Jvm_Heap - Fatal编程技术网

为什么Java堆的最大大小是固定的?

为什么Java堆的最大大小是固定的?,java,garbage-collection,jvm,heap,Java,Garbage Collection,Jvm,Heap,它需要在VM启动后增加Java堆的最大大小。技术原因是什么?垃圾收集算法是否依赖于使用固定数量的内存?或者是出于安全原因,通过消耗所有可用内存来防止Java应用程序破坏系统上的其他应用程序?我认为简短而刺耳的答案是因为Sun发现它不值得花费时间和成本来开发 这种特性最引人注目的用例是在桌面上,IMO,而Java在启动JVM的机制上一直是桌面上的一场灾难。我怀疑那些对这些问题想得最多的人倾向于关注服务器端,并查看最好留给本机包装器的任何其他细节。这是一个不幸的决定,但在为一个应用程序选择合适的平台

它需要在VM启动后增加Java堆的最大大小。技术原因是什么?垃圾收集算法是否依赖于使用固定数量的内存?或者是出于安全原因,通过消耗所有可用内存来防止Java应用程序破坏系统上的其他应用程序?

我认为简短而刺耳的答案是因为Sun发现它不值得花费时间和成本来开发


这种特性最引人注目的用例是在桌面上,IMO,而Java在启动JVM的机制上一直是桌面上的一场灾难。我怀疑那些对这些问题想得最多的人倾向于关注服务器端,并查看最好留给本机包装器的任何其他细节。这是一个不幸的决定,但在为一个应用程序选择合适的平台时,这应该是一个决定点。

我的直觉是,这与操作系统上运行的其他应用程序的内存管理有关

例如,如果您将最大堆大小设置为机箱上的RAM量,那么实际上可以让VM决定它需要多少内存(达到此限制)。这样做的问题是,虚拟机可能会有效地削弱它正在运行的机器,因为在它决定需要进行垃圾收集之前,它将接管机器上的所有内存

当您指定最大堆大小时,您要对VM说的是,允许您在需要开始垃圾收集之前使用此内存量。您不能拥有更多,因为如果您使用更多,则机箱上运行的其他应用程序将变慢,如果您使用的数量超过此数量,您将开始交换到磁盘

还要注意,它们是关于内存的两个值,即“当前堆大小”和“最大堆大小”。当前堆大小是堆大小当前使用的内存量,如果需要更多内存,它可以调整堆大小,但不能将堆大小调整到最大堆大小以上。

来自IBM(因此可能不直接适用于Sun的VM)

Java堆参数影响垃圾收集的行为。增加堆大小支持更多的对象创建。因为大型堆需要更长的时间来填充,所以在垃圾收集发生之前,应用程序运行的时间更长。然而,更大的堆也需要更长的时间来压缩,并导致垃圾收集需要更长的时间

JVM具有用于管理JVM存储的阈值。当达到阈值时,将调用垃圾收集器以释放未使用的存储。因此,垃圾收集可能会导致Java性能显著降低。在更改初始堆和最大堆大小之前,应考虑以下信息: 在大多数情况下,应将最大JVM堆大小设置为高于初始JVM堆大小的值。这允许JVM在初始堆范围内的正常、稳定状态期间高效运行,也允许JVM在高事务量期间高效运行,方法是将堆扩展到最大JVM堆大小。在一些需要绝对最佳性能的罕见情况下,您可能希望为初始堆大小和最大堆大小指定相同的值。这将消除JVM需要扩展或收缩JVM堆大小时发生的一些开销。确保区域足够大,可以容纳指定的JVM堆。 小心使初始堆大小过大。虽然较大的堆大小最初通过延迟垃圾收集来提高性能,但较大的堆大小最终会影响垃圾收集最终启动时的响应时间,因为收集过程需要更多的时间

所以,我猜您不能在运行时更改该值的原因是因为它可能没有帮助:要么堆中有足够的空间,要么没有。一旦用完,将触发GC循环。如果这还不能腾出空间,你就已经吃饱了。您需要捕获OutOfMemoryException,增加堆大小,然后重试计算,希望这次您有足够的内存

通常,除非您需要,否则VM不会使用最大堆大小,因此,如果您认为可能需要在运行时扩展内存,可以只指定一个较大的最大堆大小


我承认这有点不令人满意,而且似乎有点懒惰,因为我可以想象一种合理的垃圾收集策略,当GC无法释放足够的空间时,它会增加堆的大小。不过,我的想象力是否转化为高性能GC实现是另一回事;)

历史上,这种限制有一个原因,那就是不允许浏览器中的小程序占用所有用户的内存。从来没有这样限制的微软虚拟机实际上允许这样做,这可能导致对用户计算机的某种拒绝服务攻击。就在一年前,Sun在1.6.0 Update 10 VM中引入了一种方法,让小应用程序指定它们需要多少内存(限制在物理内存的某个固定份额),而不是总是将它们限制在64MB,即使在具有8GB或更多可用内存的计算机上也是如此


现在,由于JVM已经进化,当VM不在浏览器中运行时,应该可以摆脱这个限制,但是Sun显然从未考虑过这样的高优先级问题,尽管已经提交了许多错误报告,最终允许堆增长。

在Sun的JVM中,最后我知道,整个堆必须分配在一个连续的地址空间中。我认为,对于较大的堆值,在启动后很难添加到地址空间中,同时确保地址空间保持连续。您可能需要在启动时获得它,或者根本不需要。因此,它是固定的

即使不能立即全部使用,