JAVA对象在内存中的活动


一、New一个对象如何分配内存

当new一个对象时,先去常量池检查该类型的数据是否加载,解析和初始化过。
分配内存时,分配方法根据JAVA内存是否规整而决定

指针碰撞方法(内存规整时)

JAVA内存规整时,可以通过指针碰撞的方式来分配,即分配一段内存,将指针在内存中滑动一段距离,称为不同内存区域之间的分割线。(该方法是线程不安全的,比如当一个线程在分配内存时,指针还未滑动,时间片切到另一个线程,该线程就开始滑动本该分给前一个线程的指针。)
解决方法:
第一种方法:保证每一个指针碰撞的原子性:根据之前给出的例子,当本该分配给自己的内存因为上下文切换分配给其他线程了,那我们认为该操作失败,操作退回起点重新操作。
第二种方法:在内存中给每个不同线程预留不同的内存区域,每个线程从其独有的内存区域中分配内存,只有当这个内存区域被分配完之后,才能去寻找新的的内存来分配。

内存不规整时

当JAVA内存不规整时,即已使用的内存和空闲内存交错在内存中,这个时候就需要维护一个表来查该内存中哪些时空闲的内存,哪些是不空闲的内存。

初始化零值

所有对象都应该在分配到内存空间之后被赋予零值,不要等到用户来给每个变量赋值,但不要将对象头赋零值,对象头放着很多信息,虚拟机需要这些信息。

New指令之后调用Class文件中的方法执行构造函数。

二、对象在内存中布局

是HotSpot在对象中布局为:对象头,实例数据,对其填充
方法头存储的数据与用户定义的实例数据无关,存储着哈希值,GC年龄标志,锁等信息,虚拟机本来规定了对象头的最大存储方法Bitmap,但其实方法头存储的很多数据数据要大于Bitmap规定的最大存储值,所以把方法区的存储结构设置成了动态调整的存储方式,哪个数据所需内存大,就占用多一点空间。
在这里插入图片描述
有些对象头还包含类型指针,该指针代表这个对象是哪个类的实例,但不是所有对象都有这部分数据。如果对象是一个数组,对象头还应该包含该数组的长度数据。
实例数据存储的才是真正有效的数据,存储方式经常会看到相同宽度的字段会存储在一起,父类的字段存储在子类的前面。

对齐填充其实就是一个占位符,因为虚拟机要求每个类的大小都是8字节的倍数,所以填充一点满足这个条件。

三、对象的访问

对象的访问方式是不同的虚拟机实现的,JAVA规范中并未规定。
分为本地变量的reference来访问句柄和reference直接访问两种方式

1、句柄访问:间接方式

在这里插入图片描述

2、直接访问:直接方式,需要考虑对象数据放在哪里更方便访问。

在这里插入图片描述
句柄访问因为是间接访问,有一次跳转,所以效率没有直接访问高,但是当数据的位置发生改变时,句柄只需要改变指向数据指针所指向的位置就行了,Reference不用变。而直接方式访问状态下,reference需要改变。(HotSpot主要采用直接访问)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值