JVM是什么?有哪些内容?有哪几个区域?

目录

一、JVM是什么?

二、JVM有哪些部分组成

运行时数据区域:

1、程序计数器

2、Java堆

3、虚拟机栈

4、方法区(元空间)

5、运行时常量池(元空间中分配)

6、字符串常量池

7、本地方法栈

8、直接内存     

类加载器:

1、类加载过程

执行引擎:


一、JVM是什么?

JVM是Java Virtual Machine(Java虚拟机)的缩写,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。使得Java程序只需要生成在Java虚拟机上运行的目标代码(字节码),就可在多种平台上不加修改的运行,这也是Java能够“一次编译,到处运行的”原因。
出处:JVM是什么?深入解析JVM原理! - 掘金 (juejin.cn)icon-default.png?t=N7T8https://juejin.cn/post/6844903881063792647

二、JVM有哪些部分组成

组成:运行时数据区域、类加载器、执行引擎。

运行时数据区域

  • 程序计数器(Program Counter Register):存储当前线程执行的字节码指令地址。
  • Java堆(Java Heap):存储Java对象实例,是Java程序运行时的动态内存区域。
  • 方法区(Method Area)(在JDK1.8之后被元空间所取代:存储类的元数据信息、静态变量、常量等数据,也称为永久代(Permanent Generation)。
  • 运行时常量池(Runtime Constant Pool):每个类或接口在编译时生成一个对应的常量池表,在运行时被加载到方法区的运行时常量池中。
  • 虚拟机栈(Java Virtual Machine Stacks):每个Java方法在执行时都会创建一个栈帧(Stack Frame),用于存储局部变量表操作数栈动态链接方法出口等信息。
  • 本地方法栈(Native Method Stack):为Java虚拟机使用到的Native方法服务,与Java虚拟机栈类似,但是用于执行本地方法。
  • 直接内存(Direct Memory):通过NIO库可以直接使用内存,而不受Java堆的限制,也属于JVM的一部分。

如下图:https://javaguide.cn/java/jvm/memory-area.htm

运行时数据区域中,可以分为线程共享,和线程私有;

线程共享包含:方法区直接内存 (非运行时数据区的一部分)、运行时常量池。线程共享区域提供了多个线程之间共享数据的机制,从而实现了多线程编程的基础。

线程私有包含:虚拟机栈本地方法区程序计数器。线程私有区域保证了每个线程在执行过程中都有自己独立的内存空间,互不干扰。这些区域会随着线程的产生而产生,消亡而消亡。

1、程序计数器

        可以将程序计数器看做是一个指针,它指向线程正在运行时的字节码,每一个线程都有一个自己的程序计数器,在进行线程切换时,以便线程找到上次运行停歇的位置继续运行。

2、Java堆

        存储Java对象实例,是Java程序运行时的动态内存区域。几乎所有的对象实例和数组都存在于堆中。Java堆也是垃圾收集器管理的主要区域,因此也被称为GC堆。

        堆通常分为三个区域:新生代,老年代,永久代(后被元空间取代,存在于本地内存)。

新生代分为三个部分:Eden,s0,s1等。这些分区都是为更好的进行垃圾回收。

3、虚拟机栈

        虚拟机栈是每个线程所私有的。栈是由栈帧组成,而一个栈帧是由局部变量表操作数栈动态链接方法返回地址组成。

局部变量表(Local Variable Table):用于存储方法执行过程中的局部变量。在方法被调用时,局部变量表会被创建,用于存储方法参数以及方法内部定义的局部变量。局部变量表中的槽位可以存储各种数据类型的值,包括基本类型和对象引用等。

操作数栈(Operand Stack):也称为操作栈,用于执行方法时进行数据操作的地方。操作数栈是一个后进先出(LIFO)的栈结构,在方法执行过程中,计算过程中的临时数据和结果会被存储在操作数栈中,供字节码指令进行操作。

动态链接(Dynamic Linking):在 Java 虚拟机中,动态链接是指在运行时解析常量池中的符号引用,将其转换为直接引用的过程。动态链接的主要目的是为了支持方法调用、字段访问等操作。

方法返回地址(Return Address):用于记录方法调用完成后返回到调用者的地址。在方法被调用时,返回地址会被存储在方法栈的栈帧中,当方法执行完成后,虚拟机会根据返回地址返回到调用点继续执行。

如图:https://javaguide.cn/java/jvm/memory-area.htm

        虚拟机栈是jvm的一个核心。几乎所有的方法的调用都是通过栈来实现的。方法调用的数据需要通过栈进行传递,每一次方法调用都会有一个对应的栈帧被压入栈中,每一个方法调用结束后,都会有一个栈帧被弹出。

4、方法区(元空间)

        主要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后的代码等数据。在一些情况下也会进行垃圾回收。

5、运行时常量池(元空间中分配)

        顾名思义,是用来存放运行时的常量的。在方法区中分配空间。整数、浮点数和字符串字面量。常见的符号引用包括类符号引用、字段符号引用、方法符号引用、接口方法符号。

6、字符串常量池

        字符串常量池是 Java 中用于存储字符串字面量的一个特殊区域,它位于方法区(在 Java 8 及之前的版本)或元空间(在 Java 8 及之后的版本)中。是为了减小内存损耗的。

7、本地方法栈

        为Java虚拟机使用到的Native方法服务,与Java虚拟机栈类似,但是用于执行本地方法。

Native方法是什么?

        Native方法是指使用本地语言(如C或C++)编写的方法,而不是Java语言编写的方法。在Java程序中,可以通过native关键字声明一个方法为本地方法,然后在本地语言中实现这个方法的具体功能。

        当Java程序调用一个native方法时,实际上是调用了本地语言中对应的函数。这样的设计使得Java程序可以与底层的操作系统或其他本地资源进行交互,例如调用操作系统提供的特定功能或调用底层硬件的接口。

8、直接内存     

         直接内存并不是运行时数据区域中的。它是 Java 中一种特殊的内存分配方式,与 Java 虚拟机堆内存不同,它不受 Java 堆大小限制,也不会受到垃圾回收的管理。直接内存通常是通过 NIO(New I/O)包中的 ByteBuffer 类来操作的。

        具体来说,直接内存是通过使用操作系统的本地内存来分配和管理的,而不是通过 Java 虚拟机来分配。这样做的主要目的是为了提高 I/O 操作的性能,因为直接内存可以绕过 Java 堆,直接与操作系统内核进行交互,减少了数据在 JVM 堆和本地堆之间的拷贝过程。

类加载器:

        类加载器(Class Loader)是 Java 虚拟机(JVM)的一个重要组成部分,负责加载 Java 类文件到内存中,并生成对应的 Class 对象。类加载器是 Java 实现动态性和灵活性的关键之一,它可以根据需要从不同的来源加载类文件,如本地文件系统、网络、数据库等。

1、类加载过程

①加载(Loading): 加载阶段是指将类的字节码文件加载到内存中,并生成对应的 Class 对象。类加载器通过指定的类全限定名(fully qualified class name)或类文件的路径来获取类文件的字节码数据。 

②链接(Linking): 链接阶段分为三个步骤:验证、准备和解析。

        验证(Verification):确保加载的类符合 JVM 规范,不会危害虚拟机的正确运行。

        准备(Preparation):为类变量(静态变量)分配内存空间,并初始化为默认值(零值)。

        解析(Resolution):将类、接口、字段和方法的符号引用转换为直接引用。

③初始化(Initialization): 初始化阶段是类加载的最后一步,它负责执行类构造器(<clinit> 方法)的过程。在这个阶段,JVM 会按照程序代码的顺序执行类的静态变量赋值和静态代码块的代码,并确保类的初始化是线程安全的。

Class对象?反射机制?

在Java中,Class对象是用来表示已加载类或接口的元数据,它包含了有关类或接口的结构信息,比如类的字段、方法、构造函数等。每个类在内存中都有一个对应的Class对象,该对象在类被加载到内存中时由JVM自动生成。

Class对象可以通过以下方式获取:

  1. 调用对象的getClass()方法:例如,对于一个已实例化的对象obj,可以通过obj.getClass()获取其对应的Class对象。
  2. 使用.class字面量:例如,对于类Foo,可以使用Foo.class来获取其对应的Class对象。
  3. 使用Class类的静态方法:例如,可以使用Class.forName("类的全限定名")方法来获取指定类的Class对象。

通过Class对象,可以进行诸如实例化对象、获取类的结构信息、调用类的方法等操作,从而实现Java的反射机制。Class对象是Java语言的一种重要特性,它使得程序在运行时可以动态地加载、操作和使用类,从而提高了程序的灵活性和可扩展性。

详情可参考:https://javaguide.cn/java/jvm/classloader.htm 非常详细!

执行引擎:

        执行引擎是Java虚拟机的一部分,负责执行已加载的字节码指令。它解释字节码指令并执行对应的操作,从而实现Java程序的运行。执行引擎通常包括以下几个组成部分:

  1. 解释器(Interpreter): 解释器逐条解释字节码指令,并将其翻译成底层操作系统或硬件的指令,然后执行。

  2. 即时编译器(Just-In-Time Compiler,JIT): 即时编译器将字节码直接编译成本地机器码,以提高执行效率。JIT编译器根据程序的运行情况来动态地选择需要编译的代码块,并将其优化成更高效的形式。

  3. 垃圾回收器(Garbage Collector): 垃圾回收器负责在运行时自动回收不再使用的内存,以避免内存泄漏和程序运行过程中的内存溢出错误。

  4. 本地方法接口(Native Method Interface,JNI): 执行引擎通过本地方法接口与底层操作系统或其他编程语言交互,调用本地方法实现对底层资源的访问,如文件系统、网络等。

执行引擎是Java程序执行的核心组件之一,它负责将字节码指令转换为具体的操作,并实现程序的功能逻辑。

  • 29
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: JVM 内存模型分为以下几个区域:程序计数器、虚拟机栈、本地方法栈、堆、方法区。 程序计数器用于记录当前线程执行的字节码的行号,以便线程在恢复执行时,能够从正确的位置继续执行。 虚拟机栈用于存储方法执行时的局部变量、操作数栈、动态链接、方法出口等信息。 本地方法栈与虚拟机栈类似,但是它是为本地方法服务的。 堆是 JVM 中最大的一块内存区域,用于存储对象实例和数组。 方法区用于存储已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 以上是 JVM 内存模型各区域的作用。 ### 回答2: JVM内存模型分为五个主要区域,分别是方法区(Method Area)、堆(Heap)、栈(Stack)、程序计数器(Program Counter)和本地方法栈(Native Method Stack)。 1. 方法区:存储类的结构信息,如运行时常量池、字段、方法代码等。在JVM启动时创建,并被所有线程共享。方法区对于存储长生命周期的数据非常重要。 2. 堆:所有对象的实例以及数组都在堆中分配内存。它是JVM共享的内存区域,用来存储运行时创建的对象实例,包括实例的数据和实例方法。在堆中,GC负责管理内存的回收和分配,具体算法包括标记-清除、复制和标记-整理等。 3. 栈:每个线程在执行程序时都会有一个对应的栈,用来存储局部变量、方法参数和方法调用。栈是基于线程的,每个线程都有自己的栈,所以栈是线程私有的。栈以栈帧(Stack Frame)的形式存在,每个方法调用都会创建一个新的栈帧,方法执行结束后,栈帧被销毁。 4. 程序计数器:程序计数器是当前线程所执行的字节码指令的行号指示器。它记录着线程执行的位置,当线程执行方法时,程序计数器记录该方法中正在执行的字节码指令地址。程序计数器是线程私有的,即每个线程都有一个程序计数器。 5. 本地方法栈:本地方法栈主要用于执行本地方法,即使用的是本地语言(如C)编写的方法。它的作用类似于栈,但是栈是为执行Java方法而设计的,本地方法栈是为执行本地方法而设计的。本地方法栈也是线程私有的。 通过这五个区域JVM可以管理和分配内存,并提供给线程执行代码所需要的资源。不同的区域有不同的作用和生命周期,有效地支持了Java程序的运行和资源管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幼儿园大哥7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值