JVM内存空间说明及JAVA对象创建过程

运行时数据区说明

JVM内存空间说明及对象相关

  • 程序计数器
    • 线程内独立存在,线程之间互不影响
    • 用于记录线程的代码运行位置,通过其选取下一个执行的指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成
    • 用于在多线程切换时能够指定到正确的执行位置
    • 唯一一个没有任何OutOfMemoryError情况的区域
  • 虚拟机栈
    • 生命周期与线程相同,是java方法执行的内存模型(每个方法都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每一个方法从调用到执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程)
  • 局部变量表
    • 存放了编译器可知的各种基本类型(boolean、byte、char、short、int、float、long、
      double)、对象引用(reference类型,指向对象相关的位置)和returnAddress类型(指向一条字节码指令的地址)
    • 注意:64位长度的long和double类型的数据会占用2个局部变量空间(slot),其余数据只占用1个。
    • 异常:
      • 请求的栈的深度大于虚拟机所允许的深度(StackOverflowError异常)
      • 虚拟机栈允许扩充也允许固定长度,当扩充无法申请足够空间(OutOfMemoryError异常)
  • Java堆
    • 被所有线程共享的一块内存区域,此区域的唯一目的是存放对象实例,几乎所有对象和数组都要在堆上分配,为收集器管理的主要区域,也被称为"GC堆",一般区分为新生代和老年代
    • 异常
      • 当堆没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError
  • 方法区
    • 被所有线程共享的一快内存区域,Hotspot虚拟机使用”永久代“来实现方法区,其余虚拟机并没有,在1.8中 Hotspot已经实现了使用Native Memory来实现方法区,方法区管理较为宽松,可以实现扩展和固定空间,还可以选择不实现垃圾回收集,当空间不足时,将抛出OutOfMemory异常
    • 运行时常量池(Runtime Constant Pool)是方法区的一部分。
  • 直接内存
    • 不是虚拟机运行数据区,也不是Java规范中定义的内存区域,但是这个部分也被频繁的使用,而且也可以导致OutOfMemoryError 异常。

对象相关

  • 创建过程

    • Java堆内分配空间
    • 虚拟机进行对象设置,内存空间初始化为零值(对象头除外),设置对象头
    • 执行init
  • 对象的内存布局

    • 对象头(Header)
      • 对象运行时数据,如:HashCode、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,官方成为”Mark Word“
        JVM内存空间说明及对象相关
      • 类型指针(对象指向它的类型数据的指针),用于确定这个对象是哪个类的实例
      • 备注:若对象为数组,还有一块用于记录数组长度的数据
  • 实例数据(Instance Data)

    • 有效信息,代码中定义的各种类型的内容,包括父类集成的与子类定义的
  • 对齐补充(Padding)

    • 并不是必然存在,也没有意义,起到了占位符的作用,在Hotspot中对象大小必须为8字节的整数倍
  • 对象内存分配管理(管理方式由JAVA堆内存是否规整决定)

    • 指针碰撞:Java堆中内存绝对规整,每次分配时仅移动分界指针
    • 空闲列表:Java堆中内存零散(CMS收集器),记录空闲空间列表
  • 对象并发创建保证原子性问题

    • 采用CAS配上失败重试的方式保证更新操作的原子性
    • 本地线程分配缓冲(Thread Local Allocation Buffer,TLAB),预先在Java堆中为线程分配一定的空间,哪个线程需要分配内存就在哪个TLAB上分配,只有TLAB需要扩充时,才需要同步线程锁。
  • 对象的访问定位

    • Java程序需要通过栈上的reference类型数据操作堆的对象,但是由于reference只规定了一个指向对象的引用,没有定义定位方式,所以定位方式取决于虚拟机的实现
    • 主流定位方式
      • 使用句柄访问,Java堆内会分配句柄池,reference类型记录的是对象的句柄地址,句柄中包含了对象实例数据与类型数据各自的具体地址信息
        JVM内存空间说明及对象相关
      • 使用直接指针,reference直接指向对象地址,那么Java堆对象的布局就必须考虑如何防止访问类型数据的相关信息
        JVM内存空间说明及对象相关

相关文章:

  • 2021-04-23
  • 2021-08-18
  • 2021-10-17
  • 2021-05-15
  • 2021-12-01
  • 2021-08-15
  • 2021-07-15
  • 2021-12-23
猜你喜欢
  • 2021-09-09
  • 2021-10-24
  • 2021-03-05
  • 2021-11-27
  • 2022-12-23
相关资源
相似解决方案