我将首先给出我们创建的对象的一些细节。并会问一个问题(最后)。
我在 linux 上使用 64 位但 JVM。
我的 jvm 选项是: -Xmx6g -Xms3g -XX:MaxPermSize=256m
分析器 (jprofiler) 指示 2 个位置消耗大量内存: 1) 在这里,每秒创建大约 4 个字符串(每个 110KB),并对每个字符串执行 StringUtils.replace。还执行了一些其他字符串分配等,但分析器清楚地表明 StringUtils.replace 是持有大部分内存的东西。2)在这里,每分钟创建一个包含 4 个对象(单个类)的对象(保留大小,如果 3.5MB),并(重新)放置到静态并发哈希映射中(因此映射在任何时候都只包含 1 个对象)。父对象只有这 4 个子对象,仅此而已。这 4 个对象中的每一个都包含 10K 数组列表、10K 日期和其他字符串等。我明确地将旧的父对象(我从 map.replace() 获得的那个)分配给 null 并明确清除 (ArrayList.clear())数组列表,
内存行为是:内存使用量不断增加,并且在某一时刻主要收集(2GB)发生。次要收集(700MB)也大约每分钟发生一次。
问题:您是否认为#1 实际上导致伊甸园空间已满,因此 JVM 将 #2 中的对象推送到永久空间,因此内存使用量不断增加,直到发生重大收集?出于诊断目的,我将 #2 中的父对象更改为保留 500KB 的大小(小 7 倍,还有 1.4K 的 Date、ArrayList 等实例),我仍然看到相同的内存行为。
我将选项更改为 -Xmx12g -Xms3g -XX:MaxPermSize=256m -XX:NewSize=8g 现在,我看到内存中 #2 中的对象数量较少,我看到任期空间/旧代的增长较慢。#2 中的那些对象现在被快速收集很好,但是 CPU 使用率非常高,因为现在的次要收集非常大(8G)并且每 2 分钟发生一次。
我的目标是快速收集所有对象(所以我看不到内存使用量不断增加),但不要让次要集合太大。
关于我应该采取什么方法的任何建议?