1 背景说明

这两天做项目时遇到Jenkins自动部署随机失败的问题,当构建失败后,反复多构建几次又会成功,因为比较忙就没有花时间去查,直到有次我点了部署之后,就去做其他事情了,然后部署失败了,导致测试人员无法测试浪费了他人时间,才决心解决这个随机问题。
 
通过查看Tomcat的失败日志,找到了如下错误:
 
06-Mar-2017 19:59:02.972 SEVERE [localhost-startStop-1] org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start:
 org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/PureWaterWeixin]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:153)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:939)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1812)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Unable to complete the scan for annotations for web application [/PureWaterWeixin] due to a StackOverflowError. Possible root causes include a too low setting for -Xss and illegal cyclic inheritance dependencies. The class hierarchy being processed was [org.bouncycastle.asn1.ASN1EncodableVector->org.bouncycastle.asn1.DEREncodableVector->org.bouncycastle.asn1.ASN1EncodableVector]
    at org.apache.catalina.startup.ContextConfig.checkHandlesTypes(ContextConfig.java:2100)
    at org.apache.catalina.startup.ContextConfig.processAnnotationsStream(ContextConfig.java:2046)
    at org.apache.catalina.startup.ContextConfig.processAnnotationsJar(ContextConfig.java:1991)
    at org.apache.catalina.startup.ContextConfig.processAnnotationsUrl(ContextConfig.java:1961)
    at org.apache.catalina.startup.ContextConfig.processAnnotations(ContextConfig.java:1915)
    at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1158)
    at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:780)
    at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:305)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:95)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5154)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
    ... 10 more

06-Mar-2017 19:59:02.973 SEVERE [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Error deploying web application archive /usr/local/tomcat8/apache-tomcat-8086/webapps/PureWaterWeixin.war
 java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/PureWaterWeixin]]
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:729)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:939)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1812)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
 

2 原因分析

经过一番搜索,网上也有很多人遇到同样的问题,但是解决方案各异:
 
主要原因如下,bouncycastle这个包在两个不同版本之间存在交换继承关系的情况。
You can see from grepcode that bcprov-jdk15on:1.52 defines DEREncodableVector as
public class DEREncodableVector extends ASN1EncodableVector
 
While bcprov-jdk14:1.38 defines ASN1EncodableVector as
public class ASN1EncodableVector extends DEREncodableVector
 
当我们在项目中同时依赖这两个版本时,因为maven-shade-plugin插件会随机挑选一个类的实现,当正好挑选到这两个相互继承的类时,就会出现前文所示的循环引用错误。
 
你可以检查一下项目中是否同时引用了两个不同版本的bouncycastle,去掉一个,但我并属于这种情况。
 

3 解决方案

我仔细检查了pom文件,并不存在重复引用,但是我想起之前确实引用过一次另一个版本的bouncycastle,但是随后就更换了版本。可以肯定问题就出在这个包,但是,明明没有引用两个,为何会报错呢,而且我本地调试都是没有问题的,只有Jenkins自动构建会有这个问题。
 
只要是重复出现过的问题,就一定有某个地方不对!
 
于是我检查了一下Jenkins部署成功之后的项目lib,里面果然有bouncycastle两个不同版本的的jar包,问题出在工作空间。
 
我在Jenkins的Job配置没有每次都清理工作空间,所以在引用之前的bouncycastle版本时,构建就会把前一个版本的jar下载到lib中,然后更新pom后,又将新的jar包下载到lib中,最后打包就包含了两个版本的jar,问题就出现了。
 
清理工作空间,不再随机失败了,OK!
20170306_001
 
根据这个问题的情况,我们可以知道,就算两个版本的jar之前不存在循环引用,基于随机选择,也可能会出现一些其他的类加载或运行问题。所以,如果修改了pom中jar版本号,都需要重新清理工作空间一次,或者配置Job时就选择每次构建都清理工作空间。
20170306_002
 
完!
 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐