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

相关文章
|
前端开发 Java 关系型数据库
基于Java+Springboot+Vue开发的鲜花商城管理系统源码+运行
基于Java+Springboot+Vue开发的鲜花商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜花商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。技术学习共同进步
856 7
|
存储 安全 Java
JVM深入原理(七)(一):运行时数据区
栈的介绍:Java虚拟机栈采用栈的数据结构来管理方法调用中的基本数据,先进后出,每一个方法的调用使用一个栈帧来保存栈的组成:栈:一个线程运行所需要的内存空间,一个栈由多个栈帧组成栈帧:一个方法运行所需要的内存空间活动栈帧:一个线程中只能有一个活动栈帧栈的生命周期:栈随着线程的创建而创建,而回收会在线程销毁时进行栈的执行流程:栈帧压入栈内执行方法执行完毕释放内存若方法间存在调用,那么会压入被调用方法入栈,执行完后释放内存,再执行当前方法,直到执行完毕,释放所有内存。
280 0
|
存储 缓存 安全
JVM深入原理(七)(二):运行时数据区
堆的作用:存放对象的内存空间,它是空间最大的一块内存区域.栈上的局部变量表中,可以存放堆上对象的引用。静态变量也可以存放堆对象的引用,通过静态变量就可以实现对象在线程之间共享。堆的特点:线程共享:堆中的对象都需要考虑线程安全的问题垃圾回收:堆有垃圾回收机制,不再引用的对象就会被回收方法区的概述:方法区是存放基础信息的位置,线程共享,主要包括:类的元信息:保存了所有类的基本信息运行时常量池:保存了字节码文件中的常量池内容静态常量池:字节码文件通过编号查表的方式找到常量。
216 0
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
858 14
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
前端开发 JavaScript Java
Java打包jar运行时分离lib和jar
在`pom.xml`的`build`节点中,设置`packaging`为`jar`,并配置插件分离依赖库到`lib`目录和资源文件到`resources`目录。这样可以在运行时通过`-Dloader.path=lib,resources`加载外部依赖和资源文件,便于独立升级依赖库和修改资源文件,而无需重新打包程序。具体插件包括`maven-dependency-plugin`、`maven-resources-plugin`和`spring-boot-maven-plugin`等。
1102 2
|
存储 Java C++
JVM 运行时数据区
Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域。这 些区域都有各自的用途,以及创建和销毁的时间,有些区域随着虚拟机进程的启动而存在,有些区 域则是依赖线程的启动和结束而建立和销毁。Java 虚拟机所管理的内存被划分为如下几个区域 程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解 析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳 转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成; 为什么要线程计数器?因为线程是不具备记忆功能 Java 虚拟机
|
Java
JVM运行时数据区
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一
190 2
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
226 3
|
IDE Java 编译器
Java:如何确定编译和运行时类路径是否一致
类路径(Classpath)是JVM用于查找类文件的路径列表,对编译和运行Java程序至关重要。编译时通过`javac -classpath`指定,运行时通过`java -classpath`指定。IDE如Eclipse和IntelliJ IDEA也提供界面管理类路径。确保编译和运行时类路径一致,特别是外部库和项目内部类的路径设置。
1174 5