File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
The moose likes Java in General and the fly likes code generation/bytecode modification Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login

Win a copy of Java Interview Guide this week in the Jobs Discussion forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "code generation/bytecode modification" Watch "code generation/bytecode modification" New topic

code generation/bytecode modification

Maxim Katcharov
Ranch Hand

Joined: Sep 07, 2004
Posts: 113
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?
Ryan McGuire
Ranch Hand

Joined: Feb 18, 2005
Posts: 1046
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.

    Maxim Katcharov
    Ranch Hand

    Joined: Sep 07, 2004
    Posts: 113
    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:

    Stan James
    (instanceof Sidekick)
    Ranch Hand

    Joined: Jan 29, 2003
    Posts: 8791
    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 ]

    A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
    Maxim Katcharov
    Ranch Hand

    Joined: Sep 07, 2004
    Posts: 113
    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 , but I don't know if that'll help me or if it's the best solution anyway.
    Jim Yingst

    Joined: Jan 30, 2000
    Posts: 18671
    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.

    "I'm not back." - Bill Harding, Twister
    Maxim Katcharov
    Ranch Hand

    Joined: Sep 07, 2004
    Posts: 113
    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
    Robert Paris
    Ranch Hand

    Joined: Jul 28, 2002
    Posts: 585
    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.
    Karthik Guru
    Ranch Hand

    Joined: Mar 06, 2001
    Posts: 1209


    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

    Joined: Sep 07, 2004
    Posts: 113
    BCEL, with help from it's BCELifier tool, worked out quite nicely, thanks all for the input.
    I agree. Here's the link:
    subject: code generation/bytecode modification
    It's not a secret anymore!