JVM系列 运行时数据区

这篇具有很好参考价值的文章主要介绍了JVM系列 运行时数据区。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录

第一章 运行区实验



前言

JVM(Java虚拟机)运行区是Java程序在运行过程中被JVM所管理的内存区域。它包括了Java程序运行时的堆(Heap)、栈(Stack)、方法区(Method Area)、本地方法栈(Native Method Stacks)、程序计数器和直接内存(Direct Memory)等部分。
JVM系列 运行时数据区,面试,Java基础,JVM,jvm,运行时数据区,内存管理


一、堆(Heap)

堆(Heap)是Java程序运行时用于动态分配内存的区域,也是Java垃圾收集器进行垃圾回收的主要区域。堆内存被所有线程共享。

以JDK8为例,堆(Heap)用来存放对象,几乎所有(逃逸分析技术,栈上分配、标量替换)对象都在堆上分配,将Java堆细分的目的只是为了更好地回收内存,或者更快地分配内存,堆中没有内存分配对象,并且无法扩展时,会抛出OutOfMemoryError异常。

堆(Heap)一般管理新生代/Young区 、年老代(old区) 、String字符串常量池。

1.1、新生代/Young区

新生代里包含Eden区 与 Survival区2个区。

1.1.1、Eden区

Eden区位于Java堆的年轻代,是新对象分配内存的地方,由于堆是所有线程共享的,因此在堆上分配内存需要加锁。而Sun JDK为提升效率,会为每个新建的线程在Eden上分配一块独立的空间由该线程独享,这块空间称为TLAB(Thread Local Allocation Buffer)。在TLAB上分配内存不需要加锁,因此JVM在给线程中的对象分配内存时会尽量在TLAB上分配。如果对象过大或TLAB用完,则仍然在堆上进行分配。如果Eden区内存也用完了,则会进行一次Minor GC(young GC)。

1.1.2、Survival区

Survival区与Eden区相同都在Java堆的年轻代。Survival区有两块,一块称为from区,另一块为to区,这两个区是相对的,在发生一次Minor GC后,from区就会和to区互换。在发生Minor GC时,Eden区和Survival from区会把一些仍然存活的对象复制进Survival to区,并清除内存。Survival to区会把一些存活得足够旧的对象移至年老代。

1.2、年老代(old区)

年老代里存放的都是存活时间较久的,大小较大的对象,因此年老代使用标记整理算法。当年老代容量满的时候,会触发一次Major GC(full GC),回收年老代和年轻代中不再被使用的对象资源

二、虚拟机栈(Stack)

每个线程在创建时都会创建一个私有的JVM栈。每个方法执行的时候都会创建一个栈帧,用于存储局部变量、操作数栈、常量池引用等信息。如下图,栈帧1、栈帧2、栈帧3、栈帧N。
JVM系列 运行时数据区,面试,Java基础,JVM,jvm,运行时数据区,内存管理

2.1、栈顶缓存技术

解释执行状态下,将访问最频繁的数据(程序计数器、栈顶)缓存在物理CPU的寄存器中,以此降低对内存的读/写次数,提升执行引擎的执行效率。

2.2、溢出

如果线程请求的栈深度大于虚拟机所允许深度,将抛出StackOverflowError异常;如果Java虚拟机栈容量可以动态扩展 ,当栈扩展时无法申请到足够的内存会抛出OutOfMemoryError异常。

发生StackOverflowError异常,使用死循环递归代码可以复现。
JVM系列 运行时数据区,面试,Java基础,JVM,jvm,运行时数据区,内存管理
可以使用参数-Xss选项来设置线程的最大栈空间,例如-Xss265k

2.3、栈帧

栈的存储单位为栈帧,线程上正在执行的一个方法对应一个栈帧,栈帧是一个内存区块,是一个数据集,维系着方法执行过程中的各种数据信息。

每个栈帧包含五部分,分别包括局部变量表、操作数栈、动态链表(指向运行时常量池的方法引用)、方法返回地址和一些额外信息。
JVM系列 运行时数据区,面试,Java基础,JVM,jvm,运行时数据区,内存管理

2.3.1、局部变量表(local variables)

  • 局部变量表定义为一个数字数组,主要用于存储方法参数和定义在方法体内的局部变量,这些数据类型包括各种基本数据类型、对象引用(reference),以及returnAddress类型。

  • 由于局部变量表是线程的私有数据,不存在线程的安全问题

  • 局部变量表所需容量大小在编译器确定下来的,并保存在方法的Code属性的maximum local variables数据项中。在方法运行期间是不会改变局部变量表的大小的。

  • 局部变量表的变量只在当前方法调用中有效的,当方法调用结束后,随着方法栈帧的消耗,局部变量表也会随之销毁。

  • 局部变量表的最基本存储单位是Slot(变量槽),32位以内的类型只占用一个slot(包括returnAddress类型,引用类型),64位的类型(long和double)占用两个slot。

  • 每一slot都分配一个访问索引,占用两个slot的变量,只需要使用前一个索引即可

  • 构造方法或者实例方法(非static),该对象引用this将会存放在index为0的slot处

  • 局部变量表的变量也是重要的垃圾回收根节点,只要被局部变量表中直接或间接引用的对象都不会被回收。

2.3.2、操作数栈(Operand Stack LIFO)

  • 编译后 .Class文件的Code属性的max_stacks数据记录操作数栈的最大深度
  • 操作数栈,在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即入栈或者出栈,使用数组实现
  • 操作数栈,主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。

2.3.3、动态链接

运行期间把常量池中的符号引用转换成直接引用的过程,叫做动态链接;
每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态链接。

2.3.4、方法返回地址

方法返回地址存储的是调用该方法的pc寄存器的值。方法正常退出时,调用者的pc计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址。

2.3.5、额外信息

Java虚拟机规范,允许虚拟机实现,在栈帧之中增加一些规范里没有描述的信息,例如与调试、性能收集相关的信息。

三、方法区(MetaData Space)

方法区(MetaData Space 元空间)/Non-Heap,用于存储已被JVM加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
JVM系列 运行时数据区,面试,Java基础,JVM,jvm,运行时数据区,内存管理

3.1、方法区和永久代的关系

在JDK1.8之前,习惯把方法区称为“永久代”。HotSpot 虚拟机在1.7之前使用永久代来管理(实现)方法区,使得jvm的垃圾回收器能像管理堆内存一样来管理永久代这部分内存,而不用专门为方法区编写内存管理代码。但这种设计使得虚拟机更容易出现内存溢出问题,而不像J9和JRockit只要没有触碰到进程可用内存的上限(32位4GB),就没有问题。
JDK1.7把原本放在永久代的字符串常量池、静态变量等移出(主要剩余类型信息)
JDK1.8完全废弃了永久代的概念,改用与JRockit、J9一样,在本地内存中实现的元空间方法区无法满足新的内存分配需求时,将抛出OutOfMemoryError异常。

四、本地方法栈(Native Method Stacks)

Native Method Stacks 为虚拟机使用到的本地(Native)方法服务,本地方法栈也会在栈深度溢出或者栈扩展失败时分别抛出StackOverflowError和OutOfMemoryError异常。

五、程序计数器

程序计数器,当前线程所执行的字节码的行号指示器,字节码解释器工作时,通过改变计数器的值,执行下一条指令,此内存是JVM规范中唯一一个没有OutOfMemoryError的区域。

六、直接内存(Direct Memory)

DM并不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。但是这部分内存也被频繁地使用,而且也可能导致OutOfMemoryError异常出现,例如:NIO 中的 DirectByteBuffer 直接操作堆外内存,避免在Java堆和Native堆中来回复制数据。

同时也可以关注零拷贝(DMA)技术的应用。


总结

这些内存区域的管理和优化对于Java程序的性能和可靠性至关重要。文章来源地址https://www.toymoban.com/news/detail-712606.html

到了这里,关于JVM系列 运行时数据区的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【面试题】JDK(工具包)、JRE(运行环境和基础库)、JVM(java虚拟机)之间的关系?

    【面试题】JDK、JRE、JVM之间的关系? JDK (Java Development Kit):Java开发工具包,提供给Java程序员使用,包含了JRE,同时还包含了编译器javac与自带的调试工具Jconsole、jstack等。 JRE (Java Runtime Environment):Java运行时环境,包含了JVM,Java基础类库。是使用Java语言编写程序运行的所需环境

    2024年02月11日
    浏览(60)
  • java八股文面试[JVM]——JVM内存结构

    参考: JVM学习笔记(一)_卷心菜不卷Iris的博客-CSDN博客 JVM 是运行在操作系统之上的,它与硬件没有直接的交互 JVM内存结构:   方法区:存储已被虚拟机加载的类元数据信息(元空间) 堆:存放对象实例,几乎所有的对象实例都在这里分配内存 虚拟机栈:虚拟机栈描述的是

    2024年02月12日
    浏览(47)
  • JVM篇--Java内存区域高频面试题

    首先我们要知道java堆空间的产生过程: 即当通过java命令启动java进程的时候,就会为它分配内存,而分配内存的一部分就会用于创建堆空间,而当程序中创建对象的时候 就会从堆空间来分配内存,所以堆空间存放的主要是对象和数组; 而GC 其实说白了就是java虚拟机回收对象

    2024年02月01日
    浏览(52)
  • JVM内存模型/运行时数据区域

    java虚拟机管理这块内存,所以我们也叫运行时数据区域 这里按线程是否共享来分类,所谓线程不共享就是每个线程里面都会配一套 程序计数器 栈, 互相不干涉。 而方法区和堆是线程所有共享 意味着只有一个(这里注意堆是实际概念 方法区是一个虚拟概念) 注意:程序计

    2024年01月18日
    浏览(55)
  • Java # JVM内存管理

    程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、运行时常量池、直接内存 对象创建: 引用检查 类加载检查 分配内存空间:指针碰撞、空闲列表 分配空间初始化 对象信息设置(对象头内) 对象内存布局: 对象头 实例数据 对象填充 对象访问定位: 句柄访问 直接

    2024年02月13日
    浏览(46)
  • JVM系列 运行时数据区

    第一章 运行区实验 JVM(Java虚拟机)运行区是Java程序在运行过程中被JVM所管理的内存区域。它包括了Java程序运行时的堆(Heap)、栈(Stack)、方法区(Method Area)、本地方法栈(Native Method Stacks)、程序计数器和直接内存(Direct Memory)等部分。 堆(Heap)是Java程序运行时用于

    2024年02月08日
    浏览(41)
  • 深入探讨Java虚拟机(JVM):执行流程、内存管理和垃圾回收机制

    目录 什么是JVM? JVM 执行流程 JVM 运行时数据区 堆(线程共享) Java虚拟机栈(线程私有) 什么是线程私有? 程序计数器(线程私有) 方法区(线程共享) JDK 1.8 元空间的变化 运行时常量池 内存布局中的异常问题 1.  Java堆溢出 2.  虚拟机栈和本地方法栈溢出 JVM 类加载 1.

    2024年02月09日
    浏览(48)
  • JVM | 垃圾回收器(GC)- Java内存管理的守护者

    在编程世界中, 有效的内存管理 是至关重要的。这不仅确保了应用程序的稳定运行,还可以大大提高性能和响应速度。作为世界上最受欢迎的编程语言之一,通过Java虚拟机内部的垃圾回收器组件来自动管理内存,是成为之一的其中一项必不可少的技术点。 在许多传统的编程

    2024年02月09日
    浏览(53)
  • JVM零基础到高级实战之Java内存区域本地方法栈

    JVM零基础到高级实战之Java内存区域本地方法栈 JVM零基础到高级实战之Java内存区域本地方法栈 本地方法栈是什么? 用于作用域本地方法执行的一块Java内存区域 为什么要有本地方法栈? 与Java虚拟机栈相同,每个方法在执行的同时都会创建一个栈帧(Stack Framel)用于存储局部

    2024年02月09日
    浏览(42)
  • 【java基础面试题】jdk、jre、jvm区别

    【java基础面试题】jdk、jre、jvm区别 jdk ​ 从概念上讲JDK是JAVA开发工具,用它来开发JAVA程序,里面有很多基础类库和jre。 ​ JDK(Java Development Kit),它是功能齐全的 Java SDK,是提供给开发者使用的,能够创建和编译 Java 程序。他包含了 JRE,同时还包含了编译 java 源码的编译器

    2024年02月10日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包