Eclipse警告您,您可能会公开您认为是私有的信息。如下所示,恶意代码可以利用合成访问器。
如果您的代码需要在安全的VM中运行,则使用内部类可能是不明智的。如果您可以使用反射并拥有对所有内容的完全访问权限,则合成访问器不太可能产生可衡量的变化。
例如,考虑此类:
public class Foo { private Object baz = "Hello"; private class Bar { private Bar() { System.out.println(baz); } }}的签名
Foo实际上是:
public class Foo extends java.lang.Object{ public Foo(); static java.lang.Object access$000(Foo);}access$000是自动生成的,以允许
Bar访问单独的类
baz,并将使用Synthetic属性进行标记。生成的精确名称取决于实现。常规编译器不允许您使用此方法进行编译,但是可以使用ASM(或类似方法)生成自己的类,如下所示:
import org.objectweb.asm.*;public class FooSpyMaker implements Oppres { public static byte[] dump() throws Exception { ClassWriter cw = new ClassWriter(0); cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "Spy", null, "java/lang/Object",null); MethodVisitor ctor = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); ctor.visitCode(); ctor.visitVarInsn(ALOAD, 0); ctor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); ctor.visitInsn(RETURN); ctor.visitMaxs(1, 1); ctor.visitEnd(); MethodVisitor getBaz = cw.visitMethod(ACC_PUBLIC, "getBaz", "(LFoo;)Ljava/lang/Object;", null, null); getBaz.visitCode(); getBaz.visitVarInsn(ALOAD, 1); getBaz.visitMethodInsn(INVOKESTATIC, "Foo", "access$000", "(LFoo;)Ljava/lang/Object;"); getBaz.visitInsn(ARETURN); getBaz.visitMaxs(1, 2); getBaz.visitEnd(); cw.visitEnd(); return cw.toByteArray(); }}这将创建一个简单的类
Spy,该类将允许您调用
access$000:
public class Spy extends java.lang.Object{ public Spy(); public java.lang.Object getBaz(Foo);}使用此方法,您可以检查
baz没有反射或任何暴露它的方法的值。
public class Test { public static void main(String[] args) { Foo foo = new Foo(); Spy spy = new Spy(); System.out.println(spy.getBaz(foo)); }}该
Spy实现要求它是在相同的封装中
Foo,并且
Foo不处于密封JAR。



