java虚拟机运行时数据区介绍

简介: 最近打算将java虚拟机的相关知识点整理出来。本文先介绍下java虚拟机运行时分配的各个区域的作用

最近打算将java虚拟机的相关知识点整理出来。本文先介绍下java虚拟机运行时分配的各个区域的作用


运行时数据区域


java虚拟机在程序执行的过程中会把它所管理的内存划分为若干个不同的数据区域,每个区域都有各自的用途。结构图如下:

20190214210001385.png


程序计数器


 程序计数器(Program Counter Register)是一块较小的内存空间,这块区域是线程私有的。作用是当前线程所执行的字节码的行号指示器(记录器)。

 java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现。在任何一个确定的时间点,一个处理器(对于多核处理器就是一个内核)都只会执行一条线程中的指令,因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器。各个线程之间计数器是相互不影响的。独立存储。所以程序计数器的作用也比较突出。保存当前线程执行的位置。


java虚拟机栈


 和程序计数器一样java虚拟机栈也是线程私有的。它的生命周期和线程相同。

 虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧,用来存储局部变量表,操作栈,动态链接,方法出口等信息。每个方法从调用直到执行完成的过程,都对应一个栈幁在虚 拟机栈中从入栈到出栈的过程。


 在编译程序代码的时候,栈帧需要多大的局部变量表,多深的操作数栈都已经完全确定了,并且写入到方法表的code属性中,因此一个栈帧需要分配多少内存,不会受到运行期变量数据的影响,而仅仅取决于具体的虚拟机实现。


 一个线程中的方法调用链路可能会很长,很多方法都处于同时执行的状态。对于执行引擎来说,在活动线程中,只有处于栈顶的栈帧才是有效的,称为当前栈帧,与这个栈帧相关联的方法称为当前方法。

执行引擎运行的所有字节码指令只针对当前栈帧进行操作,在概念模型上,典型的栈帧结构如图所示:

20190214212521317.png


本地方法栈


 本地方法栈和虚拟机栈所发挥的作用是非常相似的。他们的区别仅仅是java虚拟机栈是为java方法调用服务的,而本地方法栈主要是为虚拟机调用到native方法服务的。

 如果某个虚拟机实现的本地方法接口是使用C连接模型的话,那么它的本地方法栈就是C栈。本地方法接口需要回调Java虚拟机中的Java方法,在这种情况下,该线程会保存本地方法栈的状态并进入到另一个Java栈。如下是虚拟机栈和本地方法栈的图示

20190214213316171.png


java堆


 Java堆(Java Head)是java虚拟机中所管理的内存中最大的一块。

java堆是被所有线程共享的一块内存区域。java堆的唯一目的就是存放对象实例。几乎所有的对象实例都在这里分配内存。

 Java堆是垃圾收集器管理的主要区域。因此垃圾收集器也被称作"GC堆",在垃圾收集器的角度Java堆还可以细分为:新生代和老年代在细致的区分有:Eden空间,From Survivor空间,To survivor空间等从内存分配的角度来看,线程共享的Java堆中还可以划分出每个线程私有的分配缓冲区(Thread Local Allocation Buffer TLAB)。

 不管如何划分,都与存放内容无关,无论哪个区域,存放的都是对象实例,划分的目的是为了更好的回收内存或者更快的分配内存。后面文章中具体介绍各个区域如何分配的等。

 java堆中的内存地址物理上可以不是连续的。只要逻辑上连续即可。

-Xxm和-Xms 控制堆的大小。


方法区


 方法区(Method Area)与java堆一样,是各个线程共享的内存区域。用来存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。

 方法区的大小不必是固定的,jvm可以根据应用的需要动态调整。同样方法区也不必是连续的。方法区可以在堆(甚至是虚拟机自己的堆)中分配。jvm可以允许用户和程序指定方法区的初始大小,最小和最大尺寸。

 方法区同样存在垃圾收集,因为通过用户定义的类加载器可以动态扩展Java程序,一些类也会成为垃圾。jvm可以回收一个未被引用类所占的空间,以使方法区的空间最小。

 对每个加载的类型,jvm必须在方法区中存储以下类型信息:


这个类型的完整有效名

这个类型直接父类的完整有效名(除非这个类型是interface或是 java.lang.Object,两种情况下都没有父类)

这个类型的修饰符(public,abstract, final的某个子集)

这个类型直接接口的一个有序列表

除了以上的基本信息外,jvm还要为每个类型保存以下信息:


类型的常量池( constant pool)

域(Field)信息

方法(Method)信息

除了常量外的所有静态(static)变量


20190217212657927.png

运行时常量池


 运行时常量池(Runtime Constant Pool) 是方法区的一部分。jvm为每个已加载的类型都维护一个常量池。常量池就是这个类型用到的常量的一个有序集合,包括实际的常量(string, integer, 和floating point常量)和对类型,域和方法的符号引用。池中的数据项象数组项一样,是通过索引访问的。

因为常量池存储了一个类型所使用到的所有类型,域和方法的符号引用,所以它在java程序的动态链接中起了核心的作用。


2019021721312088.png


直接内存


 直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分。但是这部分内存也会被频繁的使用到。

 在java中使用NIO的时候,Channel和缓冲区(Buffer),它可以使用Native函数库直接分配堆外内存。然后通过存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作,这样可以在某些场景中显著提高性能。避免了在java堆和Native堆中来回复制数据。

20190217213459207.png

相关文章
|
2月前
|
Java
使用IDEA创建项目运行我的第一个JAVA文件输出Helloword
本文介绍了如何使用IDEA(IntelliJ IDEA)创建一个新的Java项目,并运行一个简单的Java程序输出"Hello Word"。文章详细展示了创建项目的步骤,包括选择JDK版本、设置项目名称和路径、创建包和类,以及编写和运行代码。最后,还展示了如何通过IDEA的运行功能来执行程序并查看输出结果。
162 4
使用IDEA创建项目运行我的第一个JAVA文件输出Helloword
|
1月前
|
Java
Java关键字 —— super 详细解释!一看就懂 有代码实例运行!
文章详细解释了Java关键字`super`的用途,包括访问父类的成员变量、调用父类的构造方法和方法,并提供了相应的代码实例。
123 5
Java关键字 —— super 详细解释!一看就懂 有代码实例运行!
|
1月前
|
Java Apache Maven
Java百项管理之新闻管理系统 熟悉java语法——大学生作业 有源码!!!可运行!!!
文章提供了使用Apache POI库在Java中创建和读取Excel文件的详细代码示例,包括写入数据到Excel和从Excel读取数据的方法。
60 6
Java百项管理之新闻管理系统 熟悉java语法——大学生作业 有源码!!!可运行!!!
|
2月前
|
Java Linux
java基础(3)安装好JDK后使用javac.exe编译java文件、java.exe运行编译好的类
本文介绍了如何在安装JDK后使用`javac.exe`编译Java文件,以及使用`java.exe`运行编译好的类文件。涵盖了JDK的安装、环境变量配置、编写Java程序、使用命令行编译和运行程序的步骤,并提供了解决中文乱码的方法。
67 2
|
1月前
|
Java
jvm复习,深入理解java虚拟机一:运行时数据区域
这篇文章深入探讨了Java虚拟机的运行时数据区域,包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、元空间和运行时常量池,并讨论了它们的作用、特点以及与垃圾回收的关系。
64 19
jvm复习,深入理解java虚拟机一:运行时数据区域
|
1月前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
33 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
1月前
|
分布式计算 大数据 Java
大数据-86 Spark 集群 WordCount 用 Scala & Java 调用Spark 编译并打包上传运行 梦开始的地方
大数据-86 Spark 集群 WordCount 用 Scala & Java 调用Spark 编译并打包上传运行 梦开始的地方
26 1
大数据-86 Spark 集群 WordCount 用 Scala & Java 调用Spark 编译并打包上传运行 梦开始的地方
|
30天前
|
存储 Dart Java
Dart 虚拟机运行原理
【10月更文挑战第20天】Dart 虚拟机通过一系列复杂的机制和操作,确保 Dart 代码能够准确、高效地执行。它为 Dart 语言的广泛应用提供了坚实的基础和可靠的运行环境
25 6
|
1月前
|
IDE Java 编译器
Java:如何确定编译和运行时类路径是否一致
类路径(Classpath)是JVM用于查找类文件的路径列表,对编译和运行Java程序至关重要。编译时通过`javac -classpath`指定,运行时通过`java -classpath`指定。IDE如Eclipse和IntelliJ IDEA也提供界面管理类路径。确保编译和运行时类路径一致,特别是外部库和项目内部类的路径设置。
|
1月前
|
Java
Java关键字 —— super 与 this 详细解释!一看就懂 有代码实例运行!
本文介绍了Java中this和super关键字的用法,包括在构造方法中使用this来区分参数和成员变量、使用super调用父类构造方法和方法,以及它们在同一个方法中同时使用的场景。
130 0
Java关键字 —— super 与 this 详细解释!一看就懂 有代码实例运行!
下一篇
无影云桌面