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

标签 java linux garbage-collection jvm

固定的堆大小永远不会是最优的。您要么将其设置得太低而耗尽内存,要么将其设置得太高而浪费内存。并行运行的 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/

相关文章:

java - 使用反射与 java.math.BigInteger 交互时,我会遇到哪些问题?

php - Nginx 和 php-fpm 仅适用于某些 php 页面。怎么了?

linux - 如何使服务器不记录(存储)用户 IP 和用户代理?

linux - 如何确保数据到达存储,绕过内存/缓存/缓冲 IO?

java - 每次进行更改时都运行 mvn package 吗?

java - 如何更新数据库表中的稀疏值?

java - 如何使用 Spring Rest Hibernate 获取如图所示的 JSON 输出

git - 在 reflog 过期和 gc prune 后推送到源

javascript - Javascript/垃圾收集器中的循环引用

Java - 静态数组列表中对象的垃圾数组列表字段