Java的内存结构

什么是运行时数据区(就是我们java运行时的东西是放在那里的)
在这里插入图片描述

1 方法区(Method Area)

  • 方法区是所有线程共享的内存区域,它用于存储已被Java虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
  • 它有个别名叫Non-Heap(非堆)。当方法区无法满足内存分配需求时,抛出OutOfMemoryError异常。

2 Java堆(Java Heap)

  • java堆是java虚拟机所管理的内存中最大的一块,是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例。
  • 在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
  • java堆是垃圾收集器管理的主要区域,因此也被成为“GC堆”。
  • 从内存回收角度来看java堆可分为:新生代和老生代。
  • 从内存分配的角度看,线程共享的Java堆中可能划分出多个线程私有的分配缓冲区。
  • 无论怎么划分,都与存放内容无关,无论哪个区域,存储的都是对象实例,进一步的划分都是为了更好的回收内存,或者更快的分配内存。
  • 根据Java虚拟机规范的规定,java堆可以处于物理上不连续的内存空间中。当前主流的虚拟机都是可扩展的(通过 -Xmx 和 -Xms 控制)。如果堆中没有内存可以完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。

3 程序计数器(Program Counter Register)

程序计数器是一块较小的内存空间,它可以看作是:保存当前线程所正在执行的字节码指令的地址(行号)
由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,一个处理器都只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都有一个独立的程序计数器,各个线程之间计数器互不影响,独立存储。称之为“线程私有”的内存。程序计数器内存区域是虚拟机中唯一没有规定OutOfMemoryError情况的区域。

总结:也可以把它叫做线程计数器

例子:在java中最小的执行单位是线程,线程是要执行指令的,执行的指令最终操作的就是我们的电脑,就是 CPU。在CPU上面去运行,有个非常不稳定的因素,叫做调度策略,这个调度策略是时基于时间片的,也就是当前的这一纳秒是分配给那个指令的。

假如:线程A在看直播
在这里插入图片描述
突然,线程B来了一个视频电话,就会抢夺线程A的时间片,就会打断了线程A,线程A就会挂起
在这里插入图片描述
然后,视频电话结束,这时线程A究竟该干什么?
(线程是最小的执行单位,他不具备记忆功能,他只负责去干,那这个记忆就由:程序计数器来记录)
在这里插入图片描述

4 Java虚拟机栈(Java Virtual Machine Stacks)

  • java虚拟机是线程私有的,它的生命周期和线程相同。
  • 虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。

解释:每虚拟机栈中是有单位的,单位就是栈帧,一个方法一个栈帧。一个栈帧中他又要存储,局部变量,操作数栈,动态链接,出口等。
在这里插入图片描述
解析栈帧:

  1. 局部变量表:是用来存储我们临时8个基本数据类型、对象引用地址、returnAddress类型。(returnAddress中保存的是return后要执行的字节码的指令地址。)
  2. 操作数栈:操作数栈就是用来操作的,例如代码中有个 i =
    6*6,他在一开始的时候就会进行操作,读取我们的代码,进行计算后再放入局部变量表中去
  3. 动态链接:假如我方法中,有个 service.add()方法,要链接到别的方法中去,这就是动态链接,存储链接的地方。
  4. 出口:出口是什呢,出口正常的话就是return 不正常的话就是抛出异常落

思考:.
一个方法调用另一个方法,会创建很多栈帧吗?
答:会创建。如果一个栈中有动态链接调用别的方法,就会去创建新的栈帧,栈中是由顺序的,一个栈帧调用另一个栈帧,另一个栈帧就会排在调用者下面

5 本地方法栈(Native Method Stack)

本地方法栈很好理解,他很栈很像,只不过方法上带了 native 关键字的栈字
它是虚拟机栈为虚拟机执行Java方法(也就是字节码)的服务
native关键字的方法是看不到的,必须要去oracle官网去下载才可以看的到,而且native关键字修饰的大部分源码都是C和C++的代码。
同理可得,本地方法栈中就是C和C++的代码

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java内存结构主要可以分为以下几个部分: 1. 堆(Heap):用于存储对象实例,是Java程序中最大的一块内存空间,可通过“new”关键字创建对象时,将对象存储在堆上。 2. 栈(Stack):用于存储局部变量和方法调用,每个线程都会创建一个栈,栈中的数据是线程私有的,只有当前线程可以访问。 3. 方法区(Method Area):用于存储类信息、常量、静态变量和即时编译器编译后的代码等数据,是各个线程共享的内存区域。 4. 本地方法栈(Native Method Stack):用于存储Java调用本地方法时的参数和返回值,以及本地方法的调用和返回状态。 堆和栈是Java程序中最基本的内存结构。 堆是用来存储对象实例的,它是Java程序中最大的一块内存空间。堆内存是由JVM管理的,可以通过“new”关键字创建对象时,将对象存储在堆上。堆内存的大小可以通过JVM参数进行配置,如果堆内存不足,会抛出OutOfMemoryError异常。 栈是用来存储局部变量和方法调用的,每个线程都会创建一个栈,栈中的数据是线程私有的,只有当前线程可以访问。栈内存是由操作系统管理的,它的大小是有限制的,如果栈内存不足,会抛出StackOverflowError异常。 在方法调用时,JVM会为每个方法调用创建一个栈帧,栈帧包含了局部变量表、操作数栈、动态链接、方法返回地址等信息。当方法调用结束时,这个栈帧会被弹出栈。 总之,堆和栈是Java程序中最基本的内存结构,堆用于存储对象实例,栈用于存储局部变量和方法调用。它们的使用方式和内存管理方式都有所不同,程序员需要根据具体情况来选择合适的数据结构内存管理策略。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全栈游戏开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值