JAVA中对象的创建过程

第一步
虚拟机遇到一条new指令时,会先判断这个指令的参数是否能在常量池中找到这个类的符号引用,并且会判断这个类是否被加载。如果没有被加载的话,则执行类加载过程(可以参考上一篇类加载文章)。
第二步
为对象分配内存,主要分为两种:指针碰撞或者空闲链表。指针碰撞要求内存绝对规整,分配内存时只要把指针往空闲端挪动一段与要分配对象大小相等的距离就可以了。空闲链表不要求内存是否规整,它维护了一张列表,记录哪些空间是可用的。因此,在选择哪种内存分配方式时,取决于内存是否规整。而内存是否规整又取决于所使用的垃圾回收算法是否产生内存碎片。Serial、Serial Old、ParNew、Parallel Scavenge、Parallel Old、G1收集器都不会产生内存碎片,而CMS收集器会产生内存碎片。
另外,JAVA堆是所有线程共享的一块区域,因此会存在并发分配问题。JVM采用的方式是使用CAS+失败重试的方式,或者TLAB(事先为每个线程划分一块内存,这样线程在申请使用内存时,先使用事先分配的内存,只有不够时,才会再想JVM申请新内存,这样减少了线程同步带来的影响)的方式进行分配内存。内存分配完,就将内存空间初始化为零值。
第三步
对对象进行必要的设置,包括设置对象头(实例是哪个类的实例、类的元信息位置、GC分代年龄等),执行方法(在执行init方法之前,所有的字段都为零)。
额外:
(1)对象的定位访问有:句柄和直接访问。
(a)句柄池保存在JAVA堆中。JAVA堆中的引用指向句柄池,再由句柄池指向方法区中对象的类型以及JAVA堆中的对象实例数据。使用句柄池的好处是,对象被移动时JAVA栈中的引用可以保持不变,只要改变句柄池中指向实例数据的指针即可。
(b)直接访问是JAVA栈中的引用直接指向JAVA堆,因此可以直接访问到对象的实例数据,在对象的实例数据中有指向方法区该对象所属类型的指针。使用直接访问的好处是速度更快。
(2)对象在内存中存储的布局可以分为3块区域:
(a)对象头,里面记录了该对象的哈希码、GC分代年龄、锁状态标识等。
(b)实例数据,为对象真正存储的数据,即程序代码定义的内容,包括父类继承下来的和子类中定义的。
(c)对齐填充,为了保证对象占用的内存为8字节的倍数,如果实际对象占用内存大小不是8字节时,会进行填充以满足要求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值