日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Tomcat启动过程源码解读

發布時間:2025/3/15 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Tomcat启动过程源码解读 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

根據Tomcat源碼來看一下Tomcat啟動過程都做了什么

部分代碼為主要流程代碼,刪去了try-catch以及一些校驗邏輯,方便理解主流程

?

先來一張啟動過程時序圖,了解一下啟動順序

?

Tomcat啟動的入口類:org.apache.catalina.startup.Bootstrap#main

main方法是整個tomcat啟動時的入口。在main方法中,使用bootstrap.init()來初始化類加載器和創建Catalina實例,然后再啟動Catalina線程。

1 public static void main(String args[]) { 2 3 if (daemon == null) { 4 // Don't set daemon until init() has completed 5 Bootstrap bootstrap = new Bootstrap(); 6 try { 7 bootstrap.init(); 8 } catch (Throwable t) { 9 handleThrowable(t); 10 t.printStackTrace(); 11 return; 12 } 13 daemon = bootstrap; 14 } else { 15 // When running as a service the call to stop will be on a new 16 // thread so make sure the correct class loader is used to prevent 17 // a range of class not found exceptions. 18 Thread.currentThread().setContextClassLoader(daemon.catalinaLoader); 19 } 20 21 try { 22 String command = "start"; 23 if (args.length > 0) { 24 command = args[args.length - 1]; 25 } 26 27 if (command.equals("startd")) { 28 args[args.length - 1] = "start"; 29 daemon.load(args); 30 daemon.start(); 31 } else if (command.equals("stopd")) { 32 args[args.length - 1] = "stop"; 33 daemon.stop(); 34 } else if (command.equals("start")) { 35 daemon.setAwait(true); 36 daemon.load(args); 37 daemon.start(); 38 } else if (command.equals("stop")) { 39 daemon.stopServer(args); 40 } else if (command.equals("configtest")) { 41 daemon.load(args); 42 if (null==daemon.getServer()) { 43 System.exit(1); 44 } 45 System.exit(0); 46 } else { 47 log.warn("Bootstrap: command \"" + command + "\" does not exist."); 48 } 49 } catch (Throwable t) { 50 // Unwrap the Exception for clearer error reporting 51 if (t instanceof InvocationTargetException && 52 t.getCause() != null) { 53 t = t.getCause(); 54 } 55 handleThrowable(t); 56 t.printStackTrace(); 57 System.exit(1); 58 } 59 60 }

?

?

bootstrap.init()方法,用于初始化容器相關,首先創建類加載器,然后通過反射創建org.apache.catalina.startup.Catalina實例:

1 public void init() throws Exception { 2 3 initClassLoaders(); 4 5 Thread.currentThread().setContextClassLoader(catalinaLoader); 6 7 SecurityClassLoad.securityClassLoad(catalinaLoader); 8 9 // Load our startup class and call its process() method 10 if (log.isDebugEnabled()) 11 log.debug("Loading startup class"); 12 Class<?> startupClass = 13 catalinaLoader.loadClass 14 ("org.apache.catalina.startup.Catalina"); 15 Object startupInstance = startupClass.newInstance(); 16 17 // Set the shared extensions class loader 18 if (log.isDebugEnabled()) 19 log.debug("Setting startup class properties"); 20 String methodName = "setParentClassLoader"; 21 Class<?> paramTypes[] = new Class[1]; 22 paramTypes[0] = Class.forName("java.lang.ClassLoader"); 23 Object paramValues[] = new Object[1]; 24 paramValues[0] = sharedLoader; 25 Method method = 26 startupInstance.getClass().getMethod(methodName, paramTypes); 27 method.invoke(startupInstance, paramValues); 28 29 catalinaDaemon = startupInstance; 30 31 }

?

?

?

之后Bootstrap的demon.start()方法就會調用Catalina的start方法。

Catalina實例執行start方法。這里有兩個點,一個是load()加載server.xml配置、初始化Server的過程,一個是getServer().start()開啟服務、初始化并開啟一系列組件、子容器的過程。

org.apache.catalina.startup.Catalina#start 1 public void start() { 2 3 if (getServer() == null) { 4 load(); 5 } 6 7 if (getServer() == null) { 8 log.fatal("Cannot start server. Server instance is not configured."); 9 return; 10 } 11 12 long t1 = System.nanoTime(); 13 14 // Start the new server 15 try { 16 getServer().start(); 17 } catch (LifecycleException e) { 18 log.fatal(sm.getString("catalina.serverStartFail"), e); 19 try { 20 getServer().destroy(); 21 } catch (LifecycleException e1) { 22 log.debug("destroy() failed for failed Server ", e1); 23 } 24 return; 25 } 26 27 long t2 = System.nanoTime(); 28 if(log.isInfoEnabled()) { 29 log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms"); 30 } 31 32 // Register shutdown hook 33 if (useShutdownHook) { 34 if (shutdownHook == null) { 35 shutdownHook = new CatalinaShutdownHook(); 36 } 37 Runtime.getRuntime().addShutdownHook(shutdownHook); 38 39 // If JULI is being used, disable JULI's shutdown hook since 40 // shutdown hooks run in parallel and log messages may be lost 41 // if JULI's hook completes before the CatalinaShutdownHook() 42 LogManager logManager = LogManager.getLogManager(); 43 if (logManager instanceof ClassLoaderLogManager) { 44 ((ClassLoaderLogManager) logManager).setUseShutdownHook( 45 false); 46 } 47 } 48 49 if (await) { 50 await(); 51 stop(); 52 } 53 }

?

?

load方法解析server.xml配置文件,并加載Server、Service、Connector、Container、Engine、Host、Context、Wrapper一系列的容器。加載完成后,調用getServer().start()來開啟一個新的Server。

?

下面先看load方法怎么加載組件和容器的:

1 /** 2 * Start a new server instance. 3 */ 4 public void load() { 5 6 long t1 = System.nanoTime(); 7 8 initDirs(); 9 10 // Before digester - it may be needed 11 initNaming(); 12 13 // Create and execute our Digester 14 Digester digester = createStartDigester(); 15 16 InputSource inputSource = null; 17 InputStream inputStream = null; 18 File file = null; 19 file = configFile(); 20 inputStream = new FileInputStream(file); 21 inputSource = new InputSource(file.toURI().toURL().toString()); 22 inputSource.setByteStream(inputStream); 23 digester.push(this); 24 digester.parse(inputSource); 25 26 27 getServer().setCatalina(this); 28 getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile()); 29 getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile()); 30 31 // Stream redirection 32 initStreams(); 33 34 // Start the new server 35 getServer().init(); 36 }

?

?

?

首先利用Digester類解析server.xml文件,得到容器的配置,并創建相應的對象,并關聯父子容器。依次創建的是StandardServer、StandardService、StandardEngine、StandardHost。

然后拿到StandardServer實例調用init()方法初始化Tomcat容器的一系列組件。一些容器初始化的的時候,都會調用其子容器的init()方法,初始化它的子容器。順序是StandardServer、StandardService、StandardEngine、Connector。每個容器都在初始化自身相關設置的同時,將子容器初始化。

?

?

?

這里插入一個Tomcat中生命周期的概念。在初始化、開啟一系列組件、容器的過程中,由tomcat'管理的組件和容器,都有一個共同的特點,都實現了org.apache.catalina.Lifecycle接口,由Tomcat管理其生命周期。Lifecycle提供一種統一的管理對象生命周期的接口。通過Lifecycle、LifecycleListener、LifecycleEvent,Catalina實現了對tomcat各種組件、容器統一的啟動和停止的方式。

?

在Tomcat服務開啟過程中啟動的一些列組件、容器,都繼承了org.apache.catalina.util.LifecycleBase這個抽象類,其中的init()、start() 方法、stop() 方法,為其子類實現了統一的start和stop管理。方法中具體的initInternal()、startInternal() 和stopInternal() 方法,交由子類自己實現。

?

看一下LifecycleBase的init()和start()的實現吧:

org.apache.catalina.util.LifecycleBase#start 1 public final synchronized void init() throws LifecycleException { 2 if (!state.equals(LifecycleState.NEW)) { 3 invalidTransition(Lifecycle.BEFORE_INIT_EVENT); 4 } 5 6 try { 7 setStateInternal(LifecycleState.INITIALIZING, null, false); 8 initInternal(); 9 setStateInternal(LifecycleState.INITIALIZED, null, false); 10 } catch (Throwable t) { 11 ExceptionUtils.handleThrowable(t); 12 setStateInternal(LifecycleState.FAILED, null, false); 13 throw new LifecycleException( 14 sm.getString("lifecycleBase.initFail",toString()), t); 15 } 16 } 17 18 19 public final synchronized void start() throws LifecycleException { 20 21 if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) || 22 LifecycleState.STARTED.equals(state)) { 23 24 if (log.isDebugEnabled()) { 25 Exception e = new LifecycleException(); 26 log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e); 27 } else if (log.isInfoEnabled()) { 28 log.info(sm.getString("lifecycleBase.alreadyStarted", toString())); 29 } 30 31 return; 32 } 33 34 if (state.equals(LifecycleState.NEW)) { 35 init(); 36 } else if (state.equals(LifecycleState.FAILED)) { 37 stop(); 38 } else if (!state.equals(LifecycleState.INITIALIZED) && 39 !state.equals(LifecycleState.STOPPED)) { 40 invalidTransition(Lifecycle.BEFORE_START_EVENT); 41 } 42 43 try { 44 setStateInternal(LifecycleState.STARTING_PREP, null, false); 45 startInternal(); 46 if (state.equals(LifecycleState.FAILED)) { 47 stop(); 48 } else if (!state.equals(LifecycleState.STARTING)) { 49 invalidTransition(Lifecycle.AFTER_START_EVENT); 50 } else { 51 setStateInternal(LifecycleState.STARTED, null, false); 52 } 53 } catch (Throwable t) { 54 ExceptionUtils.handleThrowable(t); 55 setStateInternal(LifecycleState.FAILED, null, false); 56 throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t); 57 } 58 }

?

?

可以看到,init()和start()方法里,調用了initInternal()方法、startInternal()方法和stop()方法,這三者最終會走子類的具體實現。

?

上面的StandardServer的初始化過程就是一個活生生的例子。在Catalina的load過程中,getServer().init()方法就是LifecycleBase中的init()方法,調用initInternal()時是走的StandardServer的實現,StandardServer的initInternal()中會調用StandardServer的init()方法,進行子容器的初始化。然后依次初始化。

看一下代碼,了解一下StandardServer中的initInternal()實現。

1 /** 2 * Invoke a pre-startup initialization. This is used to allow connectors 3 * to bind to restricted ports under Unix operating environments. 4 */ 5 @Override 6 protected void initInternal() throws LifecycleException { 7 8 super.initInternal(); 9 10 // Register global String cache 11 // Note although the cache is global, if there are multiple Servers 12 // present in the JVM (may happen when embedding) then the same cache 13 // will be registered under multiple names 14 onameStringCache = register(new StringCache(), "type=StringCache"); 15 16 // Register the MBeanFactory 17 MBeanFactory factory = new MBeanFactory(); 18 factory.setContainer(this); 19 onameMBeanFactory = register(factory, "type=MBeanFactory"); 20 21 // Register the naming resources 22 globalNamingResources.init(); 23 24 // Populate the extension validator with JARs from common and shared 25 // class loaders 26 if (getCatalina() != null) { 27 ClassLoader cl = getCatalina().getParentClassLoader(); 28 // Walk the class loader hierarchy. Stop at the system class loader. 29 // This will add the shared (if present) and common class loaders 30 while (cl != null && cl != ClassLoader.getSystemClassLoader()) { 31 if (cl instanceof URLClassLoader) { 32 URL[] urls = ((URLClassLoader) cl).getURLs(); 33 for (URL url : urls) { 34 if (url.getProtocol().equals("file")) { 35 try { 36 File f = new File (url.toURI()); 37 if (f.isFile() && 38 f.getName().endsWith(".jar")) { 39 ExtensionValidator.addSystemResource(f); 40 } 41 } catch (URISyntaxException e) { 42 // Ignore 43 } catch (IOException e) { 44 // Ignore 45 } 46 } 47 } 48 } 49 cl = cl.getParent(); 50 } 51 } 52 // Initialize our defined Services 53 for (int i = 0; i < services.length; i++) { 54 services[i].init(); 55 } 56 }

?

?

?

再舉一個具體的例子:

?

回到剛才的啟動過程中,getServer().start()開啟服務的方法,實際就是上面提到的LifecycleBase中的start()方法。其中,會調用org.apache.catalina.core.StandardServer#initInternal方法,初始化Server并調用Service的init方法。org.apache.catalina.core.StandardServer在其實現的startInternal() 中,開啟naming resources和services,調用service的start方法,開啟所有service,調用其service的startInternal()方法。

?

下面看一下StandardServer中的startInternal()的實現:

org.apache.catalina.core.StandardServer#startInternal 1 protected void startInternal() throws LifecycleException { 2 3 fireLifecycleEvent(CONFIGURE_START_EVENT, null); 4 setState(LifecycleState.STARTING); 5 6 globalNamingResources.start(); 7 8 // Start our defined Services 9 synchronized (servicesLock) { 10 for (int i = 0; i < services.length; i++) { 11 services[i].start(); 12 } 13 } 14 }

?

?

這里的service,是org.apache.catalina.core.StandardService的實例。

?

總結一下啟動的Tomcat啟動的過程

在Catalina的load方法里,就已經調用了StandardServer里的init方法,一層一層初始化了globalNamingResources,StandardService--》StandardEngine,executors,MapperListener,Connector--》CoyoteAdapter,protocolHandler。至此就將tomcat的catalina中的組件、容器初始化完成。 接下來就是調用start方法一層一層開啟,StandardServer的startInternal方法,按層次start:globalNamingResources,StandardService--》StandardEngine,executors,MapperListener,Connector--》StandardHost,StandardContext,protocolHandler。順序基本同init過程。StandardEngine在start時,會init子容器,并調用子容器的start方法。子容器依次這樣init、start,就開啟了StandardHost和StandardContext。

參考文章:

tomcat源碼分析-Connector初始化與啟動

tomcat源碼分析-Container初始化與加載

tomcat源碼分析-http請求在Container中的執行路線

tomcat源碼解析(一)--啟動與Server.xml文件的解析

?

轉載于:https://www.cnblogs.com/z941030/p/8524882.html

總結

以上是生活随笔為你收集整理的Tomcat启动过程源码解读的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 男女操操| 成人午夜激情网 | 亚洲女同在线 | 乱子伦视频在线看 | 野外做受又硬又粗又大视频√ | 亚洲一区欧美一区 | 五月激情小说 | 午夜不卡福利 | 6080福利 | 久热草| 少妇综合网 | 姐姐的秘密韩剧免费观看全集中文 | 国产成人精品a视频一区 | 日韩av无码久久 | 国产一区二区三区视频网站 | 在线天堂中文在线资源网 | 在线电影一区二区 | 天操夜夜操 | 成年人免费av | 黄色在线免费观看网站 | 日本不卡一区二区三区在线观看 | 亚洲欧美一区二区三区久久 | 超碰在线免费 | 总裁边开会边做小娇妻h | 美日韩成人| 色情毛片 | 性欧美一级 | 琪琪色在线观看 | 香蕉视频网站在线观看 | 2018狠狠干| 偷拍女澡堂一区二区三区 | 亚洲伊人av | 无码人妻精品一区二区三区66 | 久草热视频 | 男女男精品视频站 | 伊人中文字幕 | 天美麻花果冻视频大全英文版 | 日韩欧美视频在线免费观看 | 色欲av伊人久久大香线蕉影院 | 把高贵美妇调教成玩物 | 亚洲精品综合久久 | 久久国产一级片 | 三级黄色在线视频 | 久久午夜影院 | 亚洲香蕉 | 强videoshd酒醉| 熟妇高潮一区二区三区在线播放 | 日韩欧美一区二区在线 | 99免费在线视频 | 白丝女仆被免费网站 | 婷婷中文字幕在线 | 亚洲av无码久久精品狠狠爱浪潮 | 久久久蜜桃一区二区 | 欧美一级少妇 | 亚洲最新| 精品人妻无码专区视频 | 亚洲字幕av一区二区三区四区 | 青青草原国产在线 | 日日操狠狠操 | 99色亚洲 | 国产午夜无码精品免费看奶水 | 国产成人a亚洲精品 | 成人hd | av综合色 | 日韩视频中文字幕在线观看 | 国产福利91精品一区二区三区 | 久久久久久久久久网 | 岛国av在线播放 | 九色91popny蝌蚪新疆 | 日本高清不卡在线观看 | 成人a免费| 精品盗摄一区二区三区 | 双性受孕h堵精大肚生子 | 亚洲精品一区二区三区婷婷月 | 久久综合伊人77777麻豆最新章节 | 美女破处视频 | 国产午夜视频在线播放 | 国产欧美一区二区三区在线看 | 免费av观看网址 | 日韩国产在线一区 | 久热免费视频 | 久久精品夜色噜噜亚洲a∨ 中文字幕av网 | 久久人人爽人人爽人人片av高清 | 亚洲人人爱 | 激情综合文学 | 国产精品黄在线观看 | 日韩免费精品视频 | 国产成人愉拍精品久久 | 亚洲国产日韩一区二区 | jizz免费视频 | 三级国产在线 | 国产做爰全免费的视频软件 | 芒果视频污污 | 自拍偷拍20p| 国产精品人妖 | 亚洲在线观看免费 | 久久性感美女视频 | 国产区免费观看 | 欧美日韩性 |