固定的堆大小永远不会是最优的。您要么将其设置得太低而耗尽内存,要么将其设置得太高而浪费内存。并行运行的 JVM 进程越多,这个问题就越严重。即使对于一个 JVM,也不可能使用机器中的所有 RAM。越接近最大值,被 OOM killer 杀死的风险就越大。
我理解固定堆大小的原因:垃圾回收。如果不知道还有多少内存可用,JVM 就不知道何时执行 GC。
一个想法是将这个决定从 JVM 交给内核。内核可以做出最优的全局决策,而不是次优的局部决策。我想这可以通过引入一个告诉 JVM 执行 GC 的新信号来实现。内核会在感觉有必要回收一些内存时发送此信号。
有这样的东西吗?我误解了这个问题吗?这是个坏主意吗?
最佳答案
最大堆大小的主要原因是允许管理员控制失控/泄漏的程序;它与垃圾收集完全无关。您可以使用像 ulimit
这样的操作系统工具来做同样的事情,但这些工具没有与 Java 集成,因此如果超过限制,Java 代码将无法再响应(因为大多数操作系统会在达到上限)。因此 Java 的发明者需要一种不同的方法来做到这一点:他们允许您在命令行上指定最大堆大小,并且他们为您提供了 OutOfMemoryException
,您可以在不终止的情况下捕获和处理它。
请记住,在 1994 年发布 Java 时,1GB 内存仍然很多。此外,大多数 Java VM 都在手机和嵌入式设备上运行,而这些设备的 RAM 通常为 256MB。
GC 本身通常由您拥有多少空闲堆来触发,无论堆是否有上限。 Java 总是在向操作系统请求更多内存之前尝试重新获得内存——GC 可能很昂贵,更多内存意味着更昂贵。因此,从一开始就将当前对象的数量保持在最少是一种自然的优化。之所以很多人认为最大。 heap size 会触发GC 是这样的:当Java 因为heap 限制不能从OS 分配更多的内存时,GC 会运行得非常频繁。那是大多数人意识到 GC 运行的时候。因此,当两者没有真正联系时,很容易将其混淆。
关于java - 来自内核的 GC 信号而不是固定的 JVM 堆大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28539807/