类加载时机
- 1.创建类的实例(对象)
- 2.调用类的类方法
- 3.访问类或者接口的类变量,或者为该类变量赋值
4.使用反射方式来强制创建某个类或者接口对应的java.lang.Class对象
5.初始化某个类的子类
6.直接使用java.exe命令来运行某个主类
用到就加载,不用就不加载
类加载的过程
1.加载
- 通过一个类的全限定名来获取定义此类的二进制字节流(通过包名+类名,获取这个类,准备用流来进行传输)
- 将这个字节流所代表的静态存储结构转化为运行时数据结构(在这个类加载到内存中)
- 在内存中生成一个代表这个类的java.lang.Class对象,任何类被使用时,系统都会为之建立一个jang.lang.Class对象(加载完毕创建一个clss对象)
2.验证
- 链接阶段的第一步,这一阶段为了确保Claa文件字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全(文件中的信息是否符合虚拟机规范有没有安全隐患)
3.准备
- 链接阶段的第二部,负责为类的类变量(被static修饰的变量)分配内存,并设置默认初始化值。(初始化静态变量)
4.解析
- 将类的二进制数据流中的符号引用替换为直接引用(本类中如果用到了其他类,此时就需要知道对应的类)
5.初始化
- 根据程序员通过程序制定的主观计划去初始化类变量和其他资源(静态变量赋值以及初始化其他资源)
类加载器的分类
启动类加载器(Bootstrap ClassLoader):虚拟机内置的类加载器
平台类加载器(Platform ClassLoader):负责加载JDK中一些特殊的模块
系统类加载器(System ClassLoader):负责加载用户类路径上所指定的类库
双亲委派模型
- 逻辑上的继承
为什么会出现双亲委派模型?如果没有双亲委派模型会出现什么情况?
- 双亲委派模型是可以保证多个加载器加载某个类时,最终都是由一个加载器进行加载的,确保最终加载结果相同
- 如果没有双亲委派模型的话,就比如我们自己手写了一个 java.lang.Object类,然后将此类放在classpath路径下,就会导致我们出现多个Object类,就会破坏了java类型体系中原有的基础行为。