类加载过程
- load:把硬盘上的class文件,加载到内存中
- link
- 校验:验证class文件是否符合jvm规定(比如开头是不是cafe babe)
- 准备:把静态变量赋默认值
- resolution:内存中对象的符号引用转换为直接应用
- init:给静态变量赋初始值
类加载器
- lib包中的基础类由classLoader加载
- ext包中的类由extClassLoader加载
- 应用中的类由applicationClassLoader加载
- 还可以自定义类加载器
以上按顺序加载。是属于子加载器与类加载器的关系,注意在语法上不是继承关系。
classLoader把extClassLoader加载到内存中,extClassLoader把appClassLoader加载到内存中,app加载自定义
DCL的instance对象为什么要加volation?
double check lock(双重检查锁单例)在jvm中,顺序是
- 申请内存空间
- 创建初始值
- 将对象的引用指向内存空间。
如果没有volation,可能会发生指令重排,2和3会颠倒,此时,最终结果是没有区别的。但是,一个线程在进行1、3的时候,另外一个线程判断instance == null?则会拿到默认值!
双亲委派
目的是为了:安全
类是由从子到父的内存中加载,如果父没有,则从父到子去寻找加载
打破双亲委派机制
- 如何打破:重新loadClass()方法即可
- 何时打破:
- jdk1.2之前,自定义classLoader都必须重写loadClass()
- ThreadContextClassLoader可以实现基础类调用实现类代码,通过thread.setContextClassLoader()指定
- 热启动、热部署
- osgi、tomcat都有自己的模块制定classLoader(可以加载同一类的不同版本)