关于JVM和OS中的栈帧的区别和内存浅析

关于JVM和OS中的栈帧的区别和内存浅析


刚看了黑马JVM中的栈帧的讲解,感觉和自己理解的栈帧有一定出入,查询资料研究了一下发现的确有天壤之别,可惜黑马并没有讲。

故写下这篇文章巩固一下,


OS的栈帧:

​ OS的栈帧会在调用一个函数时,分配一段内存,存入函数调用的局部变量、参数、返回地址等信息进去,列如下面这一段C程序:

c 复制代码
#include<stdio.h>
int add1(int a, int b) {
    return add2(a,b);
}
int add2(int a, int b) {
    return a + b;
}
void main(){
    add1(1,2);
}

首先,程序会把这个代码从上开始执行

当执行到main函数时,会在内存上分配如下:

这里的返回地址 指的是进入这个函数的指令地址 ,也就是**程序计数器(PC)**寄存器,里面保存的是下一条被执行的语句的位置,因为你调用了函数,PC就得移到函数代码的地方,为了执行完函数能回到原代码,就会在函数的栈帧里面保存返回地址,这样执行完函数就会通过返回地址返回到原本的地方继续执行。


接着进入add1,add2就显而易见:

栈帧是用栈来存储的,遵循先进先出,程序只能操作最顶上的栈帧!

每当执行到一个函数,就会创建一个栈帧,存储变量和对应返回地址,当执行完毕后,栈帧会被回收

这也就是为什么函数需要预先声明要用的变量的原因,计算机需要知道你的大小和所需来为你分配合适的栈帧。

你只能使用你栈帧里面的数据,一旦越界访问就会报错

总的来说,栈帧在OS里面会保存函数执行的一切信息,包括变量对象,返回地址,各种参数

但对于全局变量,以及类似于C++中的vector这种动态申请空间的,栈帧里面只会存对其的内存地址 (可以理解为指针),实际上其处于另一片区域中,具体看程序内存分配的总体图

这也被称为内存五大区:栈区 -> 堆区 -> 全局静态区 -> 常量区 -> 代码区

各个区解释如下:

内核区,是OS的系统文件或其他文件,反正不应该被程序触碰到,接触到就会报错

栈区,也就是上文提到的栈帧存放处,从上到下存储!

堆区, 存储程序手动分配的空间,也就是new,vector此类,读取较慢

全局区,存储全局变量

常量区,存储常量

代码区,存储原代码

保留区,4k大小,不作操作

对于32位计算机,全部部分加起来一共有4G

栈区是从上到下使用,堆区是从下到上

缓存区用来作缓冲,双方都能使用

一旦冲突,便会发生溢出错误

以上是OS中栈帧的简单解释


JVM的栈帧:

Java这种高级语言的栈帧和OS中的栈帧是两个东西

本质是JVM抽象出来的,和OS的栈帧没有关系

但是结构差不多,可以说较为相似

(来自小林coding)

这里的本地方法指的是native方法,不是由java实现的方法!是由C语言实现的来对底层进行交互的方法!

那本地方法栈完全可以套用前文

对于Java虚拟机栈帧,仅和OS栈帧有一点区别:其不会把数据对象存储在栈帧中,而是只会存储一个引用!

对象本身是存在堆中的,和OS的栈帧不同

对于static的变量和方法,static方法在内存上的存储方式其实和非static没有多大区别,都是同样的创建栈帧调用,只是会少一个this指针,绑定在static中,不能实现多态,可以直接调用

static变量则会直接保存在方法区,不像非staic变量存储在堆里面

堆是 JVM 中最大的一块内存区域,被所有线程共享,在虚拟机启动时创建,用于存放对象实例。

程序计数器(PC)效果和OS相同,都是存储下一条该执行的语句的地址

元空间用于存储已被虚拟机加载的类信息、常量、静态变量等数据

直接内存不属于 JVM 运行时数据区的一部分,通过 NIO 类引入,是一种堆外内存,可以显著提高 I/O 性能。


总的来说,JVM和OS的内存管理结构上其实并没有很大区别,只是需要注意,JVM的内存是对OS的内存的一次抽象,是间接实现的,不是像OS那样通过汇编直接实现.

所以说既然不是直接实现的,那就必然会对性能有影响,这也是java性能不如C的原因之一

栈帧也是对OS的栈帧的模拟,区别在于不会把所有对象都放在栈帧中,而是放在堆中,这是和OS的区别

相关推荐
明天不下雨(牛客同名)2 小时前
为什么 ThreadLocalMap 的 key 是弱引用 value是强引用
java·jvm·算法
多多*3 小时前
Java设计模式 简单工厂模式 工厂方法模式 抽象工厂模式 模版工厂模式 模式对比
java·linux·运维·服务器·stm32·单片机·嵌入式硬件
胡图蛋.5 小时前
Spring Boot 支持哪些日志框架?推荐和默认的日志框架是哪个?
java·spring boot·后端
牛马baby5 小时前
Java高频面试之并发编程-01
java·开发语言·面试
小小大侠客5 小时前
将eclipse中的web项目导入idea
java·eclipse·intellij-idea
不再幻想,脚踏实地5 小时前
MySQL(一)
java·数据库·mysql
吃海鲜的骆驼5 小时前
SpringBoot详细教程(持续更新中...)
java·spring boot·后端
迷雾骑士5 小时前
SpringBoot中WebMvcConfigurer注册多个拦截器(addInterceptors)时的顺序问题(二)
java·spring boot·后端·interceptor
别来无恙✲6 小时前
Mybatis源码分析
java·源码分析
68岁扶墙肾透6 小时前
Java安全-FastJson反序列化分析
java·安全·web安全·网络安全·网络攻击模型·安全架构·fastjson