聊聊jvm的内存结构, 以及各种结构的作用

简介: 【10月更文挑战第27天】JVM(Java虚拟机)的内存结构主要包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和运行时常量池。各部分协同工作,为Java程序提供高效稳定的内存管理和运行环境,确保程序的正常执行、数据存储和资源利用。

JVM(Java 虚拟机)的内存结构主要由以下几个部分组成,每个部分都有其特定的作用:


1. 程序计数器(Program Counter Register)


  • 定义与位置
  • 程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。在 JVM 的概念模型中,字节码解释器工作时就是通过这个计数器的值来选取下一条需要执行的字节码指令。
  • 此区域是线程私有的,即每个线程都有自己独立的程序计数器,各个线程之间互不影响。
  • 作用
  • 字节码执行顺序控制:在多线程环境下,由于线程的切换等操作,需要精确记录每个线程当前执行到的字节码位置。程序计数器确保了线程被切换回来后能继续从上次暂停的地方开始执行,保证了线程执行的连续性和顺序性。
  • 支持分支、循环和跳转操作:在执行循环、条件判断(如 if - else 语句)和方法调用(涉及跳转)等操作时,程序计数器能准确跟踪指令执行流程,使程序按照预期的逻辑执行。


2. Java 虚拟机栈(Java Virtual Machine Stack)


  • 定义与位置
  • 与程序计数器一样,Java 虚拟机栈也是线程私有的。它的生命周期与线程相同,随着线程的创建而创建,线程的结束而销毁。
  • 虚拟机栈描述的是 Java 方法执行的内存模型,每个方法在执行时都会创建一个栈帧(Stack Frame),并将其压入栈中,方法执行完毕后栈帧弹出。
  • 栈帧结构和作用
  • 局部变量表(Local Variable Table)
  • 定义:是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。在编译期就确定了其大小,并且在方法执行期间不会改变。
  • 作用:提供了方法内部数据存储的基本单元,保证了方法执行过程中对变量的快速访问和操作,是方法执行的基础数据支撑。
  • 操作数栈(Operand Stack)
  • 定义:是一个后入先出(LIFO)栈,在方法执行过程中,字节码指令向操作数栈中写入和提取操作数。
  • 作用:作为字节码指令的操作数存储和运算的场所,许多字节码指令都需要操作数栈来完成数据的传递、运算(如加法、乘法运算)和方法调用等操作。
  • 动态连接(Dynamic Linking)
  • 定义:每个栈帧都包含一个指向运行时常量池的引用,用于支持方法调用过程中的动态连接。
  • 作用:在 Java 中,方法调用可能涉及到不同类中的同名方法(如接口实现类中的方法调用),动态连接机制通过运行时常量池来确定实际调用的方法,保证了方法调用的准确性。
  • 方法返回地址(Method Return Address)
  • 定义:当一个方法执行完毕后,需要知道返回的位置,这个返回位置就存储在方法返回地址中。
  • 作用:保证了方法执行完后程序流程的正确回归,使得方法调用后的后续操作能够正常进行,无论是返回值的传递还是程序执行流程的衔接都依赖于此。
  • 整体作用
  • 为 Java 方法的执行提供了一个基于栈的运行环境,通过栈帧的压入和弹出机制,实现了方法的调用和返回,以及方法内部数据的管理和操作。


3. 本地方法栈(Native Method Stack)


  • 定义与位置
  • 本地方法栈与 Java 虚拟机栈类似,也是线程私有的。它与 Java 虚拟机栈的区别在于,Java 虚拟机栈用于执行 Java 方法,而本地方法栈用于执行本地方法(Native Method),即使用非 Java 语言(如 C 或 C++)编写的、被 Java 代码调用的方法。
  • 作用
  • 为本地方法的执行提供内存空间和执行环境,保证本地方法能够在 JVM 环境中顺利运行。在调用一些操作系统底层功能或使用硬件相关资源时,往往需要通过本地方法来实现,本地方法栈为这些操作提供了支持。


4. Java 堆(Java Heap)


  • 定义与位置
  • Java 堆是 JVM 所管理的内存中最大的一块,它是被所有线程共享的一块内存区域,在 JVM 启动时创建。
  • 堆内存的主要用途是存放对象实例,几乎所有的对象实例都在这里分配内存(除了一些特殊情况,如对象逃逸分析后确定可在栈上分配的对象)。
  • 作用
  • 对象存储:作为对象的主要存储区域,Java 堆为 Java 程序中大量的对象实例提供了存储空间。无论是简单的自定义对象,还是复杂的集合对象、框架类对象等,都在堆中分配内存。
  • 内存管理和垃圾回收重点区域:由于堆内存中对象的动态生成和销毁,随着程序的运行,堆内存中的对象会逐渐增多,其中一些对象会变成垃圾(不再被引用的对象)。因此,堆是垃圾回收机制(Garbage Collection)的重点管理区域,通过垃圾回收算法来回收垃圾对象占用的内存,以保证堆内存的有效利用。


5. 方法区(Method Area)


  • 定义与位置
  • 方法区也是所有线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等。
  • 在 Java 8 之前,方法区是在堆中的一个独立的区域,称为永久代(Permanent Generation)。Java 8 及以后,方法区的实现被元数据区(Metaspace)取代,元数据区并不在堆中,而是使用本地内存(Native Memory)。
  • 作用
  • 类信息存储:存放类的全限定名、类的父类信息、类的实现接口信息、类的访问修饰符等,这些信息是 Java 虚拟机在运行过程中识别和处理类的依据。
  • 常量存储:运行时常量池(Runtime Constant Pool)是方法区的一部分,它存储了各种字面常量(如字符串常量、基本类型的常量值)和符号常量(如类和接口的全限定名、字段和方法的名称和描述符等)。在编译阶段,这些常量被收集到常量池,在运行时可被使用。
  • 静态变量存储:类的静态变量(如public static int num;)在类加载时就会被分配到方法区中,并且在整个类的生命周期内都存在,为类的静态行为和数据共享提供了支持。
  • 代码存储:存储经过即时编译器(Just - In Compiler,JIT)编译后的代码,这些代码可以在后续的运行中被直接调用,提高了程序的运行效率。


6. 运行时常量池(Runtime Constant Pool)


  • 定义与位置
  • 运行时常量池是方法区的一部分,但在逻辑上是一个独立的概念。它在类加载时根据类的常量池(Class Constant Pool)创建,用于存储类的字面常量和符号常量。
  • 作用
  • 常量存储和共享:在 Java 程序中,很多常量需要在运行期间被使用,如字符串常量。运行时常量池为这些常量提供了集中存储的场所,并且对于相同的字面常量(如多次出现的字符串 "Hello"),在池中只会存储一份,实现了常量的共享,节省了内存空间。
  • 支持动态链接和解析:在 Java 方法执行过程中,涉及到对类、字段和方法的引用时,需要通过运行时常量池来进行动态链接和解析。例如,当调用一个方法时,字节码指令会通过运行时常量池找到对应的方法符号引用,然后将其解析为实际的方法调用,保证了 Java 程序在运行时对类和方法的准确使用。


JVM 的内存结构各部分紧密协作,为 Java 程序的运行提供了稳定、高效的内存管理和运行环境,保障了 Java 程序的正常执行、数据存储和资源利用。

相关文章
|
12天前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
28 4
|
12天前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
36 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
15天前
|
存储 缓存 算法
JVM核心知识点整理(内存模型),收藏再看!
JVM核心知识点整理(内存模型),收藏再看!
JVM核心知识点整理(内存模型),收藏再看!
|
1天前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
11天前
|
存储 监控 算法
JVM调优深度剖析:内存模型、垃圾收集、工具与实战
【10月更文挑战第9天】在Java开发领域,Java虚拟机(JVM)的性能调优是构建高性能、高并发系统不可或缺的一部分。作为一名资深架构师,深入理解JVM的内存模型、垃圾收集机制、调优工具及其实现原理,对于提升系统的整体性能和稳定性至关重要。本文将深入探讨这些内容,并提供针对单机几十万并发系统的JVM调优策略和Java代码示例。
39 2
|
12天前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
28 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
12天前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
25 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
|
15天前
|
Java API 对象存储
JVM进阶调优系列(2)字节面试:JVM内存区域怎么划分,分别有什么用?
本文详细解析了JVM类加载过程的关键步骤,包括加载验证、准备、解析和初始化等阶段,并介绍了元数据区、程序计数器、虚拟机栈、堆内存及本地方法栈的作用。通过本文,读者可以深入了解JVM的工作原理,理解类加载器的类型及其机制,并掌握类加载过程中各阶段的具体操作。
|
20天前
|
存储 Java Linux
【JVM】JVM执行流程和内存区域划分
【JVM】JVM执行流程和内存区域划分
36 1
|
21天前
|
存储 安全 Java
JVM锁的膨胀过程与锁内存变化解析
在Java虚拟机(JVM)中,锁机制是确保多线程环境下数据一致性和线程安全的重要手段。随着线程对共享资源的竞争程度不同,JVM中的锁会经历从低级到高级的膨胀过程,以适应不同的并发场景。本文将深入探讨JVM锁的膨胀过程,以及锁在内存中的变化。
21 1