(reflect) Accessing members of inner annotations types
Peter Levart
peter.levart at gmail.com
Fri Jan 3 15:55:28 UTC 2014
On 01/03/2014 03:52 PM, Peter Levart wrote:
> This is would be all right until such proxy class
> (com.sun.proxy.$Proxy1 in our example) has to access some
> package-private types in some specific package. This happens in your
> Named.List annotation implementation class. It implements a member
> method with the following signature:
>
> public Named[] value() {...
>
> ...where the return type is an array of a package-private type Named.
> Public class in com.sun.proxy package can not access package-private
> types in other packages!
Investigating this further, I found that the declaration itself is not
problematic. It's the code in the implemented proxy method that tries to
access the package-private Named class. Here's how the bytecode looks
like for such proxy method:
public final pkg.Named[] value() throws ;
Signature: ()[Lpkg/Named;
flags: ACC_PUBLIC, ACC_FINAL
Code:
stack=10, locals=2, args_size=1
0: aload_0
1: getfield #16 // Field
java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
4: aload_0
5: getstatic #67 // Field
m3:Ljava/lang/reflect/Method;
8: aconst_null
9: invokeinterface #28, 4 // InterfaceMethod
java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
* 14: checkcast #69 // class "[Lpkg/Named;"*
17: areturn
18: athrow
19: astore_1
20: new #42 // class
java/lang/reflect/UndeclaredThrowableException
23: dup
24: aload_1
25: invokespecial #45 // Method
java/lang/reflect/UndeclaredThrowableException."<init>":(Ljava/lang/Throwable;)V
28: athrow
Exception table:
from to target type
0 18 18 Class java/lang/Error
0 18 18 Class java/lang/RuntimeException
0 18 19 Class java/lang/Throwable
... I think the error is thrown at the "checkcast" bytecode. The
improvement suggested still holds. If the proxy class was generated in
the specific package, error would not be thrown. But the requirement to
take into account all implemented interfaces and all types encountered
in the interface method signatures to calculate the package of proxy
class it too strict. Only implemented interfaces and return types of all
interface methods need to be taken into consideration. Here's an example
of bytecode that illustrates how method parameters are passed to
InvocationHandler:
public final void doWith(pkg.Named[]) throws ;
Signature: ([Lpkg/Named;)V
flags: ACC_PUBLIC, ACC_FINAL
Code:
stack=10, locals=3, args_size=2
0: aload_0
1: getfield #16 // Field
java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
4: aload_0
5: getstatic #57 // Field
m3:Ljava/lang/reflect/Method;
8: iconst_1
9: anewarray #22 // class java/lang/Object
12: dup
13: iconst_0
14: aload_1
15: aastore
16: invokeinterface #28, 4 // InterfaceMethod
java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
21: pop
22: return
23: athrow
24: astore_2
25: new #42 // class
java/lang/reflect/UndeclaredThrowableException
28: dup
29: aload_2
30: invokespecial #45 // Method
java/lang/reflect/UndeclaredThrowableException."<init>":(Ljava/lang/Throwable;)V
33: athrow
Exception table:
from to target type
0 23 23 Class java/lang/Error
0 23 23 Class java/lang/RuntimeException
0 23 24 Class java/lang/Throwable
... as can be seen, no parameter types are referenced in order to wrap
the parameters with Object[] array.
Regards, Peter
More information about the core-libs-dev
mailing list