Class 文件是怎样被放在内存的
硬盘中的Class被加载的过程
1、loading
把一个class 加载到内存,懒加载,需要的时候再加载
2、linking
(1)、verification
校验class,是否满足class的格式
(2)、preparation
把class中静态变量设置成默认值 int类型 0
(3)、resolution
解析 loadeClass方法中的第二个参数 true 为解析 false 不解析
class中常量池用到的符号引用转换成可以直接访问内存的值(直接能访问到的内容)
即 将类、方法、属性等符号引用解析为直接引用
常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用
3、initializing
静态变量的赋值,赋值为初始值,调用静态变量块
在类初始化代码,给静态成员变量赋初始值
Class:load 默认值 初始化
new:申请内存 默认值 初始值
类加载器(ClassLoader)
jvm有一个类加载器的层次,分别加载不同的class
jvm中所有的class 都是被类加载器加载到内存的
一个class 被 load 到内存后, 内存中创建了两块内容
一块是将class对应的二进制内容扔进 内存中 ,同时也生成了一个class类的对象并指向二进制文件,这个对象保存在mataspace中
别的对象访问这个类的时候就是通过访问生成的这个Class类对象,然后这个class类对象再去访问二进制文件
即访问过程是 通过访问class文件对应创建的class类,然后class类从指向的二进制中获取对应二进制并解析成汇编指令
如下是获取类对应加载器的部分示例
public class T002_ClassLoaderLevel {
public static void main(String[] args) {
// null---Bootstrap ClassLoader
// 返回null的原因:Bootstrap ClassLoader 是由C++实现的,java中没有对应的class 所以返回空
// 可以理解成c++实现的一个模块
System.out.println(String.class.getClassLoader());
//null---Bootstrap ClassLoader
System.out.println(sun.awt.HKSCS.class.getClassLoader());
//sun.misc.Launcher$ExtClassLoader@6d6f6e28 --- Extension ClassLoader
System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader());
//sun.misc.Launcher$AppClassLoader@18b4aac2 --- App ClassLoader
System.out.println(T002_ClassLoaderLevel.class.getClassLoader());
// null 父加载器不是 加载器的加载器 所以 classLoader 的 classloader 都是null
System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader().getClass().getClassLoader());
// null 同上 ClassLoader 本身就是c++ 写的
System.out.println(T002_ClassLoaderLevel.class.getClassLoader().getClass().getClassLoader());
// sun.misc.Launcher$ExtClassLoader@6d6f6e28 --- T002_ClassLoaderLevel 的类加载器是APP APP的父加载器是 Ext加载器
System.out.println(new T002_ClassLoaderLevel().getParent());
System.out.println(ClassLoader.getSystemClassLoader());
}
}
加载器分类
Bootstrap: jdk 加载核心类的类加载器
Extension: 是加载扩展包中的的
App: 加载classpath 指定的类的,即加载我们自己写的类
Custom: 自定义的类加载器
Class 类加载器加载过程
双亲委派: 从子到父的过程和从父到子的过程
过程: class首先会从 Custom加载器(缓存 ——每个类加载器 维护一个list 用来管理已经加载的对象引用)中找,找到返回结果,找不到会从上层加载器APP中找,如果还是找不到再到Ext加载器中招,一直到Bootstrap加载器,(前面的find 都是从缓存中找),如果缓存中没有,则find class 并加载,如果 bootstrap没有加载到,则交给下一层加载器 ext find class 并加载 ,直到custom 。如果custom 没有找到class,则报错 ClassNotFoundException异常