一篇文章带你快速理解JVM运行时数据区 、程序计数器详解 (手画详图)值得收藏!!!

简介: 一篇文章带你快速理解JVM运行时数据区 、程序计数器详解 (手画详图)值得收藏!!!

微信截图_20220523204113.png

受多种情况的影响,又开始看JVM 方面的知识。


1、Java 实在过于内卷,没法不往深了学。


2、面试题问的多,被迫学习。


3、纯粹的好奇。 很喜欢一句话:“八小时内谋生活,八小时外谋发展。” --- 望别日与君相见时,君已有所成。共勉



地点:湖南一个小城市邵阳


作者:博主


一、运行时数据区


图示:


微信截图_20220523204239.png



补充一个点: 在运行时数据区中,灰色的为单独线程私有的,红色的为多个线程共享的,即:


  • 每个线程:独立包括程序计数器、栈、本地栈。


  • 线程间共享:堆、堆外内存(永久代或元空间、代码缓存)


运行时数据区的完整图:


不同的JVM对于内存的划分方式和管理机制存在着部分差异。这里给出一张完整的运行时数据区图。🤱


微信截图_20220523204307.png


看完上面的两张图,我想应该对JVM中所谓的运行时数据区有个大概印象了吧。下面👇会给大家再给大家带来一些粗略的讲解哈。


运行时数据区概述:


当我们通过前面的:类的加载-> 验证 -> 准备 -> 解析 -> 初始化 这几个阶段完成后,就会用到执行引擎对我们的类进行使用,同时执行引擎将会使用到我们运行时数据区 🤸‍♂️


微信截图_20220523204346.png


运行时数据区,Runtime Data Area,用于保存java程序运行过程中需要用到的数据和相关信息;经常说的把数据读到内存,包括类加载之后的信息,从磁盘读取文件信息等。即:==Java虚拟机在执行Java程序的过程中,会将涉及的数据划分到不同的内存区域去管理。==


课间休息会


微信截图_20220523204411.png


二、程序计数器(Program Counter)


概述:


程序计数器是用于存放下一条指令所在单元的地址的地方。


当执行一条指令时,首先需要根据PC中存放的指令地址,将指令由内存取到指令寄存器中,此过程称为“取指令”。与此同时,PC中的地址或自动加1或由转移指针给出下一条指令的地址。此后经过分析指令,执行指令。完成第一条指令的执行,而后根据PC取出第二条指令的地址,如此循环,执行每一条指令。


JVM中的PC寄存器是对物理PC寄存器的一种抽象模拟。


程序计数器是线程私有内存,是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError的区域。


代码讲解


JAVA代码编译后的字节码在未经过JIT(实时编译器)编译前,其执行方式是通过“字节码解释器”进行解释执行。简单的工作原理为解释器读取装载入内存的字节码,按照顺序读取字节码指令。读取一个指令后,将该指令“翻译”成固定的操作,并根据这些操作进行分支、循环、跳转等流程。


例如:


微信截图_20220523204454.png


使用javap -c -verbose ClassCode.class 命令反编译出来结果为:


微信截图_20220523204533.png


从上面的描述中,可能会产生程序计数器是否是多余的疑问。


因为沿着指令的顺序执行下去,即使是分支跳转这样的流程,跳转到指定的指令处按顺序继续执行是完全能够保证程序的执行顺序的。假设程序永远只有一个线程,这个疑问没有任何问题,也就是说并不需要程序计数器。但实际上程序是通过多个线程协同合作执行的。


首先我们要搞清楚JVM的多线程实现方式。JVM的多线程是通过==CPU时间片轮转==(即线程轮流切换并分配处理器执行时间)算法来实现的。也就是说,某个线程在执行过程中可能会因为时间片耗尽而被挂起,而另一个线程获取到时间片开始执行。当被挂起的线程重新获取到时间片的时候,它要想从被挂起的地方继续执行,就必须知道它上次执行到哪个位置,在JVM中,通过程序计数器来记录某个线程的字节码执行位置。因此,程序计数器是具备线程隔离的特性,也就是说,每个线程工作时都有属于自己的独立计数器。即私有性,每个线程都拥有私有的程序计数器


使用PC寄存器存储字节码指令地址有什么用呢?


其实在上一段文字中已经写了,这里写个缩句哈。


因为CPU需要不停的切换各个线程,这时候切换回来以后,就得知道接着从哪开始继续执行。


JVM的字节码解释器就需要通过改变PC寄存器的值来明确下一条应该执行什么样的字节码指令。


微信截图_20220523204628.png


那么 PC寄存器为什么被设定为私有的?(图解)


由于CPU时间片轮限制,众多线程在并发执行过程中,任何一个确定的时刻,一个处理器或者多核处理器中的一个内核,只会执行某个线程中的一条指令。


这样必然导致经常中断或恢复,如何保证分毫无差呢?每个线程在创建后,都会产生自己的程序计数器和栈帧,程序计数器在各个线程之间互不影响。


还是决定手画几张图来帮助大家来理解记忆:


微信截图_20220523204653.png


我想看完这个图,大家对pc 程序计数器 为什么是私有是有个大概的理解了吧。


自言自语:


更多的文章在后面拉,还会有的,路还长勒。

人生路上选择众多,但不要害怕选择,那都是人生宝贵的财富,


目录
相关文章
|
1月前
|
Java
JVM运行时数据区
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一
25 2
|
2月前
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
25 3
|
3月前
|
Java
jvm复习,深入理解java虚拟机一:运行时数据区域
这篇文章深入探讨了Java虚拟机的运行时数据区域,包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、元空间和运行时常量池,并讨论了它们的作用、特点以及与垃圾回收的关系。
75 19
jvm复习,深入理解java虚拟机一:运行时数据区域
|
3月前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
45 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
2月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
322 1
|
3月前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
45 4
|
6天前
|
存储 Java 程序员
【JVM】——JVM运行机制、类加载机制、内存划分
JVM运行机制,堆栈,程序计数器,元数据区,JVM加载机制,双亲委派模型
|
26天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
2月前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80
|
2月前
|
存储 缓存 监控
Elasticsearch集群JVM调优堆外内存
Elasticsearch集群JVM调优堆外内存
51 1