如何在运行时制作Java类的副本?

时间:2016-11-23 21:51:54

标签: java code-generation bytecode bytecode-manipulation

我有一个班级

class Foo {
    int increment(int x) {
        return x + 1;
    }
}

我想在运行时获取此类的副本,例如: G。像

这样的课程
class Foo$Copy1 {
    int increment(int x) {
        return x + 1;
    }
}

其中包含所有相同的方法,但名称不同。

Proxy似乎有助于委派,但无法复制方法。

3 个答案:

答案 0 :(得分:8)

您可以使用Byte Buddy

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);

请注意,此方法重新定义了Foo中类的任何用途,例如如果方法返回Foo,则现在返回Foo$Copy1。所有代码引用也是如此。

答案 1 :(得分:2)

答案 2 :(得分:1)

如果你能正常访问字节码,我认为使用Unsafe就足够了。

Foo.class.getClassLoader().getResourceAsStream()之类的东西可以为你提供类的字节码。

然后使用 sun.misc.Unsafe.defineClass(String name, byte[] code, int off, int len, ClassLoader classLoader, ProtectionDomain protectionDomain)在同一个类加载器和保护域中将类定义为Foo,但名称不同。

细节要弄清楚,但它可能是没有任何第三方库的最简单的方法。