🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇
⭐ JVM ⭐
🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇
今日推荐歌曲: Right Now (Na Na Na) -- Aamir 🎵🎵
系列文章目录
【JVM】Java虚拟机的 “ 类加载过程 ”-CSDN博客
目录
5. 元数据区(⽅法区 :jdk 1.8 之前这么叫)(线程共享)
前言
之前写了 JVM 的类加载机制,这篇文章会简单总结 JVM 的运⾏时数据区
运⾏时数据区
JVM运⾏时数据区域也叫内存布局,但需要注意的是它和Java内存模型((JavaMemoryModel,简 称JMM)完全不同,属于完全不同的两个概念,它由以下5⼤部分组成:
- 方法区
- 堆
- 虚拟机栈
- 本地方法栈
- 程序计数器
1. 堆(线程共享)
堆的作⽤:程序中创建的所有对象都在保存在堆中。
堆(Heap):
- 堆是Java虚拟机中所有线程共享的内存区域,用于存放对象实例。
- Java堆在JVM启动时就被创建,是垃圾回收的主要区域。大部分Java程序运行时所需的内存都是在堆上分配的。
- 堆可以分为新生代和老年代,新生代又可以分为Eden空间和两个Survivor空间。新⽣代放新建的对象,当经过⼀定GC次数之后还存活的对象 会放⼊⽼⽣代。
代码中new出来的对象,就都是在堆里.对象中持有的非静态成员变量,也就是在堆里.
2. Java虚拟机栈(线程私有)
- 虚拟机栈是线程私有的,用于存储方法执行的局部变量、操作数栈、动态链接、方法出口等信息。
- 每个方法在执行的同时都会创建一个栈帧(Stack Frame),栈帧用于存储方法的局部变量和操作数栈。
- 虚拟机栈的大小可以通过参数来设定,如果线程请求的栈深度大于虚拟机所允许的深度,将会抛出栈溢出异常(StackOverflowError)。
- 记录了java 代码的调用关系 和 java 代码的局部变量
什么是线程私有?
由于JVM的多线程是通过线程轮流切换并分配处理器执⾏时间的⽅式来实现,因此在任何⼀个确定的 时刻,⼀个处理器(多核处理器则指的是⼀个内核)都只会执⾏⼀条线程中的指令。因此为了切换线程后 能恢复到正确的执⾏位置,每条线程都需要独⽴的程序计数器,各条线程之间计数器互不影响,独⽴ 存储。我们就把类似这类区域称之为"线程私有"的内存。
3. 本地⽅法栈(线程私有)
本地⽅法栈和虚拟机栈类似,只不过Java虚拟机栈是给JVM使⽤的,⽽本地⽅法栈是给本地⽅法使 ⽤的。
4 程序计数器(线程私有)
- 程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。
- 在多线程环境下,每个线程都有自己的程序计数器,用于记录当前线程正在执行的字节码指令地址。
- 对于Java方法来说,程序计数器记录的是正在执行的虚拟机字节码指令地址,对于Native方法,程序计数器的值为undefined。
这个区域比较小的空间,专门用来存储下一条要执行的java指令的地址.
5. 元数据区(⽅法区 :jdk 1.8 之前这么叫)(线程共享)
- 方法区是线程共享的内存区域,用于存储类的结构信息、静态变量、常量、编译后的代码等数据。
- 方法区是JVM规范中的概念,不同的虚拟机实现可以选择不同的方式来实现方法区,比如使用永久代或元空间。
- 在HotSpot虚拟机中,方法区被称为“永久代”(Permanent Generation),用于存放类的加载信息、常量池、静态变量等。在JDK 8之后,永久代被元空间(Metaspace)所取代,元空间并不在堆内存中,而是使用本地内存。
咱们写的java 代码, if, while, for,各种逻辑运算....这些操作最终都会被转换成java字节码.
(javac 就会完成上述代码=>字节码)
这些字节码在程序运行的时候就会被jvm加载到内存中放到元数据区(方法区)里头.
此时,当前程序要如何执行,要做哪些事情,就会按照上述元数据区里记录的字节码依次执行了.
总结
Java虚拟机(JVM)运行时数据区域是指在JVM运行Java程序时,用于存储程序数据和执行程序的不同内存区域。这些区域包括了方法区、堆、虚拟机栈、本地方法栈和程序计数器。下面是对每个运行时数据区域的详细总结:
-
程序计数器(Program Counter):
- 程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。
- 在多线程环境下,每个线程都有自己的程序计数器,用于记录当前线程正在执行的字节码指令地址。
- 对于Java方法来说,程序计数器记录的是正在执行的虚拟机字节码指令地址,对于Native方法,程序计数器的值为undefined。
-
虚拟机栈(Java Virtual Machine Stacks):
- 虚拟机栈是线程私有的,用于存储方法执行的局部变量、操作数栈、动态链接、方法出口等信息。
- 每个方法在执行的同时都会创建一个栈帧(Stack Frame),栈帧用于存储方法的局部变量和操作数栈。
- 虚拟机栈的大小可以通过参数来设定,如果线程请求的栈深度大于虚拟机所允许的深度,将会抛出栈溢出异常(StackOverflowError)。
-
本地方法栈(Native Method Stack):
- 本地方法栈与虚拟机栈类似,但是它为Native方法服务,用于支持Java调用Native方法(即用C/C++等语言实现的方法)。
- 本地方法栈也会抛出栈溢出异常(StackOverflowError)。
-
堆(Heap):
- 堆是Java虚拟机中所有线程共享的内存区域,用于存放对象实例。
- Java堆在JVM启动时就被创建,是垃圾回收的主要区域。大部分Java程序运行时所需的内存都是在堆上分配的。
- 堆可以分为新生代和老年代,新生代又可以分为Eden空间和两个Survivor空间。
-
方法区(Method Area):
- 方法区是线程共享的内存区域,用于存储类的结构信息、静态变量、常量、编译后的代码等数据。
- 方法区是JVM规范中的概念,不同的虚拟机实现可以选择不同的方式来实现方法区,比如使用永久代或元空间。
- 在HotSpot虚拟机中,方法区被称为“永久代”(Permanent Generation),用于存放类的加载信息、常量池、静态变量等。在JDK 8之后,永久代被元空间(Metaspace)所取代,元空间并不在堆内存中,而是使用本地内存。
总的来说,JVM运行时数据区域包括了程序计数器、虚拟机栈、本地方法栈、堆和方法区,它们各自负责不同的任务,在Java程序的运行过程中扮演着重要的角色。
博客不易,希望可以帮助到大伙,动动小手点个赞我会开心很久,感谢阅览。