Reputation: 15313
I have a class
class Foo {
int increment(int x) {
return x + 1;
}
}
I want to obtain a copy of this class in runtime, e. g. a class like
class Foo$Copy1 {
int increment(int x) {
return x + 1;
}
}
Which has all the same methods, but a different name.
Proxy
seem to help with delegating, but not copying the methods with all their bodies.
Upvotes: 7
Views: 1266
Reputation: 41
@leventov what about this one? https://gist.github.com/serkan-ozal/8737583841b4b12e3a42d39d4af051ae
Upvotes: 2
Reputation: 44042
You can use Byte Buddy for this:
Class<?> type = new ByteBuddy()
.redefine(Foo.class)
.name("Foo$Copy1")
.make()
.load(Foo.class.getClassLoader())
.getLoaded();
Method method = type.getDeclaredMethod("increment", int.class);
int result = (Integer) method.invoke(type.newInstance(), 1);
Note that this approach redefines any uses of the class within Foo
, e.g. if a method returned Foo
, it would now return Foo$Copy1
. Same goes for all code-references.
Upvotes: 12
Reputation: 3800
I think using Unsafe could be enough if you have normal access to the bytecode.
Something like Foo.class.getClassLoader().getResourceAsStream()
can give you the bytecode for the class.
Then use
sun.misc.Unsafe.defineClass(String name, byte[] code, int off, int len, ClassLoader classLoader, ProtectionDomain protectionDomain)
to define the class in the same classloader and protection domain as Foo but with a different name.
The details are to figure out, but it might be the simplest approach without any third party libraries.
Upvotes: 1