JVM内存区域有哪些?为什么这么划分?
程序计数器,栈,本地方法栈,堆,方法区;
各个内存区域存储各种数据,使内存分配占用更加合理,查询效率高;
简单说说程序各个内存区域存储了哪些数据:
程序计数器:代码运行的行数
无
O
O
M
情
况
的
区
域
\color{red}{无OOM情况的区域}
无OOM情况的区域
栈:对象的引用
基
本
数
据
类
型
,
栈
帧
,
局
部
变
量
表
,
操
作
数
栈
,
方
法
出
口
\color{red}{基本数据类型,栈帧,局部变量表,操作数栈,方法出口}
基本数据类型,栈帧,局部变量表,操作数栈,方法出口
本地方法:native方法
堆:对象的存储空间
方法区:类对象,
常
量
池
(
j
a
v
a
8
)
静
态
变
量
\color{red}{常量池(java8)静态变量}
常量池(java8)静态变量,编译后的代码
上面属于基本要答到的点,可以延伸的内容:
1.什么是栈帧?栈里面存放的元素叫栈帧,每个方法从调用到执行结束,其实是对应一个栈帧的入栈和出栈。
2.StackOverflowError什么情况会产生?递归。栈是否会OOM?会的,栈的存储空间的动态扩展
3.对象是如何访问的?各有什么优劣势?
句柄访问:栈中存储的reference指向堆中的句柄池地址,句柄中存储了到对象数据的指针,该指针再指向对应的对象数据(堆中)和对象类型数据(方法区中)。
直接指针访问:栈中存储的reference直接指向堆中存储的对象数据(包含对象类型数据的指针)。
优劣势分析:使用句柄来访问的最大好处就是引用变量中存储的是稳定的句柄地址,对象被移动(在垃圾收集时移动对象是很普通的行为)时就会改变句柄中实力数据指针,但是引用变量所指向的地址不用改变。
而使用直接指针访问方式最大的好处就是速度更快,节省了一次指针定位的时间开销,但是在对象被移动时,又需要改变引用变量的地址