`
wu_quanyin
  • 浏览: 208167 次
  • 性别: Icon_minigender_1
  • 来自: 福建省
社区版块
存档分类
最新评论

Tomcat源码---启动.初始化(加载类包)分析三

阅读更多

一,启动

Tomcat是从org.apache.catalina.startup.Bootstrap#main()开始启动.代码如下:

 

  public static void main(String args[]) {

        if (daemon == null) {
            daemon = new Bootstrap();
            try {
                daemon.init();
            } catch (Throwable t) {
                t.printStackTrace();
                return;
            }
        }

        try {
            String command = "start";
            if (args.length > 0) {
                command = args[args.length - 1];
            }

            if (command.equals("startd")) {
                args[0] = "start";
                daemon.load(args);
                daemon.start();
            } else if (command.equals("stopd")) {
                args[0] = "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 {
                log.warn("Bootstrap: command \"" + command + "\" does not exist.");
            }
        } catch (Throwable t) {
            t.printStackTrace();
        }

    }

 

 从以上可以很清楚的看懂tomcat是通过参数的不同进行相应的命令调用.

 启动之前要进行相应的init()初始化,进行相应的环境设置以及包的加,以下我们查看下init的方法.

二,初始化(Bootstrap#init())

 

 public void init()throws Exception
    {

        // Set Catalina path
        setCatalinaHome();
        setCatalinaBase();

       //将tomcat/lib下的jar包进行加载
        initClassLoaders();

        //将classload设置进线程,以便我们使用时进行调用
        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();

        // 将sharedLoader设置进Catalina类中
        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,

setCatalinaHome();
 setCatalinaBase();

 

     根据源代码主要设置了以下路径:

 

     System.setProperty("catalina.home", System.getProperty("user.dir"));

2,

    //将tomcat/lib下的jar包进行加载
        initClassLoaders();

    tomcat中的加载方式是:

   a) Set up classloaders 

commonLoader (common)-> System Loader

sharedLoader (shared)-> commonLoader -> System Loader

catalinaLoader(server) -> commonLoader -> System Loader

 

    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);
        }
    }
 

   createClassLoader的加载方式:

   //这个类的主要作用是从 catalina.properties读取信息进行加载

 private ClassLoader createClassLoader(String name, ClassLoader parent)
        throws Exception {
       
   // 获取与ClassLoader相关的属性值,可能为 common.loader,server.loader, shared.loader  
        // 定义在org/apache/catalina/startup/catalina.properties  
        String value = CatalinaProperties.getProperty(name + ".loader");
        if ((value == null) || (value.equals("")))
            return parent;

        ArrayList repositoryLocations = new ArrayList();
        ArrayList repositoryTypes = new ArrayList();
        int i;
 
        StringTokenizer tokenizer = new StringTokenizer(value, ",");
        while (tokenizer.hasMoreElements()) {
            String repository = tokenizer.nextToken();

            // Local repository
            boolean replace = false;
            String before = repository;
            while ((i=repository.indexOf(CATALINA_HOME_TOKEN))>=0) {
                replace=true;
                if (i>0) {
                repository = repository.substring(0,i) + getCatalinaHome() 
                    + repository.substring(i+CATALINA_HOME_TOKEN.length());
                } else {
                    repository = getCatalinaHome() 
                        + repository.substring(CATALINA_HOME_TOKEN.length());
                }
            }
            while ((i=repository.indexOf(CATALINA_BASE_TOKEN))>=0) {
                replace=true;
                if (i>0) {
                repository = repository.substring(0,i) + getCatalinaBase() 
                    + repository.substring(i+CATALINA_BASE_TOKEN.length());
                } else {
                    repository = getCatalinaBase() 
                        + repository.substring(CATALINA_BASE_TOKEN.length());
                }
            }
            if (replace && log.isDebugEnabled())
                log.debug("Expanded " + before + " to " + replace);

            // Check for a JAR URL repository
            try {
                URL url=new URL(repository);
                repositoryLocations.add(repository);
                repositoryTypes.add(ClassLoaderFactory.IS_URL);
                continue;
            } catch (MalformedURLException e) {
                // Ignore
            }

            if (repository.endsWith("*.jar")) {
                repository = repository.substring
                    (0, repository.length() - "*.jar".length());
                repositoryLocations.add(repository);
                repositoryTypes.add(ClassLoaderFactory.IS_GLOB);
            } else if (repository.endsWith(".jar")) {
                repositoryLocations.add(repository);
                repositoryTypes.add(ClassLoaderFactory.IS_JAR);
            } else {
                repositoryLocations.add(repository);
                repositoryTypes.add(ClassLoaderFactory.IS_DIR);
            }
        }

        String[] locations = (String[]) repositoryLocations.toArray(new String[0]);
        Integer[] types = (Integer[]) repositoryTypes.toArray(new Integer[0]);
 
        ClassLoader classLoader = ClassLoaderFactory.createClassLoader
            (locations, types, parent);

        // Retrieving MBean server
        MBeanServer mBeanServer = null;
        if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
            mBeanServer =
                (MBeanServer) MBeanServerFactory.findMBeanServer(null).get(0);
        } else {
            mBeanServer = MBeanServerFactory.createMBeanServer();
        }

        ///用jmx对该classloader进行管理
        // Register the server classloader
        ObjectName objectName =
            new ObjectName("Catalina:type=ServerClassLoader,name=" + name);
        mBeanServer.registerMBean(classLoader, objectName);

        return classLoader;

    }
 

根据以上的设置tomcat主要对类加载作了以下方式:

 

b) Load startup class (reflection)

org.apache.catalina.startup.Catalina

setParentClassloader -> sharedLoader

Thread.contextClassloader -> catalinaLoader

---------------------------------------------------------------------------------------------------------------------------

以下对java中的类加载进行归纳:

可参考文章:http://blog.chenlb.com/2009/06/java-classloader-architecture.html

 

以上用线程设置classloader的目的是:

java默认的线程上下文类加载器是 系统类加载器(AppClassLoader)。

 

   使用Thread.currentThread().setContextClassLoader(classloader)时,线程上下文 Classloader就变成了指定的Classloader了。此时,在本线程或子线程的任意一处地方,调用Thread.currentThread(). getContextClassLoader(),都可以得到前面设置的Classloader。

 

如果要扩展classloader对类包进行加载也可扩展URLCloassLoader类

 

1
0
分享到:
评论

相关推荐

    apache-tomcat-7.0.81-src 源码免费下载

    4. **生命周期管理**:在`common`和`shared`目录中,可以看到Tomcat如何管理和控制各个组件的生命周期,包括启动、停止、初始化和销毁等过程。 5. **配置管理**:Tomcat的配置文件通常位于`conf`目录下,源码解析...

    apache-tomcat-7.0.88-src.tar

    1. **Catalina**: 这是Tomcat的核心组件,负责处理Servlet和JSP的生命周期管理,包括加载、实例化、初始化、服务和销毁。Catalina提供了基于容器的概念,每个Web应用程序都有一个独立的容器。 2. ** Coyote**: 这是...

    apache-tomcat-7.0.92-src.zip

    - 理解Catalina的生命周期管理,包括Servlet的加载、初始化、服务和销毁过程。 - 学习Jasper的工作流程,了解JSP如何被转换成Servlet并执行。 - 探索Coyote的连接器架构,了解如何处理HTTP请求和响应。 - 研究Tomcat...

    tomcat 7 源码分析-4 server初始化背后getServer().init()

    【标题】:“Tomcat 7 源码分析 - 4 server初始化背后getServer().init()” 在这篇文章中,我们将深入探讨Apache Tomcat 7服务器的内部工作机制,重点关注`getServer().init()`方法在服务器初始化过程中的作用。...

    apache-tomcat-6.0.29-src.zip

    4. **生命周期管理**:在`org.apache.catalina`包下,你可以看到关于容器对象(如Context、Host、Engine)的生命周期管理代码,包括初始化、加载、启动、停止和卸载等阶段。 5. **JSP编译**:Jasper负责将JSP文件...

    apache-tomcat-7.0.99-src.zip

    每个Tomcat组件都有其特定的生命周期阶段,如初始化、启动、停止和销毁。 4. **容器概念**:Tomcat使用容器的概念来组织和管理Web应用。`Host`、`Engine`、`Context`和`Wrapper`构成了容器层次,它们分别对应域名、...

    apache-tomcat-9.0.8-src可直接导入eclipse的源码

    Bootstrap负责初始化Tomcat的基本组件,如加载配置文件、创建并启动Catalina容器,以及执行其他必要的初始化任务。当你在Eclipse中设置断点在这个类中时,可以观察和理解Tomcat如何从启动到服务运行的全过程。 在...

    tomcat 源码分析系列文档

    9. "Tomcat启动源代码分析.pdf":深入到启动脚本和Java代码,解释了从启动脚本开始,如何初始化和启动Tomcat服务的全过程。 10. "tomcat类加载机制.pdf":再次聚焦于Tomcat的类加载机制,可能深入到更多细节和技巧...

    apache-tomcat-6.0.18源码

    - `org.apache.catalina.startup.Bootstrap`:Tomcat的启动入口,负责加载服务器配置并初始化Catalina。 - `org.apache.catalina.core.StandardServer`:服务器对象,管理其他服务器组件。 - `org.apache....

    servlet源码 servlet-api-src javax.servlet.Servlet源码

    在Web应用启动时,Servlet容器(如Tomcat)会根据配置加载Servlet,并调用`init()`进行初始化。当收到请求时,容器会调用`service()`,根据请求类型分发到相应的do方法。当Web应用关闭或者Servlet不再需要时,容器会...

    apache-tomcat-9.0.1源码

    Tomcat源码中实现了Servlet的生命周期管理,包括加载、初始化、服务、销毁等阶段。`org.apache.catalina.core.StandardWrapper`类负责管理单个Servlet实例的生命周期。 3. **请求处理**: `org.apache.coyote`包...

    tomcat源码分析

    解析这个脚本有助于理解Tomcat的启动过程,包括如何设置系统路径、JVM参数以及初始化Tomcat的各种配置。 2. **Tomcat启动遇到的常见问题** 在启动Tomcat时,可能会遇到端口被占用、配置文件错误、权限问题等。了解...

    TOMCAT源码分析(启动框架).pdf

    ### TOMCAT源码分析——启动框架详解 #### 一、前言 TOMCAT作为一款广泛使用的开源Java Servlet容器,其内部实现复杂且强大。本文旨在深入剖析TOMCAT的启动框架及其整体架构,帮助读者更好地理解其工作原理。...

    fast-spring-boot-源码.rar

    源码中的`EnvironmentPostProcessor`接口用于在Spring环境初始化后进行额外的配置。 10. **测试支持** 提供了方便的测试工具和配置,如`@SpringBootTest`注解,简化了单元测试和集成测试的编写。 通过深入理解...

    tomcat8源码

    Tomcat中的组件都遵循生命周期接口,包括初始化、启动、停止和销毁四个阶段。这些接口使得开发者可以在各个阶段添加自定义逻辑。 4. **类加载机制** Tomcat使用自定义的类加载器来加载Web应用中的类,以实现不同...

    tomcat源码

    1. **Servlet生命周期**:Tomcat如何加载、初始化、服务、销毁Servlet,以及ServletConfig和ServletContext的角色。 2. **线程池管理**:Tomcat如何使用Executor(`Executor`接口和`ThreadPoolExecutor`实现)来...

    tomcat7源码下载

    1. Bootstrap:启动过程始于Bootstrap类,它加载并初始化Server对象。 2. Server:Server对象包含了全局配置信息,并管理Service组件。 3. Service:Service包含一个或多个Connector(如Coyote)和一个Engine。 4...

    spring-boot-1.5.x.zip

    6. ** SpringApplication**:这是Spring Boot的入口类,负责初始化ApplicationContext并启动应用。源码中可以学习它是如何处理命令行参数,加载配置,以及启动应用的。 7. **Spring Profiles**:源码可以帮助我们...

    Tomcat源码研究.pdf

    ### Tomcat源码研究知识点概览 #### 1.1 Catalina.bat脚本解析 - **脚本功能**:`catalina.bat`是Tomcat启动过程中的关键脚本之一,其主要作用在于构建合适的Java命令行参数,进而启动Tomcat服务。此脚本根据环境...

    tomcat源码,servlet-api源码

    《深入理解Tomcat源码与Servlet-API》 Tomcat,作为Apache软件基金会的顶级项目,是Java Servlet和JavaServer Pages(JSP)的开源Web应用服务器,被广泛应用于中小型企业的Web服务部署。7.0.59版本是Tomcat的一个...

Global site tag (gtag.js) - Google Analytics