java 17起securitymanager被彻底移除,system类仅提供访问入口,实际权限校验由其执行;替代方案包括jpms模块封装、容器隔离及应用层框架(如spring security)实现细粒度控制。

System 类本身不直接控制权限,但它提供了访问和设置 SecurityManager 的入口。真正执行权限校验的是 SecurityManager 实例,而 System 类仅负责托管和暴露这个安全策略执行者。
SecurityManager 的启用与获取方式
SecurityManager 默认为 null,即不启用。只有显式启用后,敏感操作才会触发检查:
- 启动时通过 JVM 参数启用:
java -Djava.security.manager MyApp,此时使用默认实现 - 代码中手动设置:
System.setSecurityManager(new SecurityManager()),或传入自定义子类 - 获取当前实例始终用:
System.getSecurityManager(),返回 null 表示未启用
权限检查的触发机制
Java 核心类库(如 FileInputStream、Socket、System.setProperty)在执行敏感操作前,会主动调用 SecurityManager 的对应 check 方法:
- 例如
checkRead(String file)在打开文件前被调用 - 例如
checkConnect(String host, int port)在建立网络连接前被调用 - 所有 check 方法内部最终都归结为
checkPermission(Permission) - 若未授权,抛出
SecurityException;若授权,静默返回
权限模型与策略配置
权限控制基于 java.security.Permission 及其子类,每类资源有专属权限类型:
-
FilePermission控制文件读写路径(如"/tmp/-" "read") -
SocketPermission控制主机端口连接(如"example.com:80" "connect") -
RuntimePermission控制运行时行为(如"createClassLoader") - 策略由 policy 文件定义,通过
-Djava.security.policy=my.policy指定
现代 Java 中的实际地位
从 Java 17 开始,SecurityManager 已被彻底移除(JEP 411),不再受支持:
- JDK 17+ 编译或运行含
setSecurityManager的代码会报错或忽略 - 替代方案转向模块系统(JPMS)、强封装(
--illegal-access=deny)和最小权限原则设计 - 遗留系统需迁移:用
AccessController.doPrivileged替代部分特权逻辑,结合 RBAC/ABAC 框架做应用层鉴权











