securityexception 是 jvm 的 securitymanager 拦截所致,因权限不足触发策略拒绝;常见于遗留系统或显式启用安全管理器的场景,需检查启动参数、代码及 policy 文件配置。

Java SecurityException 是谁在拦你?
不是代码写错了,是 JVM 主动拒绝了操作——SecurityException 出现时,说明当前执行路径触发了安全管理器(SecurityManager)的策略检查,且没被授权。常见于 Applet、RMI、老版本 Web 容器(如 Tomcat 8 以前),或显式启用了 -Djava.security.manager 的场景。
现代 JDK(9+)已默认移除 SecurityManager,但若你在维护遗留系统、跑在受限容器里,或自己调了 System.setSecurityManager(new SecurityManager()),它就会跳出来报错。
- 典型错误信息:
java.lang.SecurityException: access denied ("java.io.FilePermission" "/tmp/config.txt" "read") - 别急着改代码——先确认是不是真需要沙箱:查启动参数有没有
-Djava.security.manager,再查代码里有没有setSecurityManager - 如果只是本地开发调试,最简单解法是直接去掉该 JVM 参数;生产环境则必须走策略配置
policy 文件怎么写才不被 ignore?
Java 沙箱靠 java.policy 文件定义权限,但它不会自动生效,必须显式指定路径或用标准位置。JVM 启动时只加载默认策略($JAVA_HOME/jre/lib/security/java.policy)和用户策略($HOME/.java.policy),其他路径得手动告诉它。
- 启动时必须加参数:
-Djava.security.policy==/path/to/your.policy(注意是两个等号,表示“仅加载此文件”,单个等号是“追加”) - 策略文件语法严格:空格、分号、引号缺一不可;权限字符串里的路径要用正斜杠,Windows 下也别用反斜杠
- 示例最小可运行条目:
grant { permission java.io.FilePermission "/tmp/-", "read,write"; }; - 别漏掉末尾分号,也别把
permission写成Permission——大小写敏感,拼错就等于没授权
FilePermission 和 SocketPermission 常见填坑点
FilePermission 和 SocketPermission 是最常配错的两类。它们的 name 字段不是路径或地址本身,而是带通配符的匹配模式,且含义容易误解。
立即学习“Java免费学习笔记(深入)”;
-
FilePermission的 name:用/tmp/-表示 “/tmp 目录及所有子路径”,用/tmp/*只匹配 /tmp 下的**直接文件**(不含子目录);想读任意路径?用">"(仅限测试,生产禁用) -
SocketPermission的 name:写"localhost:8080"只允许连本机 8080;写"*:8080"允许连任意主机的 8080;但"*"单独出现是非法的,必须带端口或"-1"(表示任意端口) - 动态端口(如 RMI 注册表)需显式放行:
permission java.net.SocketPermission "*:1024-65535", "connect,accept"; - 注意协议层:HTTP 请求底层是 socket,但
URLPermission是另一套机制,不能替代SocketPermission
为什么加了 policy 还报错?检查这三处
策略写了、参数加了、重启了,还是 SecurityException ——大概率卡在这三个地方:
- JVM 参数是否被覆盖?比如 Docker 启动脚本里写了
java -Djava.security.manager ...,但又在后面重复写了-Djava.security.policy,后者会被前者忽略(因SecurityManager初始化早于策略加载) - 策略文件编码是否为 ASCII 或 ISO-8859-1?UTF-8 带 BOM 会解析失败,javac 编译策略文件时也不认中文注释
- 权限是否落在正确的
CodeSource上?如果你用grant codeBase "file:/app/lib/-" { ... };,但 jar 实际从http://加载,那这条规则根本不会触发
沙箱真正的麻烦不在写权限,而在验证权限是否被实际应用——没有日志、没有调试钩子,只能靠 -Djava.security.debug=access,failure 开关看控制台输出,而这个开关本身也会被安全策略限制。










