[newbie] access question
| Newsgroups | gmane.comp.java.objectweb.asm |
|---|---|
| Message-ID | <[email protected]> |
Hi,
I'm fairly new to ASM, bytecode, and reflection in java. However,
I've successfully written my first ASM project and am quite happy with
it... except for one access-related problem that I'm not sure how to
fix.
The situation:
interface Callback
{
void doSomething();
}
class Impl1 implements Callback { ... }
class Impl2 implements Callback { ... }
Suppose I have an array of N Callback objects I want to invoke:
final Callback[] cbs = { new Impl1(), new Impl1(), new Impl2(), new Impl2()
};
...
// Works, but can be optimized
for (Callback cb : cbs)
{
cb.doSomething();
}
Due to the special case of the array being setup at program start, and
never changing, there is an opportunity for optimization to unroll the
loop and call doSomething() directly on the objects sequentially, also
in a way that allows the JIT compiler to de-virtualize the calls.
I've generated a class using ASM that does just this. The generated
code is equivalent to this:
class DelegateCallbacks implements Callback
{
private final Impl1 delegate0;
private final Impl1 delegate1;
private final Impl2 delegate2;
private final Impl2 delegate3;
public DelegateCallbacks(Object[] objects) {
delegate0 = (Impl1) objects[0];
delegate1 = (Impl1) objects[1];
delegate2 = (Impl1) objects[2];
delegate3 = (Impl1) objects[3];
}
@Override public void doSomething() {
delegate0.doSomething();
delegate1.doSomething();
delegate2.doSomething();
delegate3.doSomething();
}
}
Now instead of writing the for loop, I just generate this optimized
unrolled class and instantiate it with my array.
The problem arises when the most derived type of the object happens to
be private or protected, then my generated class receives a
java.lang.reflect.InvocationTargetException when its constructor
executes, presumably at the point at which I do the downcast from
Object to initialize the member.
Here is some of the code that helps generate my class constructor.
I'm using a GeneratorAdapter to help write the constructor.
...
final GeneratorAdapter ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
myMethod, null, null, cw);
... (stuff omitted)
// downcast & initialize the member variable with delegate
ga.checkCast(delegateType);
ga.putField(myType, delegateExternalName, delegateType);
...
for (int i = 0; i < numDelegates; ++i)
{
final Type delegateType = Type.getType(delegateDescriptor(i));
ga.newLabel();
ga.loadThis();
ga.loadArg(0); // push delegates array
ga.push(i); // push index into delegates array
ga.arrayLoad(delegateType); // get the current delegate object
// initialize the member variable with delegate
ga.checkCast(delegateType);
ga.putField(classType, delegateExternalName(i), delegateType);
}
ga.returnValue();
ga.endMethod();
At the point where I call checkCast, it is there (I imagine) that the
exception is originating.
I think this problem has two parts for my understanding.
1) Java reflection makes it easy to change access for fields and
methods since they extend the java.lang.reflect.AccessibleObject,
but this is a *class*_ (not just a member/method of a class), and I
don't know how to modify access to it. If it's not really simple,
a pointer to documention on this would be most appreciated.
2) If it is possible to tweak the class access, do I have to do it in
the generated code? If so, could anyone give me a hand on doing so
in ASM?
I'm wondering if I'm going to have to do something like this:
ga.<emit code to remember old access to class of delegate type>
ga.<emit code to make class of delegate accessible>
ga.checkCast(delegateType);
ga.putField(myType, delegateExternalName, delegateType);
ga.<emit code to return access of delegate class back to what it was>
Is this the right approach? I suppose the <emit> sections could possibly
be implemented in regular java code, and I only have to generate ASM code
to call those functions.
But still, I'm kind of not sure how to proceed.
Thanks!
Chris
message-footer.txt
(text/plain, 238 B)
-- You receive this message as a subscriber of the [email protected] mailing list. To unsubscribe: mailto:[email protected] For general help: mailto:[email protected]?subject=help OW2 mailing lists service home page: http://www.ow2.org/wws