JDK11升级后Log4j2 RollingFileAppender抛出FilePermission权限错误
问题现象
将JDK从8升级至11后,启动Tomcat时出现如下错误:
ERROR Could not create plugin of type class
org.apache.logging.log4j.core.appender.RollingFileAppender
for element RollingFile: java.security.AccessControlException:
access denied ("java.io.FilePermission" "/zdata/svrgrp/logs/qam1" "read")
java.security.AccessControlException: access denied ("java.io.FilePermission"
"/zdata/svrgrp/logs/qam1" "read")
Java可正常向该目录写入其他文件(例如通过命令行指定-outfile /zdata/tomcat/qam1/logs/catalina.out,输出可正常写入),但使用完全相同的catalina策略在JDK8环境下运行正常。
Log4j配置XML如下(sys:applogdir定义为/zdata/svrgrp/logs/qam1):
<?xml version="1.0" encoding="UTF-8" ?> <Configuration> <Appenders> <RollingFile name="default.file" fileName="${sys:applogdir}/myapp.log" filePattern="${sys:applogdir}/myapp.log.%d{yyyy-MM-dd}"> <PatternLayout> <Pattern>%d %-5p [%t]:${sys:bi.tomcat.instanceName} (%F:%L) - %m%n</Pattern> </PatternLayout> <TimeBasedTriggeringPolicy/> </RollingFile> <Loggers> <Root level="debug"> <AppenderRef ref="default.file"/> </Root> </Loggers> </Configuration>
核心疑问
- JDK11使用Log4j的方式是否有根本性变化导致此问题?
- 是否有其他用户遇到过同类情况?可能的变化点是什么?
问题原因与变化点
这类问题在JDK8升级到JDK11的场景中较为常见,核心原因在于JDK安全策略的细化以及Log4j在高版本JDK下的行为变更:
1. JDK安全权限检查的严格化
JDK11对安全管理器的权限校验逻辑做了明确调整:
- 在JDK8中,目录的
write权限隐含了部分read权限(比如读取目录内文件列表用于日志滚动); - 但JDK11中,RollingFileAppender初始化或执行日志滚动时,需要读取目录下的现有日志文件列表,这一步会被安全管理器明确拦截,必须显式赋予目录的
read权限。
2. Log4j 2.x的行为更新
如果使用的Log4j版本适配JDK11,部分版本的RollingFileAppender在初始化阶段增加了对目标目录的预检查:
- 主动验证目录是否存在、是否可访问,这一步需要读取目录元数据,触发
read权限检查; - 而JDK8环境下的旧版Log4j可能依赖JVM文件系统操作的隐含权限,未显式触发该检查。
解决方法
- 修改安全策略文件:在
catalina.policy中为Log4j核心包添加目标目录的read权限:
可根据实际安全需求,调整权限范围或代码源路径。grant codeBase "file:${catalina.home}/lib/log4j-core-*.jar" { permission java.io.FilePermission "/zdata/svrgrp/logs/qam1", "read,write"; }; - 验证Log4j版本兼容性:确保使用的Log4j 2.x版本支持JDK11(建议使用2.17.0及以上稳定版本),部分旧版本可能存在JDK11下的权限检查逻辑bug。
- 检查系统层面目录权限:确认Tomcat进程所属用户对
/zdata/svrgrp/logs/qam1目录拥有操作系统级别的读权限(写入正常不代表读权限已开放)。
内容的提问来源于stack exchange,提问作者Richard D Lawson

