【JVM 2】JVM 运⾏时数据区

🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇

                                    ⭐  JVM ⭐

🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇

今日推荐歌曲:  Right Now (Na Na Na)  -- Aamir  🎵🎵


系列文章目录

【JVM】Java虚拟机的 “ 类加载过程 ”-CSDN博客


目录

运⾏时数据区

1. 堆(线程共享)

2. Java虚拟机栈(线程私有)

3. 本地⽅法栈(线程私有)

4 程序计数器(线程私有)

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程序时,用于存储程序数据和执行程序的不同内存区域。这些区域包括了方法区、堆、虚拟机栈、本地方法栈和程序计数器。下面是对每个运行时数据区域的详细总结:

  1. 程序计数器(Program Counter)

    • 程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。
    • 在多线程环境下,每个线程都有自己的程序计数器,用于记录当前线程正在执行的字节码指令地址。
    • 对于Java方法来说,程序计数器记录的是正在执行的虚拟机字节码指令地址,对于Native方法,程序计数器的值为undefined。
  2. 虚拟机栈(Java Virtual Machine Stacks)

    • 虚拟机栈是线程私有的,用于存储方法执行的局部变量、操作数栈、动态链接、方法出口等信息。
    • 每个方法在执行的同时都会创建一个栈帧(Stack Frame),栈帧用于存储方法的局部变量和操作数栈。
    • 虚拟机栈的大小可以通过参数来设定,如果线程请求的栈深度大于虚拟机所允许的深度,将会抛出栈溢出异常(StackOverflowError)。
  3. 本地方法栈(Native Method Stack)

    • 本地方法栈与虚拟机栈类似,但是它为Native方法服务,用于支持Java调用Native方法(即用C/C++等语言实现的方法)。
    • 本地方法栈也会抛出栈溢出异常(StackOverflowError)。
  4. 堆(Heap)

    • 堆是Java虚拟机中所有线程共享的内存区域,用于存放对象实例。
    • Java堆在JVM启动时就被创建,是垃圾回收的主要区域。大部分Java程序运行时所需的内存都是在堆上分配的。
    • 堆可以分为新生代和老年代,新生代又可以分为Eden空间和两个Survivor空间。
  5. 方法区(Method Area)

    • 方法区是线程共享的内存区域,用于存储类的结构信息、静态变量、常量、编译后的代码等数据。
    • 方法区是JVM规范中的概念,不同的虚拟机实现可以选择不同的方式来实现方法区,比如使用永久代或元空间。
    • 在HotSpot虚拟机中,方法区被称为“永久代”(Permanent Generation),用于存放类的加载信息、常量池、静态变量等。在JDK 8之后,永久代被元空间(Metaspace)所取代,元空间并不在堆内存中,而是使用本地内存。

总的来说,JVM运行时数据区域包括了程序计数器、虚拟机栈、本地方法栈、堆和方法区,它们各自负责不同的任务,在Java程序的运行过程中扮演着重要的角色。

博客不易,希望可以帮助到大伙,动动小手点个赞我会开心很久,感谢阅览。

  • 35
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值