Tomcat类加载
一.为什么会有类加载
1.在类加载阶段,虚拟机需要完成以下3件事情
1)通过一个全限类定名来获取此类的二进制字节流
2) 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
3)在内存中生成一个代表这个类的java.lang.Class 对象,作为方法区这个类的各种数据结构访问入口
2.虚拟机将类加载过程分为三个步骤:装载(Load),链接(Link)和初始化(Initialize)链接又分为三个步骤,如下图所示:

2)链接:
验证:确保被加载类的正确性;(验证不过会抛出 java.lang.VerifyError或其子类异常)
准备:为类的静态变量分配内存,并将其初始化为默认值;
解析:把类中的符号引用转换为直接引用;
3)初始化:为类的静态变量赋予正确的初始值;
那为什么我要有验证这一步骤呢?首先如果由编译器生成的class文件,它肯定是符合JVM字节码格式的,但是万一有高手自己写一个class文件,让JVM加载并运行,用于恶意用途,就不妙了,因此这个class文件要先过验证这一关,不符合的话不会让它继续执行的,也是为了安全考虑吧。
准备阶段和初始化阶段看似有点牟盾,其实是不牟盾的,如果类中有语句:private static int a = 10,它的执行过程是这样的,首先字节码文件被加载到内存后,先进行链接的验证这一步骤,验证通过后准备阶段,给a分配内存,因为变量a是static的,所以此时a等于int类型的默认初始值0,即a=0,然后到解析(后面在说),到初始化这一步骤时,才把a的真正的值10赋给a,此时a=10。
在上述的整个过程中 链接(Link)和初始化(Initialize) 都是由虚拟机完成的,而装载则虚拟机则允许开发者自定义完成。
二.Java虚拟机类加载
Java虚拟机提供了三个类加载器
1.启动类加载器:Bootstrap ClassLoader,跟上面相同。它负责加载存放在JAVA_HOME\jre\lib(JAVA_HOME代表JDK的安装目)下,或被-Xbootclasspath参数指定的路径中的,并且能被虚拟机识别的类库(如rt.jar,所有的java.*开头的类均被Bootstrap ClassLoader加载)。启动类加载器是无法被Java程序直接引用的。
2.扩展类加载器: Extension ClassLoader,该加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载JAVA_HOME\jre\lib\ext目录中,或者由java.ext.dirs系统变量指定的路径中的所有类库(如javax.*开头的类),开发者可以直接使用扩展类加载器。
3.系统类加载器: Application ClassLoader,该类加载器由sun.misc.Launcher$AppClassLoader来实现,它负责加载用户类路径ClassPath (System.getProperty("java.class.path"))所指定路径下的类,开发者可以直接使用该类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
三.自定义类加载器
除了上面三个类加载器外,开发者还可以自定义类加载器,自定义类加载器需要实现 ClassLoader这个抽象类,可以选择重载 loadClass 或者 findClass方法。
一个自定义类加载器的例子
package com.dianping.loader;
import java.io.InputStream;
public class CustomerLoader extends ClassLoader {
public CustomerLoader() {
}
public CustomerLoader(ClassLoader parent) {
super(parent);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
try {
Class c = findLoadedClass(name);
if (c != null) return c;
if (getParent() != null) {
try {
c = getParent().loadClass(name);
} catch (ClassNotFoundException e) {
}
}
if (c == null) {
String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
InputStream in = getClass().getResourceAsStream(fileName);
if (in == null) {
return super.loadClass(name);
}
byte[] bytes = new byte[in.available()];
in.read(bytes);
c = defineClass(name, bytes, 0, bytes.length);
}
return c;
} catch (Exception e) {
throw new ClassNotFoundException(name);
}
}
}
四、类加载的双亲委任模型
双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。 这里类加载器之间的父子关系一般不会以继承(Inheritance)的关系来实现,而是都使用组合(Composition)关系来复用父加载器的代码。
双亲委任可以解决了类加载过程中的安全性问题,如果定义了一个Java基础类库中的一个类,使用双亲委任模型保证了Java基础类的加载由上层类加载器优先加载。这样可以确保即使用户编写了一个java.lang.Object的类也不会影响虚拟机加载rt.jar下的java.lang.Object的类。
当然双亲模型只是一个规范,tomcat并不是完全按照双亲模型规范的。
五、Tomcat类加载
在tomcat中类的加载稍有不同,tomcat并没有完全遵守双亲模型

1.在tomcat中 会初始化三个类加载器 commonLoader, catalinaLoader, sharedLoader 这三个类加载器都是继承 URLClassLoader这个类
加载类的路径是 ${tomcat_home}/conf/catalina.properties 文件配置的
catalinaLoader 对应的配置是 server.loader ,sharedLoader对应的是 shared.loader
默认的情况server.loader 和 shared.loader 都是没有配置,所以catalinaLoader,和 sharedLoader 其实都是 commonLoader ,他们父类加载器都是sun.misc.Launcher$AppClassLoader系统类加载器
#
#
# List of comma-separated paths defining the contents of the "common"
# classloader. Prefixes should be used to define what is the repository type.
# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute.
# If left as blank,the JVM system loader will be used as Catalina's "common"
# loader.
# Examples:
# "foo": Add this folder as a class repository
# "foo/*.jar": Add all the JARs of the specified folder as class
# repositories
# "foo/bar.jar": Add bar.jar as a class repository
common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar #
# List of comma-separated paths defining the contents of the "server"
# classloader. Prefixes should be used to define what is the repository type.
# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute.
# If left as blank, the "common" loader will be used as Catalina's "server"
# loader.
# Examples:
# "foo": Add this folder as a class repository
# "foo/*.jar": Add all the JARs of the specified folder as class
# repositories
# "foo/bar.jar": Add bar.jar as a class repository
server.loader= #
# List of comma-separated paths defining the contents of the "shared"
# classloader. Prefixes should be used to define what is the repository type.
# Path may be relative to the CATALINA_BASE path or absolute. If left as blank,
# the "common" loader will be used as Catalina's "shared" loader.
# Examples:
# "foo": Add this folder as a class repository
# "foo/*.jar": Add all the JARs of the specified folder as class
# repositories
# "foo/bar.jar": Add bar.jar as a class repository
# Please note that for single jars, e.g. bar.jar, you need the URL form
# starting with file:.
shared.loader=
2.catalinaLoader 主要用于加载Tomcat代码
3.每一个web应用会对应一个WebappClassLoader,每个应用的WebappClassLoader是不一样的,这样可以确保应用间隔离。 WebappClassLoader的父类加载器是sharedLoader,因为默认情况sharedLoader是commonLoader,所以默认情况WebappClassLoader的父类加载器是commonLoader。
这个里说Tomcat没有完全准守双亲模型的原因是 在每一个应用中,WebappClassLoader加载类的时候会有以下步骤
1. 看类是不是可以被系统类加载器加载,如果可以在返回
2. 如果这个类不可以被系统类加载加载,这交给WebappClassLoader 加载,WebappClassLoader会在WEB-INF/classes中查找
3. 在WEB-INF/classes中没有找到,则会在WEB-INF/lib中查找
4.如果在WEB-INF/lib中也没有找到则会交给父类加载加载,默认情况父类加载器是commonLoader。
5. 如果以上没有找到,则抛出异常。
WebappClassLoader会对这个类的结果进行缓存,即找到了则缓存结果,找不到也会缓存找不到,所以以上行为其实是web应用第一次加载类的时候才会发生。
六、总结当tomcat 的WEB应用需要到某个类时,则会按照下面的顺序进行类加载:
1. 使用启动类加载器:Bootstrap ClassLoader 加载 JAVA_HOME\jre\lib
2. 使用扩展类加载器: Extension ClassLoader 加载JAVA_HOME\jre\lib\ext
3. 使用系统类加载器: Application ClassLoader 它负责加载用户ClassPath (System.getProperty("java.class.path") 这个参数所指定的文件夹)所指定的类
4. 使用应用类加载器 WebappClassLoader 在该应用的WEB-INF/classes中路径中查找
5. 使用应用类加载器 WebappClassLoader 在WEB-INF/lib中查找
6. 使用sharedLoader类加载器(默认情况下sharedLoader是commonLoader) 在CATALINA_HOME/lib中加载
参考地址:1. 图解Tomcat类加载机制
Tomcat类加载的更多相关文章
- java类加载器-Tomcat类加载器
在上文中,已经介绍了系统类加载器以及类加载器的相关机制,还自定制类加载器的方式.接下来就以tomcat6为例看看tomat是如何使用自定制类加载器的.(本介绍是基于tomcat6.0.41,不同版本可 ...
- 图解Tomcat类加载机制
说到本篇的tomcat类加载机制,不得不说翻译学习tomcat的初衷. 之前实习的时候学习javaMelody的源码,但是它是一个Maven的项目,与我们自己的web项目整合后无法直接断点调试.后来同 ...
- Tomcat类加载器机制
Tomcat为什么需要定制自己的ClassLoader: 1.定制特定的规则:隔离webapp,安全考虑,reload热插拔 2.缓存类 3.事先加载 要说Tomcat的Classloader机制,我 ...
- Tomcat类加载器
1JVM类加载机制 JVM的ClassLoader通过Parent属性定义父子关系,可以形成树状结构.其中引导类.扩展类.系统类三个加载器是JVM内置的. 它们的作用分别是: 1)引导类加载器:使 ...
- 深入剖析Tomcat类加载机制
1JVM类加载机制 JVM的ClassLoader通过Parent属性定义父子关系,可以形成树状结构.其中引导类.扩展类.系统类三个加载器是JVM内置的. 它们的作用分别是: 1)引导类加载器:使用n ...
- Tomcat系列(7)——Tomcat类加载机制
1. 核心部分 1. 类加载器: 通过一个类的全限定名来获取描述此类的二进制字节流. 对于任意一个类,都需要由加载他的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一 ...
- 图解Tomcat类加载机制(阿里面试题)
Tomcat的类加载机制是违反了双亲委托原则的,对于一些未加载的非基础类(Object,String等),各个web应用自己的类加载器(WebAppClassLoader)会优先加载,加载不到时再交给 ...
- 《转载》图解Tomcat类加载机制
本文转载自http://www.cnblogs.com/xing901022/p/4574961.html 说到本篇的tomcat类加载机制,不得不说翻译学习tomcat的初衷. 之前实习的时候学习j ...
- Tomcat类加载器破坏双亲委派
转载:https://blog.csdn.net/qq_38182963/article/details/78660779 http://www.cnblogs.com/aspirant/p/8991 ...
随机推荐
- 面向面试编程代码片段之GC
x 代码 using System; using System.Threading; public static class Program{ public static void Main(){ T ...
- mac下git安装与使用
1.下载git客户端,下载地址为:https://git-scm.com/download/mac 2.打开安装包,可以看到此时的界面为: 我们需要把.pkg的安装包安装到系统当中.我双击了安装包 ...
- VUE-007-通过路由 router.push 传递 query 参数(路由 name 识别,请求链接显示参数传递)
在前端页面表单列表修改时,经常需要在页面切换的时候,传递需要修改的表单内容,通常可通过路由进行表单参数的传递. 首先,配置页面跳转路由.在 router/index.js 中配置相应的页面跳转路由,如 ...
- 20190422 8个小时的T-SQL基础视频课件-分享
链接:https://pan.baidu.com/s/1YLjtU0Ymn0rI-KMF0DFehw 提取码:yeuw 我最近缺钱..... SQLSERVER 2016视频T-SQL(一) 路径:h ...
- 基于Promise封装uni-app的request方法,实现类似axios形式的请求
https://my.oschina.net/u/2428630/blog/3004860 uni-app框架中 安装(项目根目录下运行) npm install uni-request --save ...
- 表情的战争(App名称)技术服务支持
1.进入游戏走过场动画,可以点击退出跳过此过场动画: 2.进入主界面后直接点击开始游戏进入场景跑图,进入npc对话面板,对话结束进入战斗面板: 3.战斗操作方法为玩家拖动表情牌,进行攻击或者防守,直至 ...
- IDEA搭建scala开发环境开发spark应用程序
通过IDEA搭建scala开发环境开发spark应用程序 一.idea社区版安装scala插件 因为idea默认不支持scala开发环境,所以当需要使用idea搭建scala开发环境时,首先需要安 ...
- TerminateProcess实现关闭任意程序
#include <Windows.h> #include <tchar.h> int WINAPI _tWinMain(HINSTANCE hInstance, HINSTA ...
- Qt QComBox 文本框输入itemText && 文本框查找item && 本文框添加Item &&设置显示Item数量
comBox的几种状态图如下: 图1:ui->comboBox->setEditable(true); 图2:ui->comboBox->setEditable(false ...
- Python实现bp神经网络识别MNIST数据集
title: "Python实现bp神经网络识别MNIST数据集" date: 2018-06-18T14:01:49+08:00 tags: [""] cat ...
