Tomcat 7.0.3x 启动时遇到StackOverflowError导致失败的解决办法

Tomcat 7.0.3x 启动时遇到StackOverflowError导致失败的解决办法

之前使用tomcat7时遇到启动报错问题,日志如下:

Nov 07, 2014 9:52:10 AM org.apache.catalina.core.AprLifecycleListener init

INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: T:\svn_techsuite\devtools\eclipse-jee-kepler-SR2-win32-x86_64;;.

Nov 07, 2014 9:52:10 AM org.apache.tomcat.util.digester.SetPropertiesRule begin

WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:publishserver' did not find a matching property.

Nov 07, 2014 9:52:10 AM org.apache.coyote.AbstractProtocol init

INFO: Initializing ProtocolHandler ["http-bio-8080"]

Nov 07, 2014 9:52:10 AM org.apache.coyote.AbstractProtocol init

INFO: Initializing ProtocolHandler ["ajp-bio-8009"]

Nov 07, 2014 9:52:10 AM org.apache.catalina.startup.Catalina load

INFO: Initialization processed in 734 ms

Nov 07, 2014 9:52:10 AM org.apache.catalina.core.StandardService startInternal

INFO: Starting service Catalina

Nov 07, 2014 9:52:10 AM org.apache.catalina.core.StandardEngine startInternal

INFO: Starting Servlet Engine: Apache Tomcat/7.0.37

Nov 07, 2014 9:52:11 AM org.apache.catalina.loader.WebappClassLoader validateJarFile

INFO: validateJarFile(T:\svn_techsuite\branches\techsuite_4.4_m050\techdev\projs\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\publishserver\WEB-INF\lib\servlet-api.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class

Nov 07, 2014 9:52:14 AM org.apache.catalina.core.ContainerBase startInternal

SEVERE: A child container failed during start

java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/publishserver]]

at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252)

at java.util.concurrent.FutureTask.get(FutureTask.java:111)

at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1123)

at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:800)

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)

at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)

at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)

at java.util.concurrent.FutureTask.run(FutureTask.java:166)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

at java.lang.Thread.run(Thread.java:722)

Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/publishserver]]

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)

... 7 more

Caused by: java.lang.IllegalStateException: Unable to complete the scan for annotations for web application [/publishserver]. Possible root causes include a too low setting for -Xss and illegal cyclic inheritance dependencies

at org.apache.catalina.startup.ContextConfig.processAnnotationsStream(ContextConfig.java:2109)

at org.apache.catalina.startup.ContextConfig.processAnnotationsJar(ContextConfig.java:1981)

at org.apache.catalina.startup.ContextConfig.processAnnotationsUrl(ContextConfig.java:1947)

at org.apache.catalina.startup.ContextConfig.processAnnotations(ContextConfig.java:1932)

at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1326)

at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:878)

at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:369)

at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)

at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)

at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5179)

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

... 7 more

Caused by: java.lang.StackOverflowError

at java.util.HashSet.<init>(HashSet.java:103)

at org.apache.catalina.startup.ContextConfig.populateSCIsForCacheEntry(ContextConfig.java:2252)

at org.apache.catalina.startup.ContextConfig.populateSCIsForCacheEntry(ContextConfig.java:2269)

at org.apache.catalina.startup.ContextConfig.populateSCIsForCacheEntry(ContextConfig.java:2269)

at org.apache.catalina.startup.ContextConfig.populateSCIsForCacheEntry(ContextConfig.java:2269)

at org.apache.catalina.startup.ContextConfig.populateSCIsForCacheEntry(ContextConfig.java:2269)

at org.apache.catalina.startup.ContextConfig.populateSCIsForCacheEntry(ContextConfig.java:2269)

......

 

Nov 07, 2014 9:52:14 AM org.apache.catalina.core.ContainerBase startInternal

SEVERE: A child container failed during start

java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]

at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252)

at java.util.concurrent.FutureTask.get(FutureTask.java:111)

at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1123)

at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:302)

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:732)

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

at org.apache.catalina.startup.Catalina.start(Catalina.java:684)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:601)

at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:322)

at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:456)

Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)

at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)

at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)

at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)

at java.util.concurrent.FutureTask.run(FutureTask.java:166)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

at java.lang.Thread.run(Thread.java:722)

Caused by: org.apache.catalina.LifecycleException: A child container failed during start

at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1131)

at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:800)

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

... 7 more

 

Nov 07, 2014 9:52:14 AM org.apache.catalina.startup.Catalina start

SEVERE: Catalina.start: 

org.apache.catalina.LifecycleException: Failed to start component [StandardServer[8005]]

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)

at org.apache.catalina.startup.Catalina.start(Catalina.java:684)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:601)

at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:322)

at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:456)

Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Catalina]]

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)

at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:732)

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

... 7 more

Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina]]

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)

at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

... 9 more

Caused by: org.apache.catalina.LifecycleException: A child container failed during start

at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1131)

at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:302)

at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

... 11 more

 

Nov 07, 2014 9:52:14 AM org.apache.catalina.startup.Catalina start

INFO: Server startup in 3810 ms

使用tomcat 7.0.3x版本的同学可以发现tomcat启动慢了不少,而且还可能遇到如下启动时异常: 

 

Unable to complete the scan for annotations for web application [] due to a StackOverflowError. Possible root causes include a too low setting for -Xss and illegal cyclic inheritance dependencies. 

 

tomcat7.0.3X版本支持servlet3.0的特性,比如说支持@WebServlet@WebListener等等,要支持这些特性,tomcat就得去扫描所有的jar包里面的每个类。这个异常表明在扫描jar包的时候,递归调用太深,导致栈溢出了,tomcat给了一个馊主意,让你增大xss,这个还是不好,xss加大了,可用线程数就少了。 

 

分析tomcat源代码,发现它扫描的流程如下: 

 

step-1.扫描所有jar包 

 

step-2.通过查找jar包中META-INF/services/javax.servlet.ServletContainerInitializer文件内的定义,初始化ServletContainerInitializer实现 

 

step-3.如果web.xml(3.0+版本的根元素web-app)中配置了metadata-complete="true" 或者没有找到ServletContainerInitializer实现,都不会继续扫描jar包 

 

所以综合一下可以得出下面的解决办法:

  1. web.xml中加入了metadata-complete="true"。在很多场景下,这个异常能够避免。但是使用诸如 spring-web-3.1.0.RELEASE 或者 jersey-servlet-1.17.1 就杯具了,因为jar包中定义了一个ServletContainerInitializer,还是导致了扫描jar包。 
  2. 可以用另外的办法来解决这个问题,我们让tomcat不扫描指定的jar包,tomcat就要轻松得多了,org.apache.tomcat.util.scan.StandardJarScanner中定义了defaultJarsToSkip,有了这个东东,我们就可以跳过某些jar包。如果你不想使用servlet3.0 annotation支持,在tomcatcatalina.properties配置文件中tomcat.util.scan.DefaultJarScanner.jarsToSkip的最后加一个",jersey-*"或者",spring-*",这样就不会扫描所有的jar包了。这个副作用是一旦这样设置后,所有部署在该Tomcat下的应用均受到影响。
  3. jar包中含有META-INF/services/javax.servlet.ServletContainerInitializer的定义去掉。这种方式有一定的副作用,会造成该jar不能在其他地方通用,但好处是只影响该web应用而不会影响到Tomcat的配置(假如该Tomcat下有多个Web应用同时发布)
  4. jar包中含有META-INF/services/javax.servlet.ServletContainerInitializer中所定义的实现类改写,使用相同的包路径和类名,但是在实现那个onStartup方法时不做任何事情,这样因为改写类放在WEB-INF/classes中,它会在jar之前加载完成,所以也就屏蔽了jar中原有的类实现逻辑。这种方式的好处是既不用修改Tomcat配置,也不用修改jar文件,而且只会影响到本身的这个Web应用。

最后强调一点:

tomcat在处理扫描是还有个小bug,比如我遇到了 

SEVERE: Unable to process Jar entry [__MACOSX/cn/****/._HandlerFactory.class] from... 

这是tomcat在扫描到以.class为后缀的文件后,就想当然认为是java的字节码class文件,很明显,此文件都不是java类文件。tomcat不应该根据后缀为.class就一定是java类文件。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值