2010-01-08 61 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將被卸載,但當然,這可能需要不知道的時間)。