简体   繁体   English

Java:在运行时扩展 Class

[英]Java: Extending Class At Runtime

I have the capability to extend a class at compile time, but I need to be able to create an instance of this subclass at runtime using an instance of the superclass that was already instantiated.我有能力在编译时扩展 class,但我需要能够在运行时使用已经实例化的超类实例创建该子类的实例。

This should be possible in theory because superclass constructors are already called before the subclass constructor.这在理论上应该是可能的,因为超类构造函数已经在子类构造函数之前被调用。

I do not have access to the program sufficiently to change the instantiation to my subclass nor to interrupt the original instantiation.我没有足够的权限访问该程序,无法将实例化更改为我的子类,也无法中断原始实例化。

Use Case: There is an existing array of instances of class X. My code is loaded in after.用例:有一个现有的class X的实例数组。我的代码是在之后加载的。 I need to override one of the methods of one of the instances X with my loaded subclass Y extends X. The parent program accesses the objects only through that array, so I want to replace that array element with my Y instance, but it needs to behave as if it were instantiated originally into that array.我需要用我加载的子类 Y 扩展 X 覆盖其中一个实例 X 的方法之一。父程序仅通过该数组访问对象,因此我想用我的 Y 实例替换该数组元素,但它需要表现得好像它最初被实例化到该数组中一样。 I cannot just enclose the superclass instance and forward calls, and there are difficult complications with reinstantiating the superclass.我不能只包含超类实例并转发调用,并且重新实例化超类时会遇到困难。

I hope that is more clear.我希望这更清楚。

To reiterate what you are trying to do..重申你正在尝试做的事情..

Within the JVM, there exists an instance of ClassA.在 JVM 中,存在一个 ClassA 实例。 You would like to dynamically modify the class heiarchy of ClassA, such that a new class exists called ClassB which derives from ClassA.您想要动态修改 ClassA 的 class 层次结构,以便存在一个名为 ClassB 的新 class,它派生自 ClassA。 Then you would like to instantiate an instance of ClassB but have it's subclass implementation be that of the existing instance of ClassA.然后您想实例化 ClassB 的一个实例,但它的子类实现是 ClassA 的现有实例的子类实现。 Something like a memory replacement.类似于 memory 的替代品。

You might want to look into http://www.jboss.org/javassist .您可能需要查看http://www.jboss.org/javassist What you would need to do is replace the ClassLoader, then determine when ClassA is being loaded, then instantiated.您需要做的是替换 ClassLoader,然后确定何时加载 ClassA,然后实例化。 You'd then need to construct ClassB and return that instead.然后,您需要构造 ClassB 并将其返回。

Update更新

After a little more research there is still the possibility you can do what you want.经过更多研究后,您仍然有可能做自己想做的事。 IDE's like Eclipse support HotSwap'ing method implementations while debugging.像 Eclipse 这样的 IDE 在调试时支持 HotSwap 方法实现。 They use the Instrumentation API.他们使用仪器 API。

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

You can replace method bodies but not add or remove methods themselves.您可以替换方法体,但不能添加或删除方法本身。 So while you won't be able to change the type to your new type, you can completely replace the method implementation with your new implementation.因此,虽然您无法将类型更改为新类型,但您可以用新实现完全替换方法实现。

I would suggest using cglib :我建议使用cglib

cglib is a powerful, high performance and quality Code Generation Library, It is used to extend JAVA classes and implements interfaces at runtime cglib 是一个功能强大、高性能和高质量的代码生成库,它用于扩展 JAVA 个类并在运行时实现接口

You may find some examples here: https://github.com/cglib/cglib/wiki你可以在这里找到一些例子: https://github.com/cglib/cglib/wiki

Have you looked at Java Proxies?你看过 Java 代理吗?

Here is a snippet from Javadoc:这是来自 Javadoc 的片段:

"A dynamic proxy class (simply referred to as a proxy class below) is a class that implements a list of interfaces specified at runtime when the class is created" “动态代理class(以下简称代理class)是一个class,它实现了创建class时在运行时指定的接口列表”

I don't know if it's a sollution but if you have我不知道这是否是一个解决方案,但如果你有

public static Foo foo = new Foo();

and you want to replace it with Bar which extends Foo make Bar an Wrapper for of Foo and use reflection to let foo point to your Bar instance.并且您想用扩展 Foo 的 Bar 替换它,使 Bar 成为 Foo 的包装器,并使用反射让 foo 指向您的 Bar 实例。

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

and

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

} }

As told I don't know if this is possible in your case.如前所述,我不知道您的情况是否可行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM