这种行为在java 5 / 6中仍然存在吗?
不完全符合描述;我从未见过编译器是真的:
为了允许这个单独的类访问外部类的字段,编译器以静默方式将这些字段从 private 更改为包范围!
相反,IIRC Sun Java 3/4创建了一个访问器,而不是修改字段。
Sun Java 6 (javac 1.6.0_16 ) 创建了一个静态访问器:
public class InnerExample {
private int field = 42;
private class InnerClass {
public int getField () { return field; };
}
private InnerClass getInner () {
return new InnerClass();
}
public static void main (String...args) {
System.out.println(new InnerExample().getInner().getField());
}
}
$ javap -classpath bin -private InnerExample
Compiled from "InnerExample.java"
public class InnerExample extends java.lang.Object{
private int field;
public InnerExample();
private InnerExample$InnerClass getInner();
public static void main(java.lang.String[]);
static int access$000(InnerExample);
}
$ javap -classpath bin -c -private InnerExample
static int access$000(InnerExample);
Code:
0: aload_0
1: getfield #1; //Field field:I
4: ireturn
这实际上是一种安全风险吗,因为除了外部类和内部类之外,任何试图访问外部类的私有成员的类都不会兼容?
我在这里推测了一下,但是如果你针对类进行编译,它不会,但是如果你添加,那么你可以编译使用访问器的代码。access$000
import java.lang.reflect.*;
public class InnerThief {
public static void main (String...args) throws Exception {
for (Method me : InnerExample.class.getDeclaredMethods()){
System.out.println(me);
System.out.printf("%08x\n",me.getModifiers());
}
System.out.println(InnerExample.access$000(new InnerExample()));
}
}
有趣的是,综合访问器具有修饰符标志,如果添加包级静态方法,则它具有标志 。在第二版的JVM规范中,没有关于该标志值的内容,但它似乎阻止了javac看到该方法。00001008
00000008
所以看起来那里有一些安全功能,但我找不到任何关于它的文档。
(因此,在CW中发表这篇文章,以防有人知道0x1000在类文件中的含义)