Java模块系统对synthetic合成字段的访问控制是否失效?
问题解答
核心结论
Java模块系统的访问控制对synthetic(合成)字段完全生效,你观察到的两类字节码库的行为差异和synthetic修饰符没有任何关系。synthetic仅为字节码层面的标记位,作用是标识该成员不是用户源码级声明的,供编译、运行时工具做过滤处理,JVM规范中没有任何规则规定synthetic成员可以豁免模块访问检查。
差异原因拆解
两类库的行为差异来自于代理类生成和加载时的权限上下文绑定逻辑不同:
- Javassist生成的代理类直接在未命名模块的独立上下文中加载,类加载的验证阶段需要解析
Method[] _methods_字段的类型引用java.lang.reflect.Method,此时未命名模块不在java.base的java.lang.reflect包导出目标列表中,所以直接抛出java.lang.IllegalAccessError,符合预期。 - Byte Buddy生成代理类时,默认会将生成类的访问上下文绑定到触发代理生成的业务类所在的模块,如果你的触发类属于
java.base中配置的<some java and custom modules>导出列表中的模块,那么生成的代理类会继承该模块的访问权限,相当于拿到了访问java.lang.reflect包的授权,因此不会抛出访问错误。
验证方案
你可以通过两个简单操作验证上述结论:
- 将触发Byte Buddy生成代理的代码移动到未命名模块中,确保该模块不在
java.base的导出目标列表中,此时运行会触发和Javassist场景完全一致的IllegalAccessError - 手动修改Javassist生成的类,给
_methods_字段加上synthetic修饰符,运行依然会抛出访问错误,直接证明synthetic修饰符不影响模块访问控制逻辑
内容的提问来源于stack exchange,提问作者Liberator
相关产品推荐
相关产品推荐

