Java类的生命周期-加载阶段
本篇即将讲述类的加载阶段步骤,并使用JDK自带的HSDB工具查看加载阶段时虚拟机中的内存信息
类的生命周期
首先在java中类的生命周期描述了类的加载、使用到卸载的一系列过程,我们一般将其分为五大阶段:
但是也有人将其分为七个阶段,就是将”连接“阶段细致拆分为三个阶段:验证、准备、解析,我们本篇只讨论加载
阶段,所以无论是哪一种、对于我们都无伤大雅
加载阶段的步骤
-
通过JVM中的
类加载器
,根据类的全限定名通过不同的渠道 以二进制流的形式加载字节码文件
为什么加载字节码文件要通过不同渠道呢,其实在这个步骤中,不单单是本地磁盘上的字节码文件,也能通过其他渠道加载,比如说Spring框架的动态代理
,会在程序运行时动态生成类,那么此时类加载器会根据全限定名找到其所在的内存区域并读取。甚至是通过网络传输的类也可以加载 -
类加载器加载完毕后,将字节码文件中的信息全部保存到
方法区
当中
方法区是一块专门的内存区域,但他实际上只是java虚拟机规范中设计出来的虚拟概念,不同虚拟机、不同版本用到的实际内存空间都不相同 -
紧接着第二步,此时会在方法区中生成一个
InstanceKlass
对象,用来保存所有的类信息
其中InstanceKlass类中保存了类的基本信息、常量池、字段、方法、属性等等,还包括实现特殊功能的信息,比如实现多态的虚方法表
-
java虚拟机还会在堆中生成一份与方法区数据类似的
java.lang.class
对象
其作用是在java代码中获取类的信息以及存储静态字段数据,当我们实现反射时,先需要拿到类的基本信息,也就是Class对象,再获取其字段、方法等信息进行操作,而方法区中的InstanceKlass对象与堆中的java.lang.class对象有一个引用使其彼此关联
此时你可能会发现,为什么堆区和方法区中都要有一个用来存放类的基本信息的对象呢,为什么不只留一块空间,把类信息以及反射、静态字段等等全部存放起来呢?
其实呢,InstanceKlass对象是由C++编写的,java代码不能直接操作,所以java虚拟机就创建了一个用java包装的java.lang.Class对象,方便开发时进行访问,其次,java.lang.Class中的字段信息是少于InstanceKlass对象的,因为其中有很多类在开发中并不需要,也不能轻易被访问,所以为了数据安全性考虑,开辟了这样两块空间。