views:

97

answers:

1

Hi, in reflection, the private field can be access via getDeclaredField() and setAccessible(true). How to access the private field of a outside class via Objectweb ASM bytecode API? I set to get the private field from something like, via

Field current = sourceObject.getDeclaredField(privateFieldName);
Field.setAccessible(true);
Type sourceType = Type.getType(sourceObject.getClass());
mv.visitFieldInsn(Opcodes.GETFIELD,
                  sourceType.getInternalName(),
                  privateFieldname,
                  Type.getDescriptor(current.getType()));

When the byte code is executed and to get the private field, I always got an error "java.lang.IllegalAccessError "

Any clue? Thanks a bundle,

+2  A: 

You can't do it like that. The setAccessible(true) will only affect the current field-reference in the current execution of your program (that is, it will not affect the execution of the resulting modified program).

To access a private field when running your modified program, you basically have to embed the corresponding reflection-steps into the program.

To access a private field YourClass.thePrivatefield of some object stored in local variable varId you do something like

// Get hold of the field-reference
mv.visitLdcInsn(Type.getType("LYourClass;"));
mv.visitLdcInsn("thePrivateField");
mv.visitMethodInsn(INVOKEVIRTUAL,
                   "java/lang/Class",
                   "getDeclaredField",
                   "(Ljava/lang/String;)Ljava/lang/reflect/Field;");

// Duplicate the reference
mv.visitInsn(DUP);

// Call setAccessible(true) using the first reference.
mv.visitInsn(ICONST_1);
mv.visitMethodInsn(INVOKEVIRTUAL,
                   "java/lang/reflect/Field",
                   "setAccessible",
                   "(Z)V");

// Call get(yourObject) using the second reference to the field.
mv.visitInsn(ALOAD, varId);
mv.visitMethodInsn(INVOKEVIRTUAL,
                   "java/lang/reflect/Field",
                   "get",
                   "(Ljava/lang/Object;)Ljava/lang/Object;");

If the field you're trying to make accessible is part of the cobe base that your'e rewriting, you could obviously also make that field public by using ACC_PUBLIC instead of ACC_PRIVATE.

aioobe
Great. I will try it. By the way, is this Java ASM or BCEL? Thanks
erwin davis
ASM.............
aioobe