系统相关
首页 > 系统相关> > JVM面试(三)-对象创建、分配内存、对象的内存布局、对象访问定位

JVM面试(三)-对象创建、分配内存、对象的内存布局、对象访问定位

作者:互联网

对象创建、分配内存、对象的内存布局、对象访问定位

对象创建方式

对象创建过程

  1. 虚拟机遇到一条new指令时,先检查 常量池 是否 已经 加载相应的类,如果没有,必须先执行相应的类加载,也就是 检查 这个new指令的参数 是否能 在常量池中 定位到一个类的 符号引用,并且检查 这个符号引用代表的类 是否已经被加载、解析、初始化过
  2. 类加载通过后,接下来分配内存,对象所需的内存大小 在 类加载完成后 便可以确定。为对象分配空间 = 把一块确定大小的内存 从 java堆中划分出来
  3. 内存分配完成后,jvm要将 分配到的内存空间 都初始化为零值。这一步操作保证了 对象的实例字段 在java代码中 可以不赋初始值就能直接访问,程序能访问到 这些字段的 数据类型 所对应的零值
  4. 接下来jvm要对 对象 进行必要的设置,例如,这个对象 是哪个类的实例、如何能找到类的元数据信息、对象的hash码、对象的GC分代年龄等信息。这些信息 存放在 对象的对象头中
  5. 执行new指令之后会接着执行init方法,把对象 按照程序员的意愿进行初始化

为对象分配内存

指针碰撞

如果Java堆的内存是规整,即所有用过的内存放在一边,而空闲的的放在另一边
分配内存时 将 位于中间的指针指示器 向空闲的内存移动一段 与 对象大小相等的距离,这样便完成分配内存工作

空间列表

如果Java堆的内存不是规整的,则需要 由虚拟机 维护一个列表 来记录 那些内存是可用的,这样在分配的时候 可以从列表中 查询到 足够大的内存分配给对象,并在分配后更新列表记录

选择哪种分配方式是由 Java 堆是否规整来决定的,而 Java 堆是否规整 又由 所采用的 垃圾收集器 是否 带有压缩整理功能决定

处理并发安全问题

对象的创建在虚拟机中是一个非常频繁的行为,哪怕只是修改一个指针所指向的位置,在并发情况下也是不安全的,有可能出现正在给对象A分配内存,指针还没来及修改,对象B又同时使用了原来的指针来分配内存的情况
两种解决方案

TLAB

TLAB内存空间位于Eden区。默认TLAB大小为占用Eden Space的1%

对象的内存布局

对象 在内存中的 存储布局分为三块区域:

对象头包括两部分信息:

在这里插入图片描述

如果对象是一个数组,header中还必须有一块用于记录 数组长度的 数据。因为jvm无法通过数组的 元数据中 确定数组的大小

对象访问定位

Java程序需要通过 JVM 栈上的引用 访问 堆中的具体对象
对象的访问方式取决于 JVM 虚拟机的实现
目前主流的访问方式有 句柄 和 直接指针 两种方式

句柄访问方式好处:reference中存储的是 句柄地址,在对象 被移动时,只改变 句柄中的 实例数据指针, reference本身不需要修改
指针访问方式好处:速度快,节省了一次指针定位的时间开销

指针访问方式

reference中存储的直接就是 对象地址
在这里插入图片描述

句柄访问方式

java堆中 会划分出 一块内存 作为句柄池,reference中存储的就是 对象的句柄(的)地址
句柄中 包含了 对象实例数据 与 对象类型数据 各自的具体地址信息
在这里插入图片描述

标签:对象,句柄,内存,分配内存,TLAB,JVM,指针
来源: https://blog.csdn.net/weixin_38405646/article/details/120190686