下载源码

https://www.cnblogs.com/grasp/p/10061577.html

一般启动tomcat 都是使用 startup.bat

set "EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat"
...
call "%EXECUTABLE%" start %CMD_LINE_ARGS%

最终调用的是 catalina.bat, 在 270 行设置了tomcat 的启动主类

set _EXECJAVA=%_RUNJAVA%
set MAINCLASS=org.apache.catalina.startup.Bootstrap
set ACTION=start
set SECURITY_POLICY_FILE=
set DEBUG_OPTS=
set JPDA=

接下来我们看 Bootstrap 主类

public static void main(String args[]) {synchronized (daemonLock) {if (daemon == null) {Bootstrap bootstrap = new Bootstrap();try {bootstrap.init();} catch (Throwable t) {handleThrowable(t);t.printStackTrace();return;}daemon = bootstrap;} else {Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);}}//......
}

问题, 我们看源码一定要带着问题去看

new Bootstrap()  做了什么

bootstrap 没有显示构造器, 只有一个静态代码块, 设置了一些全局参数

public final class Bootstrap {//....static {// 从系统变量中获取一个user.dir, 这个值为工程目录, tomcat-src/String userDir = System.getProperty("user.dir");// 这个变量是从启动命令哪里获取的 -Dcatalina.home=catalina-homeString home = System.getProperty(Constants.CATALINA_HOME_PROP);File homeFile = null;if (home != null) {File f = new File(home);try {homeFile = f.getCanonicalFile();} catch (IOException ioe) {homeFile = f.getAbsoluteFile();}}if (homeFile == null) {// 获取 引导jar 包位置File bootstrapJar = new File(userDir, "bootstrap.jar");if (bootstrapJar.exists()) {File f = new File(userDir, "..");try {homeFile = f.getCanonicalFile();} catch (IOException ioe) {homeFile = f.getAbsoluteFile();}}}//....}
}

接下来我们进入 bootstrap.init()

public void init() throws Exception {// 初始化tomcat 类加载器initClassLoaders();// 设置当前线程的类加载器Thread.currentThread().setContextClassLoader(catalinaLoader);// 使用类加载器去加载类SecurityClassLoad.securityClassLoad(catalinaLoader);if (log.isDebugEnabled())log.debug("Loading startup class");// 创建Catalina实例Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");Object startupInstance = startupClass.getConstructor().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] = sharedLoader;// 设置Catalina的加载器Method method =startupInstance.getClass().getMethod(methodName, paramTypes);method.invoke(startupInstance, paramValues);catalinaDaemon = startupInstance;}
 

initClassLoaders()   初始化tomcat类加载器

tomcat 类加载器分为4种

  • commonLoader   tomcat 和 webApp 共同类的类加载器
  • catalinaLoader    加载唯独是tomcat的类
  • sharedLoader     加载webApp 共同的类
  • webAppLoader   加载webApp 独有的类

我们就看第一个里面的实现都做了些什么

commonLoader = createClassLoader("common", null);

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) {handleThrowable(t);log.error("Class loader creation threw exception", t);System.exit(1);}}private ClassLoader createClassLoader(String name, ClassLoader parent)throws Exception {// CatalinaProperties 就是 conf/catalina.properties// common.loader="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"String value = CatalinaProperties.getProperty(name + ".loader");if ((value == null) || (value.equals("")))return parent;// value 当前类加载器的加载范围value = replace(value);List<Repository> repositories = new ArrayList<>();// 拆分value, 变成集合, 理解就是,分割String[] repositoryPaths = getPaths(value);for (String repository : repositoryPaths) {// Check for a JAR URL repositorytry {@SuppressWarnings("unused")URL url = new URL(repository);repositories.add(new Repository(repository, RepositoryType.URL));continue;} catch (MalformedURLException e) {// Ignore}// Local repositoryif (repository.endsWith("*.jar")) {repository = repository.substring(0, repository.length() - "*.jar".length());repositories.add(new Repository(repository, RepositoryType.GLOB));} else if (repository.endsWith(".jar")) {repositories.add(new Repository(repository, RepositoryType.JAR));} else {repositories.add(new Repository(repository, RepositoryType.DIR));}}// 最终是一个 URLClassLoader 的实例return ClassLoaderFactory.createClassLoader(repositories, parent);}

回到  bootstrap.init() 的 SecurityClassLoad.securityClassLoad(catalinaLoader);

使用 catalinaLoader 加载类

public final class SecurityClassLoad {public static void securityClassLoad(ClassLoader loader) throws Exception {securityClassLoad(loader, true);}static void securityClassLoad(ClassLoader loader, boolean requireSecurityManager) throws Exception {if (requireSecurityManager && System.getSecurityManager() == null) {return;}loadCorePackage(loader);//....}private static final void loadCorePackage(ClassLoader loader) throws Exception {final String basePackage = "org.apache.catalina.core.";loader.loadClass(basePackage + "AccessLogAdapter");loader.loadClass(basePackage + "ApplicationContextFacade$PrivilegedExecuteMethod");//.....}
}

bootstrap.init() 再往下走, 创建Catalina 实例

public void init() throws Exception {//....// 反射创建Catalina实例Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");Object startupInstance = startupClass.getConstructor().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] = sharedLoader;// 反射调用 setParentClassLoader 设置Catalina的类加载器Method method =startupInstance.getClass().getMethod(methodName, paramTypes);method.invoke(startupInstance, paramValues);catalinaDaemon = startupInstance;
}

小结

  • bootstrap.init() 就到此为止
  • tomcat 源码还是比较简单的
  • new Bootstrap , 设置了一些环境变量, 确定了运行目录
  • bootstrap.init(), 创建tomcat 类加载, 设置类加载器, 加载类, 创建 Catalina 实例,
  • Catalina 与 Server 关系是一对一

下一章, 解析 server.xml 组件实例化

https://blog.csdn.net/weixin_42209307/article/details/108657869

(5.0) Tomcat 8 源码, 初始化 bootstrap相关推荐

  1. (5.2) Tomcat 8 源码, 初始化组件

    上一章, 实例化组件 接着我们上一章, 实例化组件之后开始, 不要迷路了 // Catalina.java public void load() {//... 省略实例化部分代码// 把Catalin ...

  2. 《MySQL 8.0.22执行器源码分析(3.2)关于HashJoinIterator》

    在本文章之前,应该了解的概念: 连接的一些概念.NLJ.BNL.HashJoin算法. 目录 关于join连接 probe行保存概念 Hashjoin执行流程(十分重要) HashJoinIterat ...

  3. vue 2.0响应式源码实践,麻麻,我再也不怕被面试官提问啦

    vue2.0/vue3.0响应式源码实践,麻麻,我再也不怕被面试官提问啦 写在前面 vue2.0响应式源码实现 1. 先创建一个对象 2.实现observer方法 3.接下来我们对observer函数 ...

  4. spring-boot-2.0.3启动源码篇二 - run方法(一)之SpringApplicationRunListener

    前言 Springboot启动源码系列还只写了一篇,已经过去一周,又到了每周一更的时间了(是不是很熟悉?),大家有没有很期待了?我会尽量保证启动源码系列每周一更,争取不让大家每周的期望落空.一周之中可 ...

  5. mosquitto客户端对象“struct mosquitto *mosq”管理下篇(mosquitto2.0.15客户端源码分析之四)

    文章目录 前言 5 设置网络参数 5.1 客户端连接服务器使用的端口号 `mosq->port` 5.2 指定绑定的网络地址 `mosq->bind_address` 5.3 客户端连接服 ...

  6. 基于Android7.0的Launcher3源码分析(1)——框架设计分析

    从事Android rom一年多,一直在负责 Launcher 相关的工作.最近打算写些文章记录下自己对这个模块的理解和源码实现的一些解析. 这些文章将会基于 Android 7.0 的 Launch ...

  7. EntLib.com Forum – 开源ASP.NET论坛 v4.0(提供源码下载)

    EntLib.com Forum – 开源ASP.NET论坛 v4.0(提供源码下载)  EntLib.com Forum 开源ASP.NET 论坛系统是EntLib.com 小组基于YAF开源论坛进 ...

  8. jsoncpp-src-0.5.0.tar.gz 源码错误!!!!

    近期在做毕设,使用到了JsonCpp0.5.0版本号的源码! 依照网上的安装配置教程,搭建好环境后就能够使用了! 在这里就不浪费空间去将怎样搭建开发环境了!请大家去google一下就好了! 在解析一个 ...

  9. php的setinc方法,thinkphp3.2.0 setInc方法 源码全面解析

    搜索热词 我们先来看一下setInc的官方示例: 需要一个字段和一个自增的值(默认为1) 我们通过下面这个例子来一步步分析他的底层是怎么实现的: class TestController extend ...

最新文章

  1. 「情报局41」人工智能的下一个目标是什么?了解业务用例
  2. [ZT]经典月薪4000过日子
  3. Linux别名的创建删除【alias】和【unalias】
  4. ASP.NET中App_Code,App_Data等文件夹的作用
  5. c语言中左右对齐的作用,c语言中右对齐的符号
  6. Where is ABAP Netweaver HTTP 304 not modified set
  7. Button的设置及各种属性
  8. .NET Core 3.0愈加成熟,微软将不再把.NET Framework API移植给它
  9. 决定项目生死的关键:是商业模式,而不是成本
  10. 微服务发展的历史_“美丽新羌 光照未来” 新羌社区开展微视频宣传片拍摄活动...
  11. 娱乐开源commons-email-1.x包
  12. 微软拆分 VS Code 中 Python 扩展,部分功能可独立下载
  13. 突发!Java首度“落泪”,愿永久祝福Python!网友:我也想哭!
  14. IBM ThinkPad错误代码列表
  15. 贪吃蛇系列之七——有吃的啦
  16. GPS模块编程之NMEA0183协议
  17. 查看计算机安装程序版本,Product Key Explorer(程序密钥显示工具)
  18. Linux学习总结(62)——什么是堡垒机?为什么需要堡垒机?
  19. 深度神经网络主要模型,深度神经网络预测模型
  20. Ubuntu安装与Xshell的配置

热门文章

  1. github样式错乱 解决
  2. pyx文件 生成pyd 文件用于 cython调用
  3. OpenCV优化:图像的遍历4种方式
  4. Cissp-【第4章 通信与网络安全】-2021-3-14(476页-542页)
  5. java中的localDate类_java8-LocalDate类
  6. Java报错:java.math.BigDecimal cannot be cast to java.lang.String
  7. 怎样在计算机页面加密,怎么给文件加密并加密后隐藏起来?
  8. python 进度条程序_Python:显示程序运行进度条
  9. python虚拟环境的作用_python虚拟环境搭建
  10. 计算机技能测试小学老师,小学信息技术教师专业技能测习题-20210726171728.docx-原创力文档...