内部类能直接访问外部类的私有成员,JVM 以前是靠编译器生成 access$000 桥接方法来实现的。Java 11 的嵌套伙伴(Nestmates)让 JVM 直接允许。这篇用 javap 对比两种编译结果,并用反射与故意破坏的类文件验证行为。
[--release 21] 类文件 ['Outer$Inner.class', 'Outer$Nested.class', 'Outer.class'];总大小 2440 字节;major version 65
Outer 里的 access$ 合成方法: 无
Outer 有 NestMembers 属性: True ;Outer$Nested 有 NestHost 属性: True
[--release 8] 类文件 ['Outer$1.class', 'Outer$Inner.class', 'Outer$Nested.class', 'Outer.class'];总大小 2696 字节;major version 52
Outer 里的 access$ 合成方法: ['static int access$000(Outer);', 'static java.lang.String access$100();']
Outer 有 NestMembers 属性: False ;Outer$Nested 有 NestHost 属性: False peek=7,call=hidden,both=12,viaInner=5
getNestHost: Outer→Outer,Nested→Outer,Inner→Outer
getNestMembers: [Outer, Outer$Inner, Outer$Nested]
isNestmateOf: Nested~Inner=true,Nested~String=false;String.getNestHost()=String
反射读私有字段 Outer.secret:从 Probe(不是嵌套成员)不调用 setAccessible → IllegalAccessException: class Probe cannot access a member of class Outer with modifiers "private"
但经由 Outer$Nested.peek(它是 Outer 的嵌套成员)读到:7旧的 Outer$Nested(声明 NestHost: Outer)+ 新的 Outer(没有 NestMembers): Caused by: java.lang.IllegalAccessError: class Outer$Nested tried to access private field Outer.secret (Outer$Nested and Outer are in unnamed module of loader 'app'), (Type Outer$Nested (loader: 'app') is not a nest member of type Outer (loader: 'app'): curren 同样的组合用 --release 8 编出来的旧 Outer$Nested(用 access$ 方法): Caused by: java.lang.NoSuchMethodError: 'int Outer.access$000(Outer)'