Java 和 PHP 应用程序的 GC 和内存行为?



这个问题是关于当请求需要的内存多于分配给 Pod 的内存时垃圾收集行为。如果 GC 无法释放内存,它会继续连续运行 GC 还是丢弃 的记忆。

一个 pod 包含基于 java 的应用程序,另一个包含基于 PHP 的应用程序。在java的情况下,xmx值与给pod限制的值相同。

我只能谈谈Java GC。 (PHP 的 GC 行为会有所不同。

如果 GC 无法释放内存,它会在固定间隔后继续连续运行 GC 还是抛出内存。

这取决于 JVM 选项。

JVM 从堆的初始大小开始,并根据需要对其进行扩展。 但是,它只会将堆扩展到固定的最大大小。 当 JVM 从选项 (-Xmx( 或缺省堆大小规则启动时,该最大大小确定。 启动后无法更改。

随着使用的堆空间接近限制,GC 可能会越来越频繁地发生。 现代 JVM 上的缺省行为是监视执行垃圾回收所花费的 % 时间。 如果超过(可配置(阈值,您将收到一个 OOME,其中包含有关已超出 GC 开销阈值的消息。 即使有足够的空间"跛行"更长时间,也会发生这种情况。

您可以关闭 GC 开销限制的内容,但这是不可取的。

如果 JVM 在执行完整的垃圾回收没有足够的堆空间,它也会抛出 OOME。

最后,如果 JVM 尝试增加堆并且操作系统拒绝为其提供它请求的内存,它将抛出 OOME。 发生这种情况的原因可能是:

  • 操作系统内存已用完
  • 操作系统的交换空间已用完
  • 进程已超过ulimit,或
  • 进程组(容器(已超出容器限制。

JVM只是勉强知道其环境中可用的内存。 在裸机操作系统或虚拟机监控程序下的 VM 上,默认堆大小取决于 RAM 量。 在裸机操作系统上,即物理 RAM。 在 VM 上,它将是...来宾操作系统将其视为其物理内存的内容。

使用 Kubernetes,应用程序可用的内存可能会受到 cgroups 或类似内容进一步的限制。 我知道最近的Java版本进行了调整,使它们更适合在容器中运行。 我认为这意味着他们在计算默认堆大小时可以使用 cgroup 内存限制而不是物理内存大小。

最新更新