来自内核的GC信号,而不是固定的JVM堆大小



固定的堆大小永远不会是最佳的。你要么把它设置得太低而耗尽内存,要么把它设得太高而浪费内存。并行运行的JVM进程越多,这个问题就越严重。即使对于一个JVM,也不可能在一台机器中使用所有RAM。你越接近最大值,你就越有可能被OOM杀手杀死。

我理解固定堆大小的原因:垃圾收集。如果不知道还有多少内存可用,JVM将不知道何时执行GC。

一个想法是将这个决定从JVM传递到内核。内核可以做出最优的全局决策,而不是次优的局部决策。我想这可以通过引入一个新信号来工作,该信号告诉JVM执行GC。每当需要回收一些内存时,内核就会发送这个信号。

像这样的东西存在吗?我误解了这个问题吗?这是个坏主意吗?

最大堆大小的主要原因是允许管理员检查失控/泄漏的程序;它与垃圾收集完全无关。您可以使用像ulimit这样的操作系统工具做同样的事情,但这些工具没有与Java集成,因此如果超过限制,Java代码将无法再响应(因为当达到限制时,大多数操作系统都会强制终止进程)。因此,Java的发明者需要一种不同的方法来实现这一点:他们允许您在命令行上指定最大堆大小,并为您提供OutOfMemoryException,您可以在不终止的情况下捕获和处理它。

请记住,在1994年Java发布时,1GB的内存仍然很大。此外,大多数Java虚拟机都运行在256MB RAM的手机和嵌入式设备上。

GC本身通常由您有多少可用堆来触发,无论堆是否有上限。Java总是试图在向操作系统要求更多内存之前重新获得内存——GC可能很昂贵,而更多内存意味着更昂贵。因此,从一开始就将当前对象的数量保持在最小是一种自然的优化。很多人认为最大堆大小会触发GC的原因是:当Java由于堆限制而无法从操作系统中分配更多内存时,GC会经常运行。这是大多数人意识到GC运行的时候。因此,当这两件事并没有真正联系在一起时,很容易混淆这一点。

固定的堆大小永远不会是最佳的。

堆大小本身从来都不是固定的。它根据应用程序的需要而增长和收缩。自从Java5以来,有一个功能可以让您在集合不使用X%空间的情况下将内存返回到操作系统。它是使用XX:MaxHeapFreeRatio属性进行调优的。

只要有必要,内核就会发送这个信号回收一些内存。

例如,内核如何知道java是否占用内存,或者它是否可以从java中回收一些内存?应用程序是否真的需要4GB的ram,或者是否存在占用更多内存并导致OOM的线程泄漏?内核永远不会知道这一点。

像这样的东西存在吗?

XX:MaxHeapFreeRatio属性是我所知道的最接近于将内存返还给操作系统的属性。

我链接到的文档中有更多关于为这些属性设置正确值的建议。

除非你有停顿的问题,试着给予尽可能多的内存对于虚拟机来说是可能的。默认大小(64MB)通常太大小的

将-Xms和-Xmx设置为相同的值可通过以下方式提高可预测性从虚拟机中删除最重要的大小决定。另一方面,如果您糟糕的选择。

一定要在增加处理器,因为分配可以并行化。

最新更新