Java GC一直在旋转,尽管有很多空闲堆

Java GC一直在旋转,尽管有很多空闲堆,java,garbage-collection,Java,Garbage Collection,我有一个运行-mx7000m的应用程序。我可以看到它被分配了5.5 GB的堆。然而由于某些原因,它不断地进行GCing,而作为CMS,它被证明是相当CPU密集型的。因此,它已经分配了5.5 GB的堆,但不知何故,它花费了所有CPU时间试图使使用的堆尽可能小,大约2 GB,而其他3.5G由JVM分配,但未使用 我有几个配置完全相同的服务器,五分之二的服务器都是这样运行的。怎么解释呢 它是Java6,标志是:-server-XX:+printgcdatastamps-Duser.timezone=A

我有一个运行
-mx7000m
的应用程序。我可以看到它被分配了5.5 GB的堆。然而由于某些原因,它不断地进行GCing,而作为CMS,它被证明是相当CPU密集型的。因此,它已经分配了5.5 GB的堆,但不知何故,它花费了所有CPU时间试图使使用的堆尽可能小,大约2 GB,而其他3.5G由JVM分配,但未使用

我有几个配置完全相同的服务器,五分之二的服务器都是这样运行的。怎么解释呢


它是Java6,标志是:
-server-XX:+printgcdatastamps-Duser.timezone=America/Chicago-Djava.awt.headless=true-Djava.io.tmpdir=/whatever-Xloggc:logs/gc.log-XX:+PrintGCDetails-mx7000m-XX:MaxPermSize=256m-XX:+useConcmarkswipegc
触发CMS gc的默认阈值是70%(在Java6中)。经验法则是堆大小应该是完整GC后使用的堆的2.5倍左右(但您的用例可能会有所不同)

因此,在你的情况下,说你有

- 2.5 GB of young generation space
- 3 GB of tenured space.
当您的永久空间达到70%或~2.1GB时,它将开始清理该区域

所涉及的设置是
-XX:CMSInitiatingOccupancyFraction=70

但是,如果您想减少对GC的影响,最简单的方法就是创建更少的垃圾。i、 e.使用内存探查器,确保分配率尽可能低。如果您正在创建CPU可以处理的100 MB/s或1 MB/s或更少的垃圾,那么您的系统将运行得非常不同


由于区域的相对大小可能不同,您可能会有不同的服务器运行,比如说您有0.5 GB的年轻服务器和5.0 GB的终身服务器,您不应该看到这一点。差异可能完全取决于启动进程时机器有多忙,或者从那时起它做了什么。

无论堆的大小如何,GC运行的时间大致与应用程序创建对象的速度成正比,并且只受堆大小的轻微影响。看起来我在前面读了一些东西。确定发电占用率,了解更多关于CMS的信息并对其进行调整。创建更少的垃圾很难,你可以看出这是一个相当大的应用程序。我知道这要视情况而定,但如果这是年轻一代溢出的问题,您会建议调整到更大的空间以容纳年轻的分数还是更小的分数?更大还是更小?@KonradGarus使用分析器,不管你的应用程序有多复杂,你只需从前三名最严重的违规者开始,然后继续工作。我敢打赌,在你的前十名中,有些东西已经不再需要了;)@KonradGarus我更喜欢较大的Eden大小(高达24 GB)和较小的永久空间,并将大部分数据存储在堆外(50 GB到10 TB)。有很多选择,但当我开始咨询新的应用程序时,最简单的方法是从内存分析器开始。我使用非堆运行的最大JVM是100 TB(仅作为测试;)