由于ClassLoader问题导致ClassCastException的解决方案

时间:2011-08-16 06:50:37

标签: java classloader classcastexception

我有两个加载相同类的ClassLoader。所以,显然这些不能相互投射。但是我需要访问在另一个ClassLoader中创建的对象。

我可以访问两个ClassLoader。如何在其他类中使用该对象?我不需要将对象转换为与当前ClassLoader匹配。

但问题是返回的对象的类型是Object。所以,我必须抛弃该对象来访问某些方法。我怎样才能做到这一点?像下面这样的正常转换会导致ClassCastException,我已经知道了。

Mojo mojo = (Mojo) descriptor.getMojo();

descriptor#getMojo()返回Mojo类型的对象,但该方法返回Object。怎么办呢?

如果您需要更多信息,请与我们联系。

我已经阅读了关于类加载的所有理论,但没有人为此指定了适当的解决方案。

5 个答案:

答案 0 :(得分:8)

AFAIK,不,你不能在另一个类加载器中转换由一个类加载器加载的类的对象。

  • 一种解决方案是创建一个“通用”类加载器,它加载要由自定义类加载器使用的类。因此,在您的情况下,您将有一个新的类加载器,它将加载给定的类,您的自定义类加载器将扩展此类加载器。
  • 另一种解决方案是在两个类加载器之间传递“序列化”状态。将一个实例序列化为一个字节数组,并通过反序列化对象流来重构另一个类加载器中的对象。

答案 1 :(得分:1)

反思并不是那么糟糕,在这里是合适的 这是一个Maven插件,BTW?

你会想要这样的东西:

Mojo mojo = (Mojo)descriptor.getClass().getMethod("getMojo").invoke(descriptor);

我遗漏了很多 - 特别是异常处理 - 但这应该会引导你到你需要的Javadoc。这很好,但请仔细阅读。

如果你还有两个Mojo课程,那么演员阵容将会破裂,你将不得不做更多的反思来做你需要做的任何与邪恶的双胞胎Mojo。

答案 2 :(得分:0)

为什么你有2个CloassLoader,它们会加载同一个类?这可能是一个编程问题。听起来你正在某个地方缓存ClassLoader并以错误的方式重用它们。如果不是这种情况,请尝试使用MultiClassLoader。

创建一个包含多个其他类加载器的MultiClassLoader。您可以使用这些MultiClassLoader加载所需的所有类。但是你必须在开始时创建这些MultiClassLoader,而不是在加载类时。

public class MultiClassLoader extends ClassLoader

您将拥有一个类加载器集合,并在findClass(...)中迭代所有这些已注册的加载器。

protected Class findClass(String aName) throws ClassNotFoundException {
   for (Iterator iter = multiLoaders.iterator(); iter.hasNext();) {
      ClassLoader tmpLoader = (ClassLoader)iter.next();
      try {
         return tmpLoader.loadClass(aName);
      } catch (ClassNotFoundException e) {
      }
   }
   throw new ClassNotFoundException(aName);
}

答案 3 :(得分:0)

最简单的方法是使用反射。这允许你在“普通”代码中搜索任何你能做的事情。

答案 4 :(得分:0)

我认为更好的选择是只存储字节数组而不是对象。在deserliazing,获取字节数组并转换为对象。

我遇到了同样的问题和字节数组方法。

ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutput out = null;
    try {
        out = new ObjectOutputStream(bos);
        out.writeObject(cachedValue);
        byte b[] = bos.toByteArray();

        //Store in DB, file wherever here using b[]. I am not writing code to store it as it may vary in your requirement.

    } catch (IOException e) {
        e.printStackTrace();
    }

从字节数组中读取:

ByteArrayInputStream bis = new ByteArrayInputStream(<<read byte[] where you stored earlier>>);
    ObjectInput in = null;

    try {
        in = new ObjectInputStream(bis);
        <Your Class >cachedRes = ( Your Class) in.readObject();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }