【Java】の基础——JVM内存区域

    • Java虚拟机内存区域
      • 程序计数器
      • Java虚拟机栈
      • 本地方法栈
      • Java堆
      • 方法区
    • 对象创建过程
      • 类加载检验
      • 分配内存
        • 方法1指针碰撞
        • 方法2空闲列表
      • 在对象头中设置对象信息
    • 对象的内存布局
      • 对象头
      • 实例数据
      • 对齐填充
    • 对象的访问定位
        • 两者区别

Java虚拟机内存区域

Java虚拟机的运行时数据区划分为几个不同区域。
这里写图片描述

程序计数器

程序计数器:当前线程所执行的字节码的行号指示器。
线程私有(即每条线程都有一个独立的程序计数器)。

Java虚拟机栈

虚拟机栈:Java 方法的内存模型。
线程私有
每个方法执行时都会创建一个栈帧
栈帧:存储局部变量表、操作数栈、动态链接、方法出口等信息。

局部变量表:
    1. 基本数据类型(boolean,byte,char,short,int,float,long,double)
    2. 对象引用(reference类型,指向对象起始地址的指针)
    3. returnAddress类型

本地方法栈

本地方法栈:与虚拟机栈相似。只不过虚拟机栈为Java方法服务,本地方法栈为Native方法服务。

Java堆

Java堆:存放对象实例
所有线程共享
Java堆还可以细分为“新生代”和“老年代
Java堆是垃圾收集器管理的主要区域,因此很多时候也被称作“GC堆

方法区

方法区:存储已被虚拟机加载的类信息常量静态变量、即时编译器编译后的代码等数据。
所有线程共享
方法去也被称为“永久代

对象创建过程

1.类加载检验

2.分配内存

方法1:指针碰撞

用过的内存和未使用的内存中间通过一个指针作为分界点,分配内存的时候去移动这个指针。

方法2:空闲列表

在一个列表上记录哪些内存块是可用的,分配的时候找一块足够大的划分给对象。

当然,这种分配过程并发情况下不是线程安全的。于是虚拟机采用两种方法避免冲突:
1. CAS配上失败重试,保证更新操作的原子性
2. 本地线程分配缓冲,即TLAB(每个线程在Java堆中先分配一小块内存,如果用完在分配新的空间时再同步锁定)

3.在对象头中设置对象信息

虚拟机对对象进行必要的设置:对象是哪个类的实例、如何找到类的元数据信息、对象的哈希码、对象的GC分代年龄等,存放在对象头中。

对象的内存布局

对象在内存中布局分为三块:对象头实例数据对齐填充

1.对象头

对象头包括两部分
1. 第一部分用于存储对象自身的运行时数据
2. 另一部分是类型指针、即对象指向它的类元数据的指针

2.实例数据

对象真正存储的有效信息,程序代码中定义的各类型的字段内容

3.对齐填充

不是必然存在的,只起到占位符的作用。

对象的访问定位

reference类型只规定了一个指向对象的引用,我们有两种方式去访问它:句柄,直接指针。
1. 使用句柄访问
这里写图片描述
2. 使用直接指针访问
这里写图片描述

两者区别:

使用句柄:在对象被移动时只改变句柄中的实例数据指针,reference不变。
使用直接指针:速度快,节省了一次指针定位的时间开销。

你可能感兴趣的:(Java,java,虚拟机)