【JVM】Java对象创建的流程步骤

简介: 【JVM】Java对象创建的流程步骤

· 本文摘要

· 罗列Java创建对象的各种方式;

· 讲解Java对象创建的流程步骤;

一、Java创建对象的各种方式


   · 1. 用关键字new,老少皆知的方法:StringBuffer sb = new StringBuffer();

   · 2. 在单例模式(一种设计模式)中创建对象,本质上也是用关键字new,见下面的代码示例:

/**
 * 单例模式
 * 饿汉式(静态常量)
 */
public class BaseConfig {
    private final static BaseConfig INSTANCE = new BaseConfig();
    private BaseConfig () {}//私有构造子
    public static BaseConfig getInstance() {//在这里返回对象,其实也用了new
        return INSTANCE;
    }
}

   · 3. 在工厂模式Factory、建造者模式Builder(也是设计模式)中创建对象,本质上也是用关键字new。

   · 4. 反射机制,利用Class.newInstance()。值得注意的是,Class.newInstance()创建对象时的特点有:弱类型,低效率,只能调用无参构造。这里还需要区别Class.forName(),Class.forName()返回的是一个类,并不是对象。

 · 5. 利用Constructor.newInstance()。Constructor.newInstance()可以调用任意构造函数。

   · 6. 使用克隆clone(),使用前保证对象实现了cloneable()。

   · 7. 反序列化。开发中经常会对类实现序列化接口,反序列化支持我们把二进制数据、网络数据转化为Java对象保存在内存中。

   · 8. 使用第三方库Objenesis。

二、Java创建对象的步骤


   · 第一步:检测类是否已经加载。

  当JVM即将创建对象前,先去检查常量池中是否有此类的符号引用,并且检查此类是否已加载、链接、初始化。如果没有,需要类加载器来加载此类,参考:类加载器基础知识。

   · 第二步:为对象分配内存。

类加载完成以后,虚拟机就开始为对象分配内存,此时所需内存的大小就已经确定了。只需要在堆上分配所需要的内存即可。


   具体的分配内存有两种情况:第一种情况是内存空间绝对规整,第二种情况是内存空间是不连续的。


       · 指针碰撞:假设Java堆中内存是绝对规整的,所有用过的内存都放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离,这种分配方式称为“指针碰撞”(Bump the Pointer)。


       · 空闲列表:如果Java堆中的内存并不是规整的,已使用的内存和空闲的内存相互交错,那就没有办法简单地进行指针碰撞了,虚拟机就必须维护一个列表,记 录上哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例, 并更新列表上的记录,这种分配方式称为“空闲列表”(Free List)。


 · 第三步:处理并发安全问题。

由于对象分配的内存是放在堆中的,堆作为线程共享的数据区,当线程数大于1时,会涉及到线程安全问题。需要通过一定的方式来处理并发安全问题。

   第一种是采用同步的办法,为对象空间加锁,使用CAS来保证操作的原子性。

   另一种是每个线程分配内存都在自己的空间内进行,即是每个线程都在堆中预先分配一小块内存,称为本地线程分配缓冲(TLAB),分配内存的时候再TLAB上分配,互不干扰。


 · 第四步:初始化分配的空间。

内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头), 如果使用TLAB,这一工作过程也可以提前至TLAB分配时进行。这一步操作解释了对象的实例字段在Java代码中为什么可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。


 · 第五步:设置对象头。

   分配完内存空间,初始化零值之后,虚拟机还需要对对象进行其他必要的设置,设置的地方都在对象头中,包括这个对象所属的类,类的元数据信息,对象的hashcode,GC分代年龄等信息。

在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了。但从Java程 序的视角来看,对象创建才刚刚开始<init>方法还没有执行,所有的字段都还为零。

  · 第六步:执行init方法(执行构造器)。

相关文章
|
12月前
|
设计模式 网络协议 数据可视化
Java 设计模式之状态模式:让对象的行为随状态优雅变化
状态模式通过封装对象的状态,使行为随状态变化而改变。以订单为例,将待支付、已支付等状态独立成类,消除冗长条件判断,提升代码可维护性与扩展性,适用于状态多、转换复杂的场景。
1223 157
|
缓存 安全 Java
Java反射机制:动态操作类与对象
Java反射机制是运行时动态操作类与对象的强大工具,支持获取类信息、动态创建实例、调用方法、访问字段等。它在框架开发、依赖注入、动态代理等方面有广泛应用,但也存在性能开销和安全风险。本文详解反射核心API、实战案例及性能优化策略,助你掌握Java动态编程精髓。
|
前端开发 Java API
2025 年 Java 全栈从环境搭建到项目上线实操全流程指南:Java 全栈最新实操指南(2025 版)
本指南涵盖2025年Java全栈开发核心技术,从JDK 21环境搭建、Spring Boot 3.3实战、React前端集成到Docker容器化部署,结合最新特性与实操流程,助力构建高效企业级应用。
3402 1
|
JavaScript 安全 前端开发
Java开发:最新技术驱动的病人挂号系统实操指南与全流程操作技巧汇总
本文介绍基于Spring Boot 3.x、Vue 3等最新技术构建现代化病人挂号系统,涵盖技术选型、核心功能实现与部署方案,助力开发者快速搭建高效、安全的医疗挂号平台。
550 3
|
消息中间件 Java 数据库
Java 基于 DDD 分层架构实战从基础到精通最新实操全流程指南
本文详解基于Java的领域驱动设计(DDD)分层架构实战,结合Spring Boot 3.x、Spring Data JPA 3.x等最新技术栈,通过电商订单系统案例展示如何构建清晰、可维护的微服务架构。内容涵盖项目结构设计、各层实现细节及关键技术点,助力开发者掌握DDD在复杂业务系统中的应用。
2195 0
|
Java 编译器
Java 17 Switch表达式:更简洁、更强大的流程控制
Java 17 Switch表达式:更简洁、更强大的流程控制
1377 111
|
存储 人工智能 JavaScript
Java从作用域到对象高级应用​
本内容详细讲解了JavaScript中的作用域类型(函数作用域、块作用域、全局作用域)、作用域链、垃圾回收机制、闭包、变量提升、函数参数、数组方法、内置构造函数、对象高级知识、原型链、对象赋值、深浅拷贝、递归、异常处理及this指向等内容,全面覆盖JS核心概念与编程技巧。
193 0
JAVA基础——三种流程控制语句
JAVA基础——三种流程控制语句
475 0
JAVA基础——三种流程控制语句
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
629 1
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
560 1