虚拟机的类加载机制
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。
类的加载过程:
加载—>验证—>准备—>解析—>初始化
加载:查找并加载类的二进制文件
需要完成3件事:
- 通过一个类的全限定名来获取定义此类的二进制字节流
- 将这个字节流的金泰存储结构转为方法区的运行时数据结构
- 在内存中生成java.lang.Class对象,作为方法区这个类的各种数据的访问入口
验证:确保被加载类的正确性
- 文件格式验证:是否以魔数0xCAFEBABE开头
- 元数据验证
- 字节码验证
- 符号引用验证
准备:正式为类变量分配内存并设置类变量初始值,变量使用的内存在方法区分配。
public static int value = 123; //在初始化阶段才赋值为123,准备阶段为0
public static final int value = 123; //在准备阶段就被赋值为123
解析:虚拟机将常量池内的符号引用替换为直接引用
初始化:为类的静态变量初始化
静态块中可以给静态变量赋值,但不允许访问,否则会提示“非法向前引用”。
类加载器
双亲委派模型
启动类加载器 <— 扩展类加载器<— 应用程序类加载器<— 自定义类加载器
工作过程:
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求的时候,子加载器才会尝试自己去加载。
使用双亲委派模型的好处是:Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar中,无论哪个类加载器加载这个类,最终都是委派给启动类加载器进行加载,因此,Object类在程序的各种类加载器环境中都是同一个类。
先检查是否已经被加载过,若没有加载则调用父加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。如果父加载失败,抛出ClassNotFoundException异常后,再调用最的findClass()方法进行加载。
双亲委派模型的代码在java.lang.ClassLoader.loadClass()中:
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
Tomcat的Classloader体系结构
CommonClassLoader <— CatalinaClassLoader
^— SharedClassLoader<— WebAppClassLoader
网友评论