jar冲突问题解决方法记录
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
jar冲突问题解决方法记录
目录
1 问题现象 (2)
2 处理方法 (2)
2.1 测试环境 (2)
2.2 访问报错情况 (2)
2.3 错误查找步骤 (3)
2.3.1 参数配置 (3)
2.3.2 启动程序查看verbose:class监视效果 (3)
3 处理冲突 (4)
4 总结 (4)
1问题现象
前期做了一个简单的rest服务端应用。
开发测试期都在windows下的
java+tomcat下运行,一直运行良好。
最近为了进行技术培训,准备把该示例放到Linux的服务上。
直接动手,同样版本的java+tomcat在我的Linux服务器(Ubuntu14.04的虚拟机)上走起。
轻松运行起来,没问题。
好吧,自己简单测试一下。
index.jsp没问题,service页面,也没问题。
点击查看wadl。
哦,404。
2处理方法
既然windows下没问题,Linux下有问题,明细是有jar冲突,在windows 中和Linux中ClassLoader加载到了不同的jar中的同名class。
那咱就把他找出来。
最简单粗暴的方法:日志中已经指明了出错的类,那么只要知道报错时使用的class加载自那个jar,和正确时的class加载自那个jar,那不就能轻松搞定了。
思路有了,开始找工具方法。
2.1测试环境
Windows环境(不报错):
Windows7 (64位) + jdk1.8.0_60(64位) + tomcat-8.0.26(64位)
Linux环境(访问wadl报错):
Ubuntu14.04.1(X86_64)+ jdk1.8.0_60(64位) + tomcat-8.0.26(64位) 2.2访问报错情况
ng.NoClassDefFoundError: javax/ws/rs/MessageProcessingException org.apache.cxf.jaxrs.impl.ResponseBuilderImpl.build(ResponseBuilderImp l.java:69)
org.apache.cxf.jaxrs.model.wadl.WadlGenerator.handleRequest(WadlGenera tor.java:257)
org.apache.cxf.jaxrs.impl.RequestPreprocessor.handleMetadataRequest(Re questPreprocessor.java:216)
org.apache.cxf.jaxrs.impl.RequestPreprocessor.checkMetadataRequest(Req uestPreprocessor.java:200)
org.apache.cxf.jaxrs.impl.RequestPreprocessor.preprocess(RequestPrepro cessor.java:84)
org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAX RSInInterceptor.java:117)
org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXR SInInterceptor.java:101)
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseIntercepto rChain.java:271)
org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitia tionObserver.java:121)
org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractH TTPDestination.java:239)
org.apache.cxf.transport.servlet.ServletController.invokeDestination(S ervletController.java:223)
org.apache.cxf.transport.servlet.ServletController.invoke(ServletContr oller.java:203)
org.apache.cxf.transport.servlet.ServletController.invoke(ServletContr oller.java:137)
org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpri ngServlet.java:159)
org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(Abs tractHTTPServlet.java:286)
org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTT PServlet.java:211)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractH TTPServlet.java:262)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 2.3错误查找步骤
2.3.1参数配置
根据以上错误信息判断,应当是系统中javax.ws.rs包存在冲突。
在Linux下进行tomcat启动命令配置。
修改catalina.sh。
在其中增加
JAVA_OPTS的设置:JAVA_OPTS="$JAVA_OPTS -verbose:class"
作为对比在windows下进行tomcat启动命令配置。
修改catalina.out,在其中增加JAVA_OPTS的设置:set "JAVA_OPTS=%JAVA_OPTS% -verbose:class"
2.3.2启动程序查看verbose:class监视效果
分别启动tomcat。
在Linux下,错误日志记录到catalina.out中。
在windows 下默认会输出到console中。
为便于查看输出日志,在windows下可以使用catalina.bat run > ..\logs\tomcat.log 2>&1将console的日志重定向到日志文件
tomcat.log中。
在Linux的日志catalina.out中,查找相应的包javax.ws.rs。
根据日志信息:[Loaded javax.ws.rs.GET from
file:/apache-tomcat-8.0.26/webapps/demoapp/WEB-INF/lib/jsr311-api-1.0.jar] 可知,该包从javax.ws.rs-api-2.0.1.jar中加载(出错时往往会发现,同一个包,会从不同的jar中加载class)。
检查发现在该jar中没有
javax.ws.rs.MessageProcessingException类。
而在tomcat的日志中,查找相应的包javax.ws.rs。
根据日志信息:
[Loaded javax.ws.rs.MessageProcessingException from
file:/D:/appserver/tomcat/tomcat-8.0.26/webapps/demoapp/WEB-INF/lib/javax.ws.r s-api-2.0-m10.jar]可知javax.ws.rs在以上两个jar中均存在。
3处理冲突
使用解压缩工具查看两个jar包。
根据Linux下出错的错误提示,查看javax.ws.rs.MessageProcessingException类并比较两个jar判断其等效性。
在此次处理中,看到javax.ws.rs-api-2.0-m10.jar可以包含jsr311-api-1.0.jar。
简单删掉jsr311-api-1.0.jar即可处理冲突。
删掉jsr311-api-1.0.jar,再在Linux启动程序,进行测试,直接搞定。
最后,当然记着把-verbose:class去掉。
4总结
通过此次问题处理经历,可以判断jar冲突问题均可以采用此方法解决。
Linux下和windows下java加载顺序存在一些细微差别。
建议程序部署前都在现场OS及软件环境下进行测试。
什么:没有现场服务器的操作系统应用服务环境?试试用docker构建一个现场服务器环境。
现场使用AIX,solaris……。
别担心,他们都投入容器怀抱,宣布支持Docker了。