2010-01-08 73 views
2

这是问题的简化版本:的Java铸造/类加载器发出

SomeClass c = (SomeClass) obj.getSomeClassParent() 

并不总是,但有时会发生触发例外

org.somepackage.SomeClass can't be cast to org.somepackage.SomeClass 

这怎么可能?我想这与JAI imageio是原生lib这个事实有关,但转发这种情况怎么会发生?我可能错过了什么,但是什么?

I'm using JAI imageio version 1.1 
dcm4che 2.0.21 DICOM lib 

这里是原代码

ImageInputStream iis = ImageIO.createImageInputStream(src); 
    Iterator<ImageReader> iter = ImageIO.getImageReadersByFormatName("DICOM"); 
    ImageReader reader = iter.next(); 
    DicomImageReadParam param = (DicomImageReadParam) reader.getDefaultReadParam(); 

而原来的异常

org.dcm4che2.imageio.plugins.dcm.DicomImageReadParam can't be cast to  
org.dcm4che2.imageio.plugins.dcm.DicomImageReadParam 

Exception Image http://img215.imageshack.us/img215/3894/exception.jpg

+0

可能的重复:http://stackoverflow.com/questions/826319/classcastexception-when-casting-to-the-same-class – 2010-01-08 18:36:21

回答

7

我认为它可以发生,如果

  1. 一个SomeClass实例从类加载器加载X(所以它的类是CL X的SomeClass或让我们叫它:CL(X).SomeClass
  2. ,但它是在一个不同的类加载器正在施放。例如。当前线程类加载器为Y如此SomeClass实际上是CL(Y).SomeClass

所以,你必须:

  • 实例类= CL(X).SomeClass
  • 类转换目标= CL(Y).SomeClass

或者换句话说 - 不是同一个班级 - 因此班级强制例外。


可能的重复:ClassCastException when casting to the same class - 它也有一些很好的建议。

+2

你基本上在这里。问题是每个实例都由不同的类加载器加载,因此每个这些实例上的getClass()将返回同一个类的不同实例。你应该稍微编辑一下,因为一个类在两个类加载器中都被加载,而不是一个实例和另一个类中的实例,这实际上是不可能的。 – Robin 2010-01-08 18:40:26

+0

确实'SomeClass'在两个类加载器中都被加载,但是我认为该类型是从一个在CL X中加载的类的实例,到一个加载到CL Y的类。我将编辑答案。 – 2010-01-08 18:47:11

+0

@Ehrann Mehdan - 更清楚,但你应该删除序列化的一点,这不适用于这种情况。 – Robin 2010-01-08 19:07:57

1

奇怪,你有没有尝试将它转换为它扩展的对象,不知道它是否有你需要的功能,但可能值得尝试看看它是否仍然会抛出异常。

1

从图像中我看到它看起来像一个Web应用程序。我读'卡塔利娜'。所以这是一个很大的机会,这是一个纯粹的类加载问题。

例如,如果您从ImageIO类获取的ImageReader由不同的类加载器加载(可能是因为它部署在不同的webapp中),所以getDefaultReadParam()方法返回的DicomImageReadParam对象是 - 技术上讲的 - 不同课程的实例。

2

我想你有一个问题,因为类加载器和本地库之间的不匹配。本地库加载并与类加载器相关联,但是,程序只能加载真实加载本地库的一个实例。所以,如果你在类加载器A中加载本地库,并且它输出的类将与类加载器A相关联。如果以后在类加载器B中加载了相同的本机库,则不会再真正加载它,它仍然会传递类加载器A的类,以便重新部署Web应用程序,或者在同一个Web服务器中有2个Web应用程序它们使用相同的本地库。

如果可能,您应该尝试将本机库置于Web服务器的基类路径中,以便它将由基类加载器加载,从而可供任何Web应用程序使用。如果你不能这样做,并且问题只是一个重新部署问题,那么你可能需要在重新部署之前取消部署和等待一段时间(理论上,当与它关联的类加载器被GCed时,本地lib将被卸载,但当然,这可能需要不知道的时间)。