首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >java对象的创建过程

java对象的创建过程

作者头像
贪挽懒月
修改2021-11-29 11:00:26
修改2021-11-29 11:00:26
6650
举报
文章被收录于专栏:JavaEEJavaEE
  • 面试官:创建java对象有哪几种方式?
  • 小白:new、clone、反射、反序列化。
  • 面试官:那你知道 new 一个对象的时候,JVM 做了哪些事吗?说说具体的过程。
  • 小白:就是 new 一下,然后在堆分配内存 ……
  • 面试官:你先回家等通知吧。

所以你知道 new 一个对象的时候做了哪些事,具体过程是怎样的吗?其实主要经历了如下过程:

  • 检查类是否加载过;
  • 分配内存;

1. 检查类是否加载过:

在之前 JVM 系列文章中说过,类通过 ClassLoader 生成一个模板,这个模板放在方法区(1.7的实现叫永久代,1.8的实现叫元空间),这个模板就包含了类的结构信息,包括方法、属性、常量池等。 new 一个对象的时候,首先会检查是否已经生成了类的模板。如果有,就直接拿来用;如果没有,就先加载类生成类的模板。

2. 分配内存:

经过了第一步之后,就要为对象分配内存,这个过程在堆中进行。分配内存有两种方式,一个叫指针碰撞,一个叫空闲列表。至于具体用哪种方式,取决于堆内存是否连续。之前的 JVM 垃圾回收文章中说到过,如果采用标记清除算法进行垃圾回收,就会产生内存碎片,如果是用标记整理,就不会有内存碎片。如果没有内存碎片,就用指针碰撞,否则就用空闲列表。

  • 指针碰撞:用过的内存放一边,没用过的放另一边,中间有个指针作为分界线,采用该方式为对象分配内存时,只需要将指针向未用过的内存方向移动对象所需内存大小即可。
  • 空闲列表:有内存碎片的时候,虚拟机会维护一个列表,列表记录了哪些位置的内存是可用的,给对象分配内存时就会找一块够大的内存去分配,然后更新列表记录。

3. 初始化零值:

什么叫初始化零值?你有没有发现,我们在类中定义的成员变量,是不需要赋初始值也可以使用的,而局部变量,没进行初始化去使用就会报错。这是为什么呢?就是因为在对象的创建过程中有“初始化零值”这一步。比如定义了一个 int 类型的成员变量,拿来用的时候,默认值是0,而不是null,这就是初始化零值。

4. 设置对象头:

什么是对象头?JVM 在存储对象时,增加的一些标记字段,用于增强对象的功能,这就是对象头。java 对象头包括:

  • Mark word:存储对象自身的一些数据,比如 hashCode,gc 分代年龄等;
  • Klass pointer:存储指针,JVM 通过这个指针来确定该对象是哪个类的实例;
  • array length:如果对象是数组,那么还会存储数组的长度。

5. 执行init方法:

经过上面四个步骤,一个新的 java 对象就已经产生了,最后就是执行 init 方法,让对象按照程序猿的意愿,进行初始化。什么叫按照程序猿的意愿初始化?就是你 new 对象的时候传了哪些参数,属性值是什么。

内存分配的过程中,如何保证线程安全呢?JVM 采用 TLAB + CAS 的方式保证线程安全。

TLAB 就是为每个线程预先在伊甸园区分配一块内存,JVM 要给对象分配内存的时候,首先会用 TLAB,即预先分配的这块内存,如果不够,就用 CAS 一直重试。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/8/9 上午,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档