Java 17起SecurityManager被废弃、Java 21彻底移除,传统沙箱模型失效;替代方案包括:模块系统(JPMS)限制包可见性、JVM参数禁用危险操作、字节码增强实现运行时拦截、应用层显式鉴权API统一管控权限。

Java 17 开始,System.setSecurityManager 被标记为废弃(Deprecated),Java 21 正式移除。这意味着基于传统 Security Manager 的沙箱模型不再可用,权限管控必须转向更现代、更明确的机制。
用模块系统(JPMS)限制类可见性与包访问
Java 9 引入的模块系统是替代 Security Manager 的核心方案之一。它从编译期和运行期强制隔离代码边界,天然限制敏感 API 的访问路径。
- 在
module-info.java中显式声明requires和exports,避免默认导出全部包 - 对敏感包(如
java.lang.reflect或jdk.internal)不导出,也不requires非必要模块 - 使用
opens仅在必要时开放反射访问,且限定到具体模块,例如:opens com.example.config to java.xml.bind;
用 JVM 启动参数禁用危险操作
很多高危能力(如反射访问私有成员、JNI 加载、系统属性修改)可通过 JVM 参数关闭,比运行时检查更轻量、更可靠。
-
--illegal-access=deny:阻止非法反射访问(Java 16+ 默认启用) -
--add-opens java.base/java.lang=ALL-UNNAMED:仅按需开放特定包,避免全局放开 -
-Djava.security.manager=allow已无效,但可配合-Dsun.reflect.debug=true辅助排查反射调用来源 - 禁用 JNI:
-XX:+DisableExplicitGC不直接相关,但可通过移除Runtime.getRuntime().load()调用并监控java.library.path实现间接控制
用字节码增强或代理框架做运行时行为拦截
对于仍需动态权限决策的场景(如插件系统、脚本执行),可借助 Java Agent 或类加载器改造,在方法调用前插入校验逻辑。
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
立即学习“Java免费学习笔记(深入)”;
- 使用 Byte Buddy 或 ASM 在类加载时重写敏感方法(如
FileOutputStream.<init>()</init>、System.setProperty()),插入策略检查 - 自定义
ClassLoader,对来自不可信源的类禁止加载java.*或javax.*下的敏感类 - 结合
SecurityManager的历史日志(如有遗留),定位哪些调用曾触发 checkPermission,将其映射为新拦截点
用应用层权限模型 + 显式鉴权 API 替代沙箱
放弃“自动拦截”,转为“主动声明+显式校验”。这是当前主流框架(Spring Security、Apache Shiro)的实际做法。
- 定义资源级权限(如
"file:read:/tmp/*"、"jmx:query:java.lang:type=Memory") - 在关键入口(如文件操作前、JMX 查询前)调用
SecurityContext.hasPermission(...) - 结合运行时身份(Subject/Principal)和上下文(租户、标签、时间窗口)做细粒度判断,而非依赖类加载器或堆栈深度
- 利用
StackWalker快速获取调用链,辅助审计——但不用于权限决策(易被绕过)
不复杂但容易忽略:真正关键的不是“怎么拦”,而是“谁该有权限”。把权限逻辑从业务代码中解耦,统一建模、集中配置、可审计追踪,比复刻旧沙箱更有长期价值。

















