1.1总体结构图
1.2 类加载器子系统的作用
1 类加载子系统负责从文件系统中加载class文件,class文件在文件的开头有特定文件标识。
2 ClassLoader只负责class文件的加载。
3 加载的类信息存放在方法区的内存空间。
方法区的概念:
存放运行时常量池信息:{
字符串的字面变量,数字常量}
1.3 ClassLoader角色的作用
1 class文件【Car.class】存放在本地磁盘中
2 class文件加载到JVM的方法区中
步骤1———(运输员:ClassLoader)————>步骤2
1.4 类的加载过程
1.4.1 加载(Loading)
1 通过一个类的全限定名获取定义此类的二进制字节流
2 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
3 在内存中生成一个代表这个类的java.lang.Class对象【反射机制】,作为方法区这个类的各种数据的访问入口
1.4.2 链接(Linking)
1 验证(verify):
确保class文件的字节流中包含信息符合当前虚拟机的要求,保证类加载的正确性。
2 准备(prepare):
为类变量分配内存并且设置该类变量的默认初始值【0】
注意:
这里不包括final修饰的static,因为final在编译的时候就会被分配了,准备阶段会显示的初始化。
这里也不会为实例变量分配内存,实例变量会随着对象一起分配到java heap中
3 解析(Resolve):
将常量池内的符号引用转化为直接引用的过程。
1.4.3 初始化(Initialization)
初始化就是执行类构造器方法< clinit >() 的过程。
javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来。
若该类具有父类,则JVM会保证子类的< clinit >()执行之前,先执行父类的< clinit >()
Demo
注意:
a的赋值过程:
1 Linking的prepare阶段:a = 0;
2 clinit阶段: a =1
1.5 类加载器的分类
按是否继承了ClassLoader分为:引导类加载器和自定义类加载器
其上下层的关系图:
1.5.1 引导类加载器(Bootstrap ClassLoader)
1使用的c/c++语言
2加载java的核心库以java javax sun开头的类
3 没有父加载器
4是直接获取不到
1.5.2 扩展类加载器(Extension ClassLoader)
1java语言编写
2继承抽象类ClassLoader
3父加载器为启动类加载器
1.5.3 系统类加载器(AppClassLoader)
1java语言编写
2继承ClassLoader
3父加载器为扩展类加载器
4程序默认的类加载器
对引导类加载器 扩展类加载器 系统类加载器的Demo
1.5.4 自定义类加载器
意义:
隔离加载类
修改类的加载方式
扩展加载源
防止源码泄露
实现步骤:
1 继承java.lang.ClassLoader类
2重写findClass()方法
Demo
1.6 ClassLoader
获取ClassLoader的途径
1.7 双亲委派机制(面试重点)
JVM对class文件是按需加载的方式,加载某个类的class文件时,JVM采用的是双亲委派机制,即把请求交给父类处理。
1.7.1 工作原理
Demo
java.lang.String 类是java核心类,是由引导类加载器加载的,但是在原javaAPI中是没有main方法的。所以就凸显了双亲委派机制的优势:保护程序安全,防止核心API被篡改。
1.8 其他重要知识点
判断两个class对象是否为同一个类存在的两个必要条件
1 类的完整类名必须一致,包括包名
2 加载这个类的ClassLoader必须相同
类的主动使用和被动使用
会不会导致类的初始化是分类依据。