自动内存管理机制

虚拟机运行时数据区

  1. 程序计数器
  2. 虚拟机栈/本地方法栈
  3. 方法区
  4. 堆区
  • 程序计数器
    每个线程都有一个独立的计数器,并与其他线程隔离,通过改变计数器的值进行字节码指令的操作,实现分支、跳转、循环、异常处理、线程恢复……等功能。
  • 虚拟机栈
    线程私有,生命周期与线程相同,每个方法执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口信息等。每个方法的调用(入栈)直至执行完成(出栈)的过程,对应值一个栈帧在虚拟机栈中的入栈和出栈过程。
    局部变量表储存了编译期可知的各种基本类型、引用(非对象本身)、returnAdress(指向一串字节码指令的地址),其空间在编译器分配,方法在帧中分配多大的局部变量空间是编译器就确定的,不会在运行时发生改变。
    如果线程请求栈深度大于虚拟机允许深度,抛出StackOverflowError异常
    如果虚拟机栈可以动态扩展,但在扩展时无法申请到足够内存,抛出OutOfMemoryError异常
  • 本地方法栈
    类似虚拟机栈,区别为虚拟机栈为虚拟机执行java方法,本地方法栈执行非java代码。

  • 线程共享,虚拟机启动时创建,用来存放对象实例,几乎所有的对象实例在此处分配内存。物理上可连续可不连续,保证逻辑连续即可,同时大小有固定有扩展,若扩展失败,则抛出OutOfMemoryError异常。
  • 方法区
    线程共享,用于存储虚拟机已经加载的常量,类信息,静态变量等。内存可连续可不连续,可固定可扩展,无法扩展时抛出OutOfMemoryError异常。
  • 运行时常量池
    方法区的一部分,用于存放编译期间产生的各种字面量和符号引用。
  • 直接内存
    并不是运行时数据区一部分,也不是虚拟机规范中定义的内存区域。NIO类能够使用native函数创建堆外内存,然后通过储存在堆里的DirectByteBuffer对象对这块内存进行引用操作,避免java堆和native堆来回复制数据,提高部分场景应用,但该内存仍然受限于物理内存,也可能产生OutOfMemoryError异常。

HotSpot对象

  • 对象创建
    首先进行类加载检查,通过后为对象在堆中分配内存区域。
    • 若堆中内存规整(指针分界,一边用过,一边还没用),直接将指针移动对象大小等距离,该方法称为 “指针碰撞”
    • 若堆中内存不规整,虚拟机需要额外维护一份列表,从列表中找出一块足够分配对象内存的区域,该方法成为 空闲列表
  • 指针碰撞时的线程安全
    当多线程操作时,指针的移动可能发生危险,如一个线程A正在分配内存还未移动指针,线程B又使用该线程分配新的内存。有两种方案解决:
    • 对指针操作进行加锁,使用CAS保证原子性。
    • 给线程划分相对独立的堆区域(本地线程分配缓冲,TLAB),各个线程创建对象分配内存时在自己的TLAB分配,只有当TLAB不够需要新的TLAB时才会进行同步操作。
  • 零值初始化
    内存分配后对对象进行初始化零值,可以保证对象字段不被赋初始值也可以直接使用。
  • 设置对象头
  • init初始化

对象的内存布局

  1. 对象头
  2. 实例数据
  3. 对齐填充
  • 对象头

    • MarkWord(运行时数据),存储hashcode、GC分代年龄,锁状态标志,线程持有的锁、偏向线程ID等
    • 类型指针,对象指向它的类元数据的指针,虚拟机通过这个指针确定该对象是哪个类的实例。并不是所有虚拟机都有类型指针。
  • 实例数据
    对象真正存储的有效信息,程序代码中定义的各种类型字段的内容。存储顺序收到虚拟机策略参数和在java代码中定义的顺序有关。HotSpot默认规范是相同宽度的字段总是分配在一起(longs/doubles,ints,shorts/chars……)

  • 对齐填充
    非必须,占位符左右,对象大小必须是8的整数倍,对象头满足,而实例数据不一定,该字段用来填充补齐。

对象的使用

通过栈中的reference来操作堆中的对象,reference访问对象的方式主要有两种:

  • 句柄
    • 堆中划分一块作为句柄池,reference储存句柄地址,句柄中存储着实例数据与类型数据具体的地址信息。
    • 好处是reference储存的数据稳定,对象移动时只需要改变句柄中的实例数据指针。
      在这里插入图片描述
  • 直接指针
    • reference储存的是对象的地址信息。
    • 好处是速度快,无需一次额外的地址指针操作。
      在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值