簡體   English   中英

將 java 對象/類從一個類加載器復制到另一個類加載器

[英]Copy java object/class from one classloader to another classloader

嗨,有沒有辦法將一個類加載的上下文(屬性等)從一個類加載器(例如“制造”類 Point)復制到另一個類加載器?

澄清一下,例如:我在 CL 1 上有一個對象 Point。現在在另一個 CL2 上運行,我想在 CL 3 中創建這個對象。

一些對象:

class Point {
int x;
int y;
public Point() {}
//getters and setters

風景:

... 
class CL2 {

// Running on CL 2
...
// Point obj from CL 1
Object point = gotFromCL1();

// Want to create the object on Cl2
Object pointCL2 = point.conversion();

但是我不能使用 sun.reflection(不可用)並且序列化不起作用,因為 CL2 會自動用 CL 1“重建”對象。

我想到的一個解決方案是做一個“100%”的 java 反射 rconstruct,基本上從 CL2 獲取對象的字段並在新的 obj 上設置。

PS:它需要在 Java 1.4.2 上運行 :'(

如果您需要執行以下操作之一,請參閱Transloader了解如何在 ClassLoader 之間復制類:

  • 幾乎任何對象圖從一個 ClassLoader克隆到另一個

  • 從外部 ClassLoader 獲取任何對象並調用其上的任何方法而不克隆它

如果該類與您在案例中描述的一樣簡單,則可以查看XMLEncoder 使用它有很大的限制,但在簡單的情況下它應該可以完成工作。

編輯:鑒於此限制,我會說將數據放在 Map 中並使用它。 您甚至可以讓這兩個類在內部將它們的狀態存儲在 Map 中,以便移動非常流暢。

如果這不起作用,那么您似乎面臨着自己的 XML/JSON 或純 CSV 卷,具體取決於數據的復雜性。

我相信他有相同的類(具有相同的名稱)但由兩個類加載器加載和定義。 最好的辦法是修復你的系統,這樣類就不會被加載兩次。

PowerMock 類加載還提供了類似於 TransLoader 的東西,它支持更高級的用例,例如(某些)反射。 您可以輕松地執行 Runnable 或 Callable:

ClassloaderExecutor cle = new ClassloaderExecutor(classloader);
cle.execute(aRunnable); 
Object result = cle.execute(aCallable); // Result is cloned back to original CL

查看 svn repo 中的測試用例

它也可以在 Maven 中使用:

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-classloading</artifactId>
    <version>1.4.6</version>
</dependency>

有幾種選擇。 如果您的類是Serializable ,您可以序列化它並使用另一個 ClassLoader 再次反序列化它。 Spring 的ConfigurableObjectInputStream在這里提供了很好的幫助:

ByteArrayOutputStream stream = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(stream);
out.writeObject(object);
byte[] data = stream.toByteArray()

Object result = new ConfigurableObjectInputStream(new ByteArrayInputStream(data), classLoader).readObject();

您可以通過包含使用 maven 來獲取它

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.2.8.RELEASE</version>
</dependency>

如果您的類不可序列化,您可以按照@Johan 的建議使用 PowerMock 組件將對象克隆到另一個 ClassLoader。 如果您只想將對象復制到不同的 ClasLoader,您可以像這樣使用 PowerMock 的DeepCloner

DeepCloner deepCloner = new DeepCloner(classLoader);
Object result = deepCloner.clone(object);

為此,您需要以下依賴項:

<dependency>
   <groupId>org.powermock</groupId>
   <artifactId>powermock-classloading-xstream</artifactId>
   <version>2.0.7</version>
</dependency>

暫無
暫無

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

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