一文弄懂-Java:类的加载过程

createh53周前 (12-10)技术教程20

0 文由

其一,工欲善其事,必先利其器。编程语言是软件开发工作中基础的基础。

其二,学习的两重境界,知其然,知其所以然。前者回答了“是什么”,后者回答“为什么”。笔者力求在这两方面“雨露均沾”。

其三,因此本文欲以尽量短的篇幅来尝试回答:Java的class类文件的加载过程是怎样的?

其四,本文所涉及的技术话题“Java中类的加载过程”,这也是一道Java/大数据开发工程师岗位求职中相对较为遇见的问题。

Eg:请你谈谈类的加载过程?


1 类的加载过程

[类的加载过程]

精简解释:

JVM虚拟机.class文件类信息加载内存,并进行解析生成对应的class对象的过程。


通俗解释:

JVM在执行某段代码时,遇到class A,然而,此时内存中并没有class A的相关信息,于是JVM就会到相应的class文件中去寻找class A的类信息,并加载进内存中,这就是我们所说的类加载过程。

即 JVM不是一开始就把所有的类都加载进内存中,而是只有第一次遇到某个需要运行的类时才会加载,且只加载一次


step1 加载

一个Java文件从编码完成到最终执行,一般主要包括2个过程:编译 + 运行

? 1 编译

编译:把java源文件,通过javac命令编译成字节码(.class文件) (.java文件→.class文件)

? 2 运行

运行:即是把编译生成的.class文件交给Java虚拟机(JVM)执行。(.class文件→JVM执行)


step2 链接

链接阶段:可细分为验证准备解析3个子过程。

验证: 主要是为了保证加载进来的字节流符合虚拟机规范,不会造成安全错误。

【验证内容】

对于文件格式的验证。比如常量中是否有不被支持的常量?文件中是否有不规范的或者附加的其他信息?

对于元数据的验证。比如该类是否继承了被final修饰的类?类中的字段,方法是否与父类冲突?是否出现了不合理的重载?

对于字节码的验证。保证程序语义的合理性,比如要保证类型转换的合理性。

对于符号引用的验证。比如校验符号引用中通过全限定名是否能够找到对应的类?校验符号引用中的访问性(private,public等)是否可被当前类访问?

准备:主要是为类变量(注意,不是实例变量分配内存,并且赋予初值

【初值】

初值,不是代码中具体写的初始化的值,而是Java虚拟机根据不同变量类型的默认初始值

比如:8种基本类型的初值,默认为0;引用类型的初值则为null;

但,常量的初值即为代码中设置的值:final static tmp = 456, 那么,该阶段tmp的初值就是456


解析:将常量池内的符号引用替换为直接引用的过程。

在解析阶段,虚拟机会把所有的类名方法名字段名这些【符号引用】替换为具体的内存地址或偏移量,也就是【直接引用

【符号引用】

即一个字符串,但是这个字符串给出了一些能够唯一性识别一个方法,一个变量,一个类的相关信息。

【直接饮用】

可以理解为一个内存地址,或者一个偏移量。


比如:

类方法,类变量的直接引用是指向方法区的指针;

而实例方法,实例变量的直接引用则是从实例的头指针开始算起到这个实例变量位置的偏移量。

现调用方法hello(),此方法的地址:1234567,则:hello就是符号引用,1234567就是直接引用。

Step3 初始化

初始化:这个阶段主要是对类变量初始化,是执行类构造器的过程。

只对static修饰的变量或语句进行初始化。

如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类。

如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。


2 小结

总结类加载过程只是一个类生命周期的一部分;

其前,有编译的过程,只有对源代码编译之后,才能获得能够被虚拟机加载的字节码文件;

其后,还有具体的类使用过程,当使用完成之后,还会在方法区垃圾回收的过程中进行卸载。

3 参考文献

  • 面试官:请你谈谈Java的类加载过程 - Zhihu/虫哥

https://zhuanlan.zhihu.com/p/33509426

相关文章

Java类的定义及其实例化

类必须先定义才能使用。类是创建对象的模板,创建对象也叫类的实例化。下面通过一个简单的例子来理解Java中类的定义:对示例的说明:public 是类的修饰符,表明该类是公共类,可以被其他类访问。修饰符将...

SpringBoot使用不同的策略动态地调用某个接口的实现类

1、前言经常遇到这样的一个需求,前端传的实体类型相同,后端需要根据实体类中的某一个字符串,动态地调用某一个类的方法。在SpringBoot中,我们可以理解成,一个Controller接口对应多个Ser...

详细介绍一下Java中的类加载过程?

在Java中类的加载过程是Java虚拟机将类的字节码加载到内存中、进行验证、然后解析和初始化的过程。在这个过程中涉及多个步骤和执行阶段。Java的类加载机制是动态的,即类在运行时才会被加载。这种机制为...