简体   繁体   English

将 java 对象/类从一个类加载器复制到另一个类加载器

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

Hi is there a way to copy one class loaded context (atrributes etc) from one classloader (for instance a 'made' class Point) to another classloader?嗨,有没有办法将一个类加载的上下文(属性等)从一个类加载器(例如“制造”类 Point)复制到另一个类加载器?

Making clear, Example: I have an object Point on CL 1. Now running on another CL2, I want to creat this object in CL 3.澄清一下,例如:我在 CL 1 上有一个对象 Point。现在在另一个 CL2 上运行,我想在 CL 3 中创建这个对象。

Some obj:一些对象:

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

Scenery:风景:

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

But I can't use sun.reflection (not available) and serialization doesn't work since CL2 automatically "reconstruct" the object with CL 1.但是我不能使用 sun.reflection(不可用)并且序列化不起作用,因为 CL2 会自动用 CL 1“重建”对象。

One solution that I tought was do an "100%" java reflection rconstruct, basically getting the fields of object from CL2 and setting up on the new obj.我想到的一个解决方案是做一个“100%”的 java 反射 rconstruct,基本上从 CL2 获取对象的字段并在新的 obj 上设置。

PS: It needs to run on Java 1.4.2 :'( PS:它需要在 Java 1.4.2 上运行 :'(

See Transloader on how to copy classes between ClassLoaders if you need to do one of the following:如果您需要执行以下操作之一,请参阅Transloader了解如何在 ClassLoader 之间复制类:

  • Clone almost any object graph from one ClassLoader to another几乎任何对象图从一个 ClassLoader克隆到另一个

  • Take any object from a foreign ClassLoader and invoke any method on it without cloning it从外部 ClassLoader 获取任何对象并调用其上的任何方法而不克隆它

If the class is as simple as you describe it in your case, you could look at XMLEncoder .如果该类与您在案例中描述的一样简单,则可以查看XMLEncoder There are significant restrictions using it, but in simple cases it should get the job done.使用它有很大的限制,但在简单的情况下它应该可以完成工作。

EDIT: Given this limitation, I would say put the data in a Map and use that.编辑:鉴于此限制,我会说将数据放在 Map 中并使用它。 You could even have the two classes store their state in a Map internally so that movement is pretty fluid.您甚至可以让这两个类在内部将它们的状态存储在 Map 中,以便移动非常流畅。

If that can't work, then it looks like you are facing a roll your own XML/JSON or just plain CSV, depending on the complexity of the data.如果这不起作用,那么您似乎面临着自己的 XML/JSON 或纯 CSV 卷,具体取决于数据的复杂性。

I believe he has the same Class (with the same name) but loaded and defined by two classloaders.我相信他有相同的类(具有相同的名称)但由两个类加载器加载和定义。 The best thing to do is fix your system so the class is not loaded and twice.最好的办法是修复你的系统,这样类就不会被加载两次。

PowerMock classloading also provides something similar to TransLoader and it supports more advance use cases such as (some) reflection. PowerMock 类加载还提供了类似于 TransLoader 的东西,它支持更高级的用例,例如(某些)反射。 You can easily execute a Runnable or Callable:您可以轻松地执行 Runnable 或 Callable:

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

Have a look at the test case in the svn repo.查看 svn repo 中的测试用例

It's also available in Maven:它也可以在 Maven 中使用:

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

There are several options.有几种选择。 If your class is Serializable , you can serialise it and deserialise it again using another ClassLoader.如果您的类是Serializable ,您可以序列化它并使用另一个 ClassLoader 再次反序列化它。 Spring's ConfigurableObjectInputStream is a good help here: 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();

You can get it using maven by including您可以通过包含使用 maven 来获取它

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

If your class is not serialisable, you can clone the object to another ClassLoader using PowerMock components as @Johan suggested.如果您的类不可序列化,您可以按照@Johan 的建议使用 PowerMock 组件将对象克隆到另一个 ClassLoader。 If you just want to copy the Object to a different ClasLoader, you can use PowerMock's DeepCloner like this:如果您只想将对象复制到不同的 ClasLoader,您可以像这样使用 PowerMock 的DeepCloner

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

to do that, you need the following dependency:为此,您需要以下依赖项:

<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