学习笔记—java中对象创建在虚拟机中的过程

在java的对象创建中(普通对象,不包括class对象和数组),虚拟机遇到new指令时会有以下步骤:

1.检查这个指令的参数是否能在常量池中定位到该类的符号引用,并且检查该符号引用代表的类是否被加载、解析和初始化,若没有则先进行类的加载过程。

2.在类的加载加载检查通过后,便开始为这个对象分配内存空间(对象的内存空间大小在类的加载完成后就可以确定了)。

3.内存空间分配完了之后,虚拟机将分配到的内存空间初始化为零头(不包含对象头),若使用了TLAB,这个过程会在分配TLAB的时候完成。这个过程保证了对象的实例字段不用赋初始值即可被使用。程序能访问到该对象实例的零值。

4.虚拟机接下来将对象的元数据指针,哈希值,GC分代年龄等信息设置到对象头(Object Header)中。以及根据当前运行状态是否需要设置偏向锁等。

到这里,对于虚拟机来说。已经完成了一个对象的创建了。但是对于java程序来说,对象的创建才刚开始(init方法还未执行)。一般情况下,new指令会接着执行init方法,根据设计者的意愿初始化,此时一个真正可用的对象才会产生出来。

----------------------------------------------------

下面是堆为对象分配空间时的内容补充:

由于分配的空间是在java堆中分配的。在堆中的内存空间有两种情况:

一种是内存规整的(即已分配的使用空间是连续的,未使用的空间也是连续的),此时只需要把记录临界点的指针往未分配的空间移动等大小的内存空间即可为该对象分配空间,这种方式叫 “指针碰撞”(Bump the Pointer)

另外一种是内存非规整的(即已分配的空间非连续的)。虚拟机维护了一张列表,用来标识哪些空间是空闲可用的,在分配的时候会找到足够的空间分配给该对象。这种方式叫“空闲列表”(Free List)

内存规整与否和垃圾收集器所采用的算法是否带有压缩整理功能决定的,像Serial、ParNew带有Compact过程的收集器,采用的分配算法就是Bump the Pointer。像CMS基于Mark-Sweep算法的收集器,就采用Free List分配算法。

在堆中的内存空间是所有线程共享的,那么还存在着多线程的问题。线程A新生成的对象还未完成时(此时指针还未移动),线程B需要生成一个对象。此时便会出现问题了。该如何保证更新操作的原子性?

解决这个问题有两个方案:

1.采用CAS配上失败重试的方法

2.为每个线程分配一个TLAB(Thread Local Allocation Buffer),线程需要分配内存空间,到线程对应的TLAB上分配空间即可。这种方式可以避免线程同步,提高分配效率。只有在TLAB用完,需要分配新的TLAB时才会同步锁定。

 

 

 

 

以上为个人学习心得,若有错误感谢指出,互相学习。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值