文章目录
菜鸟的一个学习笔记,欢迎大神 批评指正。
Java多线程相关知识【25】–类加载器(ClassLoader)–类加载的过程
简介
请参考官方介绍文档。
JVM内存简介
方法区
程序的一个共享区域,他在创建时即可被所有的程序共享,他是堆内的一个逻辑单元,也经常被称为“非堆”,他存放了程序的一些数据结构,还保存了程序的运行时常量池,当内存不够时,会抛出OutOfMemory异常。
运行时常量池
为方法区的一部分,可能在编译时,相关数据即被放入此区域,可提高运行时的速度。
堆
内存很大的一个区域(GC区),可存储类的对象和数组,他非线程私有的,当被标记为可回收时,会被线程进行自动回收。
虚拟机栈
线程私有,保存虚拟机的私有数据,相关的管理有程序自身进行管理,jvm不加以管理。(后进先出)
本地方法栈
存放c和c++方法的区域。
程序计数器
标记程序下一条运行的语句的编号。
结束JVM的运行周期的方式
1. 调用System.exit()进行退出
2. 正常的结束
3. 编写的程序发生异常(未处理Exception等)
4. 虚拟机运行内部出现异常
5. 虚拟机依附的操作系统异常
类加载的阶段
1.加载
进行类的查找并根据给定的名称加载类的二进制数据,只有此阶段用户可操作。
类加载的方式
1. 从本地磁盘中直接加载
2. 从内存中直接加载
3. 通过网络加载.class
可使用URLClassLoader。
4. 从zip、jar等归档文件中加载.class
5. 从数据库中提取.class
6. 动态编译
2.链接
创建对象的过程
1.第一种创建方式(通过句柄池):
栈->堆中的句柄池–|->堆中的实例池
|-> 方法区中的对象数据
2.第二种创建方式(通过指针的方式)(速度较快):
栈->堆中对象类的指针和对象实例的数据->对象类型的数据
引用和对象的关系
堆区(对象) 方法区(数据结构)
引用1->对象1->|
引用2->对象2->|--------->对象的数据结构
引用3->对象3->|
2.1. 验证
加载部分和链接部分的部分内容是可以交叉进行的,它可以提高运行效率。例如加载完成后,即可对加载成功的代码进行相关的验证。
验证的目的是为了确保类加载是正确的,若验证失败,则会出现一个VerifyError的异常。
在类的验证阶段主要进行检查以下的内容:
1.检查文件的文件格式是否为.class
2.检查魔术因子是否为0xCAFEBABE
2.检查文件的主从版本号是否支持本虚拟机
4.检查常量池中的常量类型是否受到支持
5.其他的一些认证
6.元数据的验证
- 是否有父类
- 父类是否允许继承
- 是否实现了抽象方法
- 是否覆盖了父类的final字段
- 其他语义检查
7.字节码的验证
数据流和控制流的分析,即声明为int,但赋值为long。
8.符号的验证
调用了一个不存在的方法和字段等。
2.2. 准备
为类的静态变量分配内存,并初始化为默认值。
2.3. 解析
把类中的符号引用转化为直接引用,主要有以下的几个方面。
类或接口的解析
字段解析
类方法的解析
接口方法的解析
3.初始化
为类的静态变量赋予正确的值。