欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Tomcat啟動

系統(tǒng) 2549 0
Bootstrapping Tomcat
The bootstrapping process is actually rather simple. All we have to do is:
1、Set up the environment variables required by this Tomcat instance
2、Instantiate the general class loaders that will be used for our running? Tomcat instance
3、Initialize this Tomcat instance
4、Parse the main configuration file for a Tomcat instance, server.xml,?converting each configuration element into the appropriate Tomcat?component
5、Start up our outermost Top Level Element—the Server instance
6、Set up a shutdown hook
分別看看如何執(zhí)行:
1、執(zhí)行startup.bat,調(diào)用catalina.bat進行環(huán)境變量的設(shè)置,否則通過
Bootstrap的ini()
// Set Catalina path
setCatalinaHome ();
setCatalinaBase();
2、 classloader
Our Bootstrap instance holds references to the following three class loaders:
1、commonLoader, which loads classes that are common across Tomcat, as well?
as all the web applications.
2、catalinaLoader, or serverLoader, which loads classes that are used just?
by Tomcat.
3、sharedLoader, which loads classes that are common just across all the web?
applications within a Tomcat instance.
其中:org.apache.catalina.startup.CatalinaProperties類解析catalina.properties文件,
org.apache.catalina.startup.ClassLoaderFactory?的createClassLoader()方法將.jar文件url放入set,并返回StandardClassLoader
Tomcat啟動
在ini方法中會
?
initClassLoaders();
Thread. currentThread ().setContextClassLoader( catalinaLoader );
SecurityClassLoad. securityClassLoad ( catalinaLoader );
// Load our startup class and call its process() method
if ( log .isDebugEnabled())
log .debug( "Loading startup class" );
Class startupClass =
catalinaLoader .loadClass
( "org.apache.catalina.startup.Catalina" );
Object startupInstance = startupClass.newInstance();
而其中的initClassLoaders()方法會初始化loaders,如下:
private void initClassLoaders () {
try {
commonLoader = createClassLoader( "common" , null );
if ( commonLoader == null ) {
// no config file, default to this loader - we might be in a 'single' env .
commonLoader = this .getClass().getClassLoader();
}
catalinaLoader = createClassLoader( "server" , commonLoader );
sharedLoader = createClassLoader( "shared" , commonLoader );
} catch (Throwable t) {
log .error( "Class loader creation threw exception" , t);
System. exit (1);
}
}
上面代碼
Class startupClass = catalinaLoader .loadClass ( "org.apache.catalina.startup.Catalina" );
Object startupInstance = startupClass.newInstance();
實例化了startup實例。
?
4、解析Server.xml,使用了?Apache Commons Digester?
?It takes an XML document?and a RuleSet document as inputs, and generates a graph of Java objects that?
represents the structure that is defined in the XML instance document
The pattern:sax方式,例如:Server/Service/Connector
The rule:普通有4種
1、Creational actions (create an instance of a given class to represent this? XML element)
創(chuàng)建行為
2、Property setting actions (call setters on the Java object representing this? XML element, passing in the value of either a child element or an attribute)
屬性設(shè)置
3、Method invocation actions (call the specified method on the Java object?representing this element, passing in the specified parameters)
激活方法
4、Object linking actions (set an object reference by calling a setter on one? object while passing in the other as an argument)
對象引用
Server.xml的Digester
通過Catalina.java中的 createStartDigester ()方法創(chuàng)建,并設(shè)置規(guī)則
?
5、?在 Catalina.java中調(diào)用start()方法中調(diào)用getServer().initialize();
接著:services[i].initialize();
接著:connectors[i].initialize();
。。。(詳見最后的代碼跟蹤)
6、shutdown hook
A shutdown hook is a standard Thread that encapsulates cleanup actions that?should be taken before the Java runtime exits. All shutdown hooks are called by? the runtime when the JVM is shutting down.
Therefore, the last task that we perform is to install a shutdown hook, as?implemented by CatalinaShutdownHook. This hook is registered with the? Java Runtime by invoking its addShutdownHook() method:
Runtime.getRuntime().addShutdownHook(),
CatalinaShutdownHook is an inner class of Catalina and so has access to all the?data members of Catalina. Its run() method is very simple. It just ensures that?stop() is called on this instance of Catalina. This method invokes stop() on the?StandardServer instance, which in turn performs a cascaded invocation of stop()?on all its child components. Each child does the same for its children, until the entire?server has been cleanly stopped.
使用類 CatalinaShutdownHook實現(xiàn),它繼承Thread,run中進行清理
// Register shutdown hook
if ( useShutdownHook ) {
if ( shutdownHook == null ) {
shutdownHook = new CatalinaShutdownHook();
}
Runtime. getRuntime (). addShutdownHook ( shutdownHook );
// If JULI is being used, disable JULI's shutdown hook since
// shutdown hooks run in parallel and log messages may be lost
// if JULI's hook completes before the CatalinaShutdownHook()
LogManager logManager = LogManager. getLogManager ();
if (logManager instanceof ClassLoaderLogManager) {
((ClassLoaderLogManager) logManager).setUseShutdownHook(
false );
}
}
?
啟動tomat代碼跟蹤
View Code
1、Bootstrap.java中的main方法,啟動tomcat;
調(diào)用init()方法初始化,并用Catalina.load(),獲取server對象,并調(diào)用ini方法
// ?Start?the?new?server
if ?(getServer()? instanceof ?Lifecycle)?{
try ?{
getServer().initialize();
}? catch ?(LifecycleException?e)?{
if ?(Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
throw ? new ?java.lang.Error(e);
else ?
log.error("Catalina.start",?e);
}
}?
但是server對象是怎么來的??
往回看,在load方法中,
// ?Create?and?execute?our?Digester
Digester?digester?=?createStartDigester();?中創(chuàng)建了規(guī)則,如下:

// ?Configure?the?actions?we?will?be?using
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");?
經(jīng)過反射,到類ObjectCreateRule類的begin方法中
// ?Instantiate?the?new?object?and?push?it?on?the?context?stack
Class?clazz?=?digester.getClassLoader().loadClass(realClassName);
Object?instance?=?clazz.newInstance();?
利用反射創(chuàng)建對象,其中:realClassName?=org.apache.catalina.core.StandardServer
在類org.apache.catalina.core.StandardServer構(gòu)造方法中調(diào)用ServerFactory.setServer( this );?
實現(xiàn)單例Server對象創(chuàng)建。

2、?
getServer().initialize();方法中調(diào)用service的ini方法:其中services為解析server.xml
// ?Initialize?our?defined?Services
???????? for ?( int ?i?=?0;?i?<?services.length;?i++)?{
????????????services[i].initialize();
????????}
在?initialize
執(zhí)行connector的ini方法
for ?( int ?i?=?0;?i?<?connectors.length;?i++)?{
try ?{
connectors[i].initialize();?
connectors的來源也是server.xml配置文件,默認配置:
?<Connector?connectionTimeout="20000"?port="80"?protocol="HTTP/1.1"?redirectPort="8443"/>
???????<!--?Define?an?AJP?1.3?Connector?on?port?8009?-->
????<Connector?port="8009"?protocol="AJP/1.3"?redirectPort="8443"/>


3、接下來分析connector,默認使用protocol="HTTP/1.1"協(xié)議
? // ?Initializa?adapter
????????adapter?=? new ?CoyoteAdapter( this );
????????protocolHandler.setAdapter(adapter);
生成CoyoteAdapter,并設(shè)置,調(diào)用ini方法
protocolHandler.init();
4、接下來調(diào)用
endpoint.init();?
我們了看看JIoEndpoint?類是做神馬的?
?*?Handle?incoming?TCP?connections.
?*
?*?This? class ?implement?a?simple?server?model:?one?listener?thread?accepts?on?a?socket?and
?*?creates?a? new ?worker?thread? for ?each?incoming?connection.
此類實現(xiàn)了簡單的server模型:一個監(jiān)聽線程,接受socket并且為每一個到來的連接創(chuàng)建一個worker線程
真正干活的是這個!后面我們會分析它的start方法
接下來初始化其他conector

5、當(dāng)以上初始化完成后,調(diào)用Catalina.start()方法,接著啟動server.start()方法:
((Lifecycle)?getServer()).start();?
接著調(diào)用service.start()方法
接下來是一系列的container的start,后續(xù)在分析(會部署所有的項目)

在service.start()中,調(diào)用executors,connectors的start方法,我們直接往下看
synchronized ?(executors)?{
for ?(? int ?i=0;?i<executors.size();?i++?)?{
executors.get(i).start();
}
}
// ?Start?our?defined?Connectors?second
synchronized ?(connectors)?{
for ?( int ?i?=?0;?i?<?connectors.length;?i++)?{
try ?{
((Lifecycle)?connectors[i]).start();
}? catch ?(Exception?e)?{
log.error(sm.getString(
"standardService.connector.startFailed",
connectors[i]),?e);
}
}
}?
6、直到調(diào)用protocolHandler.start();?接下來:JIoEndpoint.start();
public ? void ?start()
throws ?Exception?{
// ?Initialize?socket?if?not?done?before
if ?(!initialized)?{
init();
}
if ?(!running)?{
running?=? true ;
paused?=? false ;
// ?Create?worker?collection
if ?(executor?==? null )?{
workers?=? new ?WorkerStack(maxThreads);
}
// ?Start?acceptor?threads
for ?( int ?i?=?0;?i?<?acceptorThreadCount;?i++)?{
Thread?acceptorThread?=? new ?Thread( new ?Acceptor(),?getName()?+?"-Acceptor-"?+?i);
acceptorThread.setPriority(threadPriority);
acceptorThread.setDaemon(daemon);
acceptorThread.start();
}
}
}?
7、此方法會創(chuàng)建一個線程(acceptorThreadCount默認=1),此線程Acceptor對象,看run方法
/**
*?The?background?thread?that?listens?for?incoming?TCP/IP?connections?and
*?hands?them?off?to?an?appropriate?processor.
*/
public ? void ?run()?{
// ?Loop?until?we?receive?a?shutdown?command
while ?(running)?{
// ?Loop?if?endpoint?is?paused
while ?(paused)?{
try ?{
Thread.sleep(1000);
}? catch ?(InterruptedException?e)?{
// ?Ignore
}
}
// ?Accept?the?next?incoming?connection?from?the?server?socket
try ?{
Socket?socket?=?serverSocketFactory.acceptSocket(serverSocket);
serverSocketFactory.initSocket(socket);
// ?Hand?this?socket?off?to?an?appropriate?processor
if ?(!processSocket(socket))?{
// ?Close?socket?right?away
try ?{
socket.close();
}? catch ?(IOException?e)?{
// ?Ignore
}
}
} catch ?(?IOException?x?)?{
if ?(?running?)?log.error(sm.getString("endpoint.accept.fail"),?x);
}? catch ?(Throwable?t)?{
log.error(sm.getString("endpoint.accept.fail"),?t);
}
// ?The?processor?will?recycle?itself?when?it?finishes
}
}?
這就是前面介紹的作用:接受socket并分配處理,最終關(guān)閉socket
方法:
/**
*?Process?given?socket.
*/
protected ? boolean ?processSocket(Socket?socket)?{
try ?{
if ?(executor?==? null )?{
getWorkerThread().assign(socket);
}? else ?{
executor.execute( new ?SocketProcessor(socket));
}
}? catch ?(Throwable?t)?{
// ?This?means?we?got?an?OOM?or?similar?creating?a?thread,?or?that
// ?the?pool?and?its?queue?are?full
log.error(sm.getString("endpoint.process.fail"),?t);
return ? false ;
}
return ? true ;
}?
其中g(shù)etWorkerThread()返回的worker?thread
/**
*?Return?a?new?worker?thread,?and?block?while?to?worker?is?available.
*/
protected ?Worker?getWorkerThread()?{
// ?Allocate?a?new?worker?thread
synchronized ?(workers)?{
Worker?workerThread;
while ?((workerThread?=?createWorkerThread())?==? null )?{
try ?{
workers.wait();
}? catch ?(InterruptedException?e)?{
// ?Ignore
}
}
return ?workerThread;
}
}
在看worker對象的run方法:
public ? void ?run()?{
// ?Process?requests?until?we?receive?a?shutdown?signal
while ?(running)?{
// ?Wait?for?the?next?socket?to?be?assigned
// 當(dāng)沒有請求時,此線程一直處于等待狀態(tài),直到被喚醒,也就是notifyAll(),在之前的getWorkerThread().assign(socket)被喚醒
Socket?socket?=?await();
if ?(socket?==? null )
continue ;
// ?Process?the?request?from?this?socket
if ?(!setSocketOptions(socket)?||?!handler.process(socket))?{
// ?Close?socket
try ?{
socket.close();
}? catch ?(IOException?e)?{
}
}
// ?Finish?up?this?request
socket?=? null ;
recycleWorkerThread( this );
}
}?
最終執(zhí)行在handler.process,我們之前分析的Http11Protocol類中的內(nèi)部類實現(xiàn)了Handler,如下:
protected ? static ? class ?Http11ConnectionHandler? implements ?Handler?

對于我們的protocol="HTTP/1.1"?connector來說,此類執(zhí)行了process方法,處理socket
調(diào)用processor.process()方法處理http請求,包括servlet、靜態(tài)資源等
/**
*?Process?pipelined?HTTP?requests?on?the?specified?socket.
*
*?
@param ?socket?Socket?from?which?the?HTTP?requests?will?be?read
*?and?the?HTTP?responses?will?be?written.
*?
*?
@throws ?IOException?error?during?an?I/O?operation
*/
public ? void ?process(Socket?theSocket)
throws ?IOException?{
RequestInfo?rp?=?request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
// ?Set?the?remote?address
remoteAddr?=? null ;
remoteHost?=? null ;
localAddr?=? null ;
localName?=? null ;
remotePort?=?-1;
localPort?=?-1;
// ?Setting?up?the?I/O
this .socket?=?theSocket;
inputBuffer.setInputStream(socket.getInputStream());
outputBuffer.setOutputStream(socket.getOutputStream());
// ?Error?flag
error?=? false ;
keepAlive?=? true ;
int ?keepAliveLeft?=?maxKeepAliveRequests;
int ?soTimeout?=?endpoint.getSoTimeout();
// ?When?using?an?executor,?these?values?may?return?non-positive?values
int ?curThreads?=?endpoint.getCurrentThreadsBusy();
int ?maxThreads?=?endpoint.getMaxThreads();
if ?(curThreads?>?0?&&?maxThreads?>?0)?{
// ?Only?auto-disable?keep-alive?if?the?current?thread?usage?%?can?be
// ?calculated?correctly
if ?((curThreads*100)/maxThreads?>?75)?{
keepAliveLeft?=?1;
}
}
// 以下設(shè)置了超時,如果沒有超時,那依然使用同一個socket請求資源,此時不用重建socket,效率高
try ?{
socket.setSoTimeout(soTimeout);
}? catch ?(Throwable?t)?{
log.debug(sm.getString("http11processor.socket.timeout"),?t);
error?=? true ;
}
boolean ?keptAlive?=? false ;
while ?(started?&&?!error?&&?keepAlive?&&?!endpoint.isPaused())?{
// ?Parsing?the?request?header
try ?{
if ?(keptAlive)?{
if ?(keepAliveTimeout?>?0)?{
socket.setSoTimeout(keepAliveTimeout);
}
else ? if ?(soTimeout?>?0)?{
socket.setSoTimeout(soTimeout);
}
}
inputBuffer.parseRequestLine();
request.setStartTime(System.currentTimeMillis());
keptAlive?=? true ;
if ?(disableUploadTimeout)?{
socket.setSoTimeout(soTimeout);
}? else ?{
socket.setSoTimeout(timeout);
}
inputBuffer.parseHeaders();
}? catch ?(IOException?e)?{
error?=? true ;
break ;
}? catch ?(Throwable?t)?{
if ?(log.isDebugEnabled())?{
log.debug(sm.getString("http11processor.header.parse"),?t);
}
// ?400?-?Bad?Request
response.setStatus(400);
adapter.log(request,?response,?0);
error?=? true ;
}
if ?(!error)?{
// ?Setting?up?filters,?and?parse?some?request?headers
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try ?{
prepareRequest();
}? catch ?(Throwable?t)?{
if ?(log.isDebugEnabled())?{
log.debug(sm.getString("http11processor.request.prepare"),?t);
}
// ?400?-?Internal?Server?Error
response.setStatus(400);
adapter.log(request,?response,?0);
error?=? true ;
}
}
if ?(maxKeepAliveRequests?>?0?&&?--keepAliveLeft?==?0)
keepAlive?=? false ;
// ?Process?the?request?in?the?adapter
if ?(!error)?{
try ?{
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
adapter.service(request,?response);
// ?Handle?when?the?response?was?committed?before?a?serious
// ?error?occurred.?Throwing?a?ServletException?should?both
// ?set?the?status?to?500?and?set?the?errorException.
// ?If?we?fail?here,?then?the?response?is?likely?already
// ?committed,?so?we?can't?try?and?set?headers.
if (keepAlive?&&?!error)?{? // ?Avoid?checking?twice.
error?=?response.getErrorException()?!=? null ?||
statusDropsConnection(response.getStatus());
}
}? catch ?(InterruptedIOException?e)?{
error?=? true ;
}? catch ?(Throwable?t)?{
log.error(sm.getString("http11processor.request.process"),?t);
// ?500?-?Internal?Server?Error
response.setStatus(500);
adapter.log(request,?response,?0);
error?=? true ;
}
}
// ?Finish?the?handling?of?the?request
try ?{
rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
// ?If?we?know?we?are?closing?the?connection,?don't?drain?input.
// ?This?way?uploading?a?100GB?file?doesn't?tie?up?the?thread?
// ?if?the?servlet?has?rejected?it.
if (error)
inputBuffer.setSwallowInput( false );
inputBuffer.endRequest();
}? catch ?(IOException?e)?{
error?=? true ;
}? catch ?(Throwable?t)?{
log.error(sm.getString("http11processor.request.finish"),?t);
// ?500?-?Internal?Server?Error
response.setStatus(500);
adapter.log(request,?response,?0);
error?=? true ;
}
try ?{
rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
outputBuffer.endRequest();
}? catch ?(IOException?e)?{
error?=? true ;
}? catch ?(Throwable?t)?{
log.error(sm.getString("http11processor.response.finish"),?t);
error?=? true ;
}
// ?If?there?was?an?error,?make?sure?the?request?is?counted?as
// ?and?error,?and?update?the?statistics?counter
if ?(error)?{
response.setStatus(500);
}
request.updateCounters();
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
// ?Don't?reset?the?param?-?we'll?see?it?as?ended.?Next?request
// ?will?reset?it
// ?thrA.setParam(null);
// ?Next?request
inputBuffer.nextRequest();
outputBuffer.nextRequest();
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
// ?Recycle
inputBuffer.recycle();
outputBuffer.recycle();
this .socket?=? null ;
// ?Recycle?ssl?info
sslSupport?=? null ;
}
?

Tomcat啟動


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 色综合天天操 | 青青久草 | 欧美精品一区二区三区在线播放 | 一级做a爰片欧美一区 | 涩久久| 欧美日韩一区在线观看 | 成人欧美一区在线视频在线观看 | 伊人久久99亚洲精品久久频 | 国产成人99久久亚洲综合精品 | 九九久久精品 | 欧美精品在线一区 | 欧美日一区二区 | 黄色免费高清网站 | 天天插天天射天天操 | 欧美zozozo人禽交 | 看a网站| 欧美久久久无码精品亚洲日韩小说 | 一区二区三区欧美 | 欧美亚洲在线视频 | 国产这里只有精品 | 青娱乐综合 | 欧美韩国日本一区 | 深夜你懂的在线网址入口 | 热久久久| 特级黄一级播放 | 久久久久久久国产精品电影 | 国产精品免费观看 | 一区二区三区影院 | 日本吻胸捏胸激烈床戏视频 | 成人区视频爽爽爽爽爽 | 日本黄色免费网站 | 仇爱电视剧泰剧在线观看免费播放 | 免费看污成人午夜网站 | www久久精品 | 欧洲精品欧美精品 | 亚洲高清资源 | 日本欧美一二三区色视频 | 人人爽人人爽 | 涩涩小网站 | 亚洲人影院 | 清纯唯美亚洲综合激情 |