java 17正式支持密封类,class.issealed()可准确判断类是否声明为sealed,getpermittedsubclasses()返回显式许可的直接子类数组(未加载的类不包含在内),二者共同支撑安全框架与模块化校验。

Java 17 引入密封类(sealed classes),配合 isSealed() 和 getPermittedSubclasses() 方法,可在运行时动态检查类的密封性与许可子类列表。这对构建安全框架、代码审计工具或模块化校验器非常实用。
确认类是否为密封类
Class.isSealed() 是最直接的判断方式,返回 true 表示该类被声明为 sealed(含 non-sealed 或 final 修饰符不改变其“密封类”身份,只要源码中用了 sealed 关键字)。
- 注意:接口也可被声明为
sealed,同样适用该方法 - 非密封类(如普通
class A {})调用返回false - 即使类未加载完整(比如来自模块路径但未解析所有 permitted 子类),
isSealed()仍可靠返回
获取显式许可的子类列表
Class.getPermittedSubclasses() 返回 Class[],包含所有在源码中通过 permits 明确列出的直接子类(不含间接继承链中的类)。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 返回数组元素顺序与源码中
permits声明顺序一致 - 若类不是密封类,该方法返回
null(不是空数组) - 若某许可子类尚未加载(例如位于未读取的模块中),它不会出现在结果中 —— 这是 JVM 规范行为,需结合类加载上下文处理
- 可配合
Class.forName()尝试加载并验证每个许可类是否存在且可访问
构建轻量级密封性审计逻辑
典型审计目标包括:检查密封类是否遗漏许可项、许可类是否非法继承、或模块间许可关系是否合规。
- 遍历目标包下所有
Class,用isSealed()筛出密封类 - 对每个密封类调用
getPermittedSubclasses(),检查返回值是否为null(应有许可列表) - 对每个许可子类,验证其是否真实继承自该密封类(
isAssignableFrom())、是否被final或sealed修饰(影响进一步扩展) - 若使用模块系统,还可通过
ModuleLayer检查许可类是否属于同一模块或已导出
注意事项与常见陷阱
反射获取密封信息虽简单,但实际审计中容易忽略环境约束:
- JVM 必须运行在 Java 17+,且编译时使用
--enable-preview(仅限 Java 15/16 预览版);Java 17 正式支持无需预览标志 - 混淆工具(如 ProGuard)可能移除
permits元数据,导致getPermittedSubclasses()返回null—— 审计前需确认 class 文件保留完整属性 - 动态代理类、匿名类、Lambda 生成类永远不会是密封类,无需参与密封性检查
- 泛型类型擦除不影响密封性元数据,
List<string></string>的密封状态只取决于List类本身定义
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










