1JVM类加载机制
JVM的ClassLoader通过Parent属性定义父子关系,可以形成树状结构。其中引导类、扩展类、系统类三个加载器是JVM内置的。
它们的作用分别是:
1)引导类加载器:使用native代码实现,在rt.jar等包中搜索运行JVM所需的类,例如java.lang等包下的类。
2)扩展类加载器:负责载入标准扩展目录中的类,例如Sun的JVM的扩展目录是/jdk/jre/lib/ext。
3)系统类加载器:默认的类加载器,搜索环境变量CLASSPATH中指明的路径。
2双亲委派模型
既然类加载器是树形结构,那加载类时就需要定义类到底由当前加载器还是父加载器去搜索加载。
JVM加载模型的工作过程是:
如果一个类加载器收到了类加载的请求,它不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成。
每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的引导类加载器中。
只有父类加载无法完成这个请求时,子类加载器才会尝试自己去加载。
为什么要让父类加载器优先去加载呢?试想如果子类加载器先加载,那么我们可以写一些与java.lang包中基础类同名的类,
然后再定义一个子类加载器,这样整个应用使用的基础类就都变成我们自己定义的类了。这样就有很大的安全隐患!
所以自己编写类加载器时,如果没有特殊原因,一定要遵守类加载的双亲委派模型。
3Tomcat类加载器
Tomcat基本遵守了JVM的委派模型,但也在自定义的类加载器中做了细微的调整,以适应Tomcat自身的要求。
下面是Tomcat类加载器WebappClassLoader的核心方法loadClass()的源码。
它覆盖了父类URLClassLoader中的方法,改变了默认的类加载顺序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
public synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
Class clazz = null ;
// (0) Check our previously loaded local class cache
clazz = findLoadedClass0(name);
if (clazz != null ) {
if (log.isDebugEnabled())
log.debug( " Returning class from cache" );
if (resolve)
resolveClass(clazz);
return (clazz);
}
// (0.1) Check our previously loaded class cache
clazz = findLoadedClass(name);
if (clazz != null ) {
if (log.isDebugEnabled())
log.debug( " Returning class from cache" );
if (resolve)
resolveClass(clazz);
return (clazz);
}
// (0.2) Try loading the class with the system class loader, to prevent
// the webapp from overriding J2SE classes
try {
clazz = system.loadClass(name);
if (clazz != null ) {
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
// Ignore
}
boolean delegateLoad = delegate || filter(name);
// (1) Delegate to our parent if requested
if (delegateLoad) {
if (log.isDebugEnabled())
log.debug( " Delegating to parent classloader1 " + parent);
ClassLoader loader = parent;
if (loader == null )
loader = system;
try {
clazz = loader.loadClass(name);
if (clazz != null ) {
if (log.isDebugEnabled())
log.debug( " Loading class from parent" );
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
}
// (2) Search local repositories
if (log.isDebugEnabled())
log.debug( " Searching local repositories" );
try {
clazz = findClass(name);
if (clazz != null ) {
if (log.isDebugEnabled())
log.debug( " Loading class from local repository" );
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
// (3) Delegate to parent unconditionally
if (!delegateLoad) {
if (log.isDebugEnabled())
log.debug( " Delegating to parent classloader at end: " + parent);
ClassLoader loader = parent;
if (loader == null )
loader = system;
try {
clazz = loader.loadClass(name);
if (clazz != null ) {
if (log.isDebugEnabled())
log.debug( " Loading class from parent" );
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
}
throw new ClassNotFoundException(name);
}
|
具体分析一下:首先findLoadedClass0()和findLoadedClass()分别从本地和父类加载器的缓存中查找当前要加载的类是否已经加载过了。
之后为了避免上面提到的安全问题,Tomcat类加载器会将加载请求委派给系统类加载器。接下来根据delegate变量的设置,决定是先由自己加载,
还是先由父类加载器去加载。
这里介绍一下背景,上面的WebappClassLoader是对应一个Web应用的类加载器,其父亲是Tomcat的lib的加载器。所以delegate变量的值,
决定了Tomcat的类加载顺序。
4Tomcat6的加载顺序
所以在Tomcat 6中默认情况下,不是完全按照先Tomcat的lib再Web应用的lib这种顺序去加载类。
Jar包的加载顺序是:
1)JRE中的Java基础包
2)Web应用WEB-INF\lib下的包
3)Tomcat\lib下的包
如果想要在Web应用间共享一些Jar包,则不仅需要将公共包放在Tomcat的lib下,还要删掉Web应用lib中的包,
否则Tomcat启动时还是会优先加载Web应用lib下的包的。
ps:题外话,如果想要自己指定一个Tomcat\lib和Web应用lib之外的ClassPath,除了修改Tomcat启动脚本外,
可以为不同Web应用的Context指定一个VirtualWebappLoader,但源码注释中写到不推荐在生产环境中使用。
相关推荐
《深入剖析 Tomcat》这一资料为读者提供了深入理解Tomcat架构、内部机制及优化方法的机会。通过对Tomcat的学习,开发者不仅能够更好地部署和管理Java Web应用,还能针对实际应用场景做出合理的性能调优决策。希望...
【深入剖析Tomcat——完整目录】 Tomcat是Apache软件基金会的Jakarta项目中的一个核心项目,是一个开源的、免费的Web应用服务器,主要用于运行Java Servlet和JavaServer Pages(JSP)。Tomcat以其轻量级、易用性...
《深入剖析Tomcat》这本书是Java开发者们探索Tomcat服务器内部机制的重要参考资料,它带领读者逐步揭开Tomcat的神秘面纱,深入理解其工作原理。Tomcat作为一款轻量级的开源Web应用服务器,广泛应用于各种Java Web...
《深入剖析Tomcat》是Java开发者提升技能、深入理解Web服务背后机制的宝贵资源。通过源码分析,读者将能够更高效地部署和维护基于Tomcat的应用,同时也能为使用其他Java EE技术(如Spring、Struts)打下坚实的基础。...
《深入剖析Tomcat》是一本专注于Java Web服务器Tomcat的深度解析资料,包含了对Tomcat源码的细致分析。此资料包提供了多个文件,包括"深入剖析Tomcat源码.rar","深入剖析tomcat.pdf",以及"apache-tomcat-7.0.32-...
《深入剖析Tomcat源码》是一本专门为Java开发者和系统管理员设计的专业书籍,它旨在帮助读者深入了解Apache Tomcat服务器的工作原理及其源代码。Tomcat作为一款广泛应用的开源Servlet容器,其内部机制对于优化Web...
6. **类加载机制**:Tomcat的类加载器是如何工作的,包括Catalina、Shared、Webapp等类加载器的层次关系,以及如何避免类冲突。 7. **部署与热部署**:Tomcat如何解析WAR文件并自动部署应用,以及如何实现应用的热...
《深入剖析Tomcat》这本书是Java Web开发领域中的一本经典之作,主要针对Apache Tomcat服务器进行了详尽的解析和深入的研究。Tomcat是一款开源、轻量级的Servlet容器,广泛应用于各种Java Web应用程序的部署。这本书...
《Tomcat深入剖析》这本书是理解Apache Tomcat服务器工作原理的宝贵资料,它由美国作者撰写并被翻译成中文,适合各个层次的开发者阅读。通过深入学习,读者能够对Tomcat的内部机制有全面而深入的理解,从而更好地...
根据提供的信息,“深入剖析Tomcat 中文版 .pdf”这一标题和描述暗示这是一份关于Apache Tomcat服务器软件深入分析的中文文档。由于提供的部分内容主要包含重复的资源下载链接,并未涉及具体的知识点,因此本解析将...
【描述】:“深入剖析Tomcat,超清版,带标签”这一描述暗示了我们将会深入理解Tomcat服务器的内部工作机制,包括其核心原理、配置优化以及问题排查等方面。"超清版"可能指的是资源的清晰度,意味着提供的资料详尽且...
《深入剖析Tomcat》这本书是理解Apache Tomcat服务器工作原理的重要参考资料,非扫描版的特点意味着内容清晰、可读性强,方便读者复制和引用。Tomcat作为一款广泛应用的开源Java Servlet容器,它的性能优化、配置...
《深入剖析Tomcat》这本书是Java开发者们探索Web服务器内部工作原理的重要参考资料,它详细解析了Tomcat的源代码,帮助我们理解这个流行的开源Servlet容器的运作机制。Tomcat是Apache软件基金会的一个项目,它是Java...
【深入剖析Tomcat】 Tomcat是一款广泛使用的开源Java Servlet容器,由Apache软件基金会开发和维护。它是基于Java的Web应用程序的服务器,特别是用于部署和运行Java Servlets和JSP(JavaServer Pages)技术。本篇...
这些章节将帮助读者了解Tomcat的启动和运行机制,包括其类加载机制、内存管理、线程模型等。对于每一个技术点,作者都尽量采用了浅显易懂的语言,让即使没有深厚背景知识的读者也能够接受。 最后,随着本书的学习,...
《深入剖析TOMCAT+Tomcat权威指南(第二版)》是两本关于Apache Tomcat服务器的重量级著作,它们详尽地阐述了Tomcat的内部工作机制、配置、优化以及故障排查等方面的知识,旨在帮助读者从新手到专家,全面掌握这款广泛...
在对Tomcat的这些主要组件有了初步了解之后,接下来深入剖析每一个组件的具体功能和实现方式是理解Tomcat的关键。例如: - Catalina 作为Servlet容器的核心,需要负责Servlet的生命周期管理,包括加载、初始化、...
### 深入剖析Tomcat高清版 #### Tomcat概览与核心机制解析 Tomcat作为一款免费且开源的Servlet容器,在Java Web开发领域占据着举足轻重的地位。其核心功能在于支持Java Servlet和JavaServer Pages (JSP)技术,从而...
《深入剖析Tomcat+源码.zip》是一个包含深入解析Tomcat服务器工作原理的资源包,主要围绕《How Tomcat Works》这本书的中文版展开。Tomcat是Apache软件基金会的项目,是一个开源的Java Servlet容器,它实现了Java...