走进JVM -- 对象实例化

  • 根据某个类的声明一个引用变量指向被创建的对象,并使用此引用操作该对象.在实例化对象的过程中,JVM 中发生了什么化学反应呢?

(1) 从最简单的Object ref = new Object(); 代码进行分析,利用 javap -verbose -p 命令查看对象创建的字节码如下:

stack =2, locals=1, args_size=0
	NEW java/lang/Object
	DUP
	INVOKESPECIAL java/lang/Object.<init> ()V
	ASTORE_1
	LocalVariableTable:
		Start Length Slot Name Signature
		  8     1     0    ref   Ljava/lang/Object;
  • NEW :
    如果找不到Class对象,则进行类加载,加载成功后,则在堆中分配内存,从Object 开始到本类路径上的所有属性值都要分配内存. 分配完毕之后,进行零值初始化. 在分配过程中, 注意引用时占据存储空间的, 它是一个变量,占用4 个字节.这个指令完毕后,将指向实例对象的引用变量压入虚拟机栈顶.
  • DUP :
    在栈顶复制该引用变量, 这时的栈顶有两个指向堆内实例对象的引用变量. 如果 方法由参数,还需要把参数压入操作栈中.两个引用变量的目的不同,其中压至底下的引用用于赋值, 或者保存到局部变量表,另一个栈顶的引用变量作为句柄用相关方法.
  • INVOKESPECIAL :
    调用对象实例方法,通过栈顶的应用变量调用 方法, 是类初始化时执行的方法, 而 对象初始化时执行的方法

(2) 前面所述是从字节码的角度看待对象的创建过程,现在从执行步骤的角度分析:

  • 确认类元信息是否存在.
    当JVM 接收到new 指令时, 首先在 Metaspace 内检查需要创建的类元信息是否存在. 若不存在,那么在双亲委派模式下,使用当前类加载器以 ClassLoader+ 包名 + 类名为Key 进行查找对应的 .class 文件. 如果没有找到文件, 则抛出 ClassNotFoundException 异常. 如果找到,则进行类加载,并生成对应的Class类对象.
  • 分配对象内存.
    首先计算对象占用空间大小,如果实例成员变量是引用变量,仅分配引用变量空间即可,即4个字节大小,接着在堆中划分一块内存给新对象.在分配内存空间时,需要进行同步操作,比如采用CAS (Compare And Swap) 失败重试, 区域加锁等方式保证分配操作的原子性.
  • 设定默认值
    成员变量值都需要设定为默认值,即各种不同形式的零值.
  • 设置对象头.
    设置新对象的哈希码, GC信息, 锁信息, 对象所属的类元信息等. 这个过程的具体设置方式取决于JVM 实现.
  • 执行 init 方法
    初始化成员变量, 执行实例化代码, 调用类的构造方法, 并把堆内对象的首地址赋值给引用变量.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值