java - 多个虚拟机的垃圾收集

标签 java memory garbage-collection jvm jvm-hotspot

我们有一个通常由大约 20 个 JVM 组成的应用程序,我们向它们分发批处理作业。 20 个 JVM 在同一个操作系统中运行。在将批处理作业分派(dispatch)给其中一个之前,很难判断该作业的长度和大小。这可能需要 1 分钟或几个小时。内存消耗同样不同。

到目前为止,它运行良好,我们总共有 40GB 内存可用,我们将每个 JVM 的最大堆大小设置为 2GB(有时需要 2GB)。由于我们从来没有同时运行太多“大”批处理作业的情况,所以我们从来没有遇到内存问题。直到我们迁移到 Java 8 虚拟机。好像full GC的触发频率比较低。我们的 JVM 大部分处于闲置状态,内存使用率不断上升。当我通过调用 jcmd 触发 GC 时,我可以看到 OldGen 从大约 1GB 下降到 200MB。

我知道拥有 20 个最大 2GB 堆 + 堆栈 + 元空间的 JVM 并不是一个好的设置,它们的最大总容量将远远超过 40GB 可用内存。但这是我们必须忍受的情况。如果有一种方法可以为多个 JVM 的集群设置最大堆大小,我会感到惊讶。所以我需要想出其他解决方案。

我一直在寻找一些 VM 选项,告诉 VM 定期执行完整的 GC,这很可能会解决我们的问题。但是我找不到执行此操作的 VM 选项。

关于我们如何设置它以避免内存交换有什么建议吗?

编辑:这是 gc 日志的一个片段:

2016-04-14T01:02:49.413+0200: 37428.762: [Full GC (Ergonomics) [PSYoungGen: 28612K->0K(629248K)] [ParOldGen: 1268473K->243392K(1309184K)] 1297086K->243392K(1938432K), [Metaspace: 120332K->120320K(1181696K)], 0.3438924 secs] [Times: user=1.69 sys=0.02, real=0.35 secs] 
2016-04-14T01:02:52.442+0200: 37431.792: [GC (Allocation Failure) [PSYoungGen: 561664K->67304K(629248K)] 805056K->310696K(1938432K), 0.0315138 secs] [Times: user=0.26 sys=0.00, real=0.03 secs] 
2016-04-14T01:02:54.809+0200: 37434.159: [GC (Allocation Failure) [PSYoungGen: 628968K->38733K(623104K)] 872360K->309555K(1932288K), 0.0425780 secs] [Times: user=0.35 sys=0.00, real=0.04 secs] 
...
2016-04-14T10:09:03.558+0200: 70202.907: [GC (Allocation Failure) [PSYoungGen: 547152K->41386K(531968K)] 1545772K->1041036K(1841152K), 0.0255883 secs] [Times: user=0.18 sys=0.00, real=0.02 secs] 
2016-04-14T10:20:53.634+0200: 70912.984: [GC (Allocation Failure) [PSYoungGen: 531882K->40733K(542720K)] 1531532K->1042107K(1851904K), 0.0306816 secs] [Times: user=0.22 sys=0.02, real=0.03 secs] 
2016-04-14T10:23:10.830+0200: 71050.180: [GC (System.gc()) [PSYoungGen: 60415K->37236K(520192K)] 1061790K->1040674K(1829376K), 0.0228505 secs] [Times: user=0.17 sys=0.01, real=0.02 secs] 
2016-04-14T10:23:10.853+0200: 71050.203: [Full GC (System.gc()) [PSYoungGen: 37236K->0K(520192K)] [ParOldGen: 1003438K->170089K(1309184K)] 1040674K->170089K(1829376K), [Metaspace: 133559K->129636K(1196032K)], 1.4149811 secs] [Times: user=11.10 sys=0.02, real=1.42 secs] 

我想,如果我们每小时进行一次完整的 GC,它就能解决我们的问题。

最佳答案

随机执行 GC 是没有意义的。

我会将 GC 添加到批处理的末尾(或之后)。正是由于这一点,可能需要保留最少的内存,从而使 GC 更快,并获得最佳收缩。

关于java - 多个虚拟机的垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36691448/

相关文章:

java - RESTEasy 中的 CORS 过滤器

java - 更新 Java 中的 JFrame。复制对象

具有扩展参数的 Java 子类构造函数

python - 如何限制堆大小?

php - 有没有办法以字节为单位获取 PHP 变量的大小?

java - JVM内存管理和垃圾收集书?

java - 使用 .prop 文件以编程方式训练 NER 模型

c++ - 我不明白我在取消分配内存时做错了什么

java - 未使用的对象在堆栈中仍然可见时是否可用于垃圾回收?

c++ - Golly 哈希表和 GC 的工作原理