Java对象实例化与JVM内存分配详解

需积分: 5 0 下载量 179 浏览量 更新于2024-08-05 收藏 91KB MD 举报
"JVM-2.md" 在Java编程中,JVM(Java Virtual Machine)是开发者从初学者向高级程序员进阶过程中不可或缺的部分。本文主要探讨了对象实例化和访问定位,以及对象创建的具体过程。 ### 7.1 创建对象的方式 1. **new 关键字**:这是最常见的创建对象的方式,通过调用类的构造器来创建实例。 2. **单例类的getInstance**:在静态类方法中调用,确保类只有一个实例。 3. **Class.newInstance**:使用反射来创建对象,但在JDK 9中已被标记为过时,因为它只能调用公共无参数构造器。 4. **Constructor.newInstance**:同样使用反射,但可以调用任意参数的构造器,对构造器的权限没有要求。 5. **clone()**:不调用构造器,但需要类实现`Cloneable`接口并重写`clone()`方法。 6. **反序列化**:从文件或网络中读取序列化的对象数据来恢复对象。 ### 7.2 对象创建的过程 #### 7.2.1 加载类元信息 当JVM遇到`new`指令,它会在常量池中查找类的符号引用,并检查该类是否已加载、解析和初始化。如果未加载,会使用双亲委派模型,由类加载器根据ClassLoader+包名+类名找到相应的`.class`文件,找不到则抛出`ClassNotFoundException`。加载完成后,生成对应的Class对象,这被称为**加载阶段**。 #### 7.2.2 分配内存 加载检查通过后,JVM将为新对象分配内存。对象所需的内存大小在类加载后即可确定。内存分配主要有两种方式: 1. **指针碰撞**:当堆内存是规整的,所有已使用的内存集中在一端,分配内存就是简单地移动指针。 2. **空闲列表**:如果堆内存不规整,JVM需要维护一个空闲列表来记录可用内存块。 ### 对象分配内存的细节 - **线程安全**:在多线程环境下,内存分配通常需要同步,以避免数据竞争。如`CAS`(Compare and Swap)操作保证分配的安全性。 - **TLAB(Thread Local Allocation Buffer)**:为了减少全局锁的开销,JVM允许每个线程有自己的内存分配缓冲区,提升并发性能。 ### 7.2.3 初始化 内存分配后,接下来是对象的初始化,包括字段的默认初始化(零值或null),然后执行构造器代码,完成特定对象的初始化工作。 ### 7.2.4 对象的访问定位 对象创建完成后,需要通过引用访问,JVM使用句柄和直接指针两种方式来实现。句柄方式通过一个指针到句柄池,再由句柄到实际对象,而直接指针方式则是直接指向对象实例。 总结来说,理解JVM中对象实例化和访问定位的原理,对于优化代码性能、解决内存泄漏等问题具有重要意义,同时也是面试中常见的知识点。深入学习这些内容,有助于提升作为Java开发者的专业技能。