java并发编程笔记_01_对象头_对象内存布局_创建对象过程

java并发编程笔记_ 01 _储备知识

在学习java并发编程之前,首先要有一定的储备知识作为前提,本次以对象创建过程,对象内存布局,以及对象头做详细介绍,目的是为了更好的学习java并发编程。

1、对象创建过程

1、判断对象对应的类是否加载,解析,初始化

当jvm检测到字节码指令的new 关键字的时候,首先去检查这个指令参数能否在元空间的常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经走过类加载器的那三个阶段(加载,解析,初始化),就是判断类元信息是否存在,如果没有,那么就在双亲委派的模式下(双亲委派机制在这里不做过多解释),使用当前的类加载器以ClassLoader+包名+类名为key进行查找对应的 .class 文件。如果没有找到该.class文件则就会抛出 ClassNotFoundException ,如果可以成功的找到,则进行类的加载,并且声明对应的Class类对象

2、为对象分配内存

首先计算对象所占空间大小,接着在堆中划分一块内存给新对象(思考一个问题:堆中一定是线程共享的吗?),如果实例成员变量是引用变量,仅分配引用变量空间即可,即4个字节。

那么上面那句话是什么意思?

package cn.cmysz.blog;

public class ObjectAssignment {
    private String user;  --->引用变量
    private int age;      --->非引用变量
    private Dog dog;	  --->引用变量
}

class Dog{

}

如果当前内存是规整的,那么虚拟机将会采用指针碰撞法来为对象分配内存。意思就是所有用过的内存放在一边,空闲的内存在另一边,就好像是一个班级里面有四排桌子,其中两排紧挨着的已经被占用,那么,另外两排的就是空闲的,空闲的空间与被占用的空间就显的比较规整,中间放着一个指针作为分界点的指示器,分配内存就仅仅是把指针指向空闲那边挪一段与对象大小相等的距离罢了。如果垃圾收集器选择的是Serial、ParNew这种基于压缩算法的,虚拟机采用这种方式分配。

一般使用带有compact(整理过程的收集器时,使用指针碰撞)

如果内存不规整,已使用的内存和未使用的内存相互交错,虚拟机就需要维护一个列表,使用空闲列表分配。

意思就是虚拟机维护了一个列表,记录上哪些内存是可用的,再分配的时候从列表中找到足够大的空间为这个对象来分配内存,并且更新列表上的内容,这种分配方式就叫做空闲列表法(可以自己结合生活中的例子进行脑补)

说明:选择哪种分配方式是由java堆的规整性来决定的,而jav堆是否规整则又是由垃圾回收器是否带有压缩功能来决定的。

3、处理并发安全问题

在分配内存空间时,另外一个问题是及时保证new对象时候线程的安全性:创建对象是非常频繁的操作,虚拟机需要解决并发问题。虚拟机采用了两种方式解决并发问题:

1、cas(Compare And Swap)失败重试、区域加锁:保证指针更新操作的原子性

2、TLAb把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲区(TLAB,Thread Local Allocation Buffer)虚拟机 是否使用TLAB,可以通过-XX:+/-UserTLAB参数来决定。

4、初始化分配到的空间

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

5、设置对象的对象头

将对象的所属类(即类的元数据信息)、对象的HashCode和对象的GC信息、锁信息等数据存储在对象的对象头中。这个过程的具体设置方式取决于JVM实现。

6、执行init方法进行初始化

在Java程序的视角看来,初始化才正式开始。初始化成员变量,执行实例化代码块,调用类的构造方法,并把堆内存的对象的首地址赋值给引用变量。

因此一般来说(由字节码中是否跟随有invokespecial指令所决定),new指令之后会接着就是执行方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全创建出来。

2、对象内存布局

上图:

在这里插入图片描述

3、对象头

由于是为了学习java并发编程做知识提前储备,所以要介绍对象头

上图可以看出对象头主要是有两部分组成一个是markwork,一个是类型指针。当然这是正常一个对象的情况,如果是数组对象,在对象头中还应该存储数组的长度信息。

我们主要介绍markwork中都有那些内容,也是为了学习java并发编程做前提储备

32位操作系统对象头中markword:

64为操作系统对象头中markword:

其中的markword我们在下一个章节中介绍。。。。。

本文参照视频:
https://www.bilibili.com/video/BV1jE411j7uX?p=88
https://www.bilibili.com/video/BV1PJ411n7xZ?p=2
感谢视频中的两位老师的讲解,让我收获丰厚

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值