【JVM】java内存区域

发布于:2024-04-26 ⋅ 阅读:(17) ⋅ 点赞:(0)

目录

一、运行时数据区域

1、方法区

2、堆

3、虚拟机栈

4、本地方法栈

5、程序计数器

6、运行时常量池

二、HotSpot虚拟机的对象

1、对象的创建

指针碰撞:

空闲列表:

2、对象的内存布局

对象头

实例数据

对齐填充

3、对象的访问定位

句柄

​编辑

直接指针


一、运行时数据区域

1、方法区

用于存储类的信息(包括类的字段、方法、静态变量、常量)方法区是被所有线程共享的区域。


2、堆

用于存储对象实例和数组。堆是Java程序中最大的内存区域,堆也是被所有线程共享的区域。
在堆中分配的对象实例可以通过垃圾回收来进行自动内存管理。


3、虚拟机栈

每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。


4、本地方法栈

与虚拟机栈类似,但用于执行本地方法的调用。


5、程序计数器

每个线程都有一个程序计数器,通过改变这个计数器的值来选取下一条需要执行的字节码指令。线程切换时,程序计数器的值会被保存和恢复。各个线程之间计数器互不影响,独立存储。


6、运行时常量池

用于存放编译期生成的各种字面量与符号引用,在类加载后放到运行时常量池。(它是方法区的一部分)

二、HotSpot虚拟机的对象

1、对象的创建

在java创建对象时,我们都知道是使用new关键字。在虚拟机执行new指令时,首先检查这个类是否已经被加载、解析,检查没通过就执行类加载过程,检查通过则为新对象分配内存。

分配内存有两种常用方式:“指针碰撞” 和 “空闲列表”

指针碰撞:

使用一个指针来标记已分配和未分配内存之间的边界。在内存分配时,指针根据对象所需内存大小进行移动,指向新的分界位置。

适用于:已用内存和空闲内存分布在两侧

空闲列表:

维护一个记录空闲内存块的列表来进行内存分配和释放。列表中的每个条目包含了空闲块的起始地址和大小。

适用于:已用内存和空闲内存相互交错

2、对象的内存布局

在虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:对象头、实例数据和对齐填充。

对象头
对象头部分包括两类信息:第一类是Mark word(如下表),第二类是类型指针(虚拟机通过这个指针来确定该对象是哪个类的实例)

实例数据

对象真正存储的有效信息。

对齐填充

仅仅起着占位符的作用。(虚拟机要求对象起始地址必须是8字节的整数倍)

3、对象的访问定位

java虚拟机对于对象的访问方式主要是两种:句柄和直接指针

句柄

划分一块内存作为句柄池,reference中存储的就是对象的句柄地址。

优点:移动对象更方便(只需改引用)

直接指针

优点:访问速度快,节省内存