SecurityException是安全管理器策略拦截的结果,非程序错误;它在访问文件、网络、系统属性或反射私有成员时,因权限不足被AccessController拒绝而抛出,标志授权请求明确被拒。

SecurityException 不是凭空抛出的,它是 Java 安全管理器(SecurityManager)在运行时主动干预的结果——本质上是一种“策略驱动的拦截机制”,而非被动错误。
安全管理器是权限检查的执行者
当代码尝试访问敏感资源(如文件、网络、系统属性、反射私有成员等),JVM 并不会直接放行,而是调用当前 SecurityManager 实例的对应 checkXXX() 方法:
-
System.exit(0) → 触发
checkExit(int status) -
new FileInputStream("/etc/passwd") → 触发
checkRead(String file) -
System.getProperty("os.name") → 触发
checkPropertyAccess(String key) -
field.setAccessible(true) → 触发
checkPermission(new ReflectPermission("suppressAccessChecks"))
这些方法内部会委托给 AccessController.checkPermission(),后者依据当前线程的保护域(ProtectionDomain)和加载该类的 CodeSource,比对策略文件(.policy)中授予的权限。一旦未匹配到所需 permission,立即抛出 SecurityException。
异常不是失败信号,而是策略执行结果
SecurityException 的核心意义在于:它标志着一次**被明确拒绝的授权请求**,而非程序逻辑缺陷。例如:
立即学习“Java免费学习笔记(深入)”;
- 消息为
access denied ("java.io.FilePermission" "/tmp/data.txt" "read")→ 策略文件未授予对该路径的读权限 - 消息为
Prohibited package name: java.lang→ 属于 JVM 硬编码限制(ClassLoader.preDefineClass),与策略文件无关,但同样由 SecurityManager 拦截并抛出 SecurityException - 消息为空或仅含类名 → 建议启用
-Djava.security.debug=access,failure查看完整审计日志
变量访问受限的本质是权限模型绑定
所谓“非法访问变量”,实际分两类:
-
系统级变量(如系统属性
user.home、环境变量):受PropertyPermission或RuntimePermission控制,修改前需checkPropertyAccess()或checkPermission(new RuntimePermission("setProperties")) -
对象字段(含私有字段):反射访问触发
ReflectPermission("suppressAccessChecks");若策略未授权,setAccessible(true)就会抛出 SecurityException —— 这不是字段本身被“锁住”,而是取消访问检查这一动作被禁止
所有这些检查都发生在字节码执行过程中,由 JVM 在关键 API 入口处插入安全调用,形成一道运行时防线。
不启用 SecurityManager,就不会有这类 SecurityException
JDK 17+ 默认移除 SecurityManager,且 -Djava.security.manager 已废弃报错。真实环境中遇到 SecurityException,基本意味着:
- 运行在旧版 JDK(≤16)且显式启用了安全管理器
- 部署在强隔离容器(如某些 Applet 引擎、WebStart、遗留沙箱平台)中
- 应用自身调用
System.setSecurityManager(new SecurityManager())
此时异常不是 bug,而是沙箱按设计生效的表现。


















