Java:在运行时扩展类

我有能力在编译时扩展一个类,但我需要能够在运行时使用已经实例化的超类的实例创建该子类的实例。

这在理论上应该是可能的,因为超类构造函数已经在子类构造函数之前调用。

我无法充分访问该程序以将实例化更改为我的子类,也无法中断原始实例化。

用例:存在类X的现有实例数组。我的代码在之后加载。 我需要覆盖其中一个实例X的一个方法,我的加载子类Y扩展X.父程序只通过该数组访问对象,所以我想用我的Y实例替换该数组元素,但它需要表现得好像它最初被实例化到那个数组中。 我不能只包含超类实例和转发调用,并且重新实现超类有很多复杂的问题。

我希望更清楚。

重申你要做的事情……

在JVM中,存在ClassA的实例。 您希望动态修改ClassA的类heiarchy,以便存在一个名为ClassB的新类,它派生自ClassA。 然后,您希望实例化ClassB的实例,但是它的子类实现是ClassA的现有实例的实现。 像记忆替换的东西。

您可能需要查看http://www.jboss.org/javassist 。 您需要做的是替换ClassLoader,然后确定何时加载ClassA,然后实例化。 然后,您需要构造ClassB并返回它。

更新

经过一番研究后,你仍然可以做你想做的事。 IDE就像Eclipse一样,在调试时支持HotSwap的方法实现。 他们使用Instrumentation API。

http://zeroturnaround.com/blog/reloading_java_classes_401_hotswap_jrebel/

您可以替换方法体,但不能自行添加或删除方法。 因此,虽然您无法将类型更改为新类型,但您可以使用新实现完全替换方法实现。

我建议使用cglib :

cglib是一个function强大,性能高,质量高的代码生成库,用于扩展JAVA类并在运行时实现接口

您可以在这里找到一些示例: https : //github.com/cglib/cglib/wiki

我不知道它是否是溶剂,但如果你有

public static Foo foo = new Foo(); 

并且你想用Bar替换它,它扩展了Foo使Bar成为Foo的包装器并使用reflection让foo指向你的Bar实例。

 public class Foo extends Bar { private bar; public Foo(Bar oldInstance) { this.bar = oldInstance; } } 

 // exception handling ommitted public static void onStartup() { Class fooRefClass = FooRef.class; Field fooRef = fooRefClass.getDeclaredField("foo"); Foo foo = (Foo)fooRef.get(null); Bar bar = new Bar(foo); fooRef.set(null, bar); 

}

据我所知,我不知道你的情况是否可行。

你看过Java Proxies了吗?

这是Javadoc的一个片段:

“动态代理类(下面简称为代理类)是一个实现创建类时在运行时指定的接口列表的类”