理解java对象

本文深入剖析Java对象从创建到访问的全过程,包括类加载检查、内存分配、初始化零值、设置对象头、执行初始化方法,以及对象内存布局和访问方式。

本文用于探讨Java对象的创建、布局和访问的全过程:

对象的创建过程:

  1. 类加载检查:


    虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程。

  2. 分配内存


    在类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从 Java 堆中划分出来。

  3. 初始化零值


    内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值,这一步操作保证了对象的实例字段在 Java 的数据类型所对应的零值。代码中可以不赋初始值就直接使用,程序能访问到这些字段

  4. 设置对象头


    设置此对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息。 根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。

  5. 执行 init 方法


    在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但从 Java 程序的视角来看,对象创建才刚开始,<init> 方法还没有执行,所有的字段都还为零。执行 new 指令之后会接着执行 <init> 方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来。

内存分配方式:

  1. 指针碰撞:


    假如java堆是完全规整的,用过的放在一边,空闲的放在另一边中间放置一个指针作为分界点的指示器,此时分配内存就是将指针往空闲空间挪动对象大小相同的距离

  2. 空闲列表:


    假如java堆不是规整的,已使用的和空闲的相互交错,此时虚拟机必须维护一个列表,记录哪些是可用在分配时找到一块足够的内存空间划分给对象实例,更新表中记录。

  3. 对象频繁创建时内存分配注意事项:


    并发情况下出现线程不安全情况,给对象A分配内存,指针还没来得及修改,对象B也使用了原来指针来分配内存情况。解决方案有两种:

1. 虚拟机采用CAS失败重试来保证更新操作的原子性

2. 把内存分配动作按照线程划分在不同的空间之中,即每个线程在java堆中预先分配一小块内存,称为本地线程分配缓冲TLAB。哪个线程要分配内存,就在哪个线程的TLAB上分配,只有TLAB用完并分配新的内存时,才需要同步锁定。虚拟机是否使用,可通过-XX:+/-UseTLAB参数来设定。

对象内存布局:

对象在内存中的布局可分为3块区域:对象头、实例数据和对齐填充。

对象头:java对象头分为两部分Mark Word和Klass Point 

Mark Word:用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。

Klass Point:对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。

32位操作系统下对象的对象头组成如下:

对象寻址访问:

建立对象是为了使用对象,Java程序需要通过栈上的reference数据来操作堆上的具体对象。由于reference类型只规定了一个指向对象的引用,对象的访问方式由虚拟机实现,主流的访问方式有“句柄”和“直接指针”两种方式。

  1. 句柄访问


    java堆会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址。JVM栈中的栈帧中的本地变量表中所存储的引用地址是这个对象所对应的句柄地址,而非对象本身的地址。句柄池中的一个个对象地址有两部分组成,一部分就是对象数据在堆内存中实例池中的地址,另一部分就是对象类型在方法区中的地址。   
    好处:reference存储稳定的句柄地址,在对象被移动时只改变句柄的实例数据指针,reference本身不变。

  2. 直接指针访问


    JVM栈中的栈帧中的本地变量表中所存储的引用地址就是实例数据的地址。通过这个引用就能直接获取到实例数据的地址。
    好处:访问速度快,节省了一次访问定位的开销,由于Java中对象的访问非常频繁,所以这种方式能节约很多寻址时间。

        

 

 

 

 

 

 

 

 

 

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值