您的位置:首页 > 运维架构 > Tomcat

Tomcat启动分析(Tomcat7.0)

2016-01-25 19:35 531 查看
1)bin目录下的bootstrap.jar中的main方法启动Tomcat

org.apache.catalina.startup.Bootstrap类下的main方法

可以看到Bootstrap类使用单例方式在main方法中初始化Bootstrap对象

private static Bootstrap daemon = null;
private Object catalinaDaemon = null;
protected ClassLoader commonLoader = null;
protected ClassLoader catalinaLoader = null;
protected ClassLoader sharedLoader = null;


 调用Bootstrap对象的init()方法

public static void main(String[] args)
{
if (daemon == null)
{
Bootstrap bootstrap = new Bootstrap();
try {
bootstrap.init();
} catch (Throwable t) {
handleThrowable(t);
t.printStackTrace();
return;
}
daemon = bootstrap;
}
try
{
String command = "start";
if (args.length > 0) {
command = args[(args.length - 1)];
}

if (command.equals("startd")) {
args[(args.length - 1)] = "start";
daemon.load(args);
daemon.start();
} else if (command.equals("stopd")) {
args[(args.length - 1)] = "stop";
daemon.stop();
} else if (command.equals("start")) {
daemon.setAwait(true);
daemon.load(args);
daemon.start();
} else if (command.equals("stop")) {
daemon.stopServer(args);
} else if (command.equals("configtest")) {
daemon.load(args);
if (null == daemon.getServer()) {
System.exit(1);
}
System.exit(0);
} else {
log.warn(new StringBuilder().append("Bootstrap: command \"").append(command).append("\" does not exist.").toString());
}
}
catch (Throwable t) {
if (((t instanceof InvocationTargetException)) && (t.getCause() != null))
{
t = t.getCause();
}
handleThrowable(t);
t.printStackTrace();
System.exit(1);
}
}


Bootstrap对象的init()方法,引导类Bootstrap负责引导,在其init方法内部创建容器启动所需的类加载器,以及用于JMX监控的MBeanServer

public void init()
throws Exception
{
setCatalinaHome();
setCatalinaBase();

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[1];
paramTypes[0] = Class.forName("java.lang.ClassLoader");
Object[] paramValues = new Object[1];
paramValues[0] = this.sharedLoader;
Method method = startupInstance.getClass().getMethod(methodName, paramTypes);

method.invoke(startupInstance, paramValues);

this.catalinaDaemon = startupInstance;
}


仍然在Bootstrap类中,初始化所需要的类加载器

private void initClassLoaders()
{
try
{
this.commonLoader = createClassLoader("common", null);
if (this.commonLoader == null)
{
this.commonLoader = getClass().getClassLoader();
}
this.catalinaLoader = createClassLoader("server", this.commonLoader);
this.sharedLoader = createClassLoader("shared", this.commonLoader);
} catch (Throwable t) {
handleThrowable(t);
log.error("Class loader creation threw exception", t);
System.exit(1);
}
}


 

我们继续看到main方法中调用了Bootstrap对象的load(args)方法和start()方法

daemon.load(args);
daemon.start();


我们看到load(args)方法,Bootstrap调用Catalina的load()方法加载Server的配置(也就是server.xml),将加载的配置信息委托给Digester类进行相关内容的解析。

通过反射调用了Bootstrap对象中catalinaDaemon对象的load()方法,

private void load(String[] arguments)
throws Exception
{
String methodName = "load";
Object[] param;
Class<?>[] paramTypes;
Object[] param; if ((arguments == null) || (arguments.length == 0)) {
Class<?>[] paramTypes = null;
param = null;
} else {
paramTypes = new Class[1];
paramTypes[0] = arguments.getClass();
param = new Object[1];
param[0] = arguments;
}
Method method = this.catalinaDaemon.getClass().getMethod(methodName, paramTypes);

if (log.isDebugEnabled())
log.debug(new StringBuilder().append("Calling startup class ").append(method).toString());
method.invoke(this.catalinaDaemon, param);
}


  

我们可以看到在上面的init()方法中初始化了org.apache.catalina.startup.Catalina对象,通过之前初始化的catalinaLoader类加载器

该类在lib包下的catalina.jar包中

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[1];
paramTypes[0] = Class.forName("java.lang.ClassLoader");
Object[] paramValues = new Object[1];
paramValues[0] = this.sharedLoader;
Method method = startupInstance.getClass().getMethod(methodName, paramTypes);

method.invoke(startupInstance, paramValues);

this.catalinaDaemon = startupInstance;


  

我们看该类中的load方法是如何加载server.xml文件的。

public void load()
{
long t1 = System.nanoTime();

initDirs();

initNaming();

Digester digester = createStartDigester();

InputSource inputSource = null;
InputStream inputStream = null;
File file = null;
try {
file = configFile();
inputStream = new FileInputStream(file);
inputSource = new InputSource(file.toURI().toURL().toString());
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("catalina.configFail", new Object[] { file }), e);
}
}
if (inputStream == null) {
try {
inputStream = getClass().getClassLoader().getResourceAsStream(getConfigFile());

inputSource = new InputSource(getClass().getClassLoader().getResource(getConfigFile()).toString());
}
catch (Exception e)
{
if (log.isDebugEnabled()) {
log.debug(sm.getString("catalina.configFail", new Object[] { getConfigFile() }), e);
}
}
}

if (inputStream == null) {
try {
inputStream = getClass().getClassLoader().getResourceAsStream("server-embed.xml");

inputSource = new InputSource(getClass().getClassLoader().getResource("server-embed.xml").toString());
}
catch (Exception e)
{
if (log.isDebugEnabled()) {
log.debug(sm.getString("catalina.configFail", new Object[] { "server-embed.xml" }), e);
}
}
}

if ((inputStream == null) || (inputSource == null)) {
if (file == null) {
log.warn(sm.getString("catalina.configFail", new Object[] { getConfigFile() + "] or [server-embed.xml]" }));
}
else {
log.warn(sm.getString("catalina.configFail", new Object[] { file.getAbsolutePath() }));

if ((file.exists()) && (!file.canRead())) {
log.warn("Permissions incorrect, read permission is not allowed on the file.");
}
}
return;
}
try
{
inputSource.setByteStream(inputStream);
digester.push(this);
digester.parse(inputSource);

try
{
inputStream.close();
}
catch (IOException e) {}

getServer().setCatalina(this);
}
catch (SAXParseException spe)
{
log.warn("Catalina.start using " + getConfigFile() + ": " + spe.getMessage()); return;
}
catch (Exception e)
{
log.warn("Catalina.start using " + getConfigFile() + ": ", e); return;
}
finally {
try {
inputStream.close();
}
catch (IOException e) {}
}

initStreams();

try
{
getServer().init();
} catch (LifecycleException e) {
if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {
throw new Error(e);
}
log.error("Catalina.start", e);
}

long t2 = System.nanoTime();
if (log.isInfoEnabled()) {
log.info("Initialization processed in " + (t2 - t1) / 1000000L + " ms");
}
}

public void load(String[] args)
{
try
{
if (arguments(args)) {
load();
}
} catch (Exception e) {
e.printStackTrace(System.out);
}
}


protected boolean arguments(String[] args)
{
boolean isConfig = false;

if (args.length < 1) {
usage();
return false;
}

for (int i = 0; i < args.length; i++) {
if (isConfig) {
this.configFile = args[i];
isConfig = false;
} else if (args[i].equals("-config")) {
isConfig = true;
} else if (args[i].equals("-nonaming")) {
setUseNaming(false);
} else { if (args[i].equals("-help")) {
usage();
return false; }
if (args[i].equals("start")) {
this.starting = true;
this.stopping = false;
} else if (args[i].equals("configtest")) {
this.starting = true;
this.stopping = false;
} else if (args[i].equals("stop")) {
this.starting = false;
this.stopping = true;
} else {
usage();
return false;
}
}
}
return true;
}


看到Catalina类当中的变量,表明解析文件的位置。

protected String configFile = "conf/server.xml";


protected File configFile()
{
File file = new File(this.configFile);
if (!file.isAbsolute()) {
file = new File(System.getProperty("catalina.base"), this.configFile);
}
return file;
}


看到configFile方法创建File对象的过程

我们将看到load方法中调用getServer().init()调用 Server对象的init方法。

Catalina获取到Server的配置信息后,执行StandardServer容器的init()方法。Tomcat的所有容器类都实现了统一的Lifecycle接口,由基类LifecycleBase提供统一的init方法来负责处理容器的状态,调用模板方法initInternal来处理各个容器自身所负责的内容。关于Tomcat的容器结构可以参看本系列文章的《Tomcat7源码解读(一)——容器静态结构概述》。StandardServer容器在其initInternal()方法中完成Mbean的设定,GlobalNamingResources的初始化和类加载器的设置。然后执行StandardService容器的init方法。

StandardService同StandardServer容器,由基类LifecycleBase完成容器的生命周期状态设定,而在initInternal()方法中启动Container,Executor,Connector的init方法

StandardService类位于lib包下的catalina.jar包中,

org.apache.catalina.core.StandardService的父类中有init方法,

public final synchronized void init()
throws LifecycleException
{
if (!this.state.equals(LifecycleState.NEW)) {
invalidTransition("before_init");
}
setStateInternal(LifecycleState.INITIALIZING, null, false);
try
{
initInternal();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.initFail", new Object[] { toString() }), t);
}

setStateInternal(LifecycleState.INITIALIZED, null, false);
}


是在org.apache.catalina.util.LifecycleBase类当中,调用了initInternal()方法。

看到LifecyceBase类的父类中

protected void initInternal()
throws LifecycleException
{
if (this.oname == null) {
this.mserver = Registry.getRegistry(null, null).getMBeanServer();

this.oname = register(this, getObjectNameKeyProperties());
}
}


protected void initInternal()
throws LifecycleException
{
super.initInternal();

this.onameStringCache = register(new StringCache(), "type=StringCache");

MBeanFactory factory = new MBeanFactory();
factory.setContainer(this);
this.onameMBeanFactory = register(factory, "type=MBeanFactory");

this.globalNamingResources.init();

if (getCatalina() != null) {
ClassLoader cl = getCatalina().getParentClassLoader();

while ((cl != null) && (cl != ClassLoader.getSystemClassLoader())) {
if ((cl instanceof URLClassLoader)) {
URL[] urls = ((URLClassLoader)cl).getURLs();
for (URL url : urls) {
if (url.getProtocol().equals("file")) {
try {
File f = new File(url.toURI());
if ((f.isFile()) && (f.getName().endsWith(".jar")))
{
ExtensionValidator.addSystemResource(f);
}
}
catch (URISyntaxException e) {}catch (IOException e) {}
}
}
}

cl = cl.getParent();
}
}

for (int i = 0; i < this.services.length; i++) {
this.services[i].init();
}
}


  

看到Bootstrap类当中调用玩load方法之后,开始调用start方法,方法也是调用Catalina类当中的start方法来启动Tomcat

public void start()
{
if (getServer() == null) {
load();
}

if (getServer() == null) {
log.fatal("Cannot start server. Server instance is not configured.");
return;
}

long t1 = System.nanoTime();

try
{
getServer().start();
} catch (LifecycleException e) {
log.error("Catalina.start: ", e);
}

long t2 = System.nanoTime();
if (log.isInfoEnabled()) {
log.info("Server startup in " + (t2 - t1) / 1000000L + " ms");
}

if (this.useShutdownHook) {
if (this.shutdownHook == null) {
this.shutdownHook = new CatalinaShutdownHook();
}
Runtime.getRuntime().addShutdownHook(this.shutdownHook);

LogManager logManager = LogManager.getLogManager();
if ((logManager instanceof ClassLoaderLogManager)) {
((ClassLoaderLogManager)logManager).setUseShutdownHook(false);
}
}

if (this.await) {
await();
stop();
}
}


看到调用的还是StandardServer类的start方法来启动Tomcat容器

看到类似于init的方式,我们看到也是通过调用org.apache.catalina.util.LifeCycleBase类的start方法调用一系列的startInternal方法来启动的

public final synchronized void start()
throws LifecycleException
{
if ((LifecycleState.STARTING_PREP.equals(this.state)) || (LifecycleState.STARTING.equals(this.state)) || (LifecycleState.STARTED.equals(this.state)))
{
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStarted", new Object[] { toString() }), e);
}
else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStarted", new Object[] { toString() }));
}

return;
}

if (this.state.equals(LifecycleState.NEW)) {
init();
} else if (this.state.equals(LifecycleState.FAILED)) {
stop();
} else if ((!this.state.equals(LifecycleState.INITIALIZED)) && (!this.state.equals(LifecycleState.STOPPED)))
{
invalidTransition("before_start");
}

setStateInternal(LifecycleState.STARTING_PREP, null, false);
try
{
startInternal();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.startFail", new Object[] { toString() }), t);
}

if ((this.state.equals(LifecycleState.FAILED)) || (this.state.equals(LifecycleState.MUST_STOP)))
{
stop();
}
else
{
if (!this.state.equals(LifecycleState.STARTING)) {
invalidTransition("after_start");
}

setStateInternal(LifecycleState.STARTED, null, false);
}
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: