本人在此之前甚少接触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版本已经回退,待后续上生产验证。
新闻热点
疑难解答