简体   繁体   中英

How Tomcat Classloader separates different Webapps object scope in same JVM?

Since Tomcat can load more than one webapp at once, and those webapps can work separately, and do not disturb each other, and they work in same JVM. So I am very confused about how tomcat handle The Object scope in the same JVM.

For example I have a singleton object in both of the two different Webapps, and tomcat will generate two different singleton Object for each. I always thought that the singleton object have only one object in the same JVM, but in tomcat JVM there maybe has two or more.


I have read some info about the ClassLoader, Tomcat has its own WebAppClassLoader to load webapps. So does it mean the Object Scope here is the ClassLoader or am I wrong. Does anyone know about this or can give me some info about tomcat work memory layout?

All the secrets is behind those ClassLoader instances.

The state of the class (like all static variables, byte code and so on) is scoped by the class loader which loads that class (the class is identified by its name and the class loader loading the class. This is not exactly a scope, but thinking as scope usually helps understanding this better).

So if a class is loaded by two different class loaders, this class exists twice within the VM, it has two sets of static fields, can have different byte code (like different method implementations) and all such. "Normal" Java applications have all classes loaded by a class loader hierarchy and every class is only loaded once.

For more complex scenarios, you will need different behaviours. Sometimes you want to isolate a library from messing with your code (like plugins in eclipse or web applications in an application server).

The basic idea to isolate your program from other classes is to load those with an extra class loader and use a lot of reflection. If you want to read up on this have a look at Oracle's documentation on ClassLoaders or OSGI .

Tomcat (and a lot of other web containers / application servers) load the application with separate ClassLoader hierarchies. This isolates all classes against other (web) applications and thus also makes sure, that singletons, different class versions and all this stuff does not collide.

Remember that a class in Java is identified by its fully qualified name and the classloader that loaded it. Tomcat uses separate classloaders for each context (web application) that you deploy, thus keeping them separate. In addition, the system classloader loads the tomcat specific libraries and JVM bootstrap loader load the Java core libraries.

One thing that always gets left out when talking about singletons, is that a singleton can have only one instance per classloader . A ClassLoader limits class visibility, so the same class can exist under several different classloaders in the same VM. This allows you, among other things, to have different versions of jars loaded at the same time.

This question: Java Class Loaders seems to have some nice links and resources for further studying.

In normal Java applications when a classloader is asked to load a class it forst delegates the request to it's parent class loader and then loads it if parent class loaders cannot find the requested class.

For web application servers this slightly differs. There are generally different class loader for each web app deployed in a web application server like tomcat. For Tomcat it looks like below -

在此输入图像描述

So for web apps class loading resource happens in following order -

  1. Bootstrap classes of your JVM (Core java classes)
  2. /WEB-INF/classes of your web application
  3. /WEB-INF/lib/*.jar of your web application
  4. System class loader classes (Tomcat / Classpath specific classes)
  5. Common class loader classes (classes common to all web apps)

But note if web application class loader is configured with delegate="true" then order is changed -

  1. Bootstrap classes of your JVM (Core java classes)
  2. System class loader classes (Tomcat / Classpath specific classes)
  3. Common class loader classes (classes common to all web apps)
  4. /WEB-INF/classes of your web application
  5. /WEB-INF/lib/*.jar of your web application

For more details you can check Apache Tomcat's Class Loader HOW-TO page.

The "ID" of a class in the JVM consists of the fully qualified class name and the class loader that was used to load it. This means, if you load two classes with the same name by different class loaders they are considered different classes.

So a singleton would be singleton for a classloader - in a container/JVM; as a container/JVM might have multiple classloaders.

  1. Different App in tomcat using different classloader to seperate. For example app1 using ClassLoaderA, app2 using classloaderB.
  2. Each class will use its own classloader to load other classes. So if ClassA.class references ClassB.class then ClassB needs to be on the classpath of the classloader of ClassA, or its parents. For example In app1, com.exmaple.test1 loaded from ClassLoaderA. And com.exmaple.test1 want to new com.exmaple.test2(). By default It use its own classloader ClassLoaderA to load com.exmaple.test2. So In the view of com.exmaple.test1 it can only see its own classpath's class(app1/webapp/classes or app1/webapp/lib). And In app2, It will see a different view.
  3. In summary learn classloader you must understand the delegation model. And the visibility is the child can see the parent. but the parent can not see the child and the sibling can not see the sibling. So we can isolate different app.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM