private static Bootstrap daemon = null; 如果没有,这初始化
调用BootStrap中的init方法:
1.this.initClassLoaders(); : if deamon==null 初始化Bootstrap接着调用Bootstrap的init方法: this.initClassLoaders(),初始化三个类加载器commonLoader, catalinaLoader,sharedLoader。其中commonLoader加载器可以读取 common/classes,common/endorsed,common/lib目录下的Java类, catalinaLoader负责加载server/lib,/server/classes,sharedLoader 负责加载/shared/classes,/shared/lib。其中commonLoader,是 catalinaLoader,sharedLoader父类加载器。让deamon=t; try { this.commonLoader = this.createClassLoader("common", (ClassLoader)null); if(this.commonLoader == null) { this.commonLoader = this.getClass().getClassLoader(); }this.catalinaLoader = this.createClassLoader("server", this.commonLoader);
this.sharedLoader = this.createClassLoader("shared", this.commonLoader); } catch (Throwable var2) { handleThrowable(var2); log.error("Class loader creation threw exception", var2); System.exit(1); } else Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);//线程上下文切换器2.调用catalinaLodader加载器加载org.apache.catalina.startup.Catalina,并完成初始化
获取该类当中的setParentClassLoader方法调用ClassLoader,将sharedLoader放入。 this.catalinaDaemon=this.catalinaLoader.loadClass("org.apache.catalina.startup.Catalina").startupClass.newInstance(); this.initClassLoaders(); Thread.currentThread().setContextClassLoader(this.catalinaLoader); SecurityClassLoad.securityClassLoad(this.catalinaLoader); if(log.isDebugEnabled()) { log.debug("Loading startup class"); }Class startupClass = this.catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.newInstance(); if(log.isDebugEnabled()) { log.debug("Setting startup class properties"); }String methodName = "setParentClassLoader";
Class[] paramTypes = new Class[]{Class.forName("java.lang.ClassLoader")}; Object[] paramValues = new Object[]{this.sharedLoader}; Method method = startupInstance.getClass().getMethod(methodName, paramTypes); method.invoke(startupInstance, paramValues); this.catalinaDaemon = startupInstance; 3.判断启动参数和停止参数 try { String t2 = "start"; if(args.length > 0) { t2 = args[args.length - 1]; }if(t2.equals("startd")) {
args[args.length - 1] = "start"; daemon.load(args); daemon.start(); } else if(t2.equals("stopd")) { args[args.length - 1] = "stop"; daemon.stop(); } else if(t2.equals("start")) { daemon.setAwait(true); daemon.load(args); daemon.start(); } else if(t2.equals("stop")) { daemon.stopServer(args); } else if(t2.equals("configtest")) { daemon.load(args); if(null == daemon.getServer()) { System.exit(1); }System.exit(0);
} else { log.warn("Bootstrap: command \"" + t2 + "\" does not exist."); }4.
3 中的load方法 Method method = this.catalinaDaemon.getClass().getMethod(methodName, paramTypes); //方法名,调用参数 调用org.apache.catalina.startup.Catalina中的load方法: method.invoke(this.catalinaDaemon, param); 3.1 创建Digester 类 使用digester映射JavaBean和xml 3.2 加载配置文件 conf/server.xml 转化为inputSource 没有配置文件,则log.debug(sm.getString("catalina.configFail", new Object[]{file}), var25); 加载conf/server.xml server-embed.xml 将该类加入到digester栈顶digester.push(this);,解析 digester.parse(inputSource); xml文件 label251: { try { try { file = this.configFile(); inputStream = new FileInputStream(file); inputSource = new InputSource(file.toURI().toURL().toString()); } catch (Exception var25) { if(log.isDebugEnabled()) { log.debug(sm.getString("catalina.configFail", new Object[]{file}), var25); } }if(inputStream == null) {
try { inputStream = this.getClass().getClassLoader().getResourceAsStream(this.getConfigFile()); inputSource = new InputSource(this.getClass().getClassLoader().getResource(this.getConfigFile()).toString()); } catch (Exception var26) { if(log.isDebugEnabled()) { log.debug(sm.getString("catalina.configFail", new Object[]{this.getConfigFile()}), var26); } } }if(inputStream == null) {
try { inputStream = this.getClass().getClassLoader().getResourceAsStream("server-embed.xml"); inputSource = new InputSource(this.getClass().getClassLoader().getResource("server-embed.xml").toString()); } catch (Exception var27) { if(log.isDebugEnabled()) { log.debug(sm.getString("catalina.configFail", new Object[]{"server-embed.xml"}), var27); } } }if(inputStream != null && inputSource != null) {
try { inputSource.setByteStream((InputStream)inputStream); digester.push(this); digester.parse(inputSource); break label251; } catch (SAXParseException var28) { log.warn("Catalina.start using " + this.getConfigFile() + ": " + var28.getMessage()); return; } catch (Exception var29) { log.warn("Catalina.start using " + this.getConfigFile() + ": ", var29); return; } } 关闭IO流 3.3.调用Server方法 this.getServer().setCatalina(this); this.getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile()); this.getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile()); 3.3.1 初始化StandardServer类 server,并传入值 this.initStreams(); this.getServer().init(); //初始化生命周期 3.3.1 this.getServer().init() public interface Lifecycle void init() throws LifecycleException; 其实现类: this.setStateInternal(LifecycleState.INITIALIZING, (Object)null, false); //设置生命周期状态 this.initInternal(); this.setStateInternal(LifecycleState.INITIALIZED, (Object)null, false) load完成 4.start 获取加载器 4.1 this.initClassLoaders(); Thread.currentThread().setContextClassLoader(this.catalinaLoader); SecurityClassLoad.securityClassLoad(this.catalinaLoader); if(log.isDebugEnabled()) { log.debug("Loading startup class"); } //调用方法父类加载器 Class startupClass = this.catalinaLoader.loadClass("org.apache.catalina.startup.Catalina"); Object startupInstance = startupClass.newInstance(); if(log.isDebugEnabled()) { log.debug("Setting startup class properties"); }String methodName = "setParentClassLoader";
Class[] paramTypes = new Class[]{Class.forName("java.lang.ClassLoader")}; Object[] paramValues = new Object[]{this.sharedLoader}; Method method = startupInstance.getClass().getMethod(methodName, paramTypes); method.invoke(startupInstance, paramValues); this.catalinaDaemon = startupInstance;4.2 调用映射
Method method = this.catalinaDaemon.getClass().getMethod("start", (Class[])null); method.invoke(this.catalinaDaemon, (Object[])null); 调用Catalina.start() if(this.getServer() == null) { this.load(); } 4.2.1 调用生命周期中的start()方法 4.2.2 创建钩子程序 if(this.shutdownHook == null) { this.shutdownHook = new Catalina.CatalinaShutdownHook(); }Runtime.getRuntime().addShutdownHook(this.shutdownHook);
LogManager logManager = LogManager.getLogManager(); if(logManager instanceof ClassLoaderLogManager) { ((ClassLoaderLogManager)logManager).setUseShutdownHook(false); } 4.2.3 唤醒,停止 if(this.await) { this.await(); this.stop(); } 4.2.3.1 关闭过程 try { this.awaitThread = Thread.currentThread();while(!this.stopAwait) {
try { Thread.sleep(10000L); } catch (InterruptedException var64) { ; } } } finally { this.awaitThread = null; }} else {
try { this.awaitSocket = new ServerSocket(this.port, 1, InetAddress.getByName(this.address)); } catch (IOException var67) { log.error("StandardServer.await: create[" + this.address + ":" + this.port + "]: ", var67); return; }boolean var32 = false;
ServerSocket serverSocket;
try { var32 = true; this.awaitThread = Thread.currentThread();while(true) {
if(this.stopAwait) { var32 = false; break; }serverSocket = this.awaitSocket;
if(serverSocket == null) { var32 = false; break; }Socket socket = null;
StringBuilder command = new StringBuilder();label615: {
label614: { try { label638: { long acceptStartTime = System.currentTimeMillis();InputStream match;
try { socket = serverSocket.accept(); socket.setSoTimeout(10000); match = socket.getInputStream(); } catch (SocketTimeoutException var69) { log.warn(sm.getString("standardServer.accept.timeout", new Object[]{Long.valueOf(System.currentTimeMillis() - acceptStartTime)}), var69); continue; } catch (AccessControlException var70) { log.warn("StandardServer.accept security exception: " + var70.getMessage(), var70); continue; } catch (IOException var71) { if(this.stopAwait) { break label614; }log.error("StandardServer.await: accept: ", var71);
break label638; }int expected;
for(expected = 1024; expected < this.shutdown.length(); expected += this.random.nextInt() % 1024) { if(this.random == null) { this.random = new Random(); } }while(true) {
if(expected <= 0) { break label615; }boolean ch = true;
int var75;
try { var75 = match.read(); } catch (IOException var66) { log.warn("StandardServer.await: read: ", var66); var75 = -1; }if(var75 < 32 || var75 == 127) {
break label615; }command.append((char)var75);
--expected; } } } finally { try { if(socket != null) { socket.close(); } } catch (IOException var63) { ; }}
var32 = false;
break; }var32 = false;
break; }boolean var74 = command.toString().equals(this.shutdown);
if(var74) { log.info(sm.getString("standardServer.shutdownViaPort")); var32 = false; break; }log.warn("StandardServer.await: Invalid command \'" + command.toString() + "\' received");
} } finally { if(var32) { ServerSocket serverSocket1 = this.awaitSocket; this.awaitThread = null; this.awaitSocket = null; if(serverSocket1 != null) { try { serverSocket1.close(); } catch (IOException var62) { ; } }}
}serverSocket = this.awaitSocket;
this.awaitThread = null; this.awaitSocket = null; if(serverSocket != null) { try { serverSocket.close(); } catch (IOException var65) { ; } }}
关闭过程相当于在启动中创建一个线程等待,等到发送关闭命令以后Socket捕获这个线程然后启动关闭 程序。 4.2.3.2 关闭钩子程序 Runtime.getRuntime().removeShutdownHook(this.shutdownHook); LogManager e = LogManager.getLogManager(); if(e instanceof ClassLoaderLogManager) { ((ClassLoaderLogManager)e).setUseShutdownHook(true); } }