Java虚拟机运行时数据区精华总结
说明
本篇文章是自己学习JVM的运行数据区的总结.
文章目录
一,运行时数据区
Java虚拟机由三个子系统构成,分别是类加载子系统,JVM运行时数据区和执行引擎组成.一个Class文件先要经过类加载器–>运行时数据区–>执行引擎最终才会被执行.
而运行时数据区就是本篇文章所要重点讨论的.
Java虚拟机定义了在程序执行的时候所使用到的各种运行时数据区域. 其中一些数据区域是在Java虚拟机启动时创建的,仅在Java虚拟机退出时才被销毁. 其他数据区域是每个线程的,在创建线程时被每个线程所创建的数据区域,这些被每个线程所创建的数据区域,只有在线程退出的时候,才会被销毁.
如下图所示,这是一个比较经典的一幅结构图:
(1)程序计数器
Java虚拟机一次可以支持多个线程,所以这也就是我们经常提到的
多线程
. 每个Java虚拟机线程都有自己的程序计数器. 每个线程私有的.
在JVM中,多线程是通过线程轮流切换并分配处理器执行时间的方式来实现,在同一时刻一个处理器内核只会执行一条线程,处理器切换线程时并不会记录上一个线程执行到哪一个位置,所以为了线程切换后依然能恢复到上一次所执行到的位置
,每个线程都需要各自独立的程序计数器
.
提到程序计数器,你可能会想到操作系统中所学到的冯 ·诺伊曼计算机体系结构
如果你忘记了,整好可以通过下面这个资料来普及一下这个知识点:
冯 ·诺伊曼计算机体系结构
的主要内容之一就是“程序预存储,计算机自动执行”!处理器要执行的程序(指令序列)都是以二进制代码序列方式预存储在计算机的存储器中,处理器将这些代码逐条地取到处理器中再译码、执行,以完成整个程序的执行。为了保证程序能够连续地执行下去,CPU必须具有某些手段来确定下一条取指指令的地址。程序计数器(PC )正是起到这种作用,所以通常又称之为‘指令计数器’。**CPU总是按照PC的指向对指令序列进行取指、译码和执行,也就是说,最终是PC 决定了程序运行流向。
**故而,程序计数器(PC )属于特别功能寄存器范畴,不能自由地用于存储其他运算数据。
在程序开始执行前,将程序指令序列的起始地址,即程序的第一条指令所在的内存单元地址送入PC,CPU 按照 PC的指示从内存读取第一条指令(取指)。当执行指令时,CPU自动地修改PC 的内容,即每执行一条指令PC增加一个量,这个量等于指令所含的字节数(指令字节数),使 PC总是指向下一条将要取指的指令地址
。由于大多数指令都是按顺序来执行的,所以修改PC 的过程通常只是简单的对PC 加“指令字节数”。
(2)Java虚拟机栈
Java虚拟机栈与程序计数器一样,也是每个线程私有的. 它的生命周期也是随着现成的生命周期诞生和销毁的. 每个Java虚拟机线程都有一个私有Java虚拟机栈,与该线程同时创建. Java虚拟栈的责任: 当每个方法被执行的时候,Java虚拟机都会创建一个栈帧,用于存储
局部变量表
,操作数栈
,动态连接
,方法出口等信息
. 每一个方法被调用到执行完毕的过程,就是一个栈帧在虚拟机栈中从入栈
到出栈
的过程.
(3)本地方法栈
本地方法栈
与虚拟机栈所发挥的作用是差不做的.区别:
虚拟机栈
为虚拟机执行Java方法
服务(也就是执行字节码);本地方法栈
是为虚拟机使用到的本地方法
服务.
Java方法:
这个不用多解释了吧,例如最常见的
set和get方法
,还有自定义的方法等.
本地方法(Native Method):
简单地讲,一个Native Method就是一个java调用非java代码的接口。 一个Native Method是这样一个java的方法:该方法的实现由
非java语言实现
,比如C。这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去调用一个C的函数。
(4)Java堆
Java堆(Java Heap)是被所有线程所拥有的一块内存区域,在虚拟机启动时创建. 此内存区域的唯一目的就是
存放对象实例
,运行的Java应用程序所有的对象实例都是在此分配内存的;
(5)方法区
方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储
已经被虚拟机加载类型信息
,常量
,静态变量
,即时编译器编译后的代码缓存
等数据.
(6)运行时常量池
运行时常量池(Runtime Constant Pool)是方法区的一部分. Class文件中除了有类的
版本
,字段
,方法
,接口
等描述信息外,还有一些信息是常量池表(Constant Pool Table)
,用于存放编译期生成的各种字面量与符号引用,这部分内存将在类加载后存放到方法区运行时常量池中.
字面量:
在计算机科学中,字面量(literal)
是用于表达源代码中一个固定值的表示法(natation)。几乎所有计算机编程语言都具有对基本值的字面量表示,诸如:整数、浮点数以及字符串;而有很多也对布尔类型和字符类型的值也支持字面量表示;还有一些甚至对枚举类型的元素以及像数组、记录和对象等符合类型的值也支持字面量表示法。
字面量就是比如说int a = 1; 这个1就是字面量。又比如String a = “abc”,这个abc就是字面量。
在java中,一个java类将会编译成一个class文件。在编译时,java类并不知道引用类的实际内存地址,因此只能使用符号引用来代替。比如org.simple.People类要引用org.simple.Tool类,在编译时People类并不知道Tool类的实际内存地址,因此只能使用符号org.simple.Tool(假设)来表示Tool类的地址。而在类装载器装载People类时,此时可以通过虚拟机获取Tool类 的实际内存地址,因此便可以既将符号org.simple.Tool替换为Tool类的实际内存地址,及直接引用地址。
二,总结
JVM虚拟机包含:
- 1,程序计数器
- 2,Java虚拟机栈
- 3,本地方法栈
- 4,Java堆
- 5,方法区(6,运行时常量池;)
1,程序计数器:
在JVM中,多线程是通过线程轮流切换并分配处理器执行时间的方式来实现,在同一时刻一个处理器内核只会执行一条线程,处理器切换线程时并不会记录上一个线程执行到哪一个位置,所以
为了线程切换后依然能恢复到上一次所执行到的位置
,每个线程都需要各自独立的程序计数器
.
2,Java虚拟机栈:
当每个方法被执行的时候,Java虚拟机都会创建一个栈帧,用于存储
局部变量表
,操作数栈
,动态连接
,方法出口等信息
. 每一个方法被调用到执行完毕的过程,就是一个栈帧在虚拟机栈中从入栈
到出栈
的过程.
3,本地方法栈:
本地方法栈
与虚拟机栈所发挥的作用是差不做的.区别:
虚拟机栈
为虚拟机执行Java方法
服务(也就是执行字节码);本地方法栈
是为虚拟机使用到的本地方法
服务.
4,Java堆:
Java堆(Java Heap)是被所有线程所拥有的一块内存区域,在虚拟机启动时创建. 此内存区域的唯一目的就是
存放对象实例
,运行的Java应用程序所有的对象实例都是在此分配内存的;
5,方法区:
方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储
已经被虚拟机加载类型信息
,常量
,静态变量
,即时编译器编译后的代码缓存
等数据.
6,运行时常量池:
运行时常量池(Runtime Constant Pool)是方法区的一部分. Class文件中除了有类的
版本
,字段
,方法
,接口
等描述信息外,还有一些信息是常量池表(Constant Pool Table)
,用于存放编译期生成的各种字面量与符号引用,这部分内存将在类加载后存放到方法区运行时常量池中.
参考资料:
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.1
https://www.cnblogs.com/wjt6/p/9635752.html
http://blog.sina.com.cn/s/blog_62714d6a0100mjgs.html
https://www.cnblogs.com/chen-jack/p/7904510.html
如果对你有帮助,可以分享给你身边的朋友。 水平有限,难免会有疏漏或者书写不合理的地方,欢迎交流讨论。 作者:
TrueDei
作者主页:https://truedei.blog.csdn.net/ 转载说明:如需转载请注明原地址和作者名。
如果喜欢我的文章,还没看够可以关注我,我会用心写好每一篇文章。
- Singal Page App:使用Knockout和RequireJS创建高度模块化的单页应用引擎背景知识文档结构服务端API准备Require配置与系统配置模块中的工作模块间的工作烂图赏鉴代码送上
- Canvas 图片绕边旋转的小动画
- 探寻ASP.NET MVC鲜为人知的奥秘(3):寻找多语言的最佳实践方式
- 探寻ASP.NET MVC鲜为人知的奥秘(2):与Entity Framework配合,让异步贯穿始终
- Canvas 剪切图片
- 探寻ASP.NET MVC鲜为人知的奥秘(1):对LESS的支持
- Canvas 图片平铺设置
- Canvas 给图形绘制阴影
- State模式的经典应用场景:订单处理(c#实现)场景描述遇到问题解决问题走起
- ASP.NET SignalR 2.0入门指南介绍SignalRSignalR和WebSocket传输和回滚HTML5 传输协议Comet transports传输协议选择过程监测传输指定传输协议连接
- ASP.NET5之客户端开发:Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用Grunt和Gulp使用Grunt准备项目配置NPM配置Grunt集成起来监测文件变化与V
- 有趣的算法(三)——Hash算法
- JavaScript中的数据类型
- Logistic回归算法及Python实现
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 要一遍做对——LeetCode题目20:有效的括号
- 双指针算法练习(一)
- 一般是面试的热身题——LeetCode题目21:合并两个有序链表
- LeetCode题目22:括号生成
- OpenGL ES 3.0 | 着色器编译器
- LeetCode题目23:合并K个排序链表
- LeetCode题目24:两两交换链表中的节点
- 最难链表题——LeetCode题目25:K 个一组翻转链表
- LeetCode题目26:删除排序数组中的重复项
- PCA算法原理及实现
- LeetCode题目27:移出元素
- LeetCode题目28:实现strStr()
- LeetCode题目29:两数相除
- LeetCode题目30:串联所有单词的子串
- LeetCode题目31:下一个排列