【Java基础】Java中new一个对象时,JVM到底做了什么?

Java中new一个对象时,JVM到底做了什么?

在Java编程中,new关键字是我们创建对象的最常用方式。但你是否想过,当你写下new MyClass()时,Java虚拟机(JVM)到底在背后做了哪些工作?今天,我们就来深入探讨一下new一个对象时,JVM的完整执行流程。


1. 类加载:对象的蓝图

当你第一次使用new创建一个对象时,JVM会首先检查这个类是否已经被加载。如果没有,JVM会通过类加载器(ClassLoader)加载该类的字节码文件(.class文件)。类加载的过程包括:

  • 加载:将类的字节码加载到内存中。
  • 验证:确保字节码是合法的,不会危害JVM的安全。
  • 准备:为类的静态变量分配内存并设置默认值。
  • 解析:将符号引用转换为直接引用。
  • 初始化:执行类的静态初始化块(static {})和静态变量的赋值操作。

类加载完成后,JVM就可以基于这个“蓝图”创建对象了。


2. 内存分配:为对象安家

类加载完成后,JVM会为对象在堆内存(Heap)中分配一块空间。这块空间的大小是由对象的成员变量决定的。例如,如果一个类有两个int类型的变量和一个String类型的变量,那么JVM会分配足够的内存来存储这些数据。

注意:Java的堆内存是所有线程共享的,因此内存分配需要考虑线程安全问题。JVM会通过指针碰撞(Bump the Pointer)或空闲列表(Free List)等机制来高效地分配内存。


3. 初始化默认值:清零操作

在内存分配完成后,JVM会将对象的成员变量初始化为默认值。这些默认值包括:

  • 数值类型(如intlongdouble等)的默认值为00.0
  • 布尔类型(boolean)的默认值为false
  • 引用类型(如StringObject等)的默认值为null

这一步确保了对象在构造函数执行之前,所有的成员变量都有一个已知的初始状态。


4. 执行构造代码块:对象的“热身”

如果类中定义了构造代码块(即在类中直接使用{}包裹的代码),JVM会在调用构造函数之前执行这些代码。构造代码块通常用于执行一些通用的初始化逻辑。

例如:

public class MyClass {{System.out.println("构造代码块执行");}
}

无论调用哪个构造函数,构造代码块都会被执行。


5. 调用构造函数:对象的“出生”

接下来,JVM会调用与new语句匹配的构造函数。构造函数的主要作用是对对象进行进一步的初始化。例如:

public class MyClass {private int value;public MyClass(int value) {this.value = value;System.out.println("构造函数执行");}
}

在构造函数中,你可以为成员变量赋值,或者调用其他方法来完成对象的初始化。


6. 返回引用:对象的“身份证”

当所有初始化操作完成后,new操作会返回对象在堆内存中的引用。这个引用实际上是一个指向堆内存中对象地址的指针。程序通过这个引用来操作对象。

例如:

MyClass obj = new MyClass(10);

这里的obj就是一个引用,它指向堆内存中MyClass对象的地址。


总结:new操作的完整流程

让我们用一个简单的例子来总结new一个对象时的完整流程:

public class MyClass {private int value;{System.out.println("构造代码块执行");}public MyClass(int value) {this.value = value;System.out.println("构造函数执行");}public static void main(String[] args) {MyClass obj = new MyClass(10);}
}

输出结果:

构造代码块执行
构造函数执行

从输出中可以看到,JVM首先执行了构造代码块,然后调用了构造函数。


思考:new操作的性能开销

虽然new操作看起来很简单,但它背后涉及了类加载、内存分配、初始化等多个步骤,这些操作都会带来一定的性能开销。因此,在高性能场景下,我们需要尽量避免频繁创建对象,或者使用对象池(Object Pool)等技术来优化性能。


结语

通过本文的讲解,相信你对Java中new一个对象时的完整流程有了更深入的理解。无论是类加载、内存分配,还是构造代码块和构造函数的执行,每一步都是JVM精心设计的。掌握这些底层细节,不仅能帮助你写出更高效的代码,还能让你在面试中脱颖而出。

如果你觉得这篇文章对你有帮助,欢迎点赞、转发,并在评论区分享你的看法!我们下期再见!


关注我,获取更多技术干货!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/896507.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内网穿透:打破网络限制的利器

目录 深入理解内网穿透 内网与外网的奥秘 内网穿透的原理剖析 总结与展望 在如今这个数字化时代,网络已经成为我们生活和工作中不可或缺的一部分。但你是否遇到过这样的困扰:在家办公时,想要访问公司内部的文件服务器,却因为网…

【汽车ECU电控数据管理篇】HEX文件格式解析篇章

一、HEX格式文件是啥 HEX 文件是 Intel 公司提出的一种按地址排列的数据信息格式,通常用于存储嵌入式系统的二进制代码。它以 ASCII 码的形式记录数据,每一行以冒号开头,包含数据长度、地址、记录类型、数据和校验码等信息。HEX 文件常用于程…

深入理解 CSS pointer-events: none:穿透点击的魔法

一、什么是 pointer-events: none? pointer-events: none 是一个强大的 CSS 属性,它控制元素是否响应鼠标/触摸事件(如点击、悬停、拖拽)。当设置为 none 时,元素会变得“透明”,事件会直接穿透到下方的元…

【AHK】资源管理器自动化办公实例/自动连点设置

此处为一个自动连续点击打开检查的自动化操作案例,没有quicker的鼠键录制,不常用了,做个备份 #MaxThreadsPerHotkey 2 ; 这个是核心!!!!确保可以同时运行多个热键或标签global isRunning : tru…

html css js网页制作成品——HTML+CSS甜品店网页设计(5页)附源码

目录 一、👨‍🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨‍&#x1f…

Springboot使用Milvus的基本操作

Milvus 先得保证数据的正确安装并且正确运行 <dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId> </dependency> <dependency><groupId>io.milvus</groupId><artifactId>milvu…

初阶数据结构(C语言实现)——3顺序表和链表(2)

2.3 数组相关面试题 原地移除数组中所有的元素val&#xff0c;要求时间复杂度为O(N)&#xff0c;空间复杂度为O(1)。OJ链接 力扣OJ链接-移除元素删除排序数组中的重复项。力扣OJ链接-删除有序数组中的重复项合并两个有序数组。力扣OJ链接-合并两个有序数组 2.3.1 移除元素 1…

【力扣】2619. 数组原型对象的最后一个元素——认识原型与原型链

【力扣】2619. 数组原型对象的最后一个元素——认识原型与原型链 文章目录 【力扣】2619. 数组原型对象的最后一个元素——认识原型与原型链题目解决方案概述全局上下文函数上下文事件处理程序构造函数上下文类上下文显式 / 隐式绑定绑定方法和永久 this 上下文 方法 1&#xf…

ubuntu终端指令集 shell编程基础(一)

磁盘指令 连接与查看&#xff1a;磁盘与 Ubuntu 有两种连接方式&#xff1b;使用ls /dev/sd*查看是否连接成功&#xff0c;通过df系列指令查看磁盘使用信息。若 U 盘已挂载&#xff0c;相关操作可能失败&#xff0c;需用umount取消挂载。磁盘操作&#xff1a;使用sudo fdisk 磁…

基于Spark的电商供应链系统的设计与实现

目录 1.研究背景与意义 2、国内外研究现状 3、相关理论与技术 &#xff08;一&#xff09;分布式计算系统Spark &#xff08;二&#xff09;数据仓库Hive &#xff08;三&#xff09;读取服务器本地磁盘的日志数据Flume &#xff08;四&#xff09;分布式消息队列Kafka …

使用TortoiseGit配合BeyondCompare实现在Git仓库中比对二进制文件

使用TortoiseGit的比对工具可以直接右键&#xff0c;点击选择比对和上一版本的变化差异&#xff1a; 但是TortoiseGit只能支持比对纯文本文件的变化差异&#xff0c;如果尝试比对二进制文件&#xff0c;会提示这不是一个有效的文本文件&#xff1a; BeyondCompare可以比对二进制…

BladeX框架接口请求跨域

前端使用代理请求接口&#xff0c;接口可以正常访问。如果换全路径请求就跨域。 除了后端要配置跨域 还需要修改配置文件对OPTIONS请求的限制

Vue.js响应式基础

响应式基础​ API 参考 本页和后面很多页面中都分别包含了选项式 API 和组合式 API 的示例代码。现在你选择的是 组合式 API。你可以使用左侧侧边栏顶部的“API 风格偏好”开关在 API 风格之间切换。 声明响应式状态​ ref()​ 在组合式 API 中,推荐使用 ref() 函数来声明…

选开源CMS建站系统时,插件越多越好吗?

在选择开源CMS建站系统时&#xff0c;插件数量并不是唯一的衡量标准&#xff0c;更不能简单地说“插件越多就越好”&#xff0c;还是需要综合评估来考虑选择结果&#xff0c;以下是有关选择开源CMS系统时对插件数量的考量。 插件数量的优势插件数量可能带来的问题功能丰富性&a…

在VSCode中使用MarsCode AI最新版本详解

如何在VSCode中使用MarsCode AI&#xff1a;最新版本详解与使用场景 在当今快速发展的软件开发领域&#xff0c;人工智能&#xff08;AI&#xff09;技术的应用已经变得越来越普遍。ByteDance推出的MarsCode AI是一款强大的AI编程助手&#xff0c;旨在帮助开发者更高效地编写代…

mac修改docker的daemon.json 镜像文件

1、找到daemon.json文件的位置 docker info 可以看出位置在&#xff1a; /Users/spuer/.docker 2. 进入daemon.json 所在的目录&#xff1a; cd /Users/spuer/.docker3. 查看daemon.json的内容&#xff1a; more daemon.json可以看出&#xff0c;没有配置registry-mirrors&…

5.10 P-Tuning v2:多层级提示编码的微调革新

P-Tuning v2:多层级提示编码的微调革新 一、技术架构解析 #mermaid-svg-4Wy6vkXZi67hY9PZ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-4Wy6vkXZi67hY9PZ .error-icon{fill:#552222;}#mermaid-svg-4Wy6vkXZi67h…

Eclipse 编译项目指南

Eclipse 编译项目指南 引言 Eclipse 是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;广泛用于Java、C/C、Python等多种编程语言的开发。在Eclipse中编译项目是进行软件开发的基础步骤。本文将详细介绍如何在Eclipse中编译项目&#xff0c;包括项目设置…

【大语言模型】【整合版】DeepSeek 模型提示词学习笔记(散装的可以看我之前的学习笔记,这里只是归纳与总结了一下思路,内容和之前发的差不多)

以下是个人笔记的正文内容: 原文在FlowUs知识库上&#xff0c;如下截图。里面内容和这里一样&#xff0c;知识排版好看一点 一、什么是 DeepSeek 1. DeepSeek 简介 DeepSeek 是一家专注于通用人工智能&#xff08;AGI&#xff09;的中国科技公司&#xff0c;主攻大模型研发与…

【缓存】缓存雪崩与缓存穿透:高并发系统的隐形杀手

缓存雪崩与缓存穿透&#xff1a;高并发系统的隐形杀手 在高并发系统中&#xff0c;缓存是提升性能的重要手段。然而&#xff0c;缓存使用不当也会带来一系列问题&#xff0c;其中最常见的就是缓存雪崩和缓存穿透。这两个问题如果不加以解决&#xff0c;可能会导致系统崩溃&…