java中对象的五个步骤

java对象的创建

根据字节码来说有以下几个步骤:
对于这句java代码一共有四个字节码指令,可以通过javac命令打印出字节码指令,或者使用idea中Jclasslib插件直接查看
图一
图二
以上字节码可以通过对象的创建步骤联系起来:

new指令:

当虚拟机遇到new的字节码指令时,会去检查该指令参数是否在运行时常量池中符号引用,并且检查该符号引用是否被类加载器加载,如果没有加载,则会执行类的加载过程。通过双亲委派机制进行加载。双亲委派机制就是一个循环的机制,如果当前一直向上委托,一个类只能通过一个类加载器加载,如果名字相同而且包名相同,但是他们的类加载器不同,则还是视为不同的类。有三个类加载器,
BootStrapClassLoader,ExtClassLoader,ApplicationClassLoader,还有一些是自定义加载器。
最后new指令将未完全初始化的对象压入操作数栈的栈顶

dup指令:

duplicate表示复制的意思,它的作用是复制栈顶元素再次压入栈,为了让this指针指向自己,所以除了静态方法外,其他的普通的方法和构造器方法都存在this指针指向对象自己

invokespecial指令:

表示执行init方法,指的是执行java代码中的构造器方法,构造完成后将对象的引用压入栈

astore_1指令:

将栈顶的引用赋值给本地变量1的位置,因为本地变量0的位置已经被this指针占用

对象分配的详细步骤

第一步:检查类的加载

当jvm遇到new字节码指令时,会去运行时常量池中查找对应的符号引用,检查对应的类对象是否被jvm加载,如果没有加载则执行类加载的过程

第二步:分配对象内存

两种方式分配对象的内存:指针碰撞(bump of pointer)和空闲列表(free list)
指针碰撞需要物理内存连续的空间,需要对应的清除整理(compact)相关的垃圾清理算法(serial)才能执行指针碰撞的分配方式。简单来说就是得知a属性需要分配n的内存,则指针偏移n就能完成对a属性的内存分配
空闲列表是一个用虚拟映射维护的一个列表,物理上不连续,但是逻辑上连续。需要对应的标记清除的垃圾清理算法(CMS)。
在对象分配内存的时候会出现并发的问题,即当a线程和b线程同时需要分配对象时,当前对象分配的指针指向n,如果a的对象如果在b的对象之后,那么b的对象就会覆盖a的对象的分配。解决的方式有两种:

1.CAS乐观锁的方式:

即用一个旧值和一个期望值比较,如果相同,则更新新的指针的位置,如果失败,则拿出内存的值赋值为旧值继续分配,直到内存分配成功为止。

2.TLAB(Thread Locale Allcotion Buffer)本地线程缓存分配

分配内存时,每一个线程都在各自的缓存空间中分配,如果内存分配空间不够时,重新使用cas的方式分配内存,可以用参数设置TLAB的大小

第三步:初始化对象赋0值

初始化对象,使对象在java代码中直接可以使用实例的属性,int设置0,boolean设置false等

第四步:设置对象头

设置对象头信息(markword和klass point),他们各占8字节和4字节(开启指针压缩,未开启为八个字节),markword中包含hashCode信息(需要调用父类Object的hashCode的方法才会使对象头的hashCode有值)、年龄分代、是否偏向锁、锁标志的信息,klassPoint表示指向方法区中的类型指针(instanceClass)。

第五步:执行init方法

最后一步需要自定义的属实,即执行构造器方法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值