Tomcat之启动报错分析
今天同事的tomcat启动时报错如下:
严重: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/docs]] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:162) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:899) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:875) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652) at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1260) at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:2002) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) at java.util.concurrent.FutureTask.run(FutureTask.java:138) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) at java.lang.Thread.run(Thread.java:662) Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext.getClassLoader()Ljava/lang/ClassLoader; at org.apache.catalina.startup.WebappServiceLoader.load(WebappServiceLoader.java:96) at org.apache.catalina.startup.ContextConfig.processServletContainerInitializers(ContextConfig.java:1579) at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1280) at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:888) at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:388) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5522) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
主要原因就是因为tomcat类加载的时候加载servlet-api.jar这个jar包出了问题,但是反编译软件看servlet-api.jar是有ServletContext类中有getClassLoader这个方法。那么,肯定就是tomcat加载了其他地方的servlet-api.jar包中的ServletContext类,那么就需要了解Tomcat的类加载模型。
首先,tomcat的类模型是双亲委派模型,如下图
其中启动类加载器(通过JNI实现,无法获得其实力)、扩展类加载器是jvm自带的,其中启动类加载器加载的是%JAVA_RUNTIME_JRE%/lib该路径下的jar包,只会加载符合名称的一些jar包,例如rt.jar。扩展类加载器加载的是%JAVA_RUNTIME_JRE%/lib/ext/路径下的jar包。
其余CatalinaClassLoader、SharedClassLoader和WebAppClassLoader类加载路径在tomcat/conf/catalina.properties配置文件中(common.loader,server.loader,shared.loader).
该文参考于http://blog.****.net/czmacd/article/details/54017027