本人在此之前甚少接觸weblogic,家里的weblogic也是第一次安裝的。如果發現錯誤,敬請指正。
XX局點升級weblogic為11g,重新發包出錯。現在記錄一下處理的各種問題總結。
這是最早出現的問題,會出現類似下面的錯誤信息。
<2015-10-14 下午05時57分30秒 CST> <Error> <HTTP> <BEA-101017> <[ServletContext@1385406679[app:XXService module:XXService path:/XXService spec-version:2.5]] Root cause of ServletException.java.lang.NoSuchMethodError: org.apache.commons.io.FileUtils.copyInputStreamToFile(Ljava/io/InputStream;Ljava/io/File;)V原因分析這是weblogic部署最常見的問題,因為weblogic會自帶I一些commons-*的包,這些包的版本還比較舊。具體可以見WEBLOGIC_HOME/modules目錄的jar包。
此次采用的處理方式添加weblogic.xml并設置PRefer-web-inf-classes,即優先加載web應用下的類
<?xml version="1.0" encoding="UTF-8"?><weblogic-web-app> <container-descriptor> <prefer-web-inf-classes>true</prefer-web-inf-classes> </container-descriptor></weblogic-web-app>這是使用prefer-web-inf-classes為true之后出現的問題,會出現類似下面的錯誤信息。
The validator class: "org.apache.taglibs.standard.tlv.JstlCoreTLV" has failed with the following exception: "java.lang.ClassCastException: weblogic.xml.jaxp.RegistrySAXParserFactory cannot be cast to javax.xml.parsers.SAXParserFactory".原因分析這是weblogic部署很常見的問題,jstl會調用sax,sax是通過spi機制加載實現,獲取是weblogic的實現,但它使用的是jdk自帶的javax.xml.parsers.SAXParserFactory接口。 剛好web應用下也帶了jar包xml-apis-1.x.jar,它也有javax.xml.parsers.SAXParserFactory這個接口。根據prefer-web-inf-classes的設置,jstl代碼中用的是這個接口。 由此可知,使用classloader并不一樣,無法轉換。
此次采用的處理方式刪除WEB-INF/lib/xml-apis-1.x.jar后本地測試該問題恢復。
這是錯誤2解決后,繼續解析spring時出現的問題。
原因分析這個問題和上面的差不多,太細就不深究了。
此次采用的處理方式這種情況下,如果使用prefer-web-inf-classes為true,則需要排除存在QName的jar包并刪除,但最后沒有采用(改動太大,得不償失)。 所以這次重新設置了prefer-web-inf-classes為false,但仍然優先加載commons,如下:
<?xml version="1.0" encoding="UTF-8"?><weblogic-web-app> <container-descriptor> <prefer-web-inf-classes>false</prefer-web-inf-classes> <prefer-application-packages> <package-name>org.apache.commons.*</package-name> </prefer-application-packages> </container-descriptor></weblogic-web-app>修改后本地測試ok,但發布到生產仍然失敗。
錯誤3處理后,發布到生產仍然出錯,報錯信息如下:
18:44:57.337 [[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] ERROR com.danga.MemCached.MemCachedClient - ++++ exception thrown while trying to get object from cache for key: init_error_key_009818:44:57.351 [[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] ERROR com.danga.MemCached.MemCachedClient - com.xxx.hnxx.mybatis.entity.PlaterrorCodeBeanjava.io.IOException: com.xxx.hnxx.mybatis.entity.PlaterrorCodeBean at com.schooner.MemCached.ObjectTransCoder.decode(Unknown Source) ~[MemCached-2.6.6.jar:na] at com.schooner.MemCached.AscIIClient.get(Unknown Source) [MemCached-2.6.6.jar:na] at com.schooner.MemCached.AscIIClient.get(Unknown Source) [MemCached-2.6.6.jar:na] at com.schooner.MemCached.AscIIClient.get(Unknown Source) [MemCached-2.6.6.jar:na] at com.danga.MemCached.MemCachedClient.get(Unknown Source) [MemCached-2.6.6.jar:na] at com.xxx.hnxx.cache.mencached.MemcacheManagerClient.get(MemcacheManagerClient.java:162) [MemcacheManagerClient.class:na]上面的錯誤信息表示獲取init_error_key_0098這個可以的時候失敗,實際上這個key是在應用啟動的時候就塞進去的。
原因分析這里有很多意想不到的事情,所以詳細解釋一下。
首先,這個出現了IOException讓人聯想到是否memcached服務器連接的問題。 實際上是因為庫在實現java對象放入memcached的時候,有一個序列化/反序列化的過程(就是java自帶的那個),在反序列化的時候找不到類會出現ClassNotFoundException,然后庫將錯誤信息(就是一個類名)取出重新包裝為IOException。 所以,這實際上是一個類找不到的問題。
再者,這個問題一開始在家里的weblogic沒法重現。后來我重新檢查了生產上weblogic的啟動日志才發現了一些差異。 關鍵信息如下所示,生產上的weblogic在domain的lib目錄也是有jar包的,而家里的是沒有的。嘗試修改把jar包也拷貝一份,果然重現。
<2015-10-14 下午06時44分36秒 CST> <Notice> <WebLogicServer> <BEA-000395> <Following extensions directory contents added to the end of the classpath:/weblogic/bea/user_projects/domains/PLATFORM_DOM/lib/MemCached-2.6.6.jar:/weblogic/bea/user_projects/domains/PLATFORM_DOM/lib/MyXMLSerializer-1.0.0.jar...最后,這個問題就好解釋多了。
需要序列化/反序列化的類是在com.huawei下面的,這部分類指在web應用中存在。在system classloader是找不到的。序列化/反序列化時候,都是由web應用中的類,調用memcached庫去實現的(雖然web應用中也有,但是根據prefer-web-inf-classes設置,加載的是domain中lib目錄的)序列化只是沒什么特別。但是反序列化需要加載類,很明顯system classloader(memcached庫的classloader)是加載不到web應用中的類的。
此次采用的處理方式有好幾種方式,都列舉一下:
刪除domain中的jar包,這樣就會加載到web應用中的類,讓庫和需要序列化的類都有web classloader加載讓庫也由web優先加載,如下所示<?xml version="1.0" encoding="UTF-8"?><weblogic-web-app> <container-descriptor> <prefer-web-inf-classes>false</prefer-web-inf-classes> <prefer-application-packages> <package-name>org.apache.commons.*</package-name> <package-name>com.danga.*</package-name> <package-name>com.schooner.*</package-name> </prefer-application-packages> </container-descriptor></weblogic-web-app>指定memcached庫進行反序列化時的classloader,如下所示: ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); // MemCachedClient實例化時,會持有SockIOPool.getInstance()單利的引用 cachedClient = new MemCachedClient((String)null, true, false, classLoader, null);個人推薦的優先級是2 - 3 - 1, 盡量做到容器無關,并少動全局的東西。由于目前生產上的weblogic版本已經回退,待后續上生產驗證。
新聞熱點
疑難解答