目录
一、运行时数据区域
1、方法区
2、堆
3、虚拟机栈
4、本地方法栈
5、程序计数器
6、运行时常量池
二、HotSpot虚拟机的对象
1、对象的创建
指针碰撞:
空闲列表:
2、对象的内存布局
对象头
实例数据
对齐填充
3、对象的访问定位
句柄
编辑
直接指针
一、运行时数据区域
1、方法区
用于存储类的信息(包括类的字段、方法、静态变量、常量)方法区是被所有线程共享的区域。
2、堆
用于存储对象实例和数组。堆是Java程序中最大的内存区域,堆也是被所有线程共享的区域。
在堆中分配的对象实例可以通过垃圾回收来进行自动内存管理。
3、虚拟机栈
每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
4、本地方法栈
与虚拟机栈类似,但用于执行本地方法的调用。
5、程序计数器
每个线程都有一个程序计数器,通过改变这个计数器的值来选取下一条需要执行的字节码指令。线程切换时,程序计数器的值会被保存和恢复。各个线程之间计数器互不影响,独立存储。
6、运行时常量池
用于存放编译期生成的各种字面量与符号引用,在类加载后放到运行时常量池。(它是方法区的一部分)
二、HotSpot虚拟机的对象
1、对象的创建
在java创建对象时,我们都知道是使用new关键字。在虚拟机执行new指令时,首先检查这个类是否已经被加载、解析,检查没通过就执行类加载过程,检查通过则为新对象分配内存。
分配内存有两种常用方式:“指针碰撞” 和 “空闲列表”
指针碰撞:
使用一个指针来标记已分配和未分配内存之间的边界。在内存分配时,指针根据对象所需内存大小进行移动,指向新的分界位置。
适用于:已用内存和空闲内存分布在两侧
空闲列表:
维护一个记录空闲内存块的列表来进行内存分配和释放。列表中的每个条目包含了空闲块的起始地址和大小。
适用于:已用内存和空闲内存相互交错
2、对象的内存布局
在虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:对象头、实例数据和对齐填充。
对象头
实例数据
对象真正存储的有效信息。
对齐填充
仅仅起着占位符的作用。(虚拟机要求对象起始地址必须是8字节的整数倍)
3、对象的访问定位
java虚拟机对于对象的访问方式主要是两种:句柄和直接指针
句柄
划分一块内存作为句柄池,reference中存储的就是对象的句柄地址。
优点:移动对象更方便(只需改引用)
直接指针
优点:访问速度快,节省内存