一、类加载全过程
1.加载
一个类通过javac的编译变成字节数组,然后静态的字节数组加载到Java虚拟机的方法区中,静态数据变为运行的数据。同时在Java虚拟机的堆中产生一个java.lang.Class的对象,该对象指向前面说的运行的数据。
2.链接
它就是把java二进制数据合并到JVM运行状态中
- 验证:确保不会发生安全问题
- 准备:在方法区中对静态变量分配内存和赋初值。
- 解析:将符号引用变为直接引用
符号引用:类的类名,类里面的变量,数字等等都是抽象的符号,虚拟机不能调用它们。
3.初始化
由类构造器也叫类初始化器完成。类初始化器通过静态变量的赋值过程和静态代码块合并产生,在这里进行静态变量的赋值操作。在多线程里面,类初始化器的工作是安全的。
主动引用(类会被初始化)
- new()对象
- 创建子类对象,如果父类没被初始化,那么会先初始化父类
- 调用静态变量,静态方法
- 通过反射使用类
- main方法所在的类
被动引用(类不会被初始化)
- 定义数组,该数组类不会被初始化
- 调用常量(final修饰的变量)
- 继承情况下,调用静态域,静态域属于哪个类,那个类被初始化。
二、类加载器
1.有哪些类加载器
- 启动类加载器(bootstrap classLoder):加载JAVA_HOME/jre/lib/rt.jar
- 扩展类加载器(extends classLoder):加载JAVA_HOME/jre/lib/ext/*.jar
- 应用类加载器 (application classLoder)加载classpath下的类
- 自定义类加载器
从上到下,依次是父子关系,这里的父子关系不是继承,而是组合。其中启动类加载器是由C++写的,其余两个是Java写的并且继承了ClassLoder类。自定义类加载器是我们自己定义的。
2.双亲委托机制
双亲委托机制是代理模式的一种。其含义是,类要进行加载,先给应用类加载器,传递到扩展类加载器,再传递到启动类加载器。如果启动类加载器加载不了,让扩展类加载器加载,如果还是加载不了,就再给应用类加载器加载。这种机制保证了核心类加载的安全。
下面是实例
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(ClassLoader.getSystemClassLoader().);
System.out.println(ClassLoader.getSystemClassLoader().getParent());
System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent());
}
结果是
sun.misc.Launcher
A
p
p
C
l
a
s
s
L
o
a
d
e
r
@
73
d
16
e
93
s
u
n
.
m
i
s
c
.
L
a
u
n
c
h
e
r
AppClassLoader@73d16e93 sun.misc.Launcher
AppClassLoader@73d16e93sun.misc.LauncherExtClassLoader@15db9742
null
最后一个是null,因为启动类加载器是C++写的。
三、线程上下文类加载器
1.线程上下文类加载器是什么
它能够指定一个类加载器加载类。
2.应用场景
Java提供了很多接口,但是实现接口的类是第三方提供的。这就会造成一种,接口加载进去了,实现类加载不进去的情况。因为实现类需要用加载接口的加载器加载。扩展类加载器又只能加载JAVA_HOME/jre/lib/ext/*.jar的内容。Java就提供线程上下文加载器,来加载实现类。
三、Tomcat服务器的类加载
Tomcat上每个项目都有自己的加载器,它的类加载不是双亲委托机制,恰恰相反,它的子类能加载,就加载,子类加载不了交给父类。因为Tomcat上运行多个项目,共用同样的类加载器会发生安全问题。
四、GSOI
GSOI是面向组件编程。项目中有许多模块,每个模块都有自己的加载器。模块可以声明到处自己的包和类,其他模块调用时候,用的是谁的类。谁就是加载这个类。