我一直很好奇,为什么Java需要手动设置堆大小? 我之前的印象是,其他语言编写的程序会在运行过程中分配尽可能多的内存,直到操作系统无法再分配为止。
在Java世界中,我们需要设置堆、栈和永久代的大小。虽然这很简单,但是忘记将它们增加到足够大的数字是我见过服务器崩溃的头号原因。
为什么不能让Java随着时间的推移自动增加堆/栈/永久代的大小呢?
我一直很好奇,为什么Java需要手动设置堆大小? 我之前的印象是,其他语言编写的程序会在运行过程中分配尽可能多的内存,直到操作系统无法再分配为止。
在Java世界中,我们需要设置堆、栈和永久代的大小。虽然这很简单,但是忘记将它们增加到足够大的数字是我见过服务器崩溃的头号原因。
为什么不能让Java随着时间的推移自动增加堆/栈/永久代的大小呢?
三个原因:
我认为这是因为计算机的实际内存是有限的。因此,在某种程度上,JVM允许您在所有内存被浪费之前检测到内存泄漏。
另外,如果您在同一台计算机上运行多个JVM,则如何使每个JVM都可以“尽可能地增长”?
因为动态增加堆栈和永久代大小只会让服务器崩溃。在这样的情况下,服务器最终将耗尽所有资源。
另外,自动内存管理的开发并不像今天这么成熟。如果选择了错误的默认设置,有虚拟限制会使事情变得更容易,但它可能会使编码在后端有些不那么高效。
是的,这些只是猜测,但是合理的猜测;尤其是考虑到 Java / Oak 的起源是嵌入式机顶盒编程。嵌入式系统不会像有交换或磁盘支持的虚拟内存一样,那么为什么要让 JVM 表现得好像它是可用的呢?
虽然这是一个老话题,但我来到这里并且我认为我知道答案。
补充彼得所说的,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等早在很久以前就存在了。好的软件之所以不会失败,是因为它被良好地编写和管理。
垃圾收集发生在对象变得不可访问时,而不是在达到内存限制时。
是的,但它们并不是“立即”进行GC。需要多快进行垃圾回收取决于堆大小,这对性能可能非常重要。 - Enno Shioji