Re: [newbie] access question
Tronje Krop <[email protected]>
| Newsgroups | gmane.comp.java.objectweb.asm |
|---|---|
| Organization | Darmstadt University of Technology |
| Message-ID | <[email protected]> |
Why don't you want to let the JIT compiler decide whether to unrole or not unrole your code? As I see it, this should happen authomatically for some time: http://java.sun.com/products/hotspot/docs/whitepaper/Java_HotSpot_WP_Final_4_30_01.html If the size of the array is known and final on first execution it should run as expected. Best regards Tronje [email protected] wrote: > 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 > -- Tronje Krop <[email protected]> Encrypted eMail welcome! GPG/PGP-Key: 0x9AD43A05 68E5 A3D3 75A0 B096 AC75 62D5 8EEE 3D18 9AD4 3A05 No responsibility is taken for the correctness of the previous information. Please delete if you receive this mail unintentional.
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