【问题标题】:Java Heap Memory Allocation for multiple applications in Single Server单个服务器中多个应用程序的 Java 堆内存分配
【发布时间】:2021-07-31 15:10:51
【问题描述】:

我们有一个具有 32 GB RAM 的 Linux 服务器。因此,服务器中分配的默认堆大小是 1/4,即 8 GB。 java -XX:+PrintFlagsFinal -version | grep HeapSize

现在,我们在服务器中运行了 3 个 java 进程。


所需的最大堆大小(-Xmx) 进程 1 = 4 GB
进程 2 = 4 GB
进程 3 = 2 GB

所以最大堆大小的总和变为 10 GB,大于服务器的最大堆大小 8 GB。

这样分配最大堆大小可以吗?这会导致将来出现任何问题吗?

【问题讨论】:

  • 服务器没有“堆”。它有记忆。
  • 哦,好的。这是我在执行java -XX:+PrintFlagsFinal -version | grep HeapSize 时在Linux 服务器uintx MaxHeapSize := 8311013376 中看到的。因此,我认为这是服务器允许的最大堆大小。如果我错了,请纠正我。
  • 报告 JVM 的实际最大堆大小。见stackoverflow.com/questions/26631498/understanding-java-heap。 (即使它是允许的最大堆大小,它仍然是 JVM 堆大小......与硬件或操作系统无关。操作系统不知道进程对其内存做了什么。)
  • 知道了@Stephan C!谢谢 ! :) 现在我明白了。

标签: java linux memory jvm heap-memory


【解决方案1】:

首先:服务器拥有的内存称为内存而不是堆大小;) 你用 -Xmx 定义的东西是应用程序可以使用多少内存。这意味着您将为您的应用程序使用 10GB 的 ram 和 32GB 的 ram,这几乎不会触及服务器的限制。

编辑:但如果你像斯蒂芬写的那样分配超过 32GB 的空间,它仍然可能导致问题。

【讨论】:

    【解决方案2】:

    你应该看不到任何问题。

    正如您提到的,“默认”最大堆大小为 8 GB。这是一个上限,并不意味着分配或使用了 8 GB 内存。

    您指定两个进程需要 4 GB,其中一个需要 2 GB 最大堆。随意配置它们,它们很可能会进入三个独立的 Java 调用。这意味着您在运行时拥有的每个 JVM 都可以获得它们所需的堆数量 - 远低于 32 GB 的内存。

    但是当您看到 java 进程的虚拟内存大小大于最大堆大小时,不要开始怀疑。堆只是java使用内存的一种方式,还有其他的区域。

    我仍然相信你是安全的,除非你在同一台服务器上运行许多其他你没有告诉我们的东西。

    【讨论】:

      【解决方案3】:

      这样分配最大堆大小可以吗?这会导致将来出现任何问题吗?

      如果 8GB 是服务器的 RAM,那很可能会导致问题;见下文。

      但是报告的 8GB

      $ java -XX:+PrintFlagsFinal -version | grep HeapSize
      

      默认 MaxHeapSize 用于您的服务器硬件的 JVM1;即如果您不提供任何堆大小参数,您将获得的堆大小。它不是最大的 Java 堆大小。如果要设置实际MaxHeapSize,请使用-Xmx...

      实际可用的 RAM 将是 32GB ... 减去操作系统内核和其他进程使用的 RAM。 10GB 的 Java 堆(加上其他非堆内存)应该没问题。


      只要您有足够的交换空间,Linux 系统就可以在所有进程的总虚拟内存需求超过系统上的物理 RAM 的情况下运行。

      但是,如果您提交的虚拟内存(显着)多于物理 RAM:

      • 当进程尝试访问当前已换出的 VM 页面时,性能会受到影响。

      • 如果交换过多,Linux 将采取措施防止系统抖动。内核的 OOM 杀手进程将尝试找出导致内存需求过大的原因 .... 并 KILL -9 它。

      当 JVM 进行完整的垃圾回收时,它很可能以(基本上)随机顺序访问其大部分页面。这很可能会产生大量的分页......如果你有过度使用的内存。

      不幸的是,OOM​​ 杀手不知道它评估为候选杀手的各种进程的重要性。因此,如果您很幸运(!),它将杀死导致最多问题的 Java 进程。如果你不走运,它可能会杀死一个更关键的进程;例如您的数据库进程、ssh 守护进程等。理论上,您可以保护进程不被杀死。在实践中这样做很尴尬......而且你可能会因为保护那些应该被杀死的东西而陷入更糟糕的境地。


      1 - 在当前版本的 Java 中,默认的 MaxHeapSize 是总 RAM 的 1/4 ... 由操作系统报告。你有 32GB 的内存,所以默认 MaxHeapSize 是 8GB。

      【讨论】:

      • 有没有办法改变默认的MaxHeapSize? @斯蒂芬C
      • 没有。没有。计算默认值的算法不能更改。但是您显然可以设置-Xmx...,以便不使用默认值。
      猜你喜欢
      • 1970-01-01
      • 2022-11-25
      • 2016-09-01
      • 2022-07-22
      • 1970-01-01
      • 2018-10-22
      • 1970-01-01
      • 2017-08-26
      • 1970-01-01
      相关资源
      最近更新 更多