之前分析了Tomcat的启动脚本,如果从startup.bat开始启动Tomcat的话会发现最后会调用org.apache.catalina.startup.Bootstrap里的main方法,并且传过来的最后一个命令行参数是start,接下来的启动代码分析就从这里开始。
先看下这个main方法的代码:
/** * Main method and entry point when starting Tomcat via the provided * scripts. * * @param args Command line arguments to be processed */ public static void main(String args[]) { if (daemon == null) { // Don't set daemon until init() has completed Bootstrap bootstrap = new Bootstrap(); try { bootstrap.init(); } catch (Throwable t) { handleThrowable(t); t.printStackTrace(); return; } daemon = bootstrap; } else { // When running as a service the call to stop will be on a new // thread so make sure the correct class loader is used to prevent // a range of class not found exceptions. Thread.currentThread().setContextClassLoader(daemon.catalinaLoader); } 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("Bootstrap: command \"" + command + "\" does not exist."); } } catch (Throwable t) { // Unwrap the Exception for clearer error reporting if (t instanceof InvocationTargetException && t.getCause() != null) { t = t.getCause(); } handleThrowable(t); t.printStackTrace(); System.exit(1); } }
这里的daemon是Bootstrap类中的一个静态成员变量,类型就是Bootstrap,第10行的注释已经说明在调用过init方法之后才会给该变量赋值,初始时将是null,所以首先将实例化一个Bootstrap对象,接着调用init方法,该方法代码如下:
/** * Initialize daemon. */ public void init() throws Exception { // Set Catalina path setCatalinaHome(); setCatalinaBase(); 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(); // Set the shared extensions class loader 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] = sharedLoader; Method method = startupInstance.getClass().getMethod(methodName, paramTypes); method.invoke(startupInstance, paramValues); catalinaDaemon = startupInstance; }
这里不再逐句解释代码的作用,总的来说这个方法主要做了一下几件事:1.设置catalina.home、catalina.base系统属性,2.创建commonLoader、catalinaLoader、sharedLoader类加载器(默认情况下这三个类加载器指向同一个对象。建议看看createClassLoader方法,里面做的事情还挺多,比如装载catalina.properties里配置的目录下的文件和jar包,后两个加载器的父加载器都是第一个,最后注册了MBean,可以用于JVM监控该对象),3.实例化一个org.apache.catalina.startup.Catalina对象,并赋值给静态成员catalinaDaemon,以sharedLoader作为入参通过反射调用该对象的setParentClassLoader方法。
接下来去命令行最后一个参数,按文章开头所说是start,所以将执行34行到36行的代码,将会执行Bootstrap类中的load、start方法。
load方法代码如下:
/** * Load daemon. */ private void load(String[] arguments) throws Exception { // Call the load() method String methodName = "load"; Object param[]; Class<?> paramTypes[]; if (arguments==null || arguments.length==0) { paramTypes = null; param = null; } else { paramTypes = new Class[1]; paramTypes[0] = arguments.getClass(); param = new Object[1]; param[0] = arguments; } Method method = catalinaDaemon.getClass().getMethod(methodName, paramTypes); if (log.isDebugEnabled()) log.debug("Calling startup class " + method); method.invoke(catalinaDaemon, param); }
就是通过反射调用catalinaDaemon对象的load方法,catalinaDaemon对象在上面的init方法中已经实例化过了。
start方法与load方法相似,也是通过反射调用catalinaDaemon对象上的start方法:
/** * Start the Catalina daemon. */ public void start() throws Exception { if( catalinaDaemon==null ) init(); Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null); method.invoke(catalinaDaemon, (Object [])null); }
下面一篇文章将分析catalinaDaemon对象中的load、start两个方法,里面会涉及一个有趣的话题——Digester的使用。
相关推荐
该文件解压后就是Eclipse项目,可直接导入Eclipse 为我们研究tomcat源码提供了方便,运行org.apache.catalina.startup.Bootstrap类的main方法即可启动tomcat。
在运行Bootstrap的main方法时,将下面代码拷入到vm options 中 -Dcatalina.home=launch -Dcatalina.base=launch -Djava.endorsed.dirs=launch/endorsed -Djava.io.tmpdir=launch/temp -Djava.util.logging.manager=...
3.直接add到eclipse中的tomcat,就能启动了 测试后台密码 admin 123456 生产环境发布 1. 修改src/main/resources/production 下的 db.properties为生产环境中的数据库链接 mvn 命令打包 mvn clean package -...
apache tomcat 8.5.34 源码 Mark Directory as Sources Root: java/ Main: org.apache.catalina.startup.Bootstrap.main
使用SVN 在Apache官网checkout下来的tomcat源码,加入了4个依赖jar包,将ant工程改变成了直接可以导入eclipse的Java工程,org.apache.catalina.startup.Bootstrap是启动类,直接运行里边的main方法即可启动,方便...
深入理解Tomcat ...** Tomcat组件分析** ** Tomcat生产配置(网络io模型,调优思路)** ** Tomcat是如何启动的?NIO从接受socket到我们的servlet?** ** Tomcat如何打破双亲委派?** 0.简介 Tomcat
org.apache.catalina.startup.Bootstrap启动startup.sh/bat来启动其main(),main()调用Catalina的process() org.apache.catalina.startup.Catalina类的process():创建Digester对象,注册关闭钩子和调用...
运行环境 jdk8+tomcat8+mysql5.7+IntelliJ IDEA+maven ...4.将项目放入tomcat中并启动 5.浏览器访问localhost:8080/jsp/login/index.jsp 账号:test 密码:123456 (具体访问端口需要看本机的tomcat端口是多少)
这个项目是一个简单的教务查询系统,该练手小项目希望能帮助到大家,熟悉SSM的整合开发使用技术 ...在IntelliJ IDEA中,配置我们的Tomcat,然后把使用Maven构建好的项目添加到Tomcat中 运行 图像 登录账户 管理员账户:
开发工具 IDEA JDK1.8 TOMCAT 8.5 二、功能介绍 如博客中介绍 三、注意事项 1、管理员账号:admin密码:admin 数据库配置文件src\main\resources 下的 jdbc.properties 更改对应数据库连接配置 2、开发环境为IDEA...
开发工具 IDEA JDK1.8 TOMCAT 8.5 二、功能介绍 如博客中介绍 三、注意事项 1、管理员账号:admin密码:admin 数据库配置文件src\main\resources 下的 jdbc.properties 更改对应数据库连接配置 2、开发环境为IDEA...
开发工具 IDEA JDK1.8 TOMCAT 8.5 二、功能介绍 如博客中介绍 三、注意事项 1、管理员账号:admin密码:admin 数据库配置文件src\main\resources 下的 jdbc.properties 更改对应数据库连接配置 2、开发环境为IDEA...
开发工具 IDEA JDK1.8 TOMCAT 8.5 二、功能介绍 如博客中介绍 三、注意事项 1、管理员账号:admin密码:admin 数据库配置文件src\main\resources 下的 jdbc.properties 更改对应数据库连接配置 2、开发环境为IDEA...
开发工具 IDEA JDK1.8 TOMCAT 8.5 二、功能介绍 如博客中介绍 三、注意事项 1、管理员账号:admin密码:admin 数据库配置文件src\main\resources 下的 jdbc.properties 更改对应数据库连接配置 2、开发环境为IDEA...
开发工具 IDEA JDK1.8 TOMCAT 8.5 二、功能介绍 如博客中介绍 三、注意事项 1、管理员账号:admin密码:admin 数据库配置文件src\main\resources 下的 jdbc.properties 更改对应数据库连接配置 2、开发环境为IDEA...
介绍 我得到了tomcat 8.0的源代码,并由avenj在Intellij IDEA 14.1中对其进行了编译。 现在,如果您想阅读源代码,可以将其直接导入intellij。 结构 :二进制分发文件 :您可以通过svn签出的源代码... 运行main()方法
配置完成后,运行位于 src/main/cn/tycoding/下的SpringbootSeckillApplication中的main方法,访问 http://localhost:8080/seckill/ 进行API测试。 注意/db/sys_data.sql中秒杀商品的日期可能要修改,自行修改为...
配置完成后,运行位于 `src/main/cn/tycoding/`下的SpringbootSeckillApplication中的main方法,访问 `http://localhost:8080/seckill/` 进行API测试。 注意/db/sys_data.sql中秒杀商品的日期可能要修改,自行修改...
开发工具 IDEA JDK1.8 TOMCAT 8.5 具体功能 如博客中介绍, 三、注意事项 1、管理员账号:admin密码:admin 数据库配置文件src\main\resources 下的 jdbc.properties 更改对应数据库连接配置 2、开发环境为IDEA...