作用:负责从硬盘/网络中加载字节码信息,加载到内存中(运行时数据区的方法区中)
类加载过程:
加载
使用IO读取字节码文件,转换并存储
为每个类创建一个Class类的对象
存储在方法区中
链接(验证,准备,解析)
验证:对字节码文件格式进行验证,文件是否被污染
对基本的语法格式进行验证
准备:为静态的变量进行内存分配
public static int value = 123; value 在准备阶段后的初始值是 0,而不是 123.
静态变量在编译期间就初始化
解析:将符号引用转为直接引用
将字节码中的表现形式转为内存中表现(内存地址)
初始化
类的初始化,为类中的定义的静态变量进行赋值
public static int value = 123;value 在准备阶段后的初始值是 0,而不是 123.
类什么时候会被加载(初始化)
1.在类中运行main方法
2.通过new关键字创建对象
3.使用类中的静态变量,静态方法,静态代码块
4.反射 Class.forName(“类的地址”)
5.子类被加载
以上都是主动使用;下面两种情况为被动,且不会导致类的加载。
(1)应用该类的静态常量(final修饰,编译期间就已经赋值的)
(2)应用该类时,将类当做数组的元素类型,即构造这个类的数组
类加载器分类
具体的负责加载类的一些代码
1.引导类加载器,用c/c++语言开发的,jvm底层的开发语言,负责加载java核心类库。
与java语言无关
2.扩展类加载器:用Java语言编写的,由sun.misc.Launcher$ExtClassLoader 实现,继承自java.long.ClassLoader类,加载api中的类
3.应用程序类加载器:Java 语言编写的,由sun.misc.Launcher$AppClassLoader 实现. 派生于 ClassLoader 类.加载程序中自己开发的类。
4.自定义类加载器
双亲委派机制:
双亲委派模式要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器,请注意双亲委派模式中的父子关系并非通常所说的类继承关系,而是采用组合关系来复用父类加载器的相关代码,类加载器间的关系如下:
加载一个类时,先委托给父类加载器加载,如果父加载器没有找到,继续向上级委托,直到引导类加载器,父级找到就返回,父级如果没有找到,就委派给子级加载器。最终没有找到,就报ClassNotFoundException异常。为了先确保加载系统类
(即每个儿子都很懒,每次有活就丢给父亲去干,直到父亲说这件事我也干不了时,儿子自己想办法去完成,这不就是传说中的实力坑爹啊?)
打破双亲委派机制
通过继承ClassLoad类,重写ClassLoad类中的loadclass方法(不推荐)重写findClass方法,实现自定义的类加载
典型的tomcat中,加载部署在tomcat中的项目时,就是用的是自己的类加载器。