未知數(shù)據(jù)

          從頭看Java

             ::  :: 聯(lián)系 :: 聚合  :: 管理
            28 Posts :: 0 Stories :: 10 Comments :: 0 Trackbacks

          轉(zhuǎn)載自:http://www.javaeedev.com/blog/article.jspx?articleId=ff80808114e23046011535799b5e0ecd

          問題描述


          ClassCastException 是 JVM 在檢測到兩個(gè)類型間的轉(zhuǎn)換不兼容時(shí)引發(fā)的運(yùn)行時(shí)異常。此類錯(cuò)誤通常會(huì)終止用戶請求。本模式試圖為您提供了解和排除 ClassCastException 錯(cuò)誤最常見成因的一些基本要素。

          故障排除


          請注意,并非下面所有任務(wù)都需要完成。有些問題僅通過執(zhí)行幾項(xiàng)任務(wù)就可以解決。

           

          為什么發(fā)生此問題?

           

          在執(zhí)行幾乎任何子系統(tǒng)(Web 容器、EJB、JCA、群集等)的應(yīng)用程序代碼或 WebLogic Server 代碼內(nèi)均可能發(fā)生 ClassCastException。通過轉(zhuǎn)換,可以指示 Java 編譯器將給定類型的變量作為另一種變量來處理。對(duì)基礎(chǔ)類型和用戶定義類型都可以進(jìn)行轉(zhuǎn)換。Java 語言規(guī)范定義了允許的轉(zhuǎn)換,其中的大多數(shù)可在編譯時(shí)進(jìn)行驗(yàn)證。不過,某些轉(zhuǎn)換還需要運(yùn)行時(shí)驗(yàn)證。如果在此運(yùn)行時(shí)驗(yàn)證過程中檢測到不兼容,JVM 就會(huì)引發(fā) ClassCastException。

          假設(shè)有一個(gè) S 類型的對(duì)象,我們想把它轉(zhuǎn)換為 T 類型。

          S s;
          ...
          T t = (T) s;


          如果存在以下情況,上述轉(zhuǎn)換就可能引發(fā) ClassCastException

          public class TestCCE {
            public static void main(String args[]) {
              Object obj = new Object();
              String s = (String) obj;
            }
          }

          第二個(gè)原因?qū)嶋H上是這種錯(cuò)誤最常見的原因。這種情況在診斷上有相當(dāng)?shù)碾y度,而且需要對(duì) Java 類加載以及 WebLogic 類加載體系結(jié)構(gòu)方面的基礎(chǔ)知識(shí)有一定程度的了解。

          什么是 ClassLoader?

          ClassLoader 是允許 JVM 查找和加載類的一種 Java 類。JVM 有內(nèi)置的 ClassLoader。不過,應(yīng)用程序可以定義自定義 ClassLoader。應(yīng)用程序定義新的 ClassLoader 通常有兩個(gè)主要目的:

          ClassLoader 按層級(jí)方式進(jìn)行組織。除系統(tǒng) Boot ClassLoader 外,其它 ClassLoader 都必須有父 ClassLoader。http://e-docs.bea.com/wls/docs81/programming/classloading.html (English) 中提供了對(duì) WebLogic 類加載體系結(jié)構(gòu)的說明。

          理解類加載的關(guān)鍵


          記住以下內(nèi)容會(huì)有幫助:

          診斷

          通??梢栽诜?wù)器的日志和/或客戶端獲得完整的 ClassCastException 堆棧跟蹤。該堆棧應(yīng)能使您對(duì)涉及的 WebLogic Server 子系統(tǒng)的情況有相當(dāng)深入的了解。請根據(jù)這些信息確認(rèn)該問題是否與某個(gè)已知 WebLogic Server 問題的情況相符。如果相符,請使用相應(yīng)的解決辦法。

          如果錯(cuò)誤與所有已知問題的情況均不相符,則需要做進(jìn)一步探查。如果錯(cuò)誤出現(xiàn)在您可以編輯和編譯源代碼的類中,以下方法可能有助于您理解該問題。

          假設(shè)出現(xiàn)錯(cuò)誤的代碼行類似于:

          oo f = (Foo) bar.method();

          如果按照轉(zhuǎn)換規(guī)則該轉(zhuǎn)換應(yīng)該有效,但仍然引發(fā)了 ClassCastException,則可能的情況是:類“bar”和“Foo”是由不同的 ClassLoader 加載的。要驗(yàn)證這一點(diǎn),請像下面這樣拆分該代碼行:

           

          Object o = bar.method();
          System.err.println("The object " + o + " classloader is " +
          o.getClass().getClassLoader());
          System.err.println("Class Foo class loader is " +
          Foo.class.getClassLoader());
          Foo f = (Foo) o;
           

          典型的輸出可能與此類似:

           

          The object Foo@@3e86d0 classloader is
          sun.misc.Launcher$AppClassLoader@b9d04
          Class Foo classloader is
          weblogic.utils.classloaders.ChangeAwareClassLoader@5998cb finder:
          weblogic.utils.classloaders.MultiClassFinder@7c2528

           

          下一步是探查為什么涉及了不同的 ClassLoader。請執(zhí)行下列檢查清單中的各項(xiàng)檢查:

          • 檢查應(yīng)用程序打包情況,并檢查“Foo”是否是使用由不同 ClassLoader 加載的不同模塊打包而成。在這方面眾所周知的一個(gè)成因是 Web 應(yīng)用程序的“prefer-web-inf-classes”功能(請參閱已知的 WebLogic 問題
          • 檢查它正在使用的應(yīng)用程序代碼或某個(gè)框架代碼是否更改了 WebLogic 線程的上下文 ClassLoader,且在請求流程期間未將其還原。如果應(yīng)用程序代碼內(nèi)有對(duì) Thread.setContextClassloader(cl) 的調(diào)用,就可能存在這種情況。
          • 如果上述所有措施均無濟(jì)于事,請嘗試將問題隔離在一個(gè)簡單的、可重現(xiàn)的測試案例中,然后聯(lián)系 BEA 技術(shù)支持部門,以做進(jìn)一步探查。

          已知的 WebLogic Server 問題


          以下匯集了可導(dǎo)致 ClassCastException 錯(cuò)誤的各種情況,您在使用各種 WebLogic 子系統(tǒng)時(shí)可能會(huì)遇到這些情況。

          小程序

          有關(guān)該情況的完整說明,請參考 http://e-docs.bea.com/wls/docs81/applets/usingapplets.html (English)

          摘要:如果小程序中的 WebLogic Server 客戶端嘗試從 ClassLoader 獲取某些資源信息,且一并使用了緩存標(biāo)志和 codebase=/bea_wls_internal/classes 標(biāo)志,就可能會(huì)拋出 ClassCastException。

          解決方法:

          • 在將類路徑 servlet 用作代碼基時(shí),請不要使用“cache_option”和“cache_archive”一類的緩存選項(xiàng)。
          • 使用緩存選項(xiàng)時(shí),請不要使用 /classes (ClasspathServlet) 做為代碼基。如果要這樣做,請先使用歸檔實(shí)用程序打包客戶端 JAR。

          有關(guān)此限制的詳細(xì)信息,請參閱 http://developer.java.sun.com/developer/bugParade/bugs/4648591.html (English)。

          JCA Connector

          有關(guān)該情況的完整說明,請參考 http://e-docs.bea.com/wls/docs81/notes/issues.html (English)。

          摘要:發(fā)出連接請求時(shí),WebLogic Server 會(huì)返回一個(gè)代理對(duì)象,該對(duì)象通過資源適配器將連接對(duì)象封裝后返回到客戶端。WebLogic Server 使用該代理來提供一些功能,幫助應(yīng)用程序使用 WebLogic Server 的“J2EE 連接器體系結(jié)構(gòu)”實(shí)現(xiàn)。這些功能包括 (1) 連接泄漏檢測功能和 (2) 連接請求在啟動(dòng)使用該連接的全局事務(wù)之前發(fā)出時(shí),推遲 XAResource 登記。

          如果將連接請求返回的連接對(duì)象向原始的 Connection 類進(jìn)行了轉(zhuǎn)換,就可能發(fā)生 ClassCastException。導(dǎo)致該異常的對(duì)象不外乎在連接請求過程中:(1) 資源適配器進(jìn)行轉(zhuǎn)換時(shí)或 (2) 客戶端進(jìn)行轉(zhuǎn)換時(shí)。

          在 WebLogic Server 8.1 SP2 中,嘗試檢測由上述資源適配器情況 (1) 導(dǎo)致的 ClassCastException。如果服務(wù)器檢測到該轉(zhuǎn)換失敗,將關(guān)閉代理包裝器功能,并在連接請求期間返回連接對(duì)象(不進(jìn)行包裝)。服務(wù)器會(huì)記錄一條警告消息,說明代理包裝器已被關(guān)閉。出現(xiàn)此類轉(zhuǎn)換故障時(shí),連接泄漏檢測和 XAResource 推遲登記功能也將被關(guān)閉(但當(dāng)前在控制臺(tái)監(jiān)視中并不會(huì)就此給出任何指示)。

          WebLogic Server 嘗試以使用容器管理的安全性的客戶端身份檢測 ClassCastException。如果要這樣做,則部署的資源適配器須定義安全性 Credential。

          如果客戶端在執(zhí)行轉(zhuǎn)換時(shí)發(fā)生 ClassCastException,可按如下方式修改客戶(客戶端)代碼:

          解決方法:如果客戶端將連接對(duì)象轉(zhuǎn)換為 MyConnection,而不是將 MyConnection 作為實(shí)現(xiàn)資源適配器的 Connection 接口的一個(gè)類,請將該對(duì)象修改為一個(gè)擴(kuò)展 Connection 的接口。實(shí)現(xiàn)一個(gè)用于實(shí)現(xiàn) MyConnection 接口的 MyConnectionImpl 類。

          Servlet 動(dòng)態(tài)重新加載

          有關(guān)該情況的完整說明,請參考 http://e-docs.bea.com/wls/docs81/jsp/reference.html (English)

          摘要:要在會(huì)話過程中動(dòng)態(tài)重新加載 servlet 或 JSP,servlet 會(huì)話中存儲(chǔ)的對(duì)象必須是可序列化的。需要進(jìn)行序列化是因?yàn)?,servlet 是使用新的 ClassLoader 重新加載的,而這會(huì)導(dǎo)致此前加載的所有類(舊版本 servlet 中的類)與使用新的 ClassLoader 加載的所有類(新版本 servlet 類)發(fā)生不兼容的情況。這種不兼容會(huì)導(dǎo)致 servlet 返回 ClassCastException 錯(cuò)誤。

          使用 Prefer-web-inf-classes 功能

          有關(guān)該情況的完整說明,請參考 http://e-docs.bea.com/wls/docs81/programming/classloading.html (English)

          摘要:weblogic.xml Web 應(yīng)用程序部署描述符包含一個(gè) prefer-web-inf-classes 元素(container-descriptor 元素的子元素)。缺省情況下,此元素設(shè)置為 False。如果將此元素設(shè)置為 True,則不遵循 ClassLoader 委托模型,從而使 Web 應(yīng)用程序中的類定義的加載順序優(yōu)先于更高級(jí)別的 ClassLoader 中的類定義。這樣 Web 應(yīng)用程序就可使用其自己版本的第三方類,該類也可能是 WebLogic Server 的一部分。請參閱 weblogic.xml Deployment Descriptor Elements (English)。

          使用該功能時(shí),必須注意不要混淆使用 Web 應(yīng)用程序的類定義創(chuàng)建的實(shí)例與使用服務(wù)器的定義創(chuàng)建的實(shí)例。如果混淆了此類實(shí)例,就會(huì)發(fā)生 ClassCastException。

          群集:在 http 會(huì)話中存儲(chǔ)包含 EJBObject 的自定義對(duì)象 - CR102119

          摘要:可序列化的自定義對(duì)象會(huì)包裝 EJBObject(對(duì) EJB 的引用)。該自定義對(duì)象存儲(chǔ)在 http 會(huì)話中。會(huì)話復(fù)制時(shí),這種設(shè)計(jì)就會(huì)導(dǎo)致 ClassCastException。

          解決方法:在以后版本的 WebLogic Server 中將徹底解決該問題。目前的解決辦法是在包裝器內(nèi)存儲(chǔ) EJB 句柄(而不是 EJBObject)。

          群集:Failover 后使用 http 會(huì)話中的 EJB 句柄 - CR187062

          摘要:在群集中分別部署 webApp 和 EJB。EJB 句柄包裝在可序列化的自定義對(duì)象中,而該對(duì)象存儲(chǔ)在 http 會(huì)話中。Failover 后,通過句柄訪問 EJB 就會(huì)發(fā)生 ClassCastException。

          解決方法:在同一個(gè) ear 文件中包裝 webApp 和 EJB。該問題存在于 WLS 8.1sp2 中,目前正在等待更正。
          返回頁首

          需要更多幫助?
          如果您已經(jīng)理解這個(gè)模式,但仍需要更多幫助,您可以:

          1. http://support.bea.com/ 上查詢 AskBEA(例如,使用“ClassCastException”),以查找其它已發(fā)布的解決辦法。
          2. http://forums.bea.com/ 上,向 BEA 的某個(gè)新聞組提出更詳細(xì)具體的問題。

          posted on 2009-03-19 11:42 wangjc 閱讀(986) 評(píng)論(0)  編輯  收藏 所屬分類: workspace
          主站蜘蛛池模板: 南江县| 潍坊市| 商河县| 洪泽县| 理塘县| 深州市| 塔河县| 海安县| 来凤县| 汨罗市| 芦溪县| 河曲县| 陇西县| 安泽县| 广宗县| 眉山市| 天台县| 游戏| 荥经县| 颍上县| 桂平市| 高邑县| 芦溪县| 西安市| 军事| 阿荣旗| 福鼎市| 永福县| 玛纳斯县| 宜兰市| 静乐县| 准格尔旗| 沈阳市| 三门县| 清河县| 天水市| 湾仔区| 彭州市| 郓城县| 大石桥市| 两当县|