This looked interesting :-
... looks pretty intriguing. Faster it claims.
I did some testing last night and it's only 10% faster than regular reflection for method invocations, and only if your cache the ASM-made subclass of "MethodAccess".
There are some flaws too:
- It generates accessors for each method in a class - you may have been interested in only a single method.
- It assumed that there is no method overloading in the class
- Exceptions will pass through (no InvocationTargetException), yet are not (and cannot be) concisely listed on the throws clause of the var-args invoke method you use. You have to be aware of the exceptions that could be thrown, or catch base Exception (yeesh).
MethodAccess (the class) is in your regular classpath on use, as normal Java launch semantics. The classes that ASM generates ALSO purport to be MethodAccess (same package), but by some defineClass magic in a child class-loader, are instantiated instead of the real deal. The Java Compiler lets you think you are using static method on MethodAccess, but at runtime you are using a method with the same signature in a different class (with the same name).
It got me thinking though.
Say, for <at> Inject methods (and constructors, poss fields too)
There could be a QDox build stage that kicks in and makes an invoke class for each so-annotated method.
In the same way that GMaven allows Java and Groovy to interop in the same source buildable jar (by generating shims of the Groovy classes for the Java classes to compile against), some tricks that JetBrains and Eclipse would buy into would allow a method invocation design that was more first class than reflection. For example:
public class Foo {
<at> Inject
public void bar(Baz baz) {
}
}
public static void main(String[] args) {
Foo instance = new Foo();
Foo.bar1965ed0b.invoke(instance, new Baz());
}
// 1965ed0b is a CRC32 hash of 'Baz baz'
PicoContainer, Guice etc could speculatively look for the inner class bar1965ed0b and use it. It would still not preserve throws clauses as Pico/Guice would cast it to a interface to use it for the speed you're seeking. It would be in the same jar file of course. Shame about the extra bytes - AFAICR the min byte size of an inner class is 178.
- Paul