为什么需要指定Java堆大小?

19

我一直很好奇,为什么Java需要手动设置堆大小? 我之前的印象是,其他语言编写的程序会在运行过程中分配尽可能多的内存,直到操作系统无法再分配为止。

在Java世界中,我们需要设置堆、栈和永久代的大小。虽然这很简单,但是忘记将它们增加到足够大的数字是我见过服务器崩溃的头号原因。

为什么不能让Java随着时间的推移自动增加堆/栈/永久代的大小呢?

5个回答

7

三个原因:

  1. Java是用于编写Web应用程序的语言。通常认为让Web应用程序占用所有机器资源不是一个好主意。
  2. Java具有垃圾回收功能。除了指定内存上限外,堆大小还会触发垃圾回收。实质上,你在说“你可以使用这么多,但当你达到那个限制时,你必须整理一下”。
  3. 有许多类型的应用程序需要限制Java进程使用的内存量,例如,在两者都没有足够的内存时,其他进程继续运行更加重要。
  4. 因为能够限制堆大小是一项功能。如果你喜欢进程可以拥有无限内存的方法(如其他提到的语言),那么你可以将堆限制设置得比可能获得的更多。如果你想限制堆大小,你也可以这样做。其他语言仅具有这些可能性中的一种,使它们不太灵活。

2
你有第一点的来源吗?我以前从未听说过“Java是用于编写Web应用程序”的事情(不是我深入研究过Java的历史...) - Mike
4
神圣的误差调节。Java起源于Oak语言,旨在实现机顶盒软件,就像你可能在高级有线电视调谐器中使用的那种软件一样。至于垃圾收集方面,当对象不可访问时会进行垃圾收集,而不是在达到内存限制时进行收集。 - Edwin Buck
@Edwin Buck:垃圾收集发生在对象变得不可访问时,而不是在达到内存限制时。 是的,但它们并不是“立即”进行GC。需要多快进行垃圾回收取决于堆大小,这对性能可能非常重要。 - Enno Shioji
从通过jconsole获得的大量gc图的周期性来看,我可以向您保证垃圾收集是并发运行的,按照定时器基础释放对象,而不是按照“我们离极限有多近”的基础运行。唯一的例外可能是如果您即将超过限制,则在JVM抛出OutOfMemoryException之前,垃圾收集将有一个“最后机会”来丢弃对象。 - Edwin Buck
现在你可以在同一个JVM中找到可视化工具,比如Waratek。 - Nikos
显示剩余2条评论

6
我的理解是,Sun公司专注于销售大型计算机,并且他们希望系统管理员能够在这些计算机上进行操作。运行一个将所有内存填满的系统是使其失效并且无法有效采取恢复操作的好方法,因为您无法分配内存来创建登录shell等操作。

4

我认为这是因为计算机的实际内存是有限的。因此,在某种程度上,JVM允许您在所有内存被浪费之前检测到内存泄漏。
另外,如果您在同一台计算机上运行多个JVM,则如何使每个JVM都可以“尽可能地增长”?


1

因为动态增加堆栈和永久代大小只会让服务器崩溃。在这样的情况下,服务器最终将耗尽所有资源。

另外,自动内存管理的开发并不像今天这么成熟。如果选择了错误的默认设置,有虚拟限制会使事情变得更容易,但它可能会使编码在后端有些不那么高效。

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


0

虽然这是一个老话题,但我来到这里并且我认为我知道答案。

补充彼得所说的,Java生态系统完全为系统管理员和支持团队设计。就像管理员定义他想让应用程序使用的内存资源一样,在数据库连接(JNDI)中也是如此。在其中,您不需要向应用程序或开发人员提供数据库生产环境的位置,只需提供引用资源的名称。 太阳公司所做的一切都有一个完美的关键任务管理系统。在Solaris操作系统的情况下,Sun开发了一个称为“项目”(https://docs.oracle.com/cd/E37838_01/html/E61042/index.html)的功能,用于限制任何编程语言的应用程序中的服务器资源(如您上面提到的)。 因此,对于生产系统而言,让系统管理员知道应用程序能够使用多少资源并能够限制必要的资源是非常重要的。这不仅适用于Java或Sun产品。在.NET的情况下,可以限制这些资源(https://learn.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等早在很久以前就存在了。好的软件之所以不会失败,是因为它被良好地编写和管理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接