Я проанализировал сценарий запуска Tomcat ранее.Если вы запустите Tomcat из startup.bat, вы обнаружите, что основной метод в org.apache.catalina.startup.Bootstrap будет вызываться в конце, а последний переданный параметр командной строки start, то Здесь начинается анализ кода запуска.
Сначала посмотрите на код этого основного метода:
1 /**
2 * Main method and entry point when starting Tomcat via the provided
3 * scripts.
4 *
5 * @param args Command line arguments to be processed
6 */
7 public static void main(String args[]) {
8
9 if (daemon == null) {
10 // Don't set daemon until init() has completed
11 Bootstrap bootstrap = new Bootstrap();
12 try {
13 bootstrap.init();
14 } catch (Throwable t) {
15 handleThrowable(t);
16 t.printStackTrace();
17 return;
18 }
19 daemon = bootstrap;
20 } else {
21 // When running as a service the call to stop will be on a new
22 // thread so make sure the correct class loader is used to prevent
23 // a range of class not found exceptions.
24 Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
25 }
26
27 try {
28 String command = "start";
29 if (args.length > 0) {
30 command = args[args.length - 1];
31 }
32
33 if (command.equals("startd")) {
34 args[args.length - 1] = "start";
35 daemon.load(args);
36 daemon.start();
37 } else if (command.equals("stopd")) {
38 args[args.length - 1] = "stop";
39 daemon.stop();
40 } else if (command.equals("start")) {
41 daemon.setAwait(true);
42 daemon.load(args);
43 daemon.start();
44 } else if (command.equals("stop")) {
45 daemon.stopServer(args);
46 } else if (command.equals("configtest")) {
47 daemon.load(args);
48 if (null==daemon.getServer()) {
49 System.exit(1);
50 }
51 System.exit(0);
52 } else {
53 log.warn("Bootstrap: command \"" + command + "\" does not exist.");
54 }
55 } catch (Throwable t) {
56 // Unwrap the Exception for clearer error reporting
57 if (t instanceof InvocationTargetException &&
58 t.getCause() != null) {
59 t = t.getCause();
60 }
61 handleThrowable(t);
62 t.printStackTrace();
63 System.exit(1);
64 }
65
66 }
Демон здесь представляет собой статическую переменную-член в классе Bootstrap, а тип — Bootstrap. В комментарии к строке 10 указано, что переменная будет назначена после вызова метода init. Первоначально она будет нулевой, поэтому Bootstrap сначала создать экземпляр объекта, а затем вызвать метод init, код метода выглядит следующим образом:
1 /**
2 * Initialize daemon.
3 */
4 public void init()
5 throws Exception
6 {
7
8 // Set Catalina path
9 setCatalinaHome();
10 setCatalinaBase();
11
12 initClassLoaders();
13
14 Thread.currentThread().setContextClassLoader(catalinaLoader);
15
16 SecurityClassLoad.securityClassLoad(catalinaLoader);
17
18 // Load our startup class and call its process() method
19 if (log.isDebugEnabled())
20 log.debug("Loading startup class");
21 Class startupClass =
22 catalinaLoader.loadClass
23 ("org.apache.catalina.startup.Catalina");
24 Object startupInstance = startupClass.newInstance();
25
26 // Set the shared extensions class loader
27 if (log.isDebugEnabled())
28 log.debug("Setting startup class properties");
29 String methodName = "setParentClassLoader";
30 Class paramTypes[] = new Class[1];
31 paramTypes[0] = Class.forName("java.lang.ClassLoader");
32 Object paramValues[] = new Object[1];
33 paramValues[0] = sharedLoader;
34 Method method =
35 startupInstance.getClass().getMethod(methodName, paramTypes);
36 method.invoke(startupInstance, paramValues);
37
38 catalinaDaemon = startupInstance;
39
40 }
Я не буду здесь объяснять функцию кода предложение за предложением.В общем, этот метод в основном делает следующие вещи:
- Установите системные свойства catalina.home, catalina.base,
- Создайте загрузчики классов commonLoader, catalinaLoader, sharedLoader (по умолчанию эти три загрузчика классов указывают на один и тот же объект. Рекомендуется посмотреть на метод createClassLoader, который делает много чего, например загружает файлы в директорию, настроенную в catalina. свойства и пакет jar, родительский загрузчик последних двух загрузчиков является первым, и, наконец, регистрируется MBean, который может использоваться JVM для мониторинга объекта),
- Создайте экземпляр объекта org.apache.catalina.startup.Catalina, назначьте его статическому члену catalinaDaemon и вызовите метод setParentClassLoader объекта путем отражения с sharedLoader в качестве входного параметра.
Далее переходим к последнему параметру командной строки, как было сказано в начале статьи, start, таким образом будет выполняться код с 34 по 36 строки, а также будут выполняться методы load и start в классе Bootstrap.
Код метода загрузки выглядит следующим образом:
1 /**
2 * Load daemon.
3 */
4 private void load(String[] arguments)
5 throws Exception {
6
7 // Call the load() method
8 String methodName = "load";
9 Object param[];
10 Class paramTypes[];
11 if (arguments==null || arguments.length==0) {
12 paramTypes = null;
13 param = null;
14 } else {
15 paramTypes = new Class[1];
16 paramTypes[0] = arguments.getClass();
17 param = new Object[1];
18 param[0] = arguments;
19 }
20 Method method =
21 catalinaDaemon.getClass().getMethod(methodName, paramTypes);
22 if (log.isDebugEnabled())
23 log.debug("Calling startup class " + method);
24 method.invoke(catalinaDaemon, param);
25
26 }
Это вызов метода загрузки объекта catalinaDaemon посредством отражения Объект catalinaDaemon был создан в методе init выше.
Метод запуска аналогичен методу загрузки, а также вызывает метод запуска объекта catalinaDaemon посредством отражения:
1 /**
2 * Start the Catalina daemon.
3 */
4 public void start()
5 throws Exception {
6 if( catalinaDaemon==null ) init();
7
8 Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);
9 method.invoke(catalinaDaemon, (Object [])null);
10
11 }
В следующей статье будут проанализированы методы load и start в объекте catalinaDaemon, в котором будет затронута интересная тема — использование Digester.