大家好,我是你们的导师,经常看我朋友圈的同学应该知道,我每天会在微信上给大家免费提供以下服务!
1、长期为你提供最优质的学习资源!
2、给你解决技术问题!
3、每天在朋友圈里分享优质的技术文章!
4、每周1、3、5送纸质书籍免费送给大家,每年至少送书800本书!
5、为大家推荐靠谱的就业单位!
请注意!我上面说的5点全部都是免费的!全网你应该找不到第二家吧!
当然,大家在我私人微信上问我问题,仅限回答web前端、java相关的。
---------------------------
好了,接下来开始今天的技术分享!上次老师跟大家分享了ArrayList底层原理及实现的知识,今天跟大家分享下Java类加载的过程的知识。
1 类的生命期
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现这个类进行初始化。可以看到类的生命周期包含了加载、验证、准备、解析、初始化、使用、卸载七个步骤,其中验证、准备和解析可以叫做一步连接。其中类的加载过程是前面的3步,加载、验证、准备、解析和初始化。
1. 加载
加载,是指Java虚拟机查找字节流(查找.class文件),并且根据字节流创建java.lang.Class对象的过程。这个过程,将类的.class文件中的二进制数据读入内存,放在运行时区域的方法区内。然后在堆中创建java.lang.Class对象,用来封装类在方法区的数据结构。
类加载阶段:
(1)Java虚拟机将.class文件读入内存,并为之创建一个Class对象。
(2)任何类被使用时系统都会为其创建一个且仅有一个Class对象。
(3)这个Class对象描述了这个类创建出来的对象的所有信息,比如有哪些构造方法,都有哪些成员方法,都有哪些成员变量等。
Student类加载过程图示:
2.链接
链接包括验证、准备以及解析三个阶段。
(1)验证阶段。主要的目的是确保被加载的类(.class文件的字节流)满足Java虚拟机规范,不会造成安全错误。
(2)准备阶段。负责为类的静态成员分配内存,并设置默认初始值。
(3)解析阶段。将类的二进制数据中的符号引用替换为直接引用。
说明:
符号引用。即一个字符串,但是这个字符串给出了一些能够唯一性识别一个方法,一个变量,一个类的相关信息。
直接引用。可以理解为一个内存地址,或者一个偏移量。比如类方法,类变量的直接引用是指向方法区的指针;而实例方法,实例变量的直接引用则是从实例的头指针开始算起到这个实例变量位置的偏移量。
举个例子来说,现在调用方法hello(),这个方法的地址是0xaabbccdd,那么hello就是符号引用,0xaabbccdd就是直接引用。
在解析阶段,虚拟机会把所有的类名,方法名,字段名这些符号引用替换为具体的内存地址或偏移量,也就是直接引用。
3.初始化
初始化,则是为标记为常量值的字段赋值的过程。换句话说,只对static修饰的变量或语句块进行初始化。
如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类。
如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。
2 对象的初始化顺序
首先对象初始化会有几个东西,构造函数,构造代码块,静态代码块,静态变量,对于构造函数,构造函数只会初始化一次,用来初始化对象,构造方法只会调用一次,对象的方法可以重复调用,对于构造方法块,同构造方法一样只会在new的时候执行一次,也是用来初始化对象的,对于静态代码块,是给类进行初始化的,只会在类初始化的时候执行一次,对于静态变量,也只会在类初始化的时候初始化一次。
对于一个类,这几个的顺序如下,静态变量和代码块优先于构造代码块优先于构造函数。对于有继承的情况,这几个的顺序如下,父类静态变量、代码块优先于自雷静态变量、代码块优先于父类变量、构造代码块、构造方法优先于子类变量、构造代码块、构造方法。
3 类加载器
类加载器用于实现类的加载,java中分为了三种类加载器,启动类加载器,拓展类加载器,应用程序类加载器,其中启动类加载器是由C++编写,用于加载JAVA_HOME>\lib目录下的类,也就是我们用到的基本的像String什么的都是这个加载器加载的。
然后是拓展类加载器是用于加载<JAVA_HOME>\lib\ext中的类,这个目录下的类不常用到,最后应用程序类加载器是加载用户自己实现的类。接下来介绍下类加载器的双亲委派模型,图示:
双亲委派模型体现了类加载器之间的层次模型,除了启动类加载器外,每个加载器都有自己的父加载器,
工作过程如下:如果类加载器收到了类加载的请求,那么会将这个请求一层一层的传递到父加载器中,当父加载器反馈自己不能加载的时候才会有这个加载器加载,这样的好处是,避免一个类被多个加载器重复加载,并且由于不同加载器加载的类是不一样的,导致程序混乱。
4 总结
类加载过程只是一个类生命周期的一部分,在其前,有编译的过程,只有对源代码编译之后,才能获得能够被虚拟机加载的字节码文件;在其后还有具体的类使用过程,当使用完成之后,还会在方法区垃圾回收的过程中进行卸载(垃圾回收)。
今天就分享这么多,关于Java类加载的过程,你学会了多少?欢迎在留言区评论,对于有价值的留言,我们都会一一回复的。如果觉得文章对你有一丢丢帮助,请点右下角【在看】,让更多人看到该文章。