在 Java 中,创建对象和类的加载是两个密切相关但又相对独立的过程。下面详细解释这两个过程。
创建对象的过程
创建一个新对象的过程大致可以分为以下几个步骤:
- 类加载检查:JVM首先检查这个类是否已经被加载、链接、初始化。如果没有,系统会先进行类加载过程。
- 分配内存:为新对象分配内存。内存的分配方式有"指针碰撞"(如果内存是绝对规整的)和"空闲列表"(如果内存不是规整的,JVM会维护一个列表来记录哪些内存块是可用的)。
- 初始化零值:将分配到的内存空间都初始化为零值(不包括对象头),确保对象的属性有确定的初始状态。
- 设置对象头:JVM会将分配到的内存空间中的一部分用于存储对象头,这部分信息用于存储对象是哪个类的实例和对象的哈希码等信息。
- 执行
<init>
方法:执行构造方法,初始化对象。构造方法中可能会进行更多的内存分配(为对象属性分配内存)和操作,这个过程可能会递归地触发更多的对象创建和类加载。
类的加载过程
类的加载过程可以分为加载(Loading)、链接(Linking)和初始化(Initialization)三个主要阶段。
-
加载(Loading)
- JVM把类的.class文件读入内存,并为之创建一个
java.lang.Class
对象。类的加载来源可以是文件系统中的.class文件、网络资源或者是其他源。
- JVM把类的.class文件读入内存,并为之创建一个
-
链接(Linking)
- 验证:确保被加载类的正确性。
- 准备:为类的静态变量分配内存,并将其初始化为默认值。
- 解析:把类中的符号引用转换成直接引用(例如,将类名转换成直接指向类的内存地址的指针)。
-
初始化(Initialization)
- 执行类构造器
<clinit>
方法的过程。这个方法是由编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。该过程包括父类的初始化和接口的初始化。初始化是在类的首次使用时才进行的。
- 执行类构造器
这两个过程共同确保了Java程序运行时能够动态地加载、链接和初始化所需的所有类,同时也为Java的运行时多态和动态绑定提供了基础。