Java Tomcat Classloader 如何在同一个 JVM 中分离不同的 Webapps 对象范围?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19559210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How Tomcat Classloader separates different Webapps object scope in same JVM?
提问by Winston
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.
由于Tomcat可以同时加载多个webapp,而且这些webapp可以单独工作,互不干扰,并且在同一个JVM中工作。所以我很困惑 tomcat 如何处理同一个 JVM 中的 Object 范围。
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.
例如我在两个不同的 Webapps 中都有一个单例对象,tomcat 会为每个生成两个不同的单例对象。我一直认为单例对象在同一个 JVM 中只有一个对象,但在 tomcat JVM 中可能有两个或更多。
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?
我已经阅读了一些关于 ClassLoader 的信息,Tomcat 有自己的 WebAppClassLoader 来加载 webapps。那么这是否意味着这里的对象范围是 ClassLoader 还是我错了。有没有人知道这个或者可以给我一些关于tomcat工作内存布局的信息?
采纳答案by Matthias
All the secrets is behind those ClassLoader
instances.
所有的秘密都在这些ClassLoader
实例的背后。
The state of the class (like all static variables, byte code and so on) is scoped by the class loader which loads that class (a class is identified in JVM by its fully qualiflied name and the class loader loading the class. This is not exactly a scope, but thinking as scope usually helps understanding this better).
类的状态(如所有静态变量、字节码等)由加载该类的类加载器(一个类在 JVM 中通过其完全限定名称和加载该类的类加载器来标识。这不是完全是一个范围,但将范围视为范围通常有助于更好地理解这一点)。
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. Note that these two objects cannot be cast to each other even their names are identical. "Normal" Java applications have all classes loaded by a class loader hierarchy and every class is only loaded once.
所以如果一个类被两个不同的类加载器加载,这个类在 VM 中存在两次,它有两组静态字段,可以有不同的字节码(如不同的方法实现)等等。请注意,即使它们的名称相同,这两个对象也不能相互转换。“普通”Java 应用程序具有由类加载器层次结构加载的所有类,并且每个类只加载一次。
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).
对于更复杂的场景,您将需要不同的行为。有时您希望将库与您的代码隔离开来(例如 Eclipse 中的插件或应用程序服务器中的 Web 应用程序)。
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 ClassLoadersor OSGI.
将程序与其他类隔离的基本思想是使用额外的类加载器加载这些类并使用大量反射。如果您想详细了解这一点,请查看 Oracle 关于ClassLoaders或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.
Tomcat(以及许多其他 Web 容器/应用程序服务器)使用单独的 ClassLoader 层次结构加载应用程序。这将所有类与其他(Web)应用程序隔离开来,从而确保单例、不同的类版本和所有这些东西不会发生冲突。
回答by Kayaman
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.
在谈论单例时总是被忽略的一件事是,单例每个类加载器只能有一个实例。AClassLoader
限制类的可见性,因此同一个类可以存在于同一 VM 中的多个不同类加载器下。这使您可以同时加载不同版本的 jar。
This question: Java Class Loadersseems to have some nice links and resources for further studying.
这个问题:Java Class Loaders似乎有一些不错的链接和资源供进一步研究。
回答by Henry
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.
JVM 中类的“ID”由完全限定的类名和用于加载它的类加载器组成。这意味着,如果您通过不同的类加载器加载具有相同名称的两个类,则它们被视为不同的类。
回答by kpentchev
Remember that a class in Java is identified by its fully qualified nameandthe classloaderthat 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.
请记住,Java 中的类由其完全限定名称和加载它的类加载器标识。Tomcat 为您部署的每个上下文(Web 应用程序)使用单独的类加载器,从而使它们保持独立。此外,系统类加载器加载 tomcat 特定的库,JVM 引导加载器加载 Java 核心库。
回答by Raúl
So a singleton would be singleton for a classloader - in a container/JVM; as a container/JVM might have multiple classloaders.
因此,对于类加载器来说,单例就是单例——在容器/JVM 中;因为容器/JVM 可能有多个类加载器。
回答by Aniket Thakur
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.
在普通 Java 应用程序中,当要求类加载器加载类时,它首先将请求委托给它的父类加载器,然后在父类加载器找不到请求的类时加载它。
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 -
对于 Web 应用程序服务器,这略有不同。部署在像 tomcat 这样的 Web 应用程序服务器中的每个 Web 应用程序通常都有不同的类加载器。对于 Tomcat,它如下所示 -
So for web apps class loading resource happens in following order -
因此,对于 Web 应用程序类加载资源按以下顺序发生 -
- Bootstrap classes of your JVM (Core java classes)
- /WEB-INF/classes of your web application
- /WEB-INF/lib/*.jar of your web application
- System class loader classes (Tomcat / Classpath specific classes)
- Common class loader classes (classes common to all web apps)
- JVM 的引导类(核心 java 类)
- 您的 Web 应用程序的 /WEB-INF/classes
- 您的 Web 应用程序的 /WEB-INF/lib/*.jar
- 系统类加载器类(Tomcat / Classpath 特定类)
- 通用类加载器类(所有 Web 应用程序通用的类)
But note if web application class loader is configured with delegate="true"
then order is changed -
但请注意,如果配置了 Web 应用程序类加载器,delegate="true"
则更改顺序 -
- Bootstrap classes of your JVM (Core java classes)
- System class loader classes (Tomcat / Classpath specific classes)
- Common class loader classes (classes common to all web apps)
- /WEB-INF/classes of your web application
- /WEB-INF/lib/*.jar of your web application
- JVM 的引导类(核心 java 类)
- 系统类加载器类(Tomcat / Classpath 特定类)
- 通用类加载器类(所有 Web 应用程序通用的类)
- 您的 Web 应用程序的 /WEB-INF/classes
- 您的 Web 应用程序的 /WEB-INF/lib/*.jar
For more details you can check Apache Tomcat's Class Loader HOW-TOpage.
有关更多详细信息,您可以查看 Apache Tomcat 的Class Loader HOW-TO页面。
回答by xiaojieaa
- Different App in tomcat using different classloader to seperate. For example app1 using ClassLoaderA, app2 using classloaderB.
- 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.
- 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.
- tomcat 中的不同应用程序使用不同的类加载器进行分离。例如 app1 使用 ClassLoaderA,app2 使用 classloaderB。
- 每个类将使用自己的类加载器来加载其他类。因此,如果 ClassA.class 引用 ClassB.class,则 ClassB 需要位于 ClassA 或其父类的类加载器的类路径上。例如在 app1 中,com.exmaple.test1 从 ClassLoaderA 加载。而 com.exmaple.test1 想要新的 com.exmaple.test2()。默认情况下它使用自己的类加载器 ClassLoaderA 来加载 com.exmaple.test2。所以在com.exmaple.test1的视图中只能看到自己的classpath的class(app1/webapp/classes or app1/webapp/lib)。而在 app2 中,它会看到不同的视图。
- 总之,学习类加载器您必须了解委托模型。可见性是孩子可以看到父母。但是父母看不到孩子,兄弟姐妹也看不到兄弟姐妹。所以我们可以隔离不同的应用程序。