![](https://csdnimg.cn/release/download_crawler_static/88567539/bg1.jpg)
Jvm 对象内存分配:
对象的创建:
类加载检查、是否加载类 、加载类、分配内存、初始化、执行<int>方法
1、 类检查:
虚拟机遇见一条 new 指令后,首先将去检查这个指令参数是否能在常量池中定位
一个类的符号引用,并且检查这个符号引用代表的类是否被加载过,解析和初始化,
如果没有则必须执行相应的类加载过程。
New 指令对应到语言层次:new 关键词、对象的克隆、对象序列化等。
2 内存分配:
在类加载检查通过后,虚拟机将为新的对象分配内存,对象所需内存大小在类加载完成
后便可完全确定,为对象分配空间的任务把一块确定大小的内存从 Java 堆中划分出来,
有两个问题,
1、 如何划分内存,
2、 在并发情况下,可能会出现正在给对象 a 分配内存,指针还没来的及进行修改,
对象 b 又同时使用了原来的指针来分配内存的情况。
划分内存方法:
指针碰撞:
在 Java 堆中内存是绝对规整的,所有用过的内存都放在了一边,空闲的内存放在
另外一边,中间放一个指针作为分界点的指示器,那所分配的内存就仅仅是把那个指针向空
闲的那边进行挪动一段与对象大小相等的距离。
空闲列表
如果 Java 堆中的内存并不规整,已使用的内存和空闲内存相互交错,没有办法进
行简单的指针碰撞,而虚拟机就必须维护一个列表,记录上哪些内存块中可用的,在分配的
时候从列表中找到一块足够大的空间分配给对象实例,并且更新到列表上的记录。
解决并发问题:
Cas
虚拟机采用 cas 配上失败重试的方式来保证操作的原子性来对分配的空间动作进
行同步处理。
本地线程分配缓冲(thread local allocation buffer ,tlab)
把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在 Java 堆中
预先分配一小块内存,通过-xx:+/usertlab 参数来设置虚拟机是否使用 TLAB,-xx:tlabsize 指
定 tlab 的大小。
3、初始化
内存分配后,虚拟机需要将分配到内存空间都是初始化为零,但是不包括对象头,
如果使用 tlab,在这一工作过程中也可以提前至 tlab 分配时进行,这一步操作保证了对象的
实例字段在 Java 代码中可以不赋初始值就直接使用,程序访问到这些字段所对应的零值。
4、 设置对象头
初始化零值后,虚拟机要对对象进行必要的设置,这个对象是那个类的实例,如果
才能找到类的元数据信息、对象的哈希码、对象的 gc 分代年龄等信息,这些信息都放
在了对象的对象头 object header 中
在 hotspot 虚拟机中,对象在内存中存储布局分为三部分:对象头(header)、实例数
据 和对齐填充(padding)。
Hotspot 虚拟机的对象头包括两个部分信息,第一部分用于存储对象自身的运行数据,