views:

1159

answers:

5

Hello!

It is possible in plain Java to override a method of a class programmatically at runtime (or even create a new method)?

I want to be able to do this even if I don't know the classes at compile time.

What I mean exactly by overriding at runtime:

abstract class MyClass{
  public void myMethod();
}

class Overrider extends MyClass{
  @Override
  public void myMethod(){}
}

class Injector{
  public static void myMethod(){ // STATIC !!!
    // do actual stuff
  }
}

// some magic code goes here
Overrider altered = doMagic(
    MyClass.class, Overrider.class, Injector.class);

Now, this invocation...

altered.myMethod();

...would call Injector.myMethod() instead of Overrider.myMethod().

Injector.myMethod() is static, because, after doing "magic" it is invoked from different class instance (it's the Overrider), (so we prevent it from accessing local fields).

+2  A: 

For interfaces there is java.lang.reflect.Proxy.

For classes you'll either need a third-party library or write a fair bit of code. Generally dynamically creating classes in this way is to create mocks for testing.

There is also the instrumentation API that allows modification of classes. You can also modify classes with a custom class loader or just the class files on disk.

Tom Hawtin - tackline
@T.H.t: In your opinion, would AOP or BCEL style re-engineering be applicable in this case too? I'm faced with a similar problem currently and can't decide what to use.
kd304
AOP is very general. I much prefer ASM to BCEL. oxbow_lakes mentions cglib, which I couldn't remember the name of (and haven't used).
Tom Hawtin - tackline
+4  A: 

You can use something like cglib for generating code on-the-fly

oxbow_lakes
A: 

If I got it right, the main problem that concerns you is how to pass a static method delegate (like in C#), through the instance interface method.

You can check this article: A Java Programmer Looks at C# Delegates, which shows you how to get a reference to your static method and invoke it. You can then create a wrapper class which accepts the static method name in its constructor, and implements your base class to invoke the static method from the instance method.

Groo
+1  A: 

I wrote an article for java.net about how to transparently add logging statements to a class when it is loaded by the classloader.

It uses the Javassist library to manipulate the byte code, including using the Javassist compiler to generate extra bytecode which is then inserted in the appropriate place, and then the resulting class is provided to the classloader.

A refined version is available with the slf4j project.

Thorbjørn Ravn Andersen
+1  A: 

In java6 has been added the possibility to transform any already loaded class. Take a look at the changes in the java.lang.instrument package

diega
I even forgot that this package exists! Thanks!
ivan_ivanovich_ivanoff