• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

code generation/bytecode modification

 
Ranch Hand
Posts: 113
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'd like to add a sort of listener to an object, but I need to be able to do this at runtime. My plan is to have a 'dummy' object set whereever it needs to be, and as soon as any of its methods are called, something goes out and sets all the internal values up (anything accessing the object waits until this is finished).

So, I need a way to hijack the object. I can do this by changing the actual object, or by creating a subclass of the object. Either way, I need to put a call to Something at the start of each method, so that that Something can go about setting up the object, and holding off anything that's trying to get at the object while it's doing this.

What's the best way to go about doing this?
 
Bartender
Posts: 1205
22
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This sounds like a job for a Decorator. Here is the Decorator chapter from "Head First Design Patterns".

What I'm suggesting:
- Make a MyClassDecorator class that is a subclass of your existing MyClass.
- MyClassDecorator should have a field of type of type MyClass that gets set with a reference to an ordinary MyClass object in a constructor.
- MyClassDecorator should override each method to call something() and then the method with the same name in the wrapped object.

That way you can add or not add the "something" functionality based on some value available at runtime:



After that snippet, the rest of the code doesn't need to care whether it's dealing with a basic MyClass object or a basic MyClass object wrapped in a MyClassDecorator. They both implement the same basic MyClass interface.

This is a simplification the standard Decorator pattern in that...
  • The pattern is usually used when there is more than one type of additional functionality that might be added.
  • There is usually a separate MyClassDecorator class between MyClass and the various decorators.


  • Since there was only one decorator in this case, I decided to not bother with the extra overhead of the additional intermediate Decorator class.

    I hope this helps.

    Ryan
     
    Maxim Katcharov
    Ranch Hand
    Posts: 113
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    It does help, but I still need to be able to create this decorator at runtime - I can't code this into the classes I'll be setting up, since I don't know what those classes will be. I need to be able to take any class at all, as is, let my factory create it according to whatever, and spit it out - except I won't set it as I create it, I'll just spit out the generated dummy (sub)class (that may or may not be accessed at all, I can't tell) and set it up (via reflection, probably) as soon as anything touches it. So I need to attach a bit of code at the start of all methods that leads into that one method, something like:

     
    (instanceof Sidekick)
    Posts: 8791
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Would Proxy help? Using Proxy to Interpose on Methods went over my head pretty quickly, but it looks like what you need.
    [ May 09, 2005: Message edited by: Stan James ]
     
    Maxim Katcharov
    Ranch Hand
    Posts: 113
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    That certainly seems to be on the right track, but it looks like that solution is limited to interfaces. I'd still need to deal with classes that don't have an interface.

    I only need to create the class once, so I was considering reading in the classes, creating source code to extend the class, compiling it, and then loading and using that compiled class. That seems really messy though...

    I just started reading http://www-106.ibm.com/developerworks/java/library/j-dyn0916.html , but I don't know if that'll help me or if it's the best solution anyway.
     
    Wanderer
    Posts: 18671
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Well, I'm pretty sure you could use AspectJ for something like this. Or BCEL if you want to get your hands dirty. Both allow you to essentially rewrite class definitions at runtime. BCEL essentially lets you edit the bytecode directly; AspectJ lets you work at a higher level. You can't make completely arbitrary changes to code with AspectJ, but you can do things like inserting a log statement before all method calls in package X, or insert some new custom method calls before and after calls to method Y() in class Z. I'd look into AspectJ first.
     
    Maxim Katcharov
    Ranch Hand
    Posts: 113
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    those two seem like a lot to take in! I think I have quite a bit of reading to do.

    AspectJ looks like it needs to compile everything with a specific compiler... if this is the case, I'd rather not use it. Is this the case?


    It sure would be nice if I could just write

    and be done with it. But I guess that that's not gonna happen
     
    Ranch Hand
    Posts: 585
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    BCEL will do a few things:

    1. Since you're dealing with byte code, it's much faster when the method runs (since it's just executing the calls you added)
    2. Be a pain in the butt to work with. TRUST ME.

    However, if runtime performance is MUCH more important than development ease/speed, go with BCEL.
     
    Ranch Hand
    Posts: 1209
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    "AmazingToolForDoingThingsToClasses."


    Mind trying Spring AOP ?

    They use cglib for proxying classes and proxies for interfaces but they dont want you to bother
    You can proxy classes for all cases. So you will end up using cglib for everything.




    Do checkout autoproxy feature as well.
     
    Maxim Katcharov
    Ranch Hand
    Posts: 113
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    BCEL, with help from it's BCELifier tool, worked out quite nicely, thanks all for the input.
     
    I found a beautiful pie. And a tiny ad:
    a bit of art, as a gift, that will fit in a stocking
    https://gardener-gift.com
    reply
      Bookmark Topic Watch Topic
    • New Topic