Source code analysis of tomcat 4.1.30 Startup Process

Source: Internet
Author: User
A few days ago, in order to solve sinpool's multi-thread problem, I read the source code of tomcat 4.1.30,
It focuses on starting tomcat. I personally feel that the source code of tomcat is clearly written and easy to understand. It is worth looking.
(I have read some of the struts code before, And I feel more classic)
Then I sorted out the code after reading it and attached it below. I hope it will be useful to others. I also hope that interested siblings can read the optimistic code,
It is certainly beneficial to your own program design and code quality.

1. startup class (class containing the main () method ):
Org. apache. catalina. startup. Bootstrap
This class is the tomcat startup class and mainly performs startup according to the following steps:
1. Create three ClassLoader: common, catalina, and share. They correspond to the three Classloader of tomcat.
The classloader has a research brother. It is certainly no stranger to this. Among them, the common classloader is the classloader (that is
Classloader corresponding to the CLASSPATH set in the system environment variables), while catalina classloader is the sub-classloader of common and tomcat
The classloader of the required classes, while the shared classloader is also the sub-classloader of the common, which is the same as the classloader of catalina,
Shared classloader is used to publish the webapp classloader under all tomcat servers (each web app has its own classloader)
Classloader. These three classloader read the classes and lib directories in the common, server, and shared directories under tomcat home respectively,
Class Libraries and resources under your control are initialized.

2. Create an instance of the org. apache. catalina. startup. Catalina class and call its process method. The reflection technology of java is used here.
Then, call the process method of the instance and pass the command line parameters received by Bootstrap. The Bootstrap class does not parse the command line parameters that are passed to it.
Of course, you also set the parent classloader using the setParentClassLoader method before calling process. Here is an important introduction to classloader.
Feature, that is, if the classloader wants to load a class, instead of looking for it first, it delegates the task to its parent classloader first, and then its parent classloader
If this is not found, assign this task to your parent classloader until you find the top-level classloader, and then find the corresponding definition of the class to be loaded from top to bottom,
If the classloader is found first, it will return. So join the three classloader in tomcat described in the first point above, and you will be able to understand the classloader category of tomcat.
This is especially important for program developers. I think the brothers who have used tomcat or other app servers must have encountered a class that clearly exists but cannot be found,
Or you can always find an old version. I think it is mainly because of multiple locations, or where there are cognominal classes :-)

Ii. org. apache. catalina. startup. Catalina class
Now the program is transferred to the process Method in the org. apache. catalina. startup. Catalina class.
This method first sets the home and base directories of catalina, and then parses the command line parameters through the arguments method,
Finally, call the execute () method to start the server. The execute method is very simple. It is based on the command line parameters parsed by arguments,
Determine whether to start the server or stop the server. If it is a start server, call the start method. The following describes the start () method,
Because it is a place where tomcat is actually started :-)
1. The start method first uses Digester (this is a toolkit used in jakarta commons to parse xml files. It was originally used to parse struts configuration files,
Later, it was abstracted as a general tool, mainly used to parse xml configuration files and automatically generate corresponding class instances according to some defined rule. For details, refer
To set the parsing rules for the tomcat configuration file/conf/server. xml.
Then, use the following code to convert the data in the configuration file to an instance in the memory:

Code:
        File file = configFile();

try {

InputSource is =

new InputSource("file://" + file.getAbsolutePath());

FileInputStream fis = new FileInputStream(file);

is.setByteStream(fis);

digester.push(this);

digester.parse(is);

fis.close();

} catch (Exception e) {

System.out.println("Catalina.start: " + e);

e.printStackTrace(System.out);

System.exit(1);

}


The conversion rules are as follows (I will only give a brief introduction), such
A. Server corresponds to an org. apache. catalina. core. StandardServer class (this class is very important and is the implementation of tomcat server)
B. Server/GlobalNamingResources generate the org. apache. catalina. deploy. NamingResources class.
The familiar class configuration for listening to port 8080 is as follows:
C. Server/Service/Connector: org. apache. catalina. connector. http. HttpConnector
D. Server/Service/Engine/Host/Context/: org. apache. catalina. core. StandardContext
For more information, see the Digester document in jakarta commons and org. apache. catalina. startup. Catalina.
The createStartDigester method in this class.
After this code, a variable named server has been generated using the Digester tool, which will be used to start tomcat.
2. The program then sets some servers before startup, such as redirecting log output streams. The server startup code is as follows:

Code:
        // Start the new server

if (server instanceof Lifecycle) {

try {

server.initialize();

((Lifecycle) server).start();

try {

// Register shutdown hook

Runtime.getRuntime().addShutdownHook(shutdownHook);

} catch (Throwable t) {

// This will fail on JDK 1.2. Ignoring, as Tomcat can run

// fine without the shutdown hook.

}

// Wait for the server to be told to shut down

server.await();

} catch (LifecycleException e) {

System.out.println("Catalina.start: " + e);

e.printStackTrace(System.out);

if (e.getThrowable() != null) {

System.out.println("----- Root Cause -----");

e.getThrowable().printStackTrace(System.out);

}

}

}


The server variable was just created during Digester parsing.
(I saw this place for a long time, but later I found out that it was because I didn't know Digester much before ).
Then we can see that the server is started in three steps:
1. initialize method for server startup Initialization
2. The start method is used to start the server, mainly the service in the server and the connector in the service.
3. await method waiting for server shutdown
Here, I will focus on introducing the initialize method and start method.
Initialize method:
There is only one major task here, which is to call the initialize method of all the services defined in the server one by one,
The initialize method of each service calls the initialize method of all ctor defined in this service,
The initialize method of ctor Ctor is to create a serversocket to accept the client request.
If you look at conf/server. xml in tomcat, you can find that tomcat only defines a service called Tomcat-Standalone by default,
Only three ctor s are defined by default:
1. http ctor on port 8080
2. http ssl ctor on port 8443
3. Coyote/JK2 AJP 8009 Connector at Port 1.3
I think you must be familiar with these three ports.
Start method:
In this method, tomcat is very important, and I think it is also a highlight of tomcat design, that is, Lifecycle, which is like a bus ).
I want you to know that when you design a program, you should always separate several modules based on one principle to block the code or
Some code with similar functions is organized into a module, which is clear. For example, a purchase, sales, inventory, and finance module will exist in an invoicing system,
I think many people have also encountered this situation, that is, even though the modules are divided, if another customer says they only want the sales modules after the development, I think
Most developers must be dumpfounded, because although modules were designed at the time, these modules were written in an intertwined way and each other's interface definitions
It is very vague. Basically, the method of directly calling another module is inseparable. The Lifecycle Design Concept of tomcat can solve this problem.
In part, its principle is like a bus. For example, after a module completes an action, for example, after the sales module creates an order, it must directly call
The inventory module's api locks some of the inventory (I just give an example, the actual business is not necessarily like this), so the sales module needs to rely on the inventory module. However
Bus mode. After the order is created, we can send an order creation message to the bus, and the bus has an event registration mechanism, which is a bit like the swing event, listener,
For example, the inventory module has a listener that is used to listen to the messages created by the order for processing, so that the two modules do not depend on each other. If you are interested, look at jcp.
A topic called infobus.
Of course, this method only solves one aspect of effectively reducing the module coupling degree (because sometimes it is necessary to directly call the interface of another module,
For example, the inventory module must directly describe the information of a sales order, so it is necessary to define an interface class to describe the detailed information of the order, which is not explained here,
If you have time, you can post a topic to discuss this issue with everyone:-) do not explicitly trigger an action of another module, but send messages through the bus mechanism,
Each module has its own handler that listens to the bus and processes events of interest. This is tomcat's Lifecycle.
Return to the start method:
1. It first sends two events to the bus: BEFORE_START_EVENT and START_EVENT
2. Call the start method of each service, and then send the AFTER_START_EVENT message to notify other programs.
The start method of the service performs the following operations:
1. Send the BEFORE_START_EVENT message
2. Call the start method of the container.
3. Call the start method of ctor.
4. Finally, send the AFTER_START_EVENT message.
The start method of ctor Ctor is the socket programming that everyone is most familiar with. For details, refer to the org. apache. catalina. connector. http. HttpConnector class,
It mainly uses multi-thread operations in java to initialize an HttpProcessor thread pool, and then blocks each HttpProcessor thread through the wait method, only
When an http request is received, the HttpProcessor thread is activated through the y method to process the user's http request.

So far, I have briefly introduced the Startup Process of tomcat 4.1.30. Next time I have a chance, I will take a look at the management code of its webapp deploy and share it with you. If you have any comments on my post, you are also welcome to criticize and correct it. If you are interested, you can discuss it with me:--) It's time to go to bed late, I wish you a pleasant work on Monday.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.