【问题标题】:Why do you need to specify the Java heap size?为什么需要指定 Java 堆大小?
【发布时间】:2022-03-25 04:40:18
【问题描述】:

我一直想知道,为什么 Java 需要你手动设置堆大小?我的印象是,用其他语言编写的程序只会根据程序运行的需要分配尽可能多的内存,直到操作系统无法再分配。

在 Java 世界中,我们需要设置堆、堆栈和 permgen 大小。虽然这很简单,但忘记将这些增加到“足够大”的数字是我看到服务器宕机的第一大原因。

为什么不能告诉 Java 随着时间的推移尽可能多地增长堆/堆栈/permgen?

【问题讨论】:

    标签: java jvm jvm-arguments


    【解决方案1】:

    三个原因:

    1. 因为 Java 旨在成为编写 Web 应用程序的语言。通常认为让网络应用接管所有机器资源并不是一个好主意。
    2. 因为 Java 是垃圾收集器。除了指定内存上限外,堆大小也会触发垃圾收集。从本质上讲,您是在说“您可以使用这么多,但是当您达到该限制时,您必须进行整理”。
    3. 您确实希望限制 Java 进程使用的内存量的许多应用程序类别,例如更重要的是,当两个进程都没有足够的内存时,其他进程继续运行。
    4. 因为能够限制堆大小是一项功能。如果您喜欢进程可以拥有无​​限内存的方法(如提到的其他语言),那么您总是可以将堆限制设置为超过它可能获得的。如果你想限制堆大小,你可以这样做。其他语言只有其中一种可能的行为,因此不太灵活。

    【讨论】:

    • 你有第一点的来源吗?我以前从未听说过“java 是用来编写 web 应用程序”的事情(不是说我已经深入研究过 java 的历史……)
    • 天哪,节制不当。 Java 源自 Oak,它旨在实现机顶盒软件,就像您在复杂的有线电视调谐器中可能拥有的那种软件。就垃圾收集而言,垃圾是在对象不可访问时收集的,而不是在达到内存限制时收集的。
    • @Edwin Buck:garbage is collected when object are inaccessible, not when the memory limits are reached 是的,但它们不是“立即”GCd。您必须以多快的速度执行取决于堆大小,并且对性能非常重要。
    • 从通过 jconsole 获得的大量 gc 图的周期性来看,我可以向您保证,垃圾收集在小批量同时释放对象时运行,就像在计时器的基础上一样,而不是在“我们离极限有多近”的基础。唯一的例外可能是,如果您即将超过限制,那么垃圾收集将获得一个“最后机会”在 JVM 以 OutOfMemoryException 认输之前丢弃对象。
    • 你还可以在同一个 JVM noawadys 中找到像 Waratek 这样的东西的可视化
    【解决方案2】:

    我的解释是,Sun 是一家专注于销售 Big Box 的公司,他们喜欢系统管理员可以在这些 Box 上做事。运行一个系统来填满所有内存是一个很好的方法,它可以运行到地面并且无法有效地采取行动来恢复操作,因为你不能分配内存来创建一个登录 shell。

    【讨论】:

      【解决方案3】:

      我认为是因为计算机的实际内存是有限的。因此,从某种意义上说,JVM 允许您在所有内存被浪费之前检测到 memleaks。
      另外,如果您在同一台机器上运行多个 JVM,该怎么办——在这种情况下,您如何让每个 JVM “按需增长”?

      【讨论】:

        【解决方案4】:

        因为动态地增加堆、堆栈和 permgen 大小只会使服务器停止运行。在这样的世界中,服务器最终会泄露其所有资源。

        此外,开发自动内存管理并不像今天这样成熟。如果你选择了错误的默认值,拥有虚拟限制会让事情变得更容易,但它会使后端的编码效率降低一些。

        是的,这些都是猜测,但都是合理的;尤其是当您考虑 Java 的 / Oak 的嵌入式机顶盒编程起源时。嵌入式系统不会有交换或磁盘支持的虚拟内存,那么为什么要让 JVM 表现得好像它是可用的一样呢?

        【讨论】:

          【解决方案5】:

          老话题,但我到了这里,我想我知道答案了。

          作为 Peter 所说的补充,Java 生态系统完全是为系统管理员和支持团队设计的。就像管理员定义他希望应用程序使用的内存资源一样,数据库连接 (JNDI) 也是如此,在这种情况下,您无需向应用程序或开发人员提供数据库生产所在的位置,只需引用资源的名称。 Sun 所做的一切都有一个完美的关键任务管理系统。对于 Solaris 操作系统,Sun 开发了一种称为“项目”(https://docs.oracle.com/cd/E37838_01/html/E61042/index.html) 的功能,该功能可让管理员在任何编程语言的应用程序中限制服务器资源(如上所述)。 因此,对于生产系统来说,让系统管理员知道应用程序能够使用多少资源并能够限制必要的资源是很重要的。这并不是 Java 或 Sun 产品所独有的。在 .NET 的情况下,可以限制这些资源 (https://docs.microsoft.com/en-us/iis/configuration/system.applicationhost/applicationpools/add/processmodel)、Ruby (https://gist.github.com/jjb/7389552)、Node.JS (How do I determine the correct "max-old-space-size" for node.js?) 等。

          学习管理就像学习发展一样重要。很多人认为 Docker 是一个现代奇迹,而 FreeBSD Jails、Solaris Zones 等早已存在。好的软件之所以不会失败,是因为它写得好,管理得好。

          【讨论】:

            猜你喜欢
            • 2011-01-07
            • 1970-01-01
            • 2018-08-20
            • 2014-09-19
            • 1970-01-01
            • 2015-02-06
            • 2018-02-20
            • 1970-01-01
            • 2020-01-29
            相关资源
            最近更新 更多