我正在使用 tomcat7 和 JRE 1.8 运行 Java WebApp。该应用程序缓存大量数据(~15GB),并支持高吞吐量(~4K/sec)。由于请求率高,它在年轻代中产生了大量的对象,一些对象在年轻代的 ParNew 集合中存活下来,并被移动到幸存者,最终移动到堆内存中的老年代空间。
这些对象在老年代不断积累。CMS 会在老年代快满时启动,这会导致 stop-the-world GC。这会影响我的应用程序的延迟。
为了避免这种情况,我开始使用CMSInitiatingOccupancyFraction=85with +UseCMSInitiatingOccupancyOnly。然而,尽管有这两个选项,CMS 不会在老年代满 85% 时启动。当老年代快满了并且进行了一次stop-the-world GC时,它仍然会发生。我搜索了 的限制CMSInitiatingOccupancyFraction,但找不到任何解释该行为的相关链接。请在下面找到我的 tomcat 进程的确切命令行:
jsvc.exec -home /usr/lib/jvm/jre1.8.0_45 -user tomcat7 \
-pidfile /home/ameya/service/2.0.4-SNAPSHOT/logs/catalina-daemon.pid \
-outfile /home/ameya/service/2.0.4-SNAPSHOT/logs/catalina-daemon.out \
-errfile &1 \
-classpath /home/ameya/conf/service:/home/ameya/service/2.0.4-SNAPSHOT/bin/bootstrap.jar:/home/ameya/service/2.0.4-SNAPSHOT/bin/commons-daemon.jar:/home/ameya/service/2.0.4-SNAPSHOT/bin/tomcat-juli.jar \
-Djava.util.logging.config.file=/home/ameya/service/2.0.4-SNAPSHOT/conf/logging.properties \
-XX:+UseConcMarkSweepGC \
-XX:+CMSIncrementalMode \
-XX:+CMSIncrementalPacing \
-XX:+ExplicitGCInvokesConcurrent \
-Djava.awt.headless=true \
-XX:PermSize=1G \
-XX:MaxPermSize=5G \
-XX:+UseCMSInitiatingOccupancyOnly \
-XX:CMSInitiatingOccupancyFraction=85 \
-Xms12G -Xmx24G \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=9004 \
-Dcom.sun.management.jmxremote.local.only=false \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Duser.language=en \
-Duser.country=US \
-Dsun.net.inetaddr.ttl=30 \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/tmp/dump.tmp \
-XX:+AggressiveOpts \
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager \
-Djava.endorsed.dirs= \
-Dcatalina.base=/home/ameya/service/2.0.4-SNAPSHOT \
-Dcatalina.home=/home/ameya/service/2.0.4-SNAPSHOT \
-Djava.io.tmpdir=/home/ameya/service/2.0.4-SNAPSHOT/temp \
org.apache.catalina.startup.Bootstrap
有人可以帮我理解为什么当老一代已满 85% 时 CMS 不开始运行吗?