昨天我们学习了Java中的反射,其原理应用了Java运行中的.class文件。回头想想,我们以前在编程的过程中肯定见过这样的一个异常Java.lang.ClassNotFoundExcetpion,这背后就涉及到了java技术体系中的类加载。今天,让我们来一起了解一下。
Java类加载机制
Java中的类加载机制是java技术体系中算是比较核心的一部分,尽管我们平时接触的并不是很多,而且类加载器也并不是和大部分软件开发工作人员经常打交道的。但是我们在这里学习Java的累加器的背后的机制,能够帮助我们理解并有助于排查程序中出现的类加载失败等技术问题,就好比上篇文章的放射,学习了这些,你回头看的时候就很容易理解啦。
为什么使用类加载
在我们学习的Java语言面里,类加载是当我们的程序运行的时候完成的,这样的方式尽管会给类加载时候的主机稍微的添加点点的性能开销以外,就是能给java程序提供高度的灵活性。
类加载的过程
图1 类加载过程
我们在完成编写以.java为后缀的文件后,这些.java文件就会通过java中的编译器编译成后缀名字是.class的文件。我们走进.class文件之后,我们就可以看到这里面存储着java代码在编译转换后的虚拟指令。
当我们准备使用这个类的时候,jvm虚拟就就会加载它的.class文件,并且创建对应的.class对象,我们将这种class文件加载到jvm虚拟机的内存的这个过程称之为类加载。
图2 类加载过程
Loading(加载):加载就是我们把类的信息从文件中取得之后,再载入到JVM虚拟机的方法区/常量区里,也就是内存里面。
Verifying(验证):在这行模块我们会校验加载的结构是不是符合Java语言规范和JVM规范的描述。在这个过程中,是类转载的中最繁杂的一块,在时间上的花费也是最长的一块。我们使用的排错程序,有一大部分也是在检查这一部分的错误。
Preparing(准备):检验通过之后,我们会分配一种结构去存储类的信息,我们在这个结构中存储了我们在类中定义的成员变量,方法和接口的数据信息。
Resolving(解析):解析就是我们把这个类中常量池中的所有的 符号引用 改变成 直接引用。
Initializing(初始化):解析完成,我们就可以提取类中的变量,并且使之初始化成为合适的值。执行静态的初始化程序,可以把静态变量初始化成指定的数值
加载具体步骤
在这里我们对加载要重点掌握,其余的过程至于要了解即可。
相对于其他阶段,加载阶段,也就是说获取类的2进制的字节流的这个阶段,是我们在程序开发期可控性最强的一个阶段。原因是,加载阶段可以用我们系统提供的类加载器(ClassLoader)去获取类的2进制的字节流,当然这个也可以由我们自定义的类加载器去获取我们要的字节流。
当我们的加载完成之后,jvm虚拟机外部的2进制字节流就会按照jvm所需要的格式存储在方法区中,其中的数据存储格式都是由jvm自行定义实现。然后在Java的堆中实例化一个java.lang.Class类的对象,这个对象就是我们程序访问方法区中的数据的外部接口。
以上就是我们对Java中类加载器的介绍,看完是不是有一丝的清新感呢?
学习完了反射,动态代理,明天我们将学习动态代理,找代理好办事。
有帮助的大家的话,点个关注来个赞,让优秀成为一种习惯。
感谢坚持关注的朋友~
世界很大,幸好有你~
欢迎在评论区留下你的问题或困惑,我将每天与你分享我的观点和心得。
聚焦最新科技咨讯,探寻未来智能领域,我是Mario女陶。