What steps will reproduce the problem?
public class SimpleClass {
}
public class Test extends Instrumentation {
public void testSimpleProxy() throws IOException {
ProxyBuilder.forClass(SimpleClass.class)
.dexCache(getInstrumentation().getTargetContext().getDir("dx", Context.MODE_PRIVATE))
.handler(new SomeInvocationHandler())
.build();
}
}
What is the expected output? What do you see instead?
Using adb logcat, I'd expect no errors. The logs will, however, include errors
like:
D/dalvikvm( 4555): DEX prep '/data/data/test/app_dx/Generated-360119027.jar':
unzip in 0ms, rewrite 58ms
I/dalvikvm( 4555): DexOpt: illegal method access (call
Ljava/lang/Object;.internalClone (Ljava/lang/Cloneable;)Ljava/lang/Object; from
LSimpleClass_Proxy;)
I/dalvikvm( 4555): Could not find method test.SimpleClass.internalClone,
referenced from method SimpleClass_Proxy.internalClone
W/dalvikvm( 4555): VFY: unable to resolve virtual method 15:
Ltest/SimpleClass;.internalClone (Ljava/lang/Cloneable;)Ljava/lang/Object;
D/dalvikvm( 4555): VFY: replacing opcode 0x6f at 0x0019
I/dalvikvm( 4555): DexOpt: illegal method access (call
Ljava/lang/Object;.internalClone (Ljava/lang/Cloneable;)Ljava/lang/Object; from
LSimpleClass_Proxy;)
I/dalvikvm( 4555): Could not find method test.SimpleClass.internalClone,
referenced from method SimpleClass_Proxy.super$internalClone$java_lang_Object
W/dalvikvm( 4555): VFY: unable to resolve virtual method 15:
Ltest/SimpleClass;.internalClone (Ljava/lang/Cloneable;)Ljava/lang/Object;
D/dalvikvm( 4555): VFY: replacing opcode 0x6f at 0x0000
What's more, these errors will be repeated for every private or package-visible
method on the proxied class (or its superclasses). The ".internalClone" method
listed here (and for every created proxy) is a private method defined on
java.lang.Object, so is reported for every mock and proxy.
Please provide any additional information below.
I don't think this actually poses a functional problem, but I wanted to report
it in case it can be easily fixed. These errors obviously become quite verbose
and can get in the way of reading logcat.
The cause is the code generated in ProxyBuilder, which follows the prototype:
* public int doSomething(Bar param0, int param1) {
* if ($__handler == null) {
* return super.doSomething(param0, param1);
* }
* return __handler.invoke(this, __methodArray[4],
* new Object[] { param0, Integer.valueOf(param1) });
* }
If the "doSomething" method is private or package-visible, then the call to
super.doSomething is inaccessible from the generated proxy class. VFY spots
this and removes the super call.
Is it possible to remove the proxy method altogether for private methods? I may
be missing something, but I can't see how these should ever be called. DexMaker
Issue 24 (https://code.google.com/p/dexmaker/issues/detail?id=24) appears to be
a patch to do just this. I don't think the patch is quite right, however, as it
would prevent package-visible methods from being proxied/mocked as well.
For package-visible methods, we do need the proxy method, but perhaps the
"handler==null" case could just be an exception. This is a form of the general
problem that ProxyBuilder has with package-visible classes.
Original issue reported on code.google.com by i...@google.com on 15 Oct 2013 at 3:12
Original issue reported on code.google.com by
i...@google.com
on 15 Oct 2013 at 3:12