1、类的加载过程
Java文件通过javac编译成.class二进制字节码文件,然后交给类加载器加载到我们的虚拟机内存中,最后我们通过new 对象来实现对象的初始化,才能调用和执行这个类,类的加载有三步:加载、连接、初始化。
1.1、加载
- 将我们的java文件编译后的.class的二进制字节流文件读入到JVM内存中(1.7之前是jvm内存,1.8之后是本地内存)
- 并且在堆内存中创建我们的Class对象,作为.class文件进入内存后的数据访问入口,验证阶段就是用二进制字节流文件来检验.class的合法性,验证通过,才会将.class文件转为运行时数据结构。
1.2、连接
1.2.1、验证
- 主要是校验.class文件的合法性,涉及到jvm安全性的问题 ,比如说final类有没有被继承,包括限定修饰符的判断。
1.2.2、准备
- 主要是给类变量开辟内存空间,并且赋予默认值
1.2.3、解析
- 主要将Class在常量池中的符号引用转变为直接引用,此处针对的是静态方法及属性和私有方法与属性,因为这类方法与私有方法不能被重写,静态属性在运行期也没有多态这一说,即在编译器可知,运行期不可变,所以适合在该阶段解析,譬如类方法main替换为直接引用,为静态连接
1.3、初始化
- 主要是为变量初始化,赋予初始值的:
- 在声明类变量时直接赋值
- 在static代码块中赋值
类加载顺序
- 先加载并连接当前类
- 父类没有被加载,则去加载、连接、初始化父类,依旧是先加载并连接,然后再判断有无父类,如此循环,所以JVM先将Object加载
如果类中有初始化语句,包括声明时赋值与静态初始化块,则按顺序进行初始化 - 由此可以理解类的初始化顺序:先执行父类静态变量赋值、父类静态初始化块,再执行子类静态属性赋值、静态初始化块。
原文链接:https://blog.csdn.net/qq_41563912/article/details/116642556
2、双亲委派机制
双亲委派机制主要是存在与咱们的类加载过程中,在我们加载一个类的时候,不会直接去调用当前类所在作用域的类加载器,而是向上委派给父类加载器去加载,当父类加载器不能加载时,再向下交给我们当前类加载器加载。
比如我们自己写了一个类TestExam,我们不会自己尝试去加载,而是委派给父类加载器来加载,如果父类加载器(Bootstrap/extension)没有找到我们的这样一个类,就会向下交给子类加载器去加载,而我们写的类恰好在我们的classpath的路径下,这时系统类加载器就会加载我们这个类到JVM内存中。
双亲委派模型的好处
- 安全性(优先级):这种层级关系就代表了我们不同类加载器的优先级。比如用户自定义了一个java.lang.String类,我们这时候加载的话是启动类加载器来加载的,而自己写的这个String类就不会覆盖我们启动类加载器下的核心类库中的java.lang.String类,从而保证了我们的一个安全性。
- 避免重复加载导致的程序混乱问题:我们父类加载器加载过得类,子类加载器就不用在加载了,防止了程序混乱的问题。