ClassLoader of Tomcat Research

zhaozj2021-02-12  159

ClassLoader of Tomcat Research

Before studying Tomcat, it is generally analyzed the Tomcat overall structure by the existing UML tool, but to analyze Tomcat's process must start from the analysis of Tomcat's Startup. Tomcat starts starting from the parsing bat file, the BAT file finally calls org.apache.catalina.startup.bootstrap start class load.

A.tomcat ClassLoader:

Tomcat's own class loader (ClassLoader)

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

| Bootstrap |

| | | | |

| System |

| | | | |

Common |

| / / |

| Catalina Shared |

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

among them:

- Bootstrap - Loaded into JVM comes with $ JAVA_HOME / JRE / LIB / EXT / *. JAR

- SYSTEM

1. Load $ CATALINA_HOME / BIN / BOOTSTRAP.JAR Initialize Tomcat, execute the main method

2. $ java_home / lib / Tools.jar Sun tool class, including compiling JSP tool classes for servlet

- Classes under this directory although it is visible to Tomcat and all Web App. But the text of the web app should not

Put in this directory, all unpackable class is under $ catalina_home / common / classes,

Have a packaged jar

$ CATALINA_HOME / COMMONS / ENDORSED and $ CATALINA_HOME / COMMON / LIB, the default situation will

Contains the following packages:

1. JNDI.JAR JNDI API interface, this package is only loaded in Java 1.2, and the version JDK after 1.3 has been

Automatic loading.

2. Naming-commit.jar JNDI interface Implementation class, Tomcat uses these classes to use contexts in memory.

3. Naming-resources.jar JNDI implementation, Tomcat uses them to locate the static resource of the Web App.

4. Servlet.jar Servlet, JSP API

5. Xerces.jar XML parser, specific web apps can be overwritten in your own / web -inf / lib.

- Catalina is loaded into Tomcat to implement all interfaces, these classes are completely invisible to the web app, all unpackable classes

All jar packs of $ CATALINA_HOME / Server / Classes are under $ catalina_home / server / lib. One

This ClassLoader will take a few packages below:

1. Catalina.jar servlet container Tomcat implementation package

2. Jakarta-regexp-x.y.jar regular expression, use it when filtering

3. Servlets-xxxxx.jar servlet support package

4. Tomcat-coyote.jar Tomcat's COYOTE connection implementation package

5. Tomcat-jk.jar Web Server binding package, allow Tomcat to bind Apache and so on as Web Server

6. Tomcat-jk2.jar function

7. Tomcat-Util.jar Tomcat tool class, may be used by some connection

8. Tomcat-Warp.jar is used in Apache Server packages

- Shared loads all the classes visible to all Web App, which is not visible to Tomcat. All unpackable classes are

$ Catalina_home / shared / classes All jar packs under $ catalina_home / lib. The default includes the following packages:

1. Jasper-compiler.jar JSP compiler, compile JSP for servlet

2. Jasper-runtime.jar JSP (compiled into a servlet) running support package

3. Naming-factory.jar Support Web App Using JNDI Package

-Webappx Web App ClassLoader, when the Web App is deployed is ClassLoader being created. All Class is

Under Web-INF / CLASSES, all JARs under Web-Inf / Lib.

Pay special attention to the implementation of Web App's own ClassLoader and different:

It tries to load from the web app own directory. If it fails, please ask the Agent of the ClassLoader

This allows class load between different web apps to interfere with each other. In addition, Tomcat Server uses Catalina

ClassLoader, a general web app uses WebApp ClassLoader.

II. Org.apache.catalina.Startup.bootstrap

This class is the implementation entry point of Tomcat, we focus on the following two methods:

1. InitclassLoaders, create a ClassLoader hierarchy.

Private vidinlosliners () {

Try {

ClassLoaderFactory.SetDebug (Debug);

// Create a Common ClassLoader, no parent ClassLoader

CommonLoader = CreateClassLoader ("Common", NULL);

// Create Catalina ClassLoader, Father ClassLoader is Common

CatalinaAloader = CreateClassLoader ("Server", CommonLoader;

// Create Shared ClassLoader, Father ClassLoader is Common

SharedLoader = CreateClassLoader ("Shared", CommonLoader;

} catch (throwable t) {

LOG ("Class Loader Creation Threw Exception", T);

System.exit (1);

}

}

2. CreateClassLoader, responsible for specific creation work

Define Common, Server, Shared in $ Catalina_Home / Conf / Catalina.properties

ClassLoader loads the path of the class and some of the security permissions for some packages.

// Common Loading the path

Common.Loader = $ {catalina.home} / common / classes,

$ {catalina.home} / common / endorsed / *. jar, $ {catalina.home} / common / lib / *. jar

// Server loaded the path

Server.Loader = $ {catalina.home} / server / classes,

$ {catalina.home} / server / lib / *. jar

// Shared loads the path

Shared.Loader = $ {catalina.base} / shared / classes,

$ {catalina.base} / shared / lib / *. jar

/ **

* param name: loading name

* Param Parent: Father Loader

* ClassLoader resources three types:

* 1. Classes that is not packaged is generally a directory

* 2. Packaged JAR directory

* 3. Network resources, usually a JAR package on the Internet (Applet often uses such a loader) * /

Private ClassLoader CreateClassLoader (String Name, ClassLoader Parent)

Throws exception {

/ / Get the configuration information of the Loader from Catalina.properties

String value = Catalinaproperties.getProperty (Name ".loader");

IF ((value == null) || (Value.equals ("))))

Return Parent;

// Classes directory

Arraylist unpackedList = new arraylist ();

// jar directory

ArrayList packedlist = new arraylist ();

// Network path designated package

ArrayList Urllist = new arraylist ();

StringTokenizer tokenizer = New StringTokenizer (Value, ",");

/ / Current Loader This type of load

While (tokenizer.hasmoreElements ()) {

String repository = tokenizer.nextToken ();

// Check for a jar url repository

Try {

/ / If it is a network path append URL

Urllist.add (new url);

CONTINUE;

} catch (Malformedurlexception E) {

// ignore

}

// Local path

Boolean packed = false;

//$ (Catalina.home}

IF (repository.startswith) {

Repository = getCataLinaHome ()

repository.substring (catalina_home_token.Length ());

//$ (Catalina.Base}

} else if (repository.startswith) {Catalina_Base_token) {

Repository = getCataLinaBase ()

repository.substring (catalina_base_token.length ());

}

/ ** After the above operation, replace the path in Catalina.properties into an absolute path * /

// If it is a JAR file path

IF (repository.endswith)) {

Packed = true;

Repository = repository.substring

(0, repository.length () - "* .jar" .length ());

}

IF (PACKED) {

PackedList.Add (New file (repository));

} else {

UnpackedList.Add (New file (repository));

}

}

File [] unpacked = (file []) unpackedList.toArray (new file [0]);

File [] packed = (file []) PackedList.toArray (new file [0]);

URL [] URLS = (URL []) URLLST.TOARRAY (New URL [0]);

// Call Factory method Create ClassLoaderReturn ClassLoaderFactory.createClassLoader

(Unpacked, Packed, URLS, PARENT)

}

Three. ClassLoaderFactory

ClassLoaderFactory is a factory class for creating ClassLoader, which is relatively simple.

// Parameter meaning no longer explain, see the above analysis

Public Static ClassLoader CreateClassLoader (File Unpacked [],

File packed [],

URL URLS [],

ClassLoader Parent)

Throws exception {

IF (debug> = 1)

Log ("CREANG New Class Loader);

// construct the "class path" for this class loadinger

ArrayList List = New ArrayList ();

// Construct the URL of the File protocol through the class directory, and append List

IF (unpacked! = NULL) {

For (INT i = 0; I

FILE FILE = Unpacked [i];

IF (! file.exiss () ||! file.canread ())

CONTINUE;

IF (debug> = 1)

LOG ("Including Directory or Jar"

file.getabsolutePath ());

URL URL = New URL ("File", NULL,

File.getcanonicalPath () file.separator);

List.add (url.tostring ());

}

}

/ / Remove all JAR files in all jar directories, constructed URL one by one, and append LIST

IF (Packed! = NULL) {

For (int I = 0; i

File Directory = Packed [i];

IF (! Directory.Indirectory () ||! Directory.exists () ||

Directory.canRead ())

CONTINUE;

String filenames [] = Directory.list ();

For (int J = 0; j

String filename = filenames [j] .tolowercase ();

IF (! filename.endswith (". jar")))

CONTINUE;

File File = New File (Directory, FileNames [J]);

IF (debug> = 1)

LOG ("including jar file" file.getabsolutePath ());

URL URL = New URL ("File", NULL,

File.getcanonicalPath ());

List.add (url.tostring ());

}

}

}

// Resources of adding network paths

IF (URLS! = null) {

For (int i = 0; i

List.add (URLS [i] .tostring ());

}

// Call StandardClassLoader to create a real Loader

String array [] = (String []) list.toarray (new string ";

StandardClassLoader ClassLoader = NULL;

IF (parent == null)

ClassLoader = New StandardClassLoader (Array);

Else

ClassLoader = New StandardClassLoader (Array, Parent);

ClassLoader.SetDelegate (TRUE);

Return (ClassLoader);

}

StandardClassLoader

StandardClassLoader inherits the ability of URLClassLoader, the URLClassLoader class has the ability to load classes from the hard disk, or load the JAR file locally or remotely. This class also implements the RELOADER interface, which provides the function of automatically reloading class. We mainly look at this class below and method:

1. Constructor STANDARDCLASSLOADER

/ **

* @Param repositories URL array, see analysis

* @Param Parent Father Loader

* /

Public StandardClassLoader (String repositories [], classloader parent) {

// Call the constructor of the parent class

// The parent class constructor will use the converted repositories to generate an instance of UrlClassPath

// UCP is a class member variable ucp = new urlclasspath (URLS);

// urlclasspath is Sun's extension package, unable to continue tracking

Super (Repositories), PARENT

THIS.PARENT = Parent;

this.system = getSystemClassLoader ();

SecurityManager = system.getsecuritymanager ();

IF (repositories! = null) {

For (int i = 0; i

// Treat URL

AddRepositoryInternal (Repositories [i]);

}

}

AddRepositoryInternal

/ **

* @Param repository To process URL

* /

protected void addrepositoryinternal (string repository) {

UrlstreamHandler StreamHandler = NULL;

String protocol = parseprotocol (repository);

IF (Factory! = NULL)

StreamHandler = Factory.createURLStreamHandler (Protocol);

// The current URL is a JAR file that points to the local or network, verifying the correctness of JAR.

// The following code seems useless to verify the correctness of the JAR file, if the JAR file is incorrectly throwing an exception.

IF (! repository.endswith (file.separator) &&! repository.endswith ("/")) {

Jarfile Jarfile = NULL;

Try {

Manifest Manifest = NULL;

// JAR protocol

IF (repository.startswith ("jar:")) {URL URL = New URL (Null, Repository, StreamHandler);

JarurlConnection conn =

JARURLCONNECTION) URL.OpenConnection ();

Conn.setallowuserinteraction (false);

Conn.setdoinput (TRUE);

Conn.setdoOutput (false);

CONN.CONNECT ();

JARFILE = conn.getjarfile ();

// File protocol

} else if (repository.startswith ("file: //")) {

Jarfile = new jarfile (repository.substring (7));

// file

Else IF (repository.startswith ("File:")) {

Jarfile = new jarfile (repository.substring (5));

// Local path JAR file

Else IF (repository.endswith (". jar")) {

URL URL = New URL (NULL, Repository, StreamHandler);

UrlConnection conn = url.openConnection ();

JarinputStream JIS =

New jarinputstream (conn.getinputStream ());

Manifest = jis.getManifest ();

/ / Other cases are wrong

} else {

Throw new IllegalargumentException

("AddRepositoryInternal: Invalid URL '"

Repository "'");

}

} catch (throwable t) {

T.PrintStackTrace ();

Throw new IllegalargumentException

("AddRepositoryInternal:" T);

} finally {

IF (JARFILE! = null) {

Try {

Jarfile.Close ();

} catch (throwable t) {}

}

}

}

/ / Add a list of URLs inside the system to the system

Synchronized (repositories) {

String results [] = new string [repositories.length 1];

System.Arraycopy (Repositories, 0, Results, 0, Repositories.length);

RESULTS [Repositories.Length] = repository;

Repositories = results;

}

}

Repositories is a class variable that stores all URL lists.

Through this method, we can basically determine a few points:

1. ClassLoader can put a path to "/" or File.seParetor as a resource loaded

2. You can also use the JAR file on the local or online as a resource that is loaded into the Class, and any other form of resources (such as ZIP) is illegal.

3. The resources on the network must be in the form of a jar package

At this point, the constructor of the ClassLoader ends. 3.LoadClass method

Above we did a lot of work, the purpose is to build a ClassLoader, build the purpose of ClassLoader is to use it to load you want, so the LoadClass method is our focus, and it can completely unlock the mystery of ClassLoader. *

* Param name: Type name to load

* PARAM Resolve: If it is true, resolveclass

* /

Public Class LoadClass (String Name, Boolean Resolve)

Throws classnotfoundexception {

IF (debug> = 2)

LOG ("LoadClass (" Name "," Resolve ")")

Class Clazz = NULL;

/ / Check the cache, see if the class has been loaded

Clazz = FindloadedClass (Name);

IF (Clazz! = NULL) {

IF (debug> = 3)

LOG ("Returning Class from Cache";

IF (resolve)

ResolVeclass (Clazz);

Return (CLAZZ);

}

// If it is a Java package system ClassLoader takes loading

IF (Name.StartSwith) {

ClassLoader Loader = system;

Clazz = loader.loadclass (name);

IF (Clazz! = NULL) {

IF (resolve)

ResolVeclass (Clazz);

Return (CLAZZ);

}

Throw New ClassNotFoundException (NAME);

}

/ / Check if there is permission to do LOAD for the package corresponding to the class, the load of the package is defined in Catalina.Properties

IF (SecurityManager! = NULL) {

INT i = name.lastIndexof ('.');

IF (i> = 0) {

Try {

SecurityManager.checkpackageAccess (name.substring (0, i));

} catch (securityException se) {

String Error = "Security Violation, Attempt to Use"

"RESTRICTED CLASS:" Name;

System.out.println (Error);

SE.PrintStackTrace ();

Log (Error);

Throw new classnotfoundexception (Error);

}

}

}

/ / Do this class delegate to the parent ClassLoader to load

IF (delegate) {

IF (debug> = 3)

Log ("Delegating to Parent ClassLoader);

ClassLoader Loader = Parent;

IF (loader == null)

Loader = system;

Try {

Clazz = loader.loadclass (name);

IF (Clazz! = NULL) {

IF (debug> = 3)

LOG ("Loading Class from Parent");

IF (resolve)

ResolVeclass (Clazz);

Return (CLAZZ);

}

} catch (classnotfoundexception e) {

;

}

}

// Load this class locally

IF (debug> = 3)

"Searching Local Repositories";

Try {

// Call Tomcat to realize the core method of ClassLoader to find classes

Clazz = FindClass (Name);

IF (Clazz! = NULL) {

IF (debug> = 3)

LOG ("Loading Class from Local Repository);

IF (resolve)

ResolVeclass (Clazz);

Return (CLAZZ);

}

} catch (classnotfoundexception e) {

;

}

// If the class is not already delegated to the parent class, use the system Loader to load

IF (debug> = 3)

Log ("Delegating to Parent ClassLoader);

ClassLoader Loader = Parent;

IF (loader == null)

Loader = system;

Try {

Clazz = loader.loadclass (name);

IF (Clazz! = NULL) {

IF (debug> = 3)

LOG ("Loading Class from Parent");

IF (resolve)

ResolVeclass (Clazz);

Return (CLAZZ);

}

} catch (classnotfoundexception e) {

;

}

}

// this class was not found

Throw New ClassNotFoundException (NAME);

}

4. FindClass method

Public Class Findclass (String Name) throws classnotfoundexception {

IF (debug> = 3)

"" FindClass (" Name ") ");

// Check the definition of the package, we don't have a deeper

IF (SecurityManager! = NULL) {

INT i = name.lastIndexof ('.');

IF (i> = 0) {

Try {

IF (debug> = 4)

Log ("SecurityManager.checkpackageDefinition");

SecurityManager.checkPackageDefinition (Name.Substring (0, i));

} catch (exception se) {

IF (debug> = 4)

Log ("-> eXception -> ClassNotfoundException", SE);

Throw New ClassNotFoundException (NAME);

}

}

}

// If you cannot locate the local category, please request the parent class loading

// (Throws ClassNotFoundException if it is not found)

Class Clazz = NULL;

Try {

IF (debug> = 4)

Log ("Super.FindClass (" Name ")"); TRY {

Synchronized (this) {

Clazz = FindloadedClass (Name);

IF (Clazz! = NULL)

Return Clazz;

/ / Request parent class loading

Clazz = Super.FindClass (Name);

}

} catch (accessControlException ace) {

Throw New ClassNotFoundException (NAME);

} catch (runtimeexception e) {

IF (debug> = 4)

LOG ("-> RuntimeException RethRown", E);

Throw e;

}

IF (Clazz == Null) {

IF (debug> = 3)

LOG ("-> returning classnotfoundexception);

Throw New ClassNotFoundException (NAME);

}

} catch (classnotfoundexception e) {

IF (debug> = 3)

LOG ("-> passing on classnotfoundexception", e);

Throw e;

}

// Return The Class We Have Located

IF (debug> = 4)

"Returning Class" CLAZZ);

IF ((Debug> = 4) && (Clazz! = null))

Log ("Loaded By" Clazz.getClassLoader ());

Return (CLAZZ);

}

5. Father (URLClassLoad)'s FindClass method

As we have said, UrlclassLoader has the function of loading Class from local or network from local or network.

Briefly, the FindClass method simply invokes the RUN method of PriviledexceptionAction, and we don't have to understand this class, just look at the blue part of the blue.

Protected Class Findclass (FINAL STRING NAME) THROWS CLASSNOTFOUNDEXCEPTION {

Try {

Return (Class)

AccessController.doprivileged (new priviledexception () {

Public Object Run () THROWS ClassNotFoundException {

// Replace the class name to hard disk absolute path

String path = name.replace ('.', '/').Concat(".class ");

/ / See the instructions for UCP variables

/ / This call is mainly converted to resource (regardless of conversion details)

Resource res = ucp.getResource (path, false);

IF (res! = null) {

Try {

/ / Generate Class by Class name and class resource

Return DefineClass (Name, RES);

} catch (ioexception e) {

Throw New ClassNotFoundException (Name, E);

}

} else {

Throw New ClassNotFoundException (NAME);

}

}

}, ACC);

} catch (java.security.privilegedactionexception pae) {

THROW (ClassNotFoundException) pae.getexception ();

}

}

6. DEFINECLASS method

This method mainly calls the JVM's Native method to build a Class object. We don't have to clear the details of this class. We have to know that JVM constructs a Class object. We just pay attention to the blue part of the following.

/ **

* Param Name: Classification

* Param res: This parameter is obtained through the UCP variable, UCP is built by the URL of us, the URL is

* ClassLoader Load Class path

* For example, our hard-constructed StandClassLoader is to get resource

* Resource is the JVM used to construct the Class must condition

* /

Private class defineclass (string name, resource res) throws oException {

INT i = name.lastIndexof ('.');

URL URL = Res. GetcoDesourceURL ();

IF (i! = -1) {

String pkgname = name.substring (0, i);

// Check if package already loaded.

Package Pkg = getPackage (pkgname);

Manifest man = res. maxManifest ();

IF (pkg! = null) {

// package find, so check package sealing.

IF (pkg.issealed ()) {

// Verify That Code Source Url Is The Same.

IF (! pkg.Isessealed (url)) {

Throw new securityException

Sealing Violation: Package Pkgname "Is Sealed");

}

} else {

// Make Sure We are not attempting to seal the package

// at this code source url.

IF ((man! = null) && issealed (pkgname, man)) {

Throw new securityException

"Sealing Violation: Can't Seal Package Pkgname

": already loaded");

}

}

} else {

IF (man! = null) {

DefinePackage (Pkgname, Man, URL);

} else {

DefinePackage (Pkgname, NULL, NULL, NULL, NULL, NULL, NULL, NULL);

}

}

}

// The following is a Class of the JVM through binary code.

Byte [] b = res.getbytes ();

Java.security.cert.certificate [] CERTS = res. maxpertificates ();

CODESOURCE CS = New Codesource (URL, CERTS);

Return DefineClass (Name, B, 0, B.LENGTH, CS);

At this point, we completely decipher Tomcat's ClassLoader. Let's draw a ClassLoader constructor and the process of loadClass. It is no longer painting the sequence map, just simply represents the call relationship between each method. In fact, we can see it from above True to create a ClassLoader key role is a defineClass method for urlclassloader and jvm. These methods have been packaged or local calls. If you need further research, you need more energy. After reading this process, I believe that each person can customize themselves. ClassLoader required, such as encryption of ClassLoader.

Bootsstrap

CreateClassLoader (constructing three URLs,)

INitclassLoaders (initialized three classloaders)

ClassLoaderFactory

CreateClassLoader (Trimators, true URL)

StandardClassLoader

LoadClass

Findclass query class

UrlclassLoader

FINDCLASS

DefineClass

Reference:

Http://jakarta.apache.org/tomcat/tomcat-4.1-doc/class-loader-howto.html

Remarks:

Tomcat described herein is based on 5.0.

I really like the open source server of Tomcat, I want to study their mystery, I feel very thin, I hope to contact me, let everyone crack the Apache myth. (Chen777716@hotmail.com)

转载请注明原文地址:https://www.9cbs.com/read-7124.html

New Post(0)