簡體   English   中英

Java:在運行時擴展 Class

[英]Java: Extending Class At Runtime

我有能力在編譯時擴展 class,但我需要能夠在運行時使用已經實例化的超類實例創建該子類的實例。

這在理論上應該是可能的,因為超類構造函數已經在子類構造函數之前被調用。

我沒有足夠的權限訪問該程序,無法將實例化更改為我的子類,也無法中斷原始實例化。

用例:有一個現有的class X的實例數組。我的代碼是在之后加載的。 我需要用我加載的子類 Y 擴展 X 覆蓋其中一個實例 X 的方法之一。父程序僅通過該數組訪問對象,因此我想用我的 Y 實例替換該數組元素,但它需要表現得好像它最初被實例化到該數組中一樣。 我不能只包含超類實例並轉發調用,並且重新實例化超類時會遇到困難。

我希望這更清楚。

重申你正在嘗試做的事情..

在 JVM 中,存在一個 ClassA 實例。 您想要動態修改 ClassA 的 class 層次結構,以便存在一個名為 ClassB 的新 class,它派生自 ClassA。 然后您想實例化 ClassB 的一個實例,但它的子類實現是 ClassA 的現有實例的子類實現。 類似於 memory 的替代品。

您可能需要查看http://www.jboss.org/javassist 您需要做的是替換 ClassLoader,然后確定何時加載 ClassA,然后實例化。 然后,您需要構造 ClassB 並將其返回。

更新

經過更多研究后,您仍然有可能做自己想做的事。 像 Eclipse 這樣的 IDE 在調試時支持 HotSwap 方法實現。 他們使用儀器 API。

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

您可以替換方法體,但不能添加或刪除方法本身。 因此,雖然您無法將類型更改為新類型,但您可以用新實現完全替換方法實現。

我建議使用cglib

cglib 是一個功能強大、高性能和高質量的代碼生成庫,它用於擴展 JAVA 個類並在運行時實現接口

你可以在這里找到一些例子: https://github.com/cglib/cglib/wiki

你看過 Java 代理嗎?

這是來自 Javadoc 的片段:

“動態代理class(以下簡稱代理class)是一個class,它實現了創建class時在運行時指定的接口列表”

我不知道這是否是一個解決方案,但如果你有

public static Foo foo = new Foo();

並且您想用擴展 Foo 的 Bar 替換它,使 Bar 成為 Foo 的包裝器,並使用反射讓 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);

}

如前所述,我不知道您的情況是否可行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM