固定的堆大小永远不会是最优的。您要么将其设置得太低而耗尽内存,要么将其设置得太高而浪费内存。并行运行的JVM进程越多,这个问题就越严重。即使对于一个JVM,也不可能利用一台机器中的所有RAM。你越接近最大值,你被OOM杀手杀死的风险就越大。
我理解堆大小固定的原因:垃圾收集。如果不知道还有多少内存可用,JVM就不知道何时执行GC。
一种想法是将这个决策从JVM转移到内核。内核可以做出最优的全局决策,而不是次优的局部决策。我想这可以通过引入一个新的信号来工作,该信号告诉JVM执行GC。每当需要回收一些内存时,内核都会发送这个信号。
真的存在这样的东西吗?我误解了这个问题吗?这是个坏主意吗?
发布于 2015-02-16 20:45:47
最大堆大小的主要原因是允许管理员控制失控/泄漏的程序;它与垃圾收集完全无关。您可以使用操作系统工具(如ulimit )执行相同的操作,但这些工具不能与Java集成,因此如果超出限制,Java代码将无法再响应(因为大多数操作系统将在达到限制时强制终止进程)。因此,Java的发明者需要一种不同的方法来实现这一点:他们允许您在命令行上指定最大堆大小,并且提供了OutOfMemoryException,您可以在不终止的情况下捕获和处理它。
请记住,在1994年Java发布时,1 1GB的内存仍然很大。而且,大多数Java VM运行在移动电话和嵌入式设备上,通常使用256MB的RAM。
GC本身通常是由您有多少空闲堆触发的,无论堆是否有上限。Java总是在请求OS提供更多内存之前尝试重新获得内存- GC可能很昂贵,而更多的内存意味着更昂贵。因此,一开始就将当前对象的数量保持在最小是一种自然的优化。为什么很多人认为最大。堆大小将触发GC :当Java由于堆限制而无法从操作系统分配更多内存时,GC将非常频繁地运行。这就是大多数人意识到GC运行的时候。因此,当这两个东西并没有真正联系在一起时,很容易将它们混淆。
发布于 2015-02-16 19:07:15
固定的堆大小永远不会是最优的。
堆大小本身永远不是固定的。它可以根据应用程序的需要进行扩展和缩小。从Java 5开始,有一个特性可以让您在集合不使用X%的空间时将内存返回给操作系统。它是使用XX:MaxHeapFreeRatio属性进行调整的。
内核会在觉得有必要回收一些内存的时候发送这个信号。
例如,内核如何知道java是否占用了内存,或者它是否可以从java中回收一些内存?应用程序是否真的需要4 4GB的内存,或者是否存在占用更多内存并导致OOM的线程泄漏?内核永远不会知道这一点。
真的存在这样的东西吗?
XX:MaxHeapFreeRatio属性是我所知道的最接近于将内存回馈给操作系统的属性。
有关为这些属性设置正确值的更多建议,请参阅我所链接的文档。
除非您在暂停时遇到问题,否则请尝试向虚拟机授予尽可能多的内存。默认大小(64MB)通常太小。
将-Xms和-Xmx设置为相同的值可从虚拟机中删除最重要的调整决策,从而提高可预测性。另一方面,如果你做了一个糟糕的选择,虚拟机无法补偿。
确保随着处理器数量的增加而增加内存,因为分配可以并行化。
https://stackoverflow.com/questions/28539807
复制相似问题