• JVM运行时数据区


    JVM运行时数据区(Runtime Data Area)

    运行时数据区是把所管理的内存划分为若干不同的数据区域。这区域各有各的用途以及生命周期(各司其职)。

    运行时数据区域包含:程序计数器、Java虚拟机栈、本地方法栈、堆内存、方法区。

    • 程序计数器、Java虚拟机栈、本地方法栈则依赖程序线程的启动和结束分别创建和销毁。(线程私有)
    • 堆内存、方法区随着虚拟机的启动而一直存在。(线程共享)
      在这里插入图片描述

    1.程序计数器(Program Counter Register)

    主要用于存储下一条指令的地址。

    • 线程私有:每个线程的执行状态(位置/地址)不同
    • 运行速度最快,内存小
    • 不会(OutOfMemoryError)错误
    • 生命周期与线程生命周期一致

    问1:使用程序计数器存储字节码指令地址有什么作用?

    为了记录不同线程执行的位置(状态)等

    问2:为什么使用程序计数器记录当前线程的执行地址?

    因为CPU中的线程需要不停的切换,所以就为下一次进入CPU做好记录,以便下次更快的找到之前执行的位置。

    问3:程序计数器为什么被设定为私有的?

    因为每一个线程在切换出CPU时所执行的位置不同。

    2.Java虚拟机栈(Java Virtual Machine Stacks)

    栈主要解决程序的运行问题,即程序如何执行,或者说如何处理数据。

    • 用于保存方法的局部变量、部分结果、并参与方法的调用和返回
    • 线程请求深度大于允许的深度时报StackOverFlowError
    • 线程私有且生命周期与线程一致

    每个线程在创建时都会创建一个虚拟机栈,在线程上正在执行的每个方法都各自对应一个栈帧,即对应着一次方法的调用(栈中的数据都以栈帧为单位存储)。

    栈帧的内部结构

    • 局部变量表(Local Variables)
      一组变量存储空间,用于存放方法参数和方法内部定义的局部变量。
    • 操作数栈(Operand Stack)
      用于对表达式求值。
    • 动态链接(Dynamic Linking)
      指向运行时常量池的方法引用。
    • 方法返回地址(Return Address)
      当一个方法执行完毕之后,要返回之前调用它的地方,因此在栈帧中必须保存一个方法返回地址。

    问1:为什么是栈存储而不是寄存器存储?

    基于栈的指令在设计和实现更为简单,适用于资源受限的系统。

    • 优点:①不需要硬件支持,可移植性好,更好的实现跨平台②指令集小,编译器容易实现
    • 缺点:性能低,完成相同操作需要更过的指令集

    基于寄存器的指令在设计和实现完全依赖硬件。

    • 优点:①性能好,执行效率高②完成操作使用的指令更少
    • 缺点:可移植性差

    综上所述,由于Java语言是夸平台语言所以Java指令集都是按照栈来设计的。

    3.本地方法栈(Native Method Stack)

    • 为虚拟机调用Native方法服务的。

    问1:Java虚拟机栈和本地方法栈的异同点有哪些?

    • 相同:都是线程私有的、都有内存溢出
    • 区别:Java 虚拟机栈管理 java 方法的调用;而本地方法栈用于管理本地方法的调用,本地方法是用c语言写的。

    4.堆内存(Heap)

    堆内存主要是解决数据存储问题,“即数据怎么放,放在哪儿”,占用空间最大,用于存放实例对象。

    • 启动时创建,大小可以固定也可以调节
    • 内存空间可以不连续,但是逻辑上是连续的
    • 线程共享
    • 用于存储对象实例
    • 堆是垃圾收集器执行垃圾回收的重点区域

    堆内存区域划分

    Java8后堆内存被分为:新生区和老年区
    新生区又分为:Eden(伊甸园)和Survivor(幸存者),伊甸园:幸存者0:幸存者1 = 8:1:1

    问1:堆内存为什么要分区?

    把不同生命周期的对象存储在不同区域,这样不同的区域可以使用不同的垃圾回收算法,从而提高垃圾回收的效率。

    问2:垃圾回收算法有哪些,且之间有什么区别?

    垃圾回收算法有按照回收区域分为:部分收集和整堆收集。

    • 部分收集:新生区收集(Minor GC/Yong GC)只有新生区(Eden,S0,S1)的垃圾收集;老年区收集(Major GC/Old GC)只有老年区的垃圾收集。
    • 整堆收集(Full GC):收集整个Java堆内存和方法区的垃圾。

    注:整堆收集出现的情况:System.gc();老年区空间不足;方法区空间不足。

    字符串常量池

    • JDK7之前,字符串常量池在方法区中;在JDK8之后,将字符串常量池放在了堆空间中。
    • 主要是因为方法区只有触发Full GC时才会回收垃圾。而程序中需要大量的使用字符串,放在堆空间可以及时回收无效的字符串常量。

    5.方法区(Method Area)

    用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。

    • 启动时创建,大小可以固定也可以调节
    • 内存空间可以不连续,但是逻辑上是连续的
    • 用于存储类信息,如果加载类太多,会导致内存溢出
    • 线程共享

    方法区是很重要的系统资源,是硬盘和 CPU 的中间桥梁,承载着操作系统和应用程序的实时运行。

  • 相关阅读:
    【React-Native开发3D应用】React Native加载GLB格式3D模型并打包至Android手机端
    机器学习(七):sklearn转换器估计器及K-近邻算法
    肖sir__设计测试用例方法之状态迁移法05_(黑盒测试)
    仙人掌之歌——投石问路(3)
    DBMS 中的 2 层架构与 3 层架构
    Vue2 slot插槽学习笔记
    git的介绍、git的功能特性、git工作流程、git 过滤文件、git多分支管理、远程仓库、把路飞项目传到远程仓库(非空的)、ssh链接远程仓库,协同开发
    基于AI算法+视频监控技术的智慧幼儿园解决方案
    MySQL(存储过程,store procedure)——存储过程的前世今生 & MySQL存储过程体验 & MybatisPlus中使用存储过程
    在pytorch中对于张量维度的理解
  • 原文地址:https://blog.csdn.net/qq_44129924/article/details/126582354