1

Possible Duplicate:
Can a Java class add a method to itself at runtime?

Is it possible to synthesize a new method at runtime for a class in Java? Is there a library to make that possible?

Community
  • 1
  • 1
Frank
  • 4,341
  • 8
  • 41
  • 57
  • You should check this post : http://stackoverflow.com/questions/1054777/java-reflection-how-do-i-override-or-generate-methods-at-runtime – DayS Sep 18 '12 at 21:57
  • Short answer: no. See: http://stackoverflow.com/questions/6680674/can-a-java-class-add-a-method-to-itself-at-runtime – Nick Sep 18 '12 at 21:58

2 Answers2

4

Beyond bytecode engineering libraries, if you have an interface for your class, you could use Java's Proxy class.

With an interface:

public interface Foo {
    void bar();
}

The concrete class:

class FooImpl {
    public void bar() {
        System.out.println("foo bar");
    }
}

To process the methods called, you use InvocationHandler:

class FooInvocationHandler implements InvocationHandler {

    private Foo foo;

    FooInvocationHandler(Foo foo) {
        this.foo = foo;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
        if (method.getName().equals("bar"))
            System.out.println("foo me");
            // return null if you don't want to invoke the method below
        }
        return method.invoke(foo, args); // Calls the original method
    }
}

Then create a FooFactory to generate and wrap FooImpl instances using Proxy:

public class FooFactory {
    public static Foo createFoo(...) {
        Foo foo = new FooImpl(...);
        foo = Proxy.newProxyInstance(Foo.class.getClassLoader(),
                new Class[] { Foo.class },
                new FooInvocationHandler(foo));
        return foo;
    }
}

This would wrap the FooImpl object so that this:

Foo foo = FooFactory.createFoo(...);
foo.bar();

Prints:

foo me
foo bar

This is an alternative to the BCEL libraries, which can do this and a lot more, including generating classes from runtime information, but the BCEL libraries aren't native. (Proxy is in java.lang.reflect on everything since 1.3.)

Brian
  • 17,079
  • 6
  • 43
  • 66
3

Into a already loaded class? Not to my knowledge.

However, you may be interested in generating a new class. I see two options:

  • I made a project recently which generated a class based off of a String containing the code, and loaded it in to the system, and ran it's main method. However, this requires the JDK to be installed = highly unreliable
  • Through BCEL. This also has bads, but seems to be better overall. It requires you to have the bytecode of the method beforehand. Now you could do some trickery by, for example, making a method

like so:

public static void printTest() {
    System.out.println("Hey!");
}

And then taking a look at the bytecode, seeing where in the ConstantPool "Hey!" is stored, then taking the bytecode for the method, caching it into a byte array, then dynamically creating a method with pre-defined bytes + constant pool (that you examined before), and modifying the constantpool with your string. This would get very tricky very fast though for more complicated methods (Note: the same could be done to change what method it calls, or field it gets, like changing out to err)

Since there aren't really any good options as far as I see though, so these are your best bets

Alex Coleman
  • 7,216
  • 1
  • 22
  • 31
  • 1
    +1 for bytecode engineering, but BCEL is nearly outdated (last updated in 2006), and does not support some Java 7 features such as *invokedynamic* (although this is rarely used). Apache's ASM is a more powerful bytecode engineering library as well as being up-to-date. – FThompson Sep 19 '12 at 01:28