Ehcache配置堆缓存单位为MB时出现非法反射访问告警如何解决
告警产生原因
- JDK 9及以上版本引入了JPMS模块系统,对JDK内部的非公开API和私有字段做了强封装限制,未经授权的反射访问会触发告警,你使用的OpenJDK 11符合该限制规则。
- 当Ehcache的堆缓存配置使用字节单位(如MB、KB)作为上限时,需要动态计算每个缓存对象的实际内存占用,才能判断是否达到容量阈值。此时Ehcache会调用
org.ehcache.sizeof.ObjectGraphWalker组件,通过反射遍历缓存对象的完整对象图统计内存大小,该逻辑访问了java.util.ArrayList的私有字段elementData,因此触发了JDK的非法反射访问告警。 - 当堆缓存单位改为
entries时,Ehcache仅按缓存条目数量计数,不需要计算对象内存大小,不会触发上述反射逻辑,因此不会出现告警。
修复方案
你可以根据自己的业务场景选择以下任意一种方案:
- 优先选择调整堆缓存配置,改用
entries作为堆缓存的计数单位。如果业务可以接受按缓存条数限制堆缓存大小,这是改造成本最低的方案,你实测也确认该方案可以规避告警。 - 如果必须使用字节单位限制堆缓存大小,可以添加JVM启动参数开放对应类的反射访问权限:
如果后续出现其他JDK内置类的反射告警,可按需补充对应的--add-opens java.base/java.util=ALL-UNNAMED--add-opens参数即可。 - 升级Ehcache到更高的稳定版本。你当前使用的3.9.4版本对JDK 9+的模块系统适配不完善,升级到最新的3.10.x及以上稳定版,官方已修复了大部分非法反射访问的问题,也可以解决该告警。
- 配置Ehcache的SizeOf引擎忽略规则。你可以在Ehcache配置中指定跳过特定类、特定字段的内存大小计算,减少不必要的反射访问,不过该方案适配成本相对更高。
内容的提问来源于stack exchange,提问作者Lahiru Chandima
相关产品推荐
相关产品推荐

