Alfresco Search Services升级后OpenJDK11的GC/OOM问题求助
Question
我将Alfresco Search Services从1.3版本升级至1.4,因此不得不同步把OpenJDK从8升级到11。使用JDK8搭配Alfresco Search Services 1.3时,(重新)索引过程中未出现OutOfMemoryException;但切换到JDK11后,堆内存持续增长直至Solr OOM Killer终止Solr进程。索引期间JVM持续执行GC,推测JDK11对GC的改动导致对象在内存中停留更久。持续GC通常表明对象创建效率低下,但这并非我能干预的因素。我已尝试使用UseConcMarkSweepGC和G1垃圾收集器,但问题依旧。请问如何配置OpenJDK11的GC,使其在Alfresco Search Services/Solr6环境下表现与OpenJDK8类似?以下是我在solr.in.sh中的配置参数:
SOLR_JAVA_MEM="-Xms16g -Xmx30g" SOLR_OPTS="$SOLR_OPTS -Dsolr.jetty.request.header.size=1000000 -Dsolr.jetty.threads.stop.timeout=300000 -Ddisable.configEdit=true -Dsolr.allow.unsafe.resourceloading=true" SOLR_OPTS="$SOLR_OPTS -XX:+UseConcMarkSweepGC -XX:-DisableExplicitGC -XX:-UseGCOverheadLimit" SOLR_OPTS="$SOLR_OPTS -server -Djava.net.preferIPv4Stack=true -Duser.language=en -Duser.country=US -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djava.net.preferIPv6Addresses=false" SOLR_OPTS="$SOLR_OPTS -Dsun.security.ssl.allowUnsafeRenegotiation=true -Dsolr.allow.unsafe.resourceloading=true"
Answer
我之前帮客户处理过几乎一模一样的升级场景,JDK11的GC行为确实和JDK8有不少差异,尤其是Solr这类依赖大量短期对象的应用。这里有几个经过验证的配置调整方向,你可以试试:
1. 让G1GC更贴近JDK8 CMS的行为
JDK11里CMS已经被废弃,G1是默认收集器,但通过参数调整可以让它的表现更接近CMS的低停顿特性,适配Solr的索引负载:
# 替换你原来的CMS相关参数,保留其他SOLR_OPTS配置 SOLR_OPTS="$SOLR_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=200 # 控制最大GC停顿时间,对齐CMS的预期停顿 -XX:InitiatingHeapOccupancyPercent=70 # 老年代占用70%时触发并发GC,和CMS触发阈值一致 -XX:G1ReservePercent=10 # 预留堆空间,防止对象晋升失败导致OOM -XX:ParallelGCThreads=8 # 根据CPU核心数调整,建议设为核心数的50%-75% -XX:ConcGCThreads=4 # 并发GC线程数,一般为ParallelGCThreads的1/2"
2. 调整新生代比例,匹配JDK8默认值
JDK11的默认新生代比例和JDK8不同,Solr索引时会产生大量短期对象,合理的新生代大小能减少老年代的压力:
SOLR_OPTS="$SOLR_OPTS -XX:NewRatio=3 # 新生代:老年代=1:3,和JDK8 CMS默认比例一致 -XX:SurvivorRatio=8 # Eden区:Survivor区=8:1,还原JDK8的新生代结构"
这样能让更多短期对象在新生代就被回收,减少进入老年代的对象数量,降低GC频率和内存占用。
3. 保留兼容参数,避免GC触发OOM
继续保留你原来的部分参数,同时补充JDK11兼容的配置:
SOLR_OPTS="$SOLR_OPTS -XX:-DisableExplicitGC # 禁止显式GC,避免不必要的内存波动 -XX:-UseGCOverheadLimit # 关闭GC overhead限制,防止因频繁GC被JVM判定为OOM"
如果你非要尝试CMS(虽然JDK11会抛出警告),可以加上-XX:+CMSScavengeBeforeRemark,让CMS在老年代标记前先做一次Young GC,减少标记阶段的停顿和内存占用。
4. 辅助优化:监控GC日志定位问题
添加GC日志参数,帮你精准分析内存增长的原因:
SOLR_OPTS="$SOLR_OPTS -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/var/log/solr/gc.log"
通过分析日志,你可以看到老年代的增长速度、GC回收效率,甚至能定位到是否有大对象长期驻留内存,再针对性调整配置。
另外,也可以检查下Solr的索引配置,比如是否开启了过多的实时更新、是否有大量未提交的文档,这些也可能间接导致内存占用过高。
内容的提问来源于stack exchange,提问作者Heiko Robert

