### 类加载的时机
* 隐式加载 new 创建类的实例,
* 显式加载:loaderClass,forName等
* 访问类的静态变量,或者为静态变量赋值
* 调用类的静态方法
* 初始化某个类的子类
* 使用反射方式创建某个类或者接口对象的Class对象
* 直接使用`java.exe`命令来运行某个主类
### 类加载过程
加载->验证->准备->解析->初始化
![](https://img.kancloud.cn/ff/32/ff32d2c3025387bc61fc1c307266bff3_602x435.png)
- **加载**
类加载过程的一个阶段,ClassLoader通过一个类的完全限定名查找此类字节码文件,并利用字节码文件创建一个class对象。
- **验证**
目的在于确保class文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身的安全,主要包括四种验证:文件格式的验证,元数据的验证,字节码验证,符号引用验证。
- **准备**
为类变量(static修饰的字段变量)分配内存并且设置该类变量的初始值,(如static int i = 5 这里只是将 i 赋值为0,在初始化的阶段再把 i 赋值为5),这里不包含final修饰的static ,因为final在编译的时候就已经分配了。这里不会为实例变量分配初始化,类变量会分配在方法区中,实例变量会随着对象分配到Java堆中。
- **解析**
这里主要的任务是把常量池中的符号引用替换成直接引用
- **初始化**
这里是类记载的最后阶段,如果该类具有父类就进行对父类进行初始化,执行其静态初始化器(静态代码块)和静态初始化成员变量。(前面已经对static 初始化了默认值,这里我们对它进行赋值,成员变量也将被初始化)
* [ ] 双亲委派模式
如果一个类收到了类加载的请求,它并不会自己先去加载,而是把这个请求委托给父类加载器去执行,如果父类加载器还存在父类加载器,则进一步向上委托,依次递归,请求最后到达顶层的启动类加载器,如果弗雷能够完成类的加载任务,就会成功返回,倘若父类加载器无法完成任务,子类加载器才会尝试自己去加载,这就是双亲委派模式。就是每个儿子都很懒,遇到类加载的活都给它爸爸干,直到爸爸说我也做不来的时候,儿子才会想办法自己去加载。
![](https://img.kancloud.cn/6e/b5/6eb5502df1b2a705cc2815293ccfcda8_1240x882.png)
* [ ] 自定义类加载器
一般需要继承java.lang.ClassLoader类并重写其findclass方法。
*****
引用自 https://www.cnblogs.com/czwbig/p/11127222.html
https://blog.csdn.net/weixin_40236948/article/details/88072698
- 2111总结
- 1.面向对象
- 1.0.1 super()与this()的区别
- 1.0.2 private、default、protected、public的访问范围
- 1.0.3 continue、break、return区别
- 1.0.4 重载和重写的区别
- 1.0.5 final的特点
- 1.0.6 抽象类与接口的区别
- 1.0.7 java类型
- 1.0.8 什么是反射
- 1.0.9 类的加载机制
- 1.1.1 jvm内存结构
- 1.1.2 java垃圾回收机制
- 1.1.3 并发问题
- 1.1.3.1 线程的状态与关系
- 1.1.3.2 并发的三大性质
- 1.1.3.3 线程的实现与使用
- 1.1.3.4 线程池相关
- 1.1.3.5 并发相关方法
- 1.1.3.6 线程相关工具
- 1.1.4 jdk8特性
- 1.1.4.1 lambad表达式的使用
- 1.1.4.2 stream API
- 1.1.4.3 Optional容器使用
- 1.1.4.4 LocalDateTime
- 1.15 io流
- 1.16 动态代理实现
- 2.JavaEE
- 2.0.1 JSP四大作用域九大内置对象
- 2.0.2 cookie与session的区别
- 4.数据库相关
- 5.git版本管理
- 7.一些问题解决
- 7.1 分布式锁如何实现