美文网首页
JAVA内存区域

JAVA内存区域

作者: engineer_tang | 来源:发表于2021-11-04 07:43 被阅读0次

    JAVA程序对它所管理的内存区域进行划分,分为堆、方法区、虚拟机栈、本地方法栈、程序计数器。

    image.png

    1. 程序计数器

      1. 一块较小的内存空间,线程所私有,看作当前线程所执行的字节码的行号指示器。
      1. 如果执行的是JAVA方法,计数器记录的是正在执行的虚拟机字节码指令地址;如果正在执行的是本地方法,这个计数器值为空。
      1. 唯一没有规定任何OutOfMemoryError情况的区域。

    2. JAVA虚拟机栈

      1. 线程所私有,生命周期和当前线程相同。虚拟机栈描述的是JAVA方法执行的线程内存模型:每个JAVA方法执行时都会同步创建一个栈帧(Stack Frame),用于存储局部变量表、操作数栈、动态连接、方法出口等信息。
      1. 局部变量表存放了编译期可知的基本数据类型、对象引用类型、和returnAddress类型。
      1. 这些护具类型在局部变量表中的存储空间以局部变量槽(Slot)来表示,其中64位长度的long和double类型会占用两个变量槽,其余类型只占用一个。
      1. 当进入方法时,需要的栈帧分配的局部变量空间是确定的,指变量槽的数量,具体的内存空间需要根据单个变量槽所占用比特决定,由具体虚拟机实现确定。
      1. 该区域规定了两类异常,分别是StackOverflowError和OutOfMemoryError异常。如果线程请求的栈深度大于虚拟机所允许的深度,抛出StackOverflowError,如果JAVA虚拟机栈容量可以的动态扩展,当栈扩展时,无法申请到足够的内存会抛出OutOfMemoryError。

    3. 本地方法栈

    • !. 为虚拟机使用到的本地方法服务。

    4. JAVA堆

      1. 是所有线程共享的且是虚拟机管理的最大的一块内存区域,用于存放对象实例。

    5. 方法区

      1. 是线程共享的、用于存储已加载的类型信息、常量、静态 变量、即时编译器编译后的代码缓存等数据。

    6. 运行时常量池

      1. 是方法区的一部分,用于存放类的常量池表,存放编译期生成的各种字面量与符号引用。

    7. 对象的创建

    image.png

    7.1 分配内存方式

    分配对象时,在类加载通过后就可以确定内存的大小,根据JAVA堆的内存是否规整,内存分配分两类:

    • 指针碰撞:JAVA堆内存规整,所有被使用过的内存放一边,未被使用过的内存放另一边,中间放着一个指针作为分界点的指示器,通过往未使用过的内存一边挪动一段与对象大小相等的距离,来完成对对象内存的分配。

    • 空闲列表:JAVA堆内存不规整,需要维护一个空闲列表,来标注可用的内存区域,在分配内存时,在列表上找到一块足够大的空间划分给对象使用,并更新列表上的记录。

    7.2 安全分配内存

    为了在多线程情况下,保证分配对象的线程安全性,有两种方案:

    • 采用CAS配上失败重试的方式保证更新操作的原子性。
    • 把内存分配的动作按照线程划分在不同的空间中进行。

    相关文章

      网友评论

          本文标题:JAVA内存区域

          本文链接:https://www.haomeiwen.com/subject/aasqzltx.html