Re: Re: [newbie] access question
Tronje Krop <[email protected]>
| Newsgroups | gmane.comp.java.objectweb.asm |
|---|---|
| Organization | Darmstadt University of Technology |
| Message-ID | <[email protected]> |
Hi Chris, sorry for not answering your question first. Actually, I think there are two solutions to this problem: 1) You may change the visibility of the user-provided type to public. As information hiding is a programing paradigm it is not that much a problem, as it seems to relax it on runtime. But nontheless it is not that clean. 2) The way I do it is introducing a new public helper class in the same context as that of the private class. This helper class will provide all functions I need to expose for my purposes with a well defined API. I found the second aproach cleaner, but it creates some more overhead. Best regards Tronje PS: You have some performance values for this optimization. Thats great, but microbenchmarks are hard to make right and you never can be sure under which conditions they hold. May be you should discuss them with some folks from the performance group or the hotspot compiler group. Chris Uzdavinis wrote: > Hi, > > Thanks for your reply (as I was starting to doubt if I'd > get one at all.) > > But would you mind helping me with my problem? > > Question: How do you generate code that down-casts an > object to an arbitrary, user-provided type--even if that > type is private? > > Currently, when I generate code that does a downcast to an arbitrary > type, it works for public types, but gets a runtime exception if the type > is private (since the generated code does not have access to the type.) > > If you could help me do this, I'd be very grateful. > > Thanks again, > Chris > > PS, I appreciate the fact that you question the value of my > optimization, as trying to out-do an optimizing compiler usually > is one of those things that shows a certain naiveté. If the roles > were reversed, I'd probably question you on it too. > However, this is not wishful thinking, or some theoretical fantasy. > I _already_ have a working implementation of the optimization > I described that has significant, measurable benefit in both > contrived benchmarks as well as in my real-world application. > The problem with it is not "if it works", but "how to make it > work with private types." > > > > On Sun, Nov 21, 2010 at 2:24 AM, Tronje Krop > <[email protected]> wrote: >> 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. >> >> >> -- >> 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 >> >> > -- 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