JVM代码运行逻辑解读

 更新时间:2025年04月18日 09:18:44   作者:堕落年代  
这篇文章主要介绍了JVM代码运行逻辑,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

JVM代码运行逻辑

理解一个Java程序在JVM中的执行流程,有助于深入理解JVM内存管理和运行机制。

让我们通过一个简单的Java代码示例,结合JVM的各个内存区域和执行过程,逐步分析一个Java程序在JVM中的执行逻辑。

示例代码

public class HelloWorld {
    // 静态变量存放在方法区
    private static String greeting = "Hello, World!";
    
    // 成员变量存放在堆内存
    private int number;

    public HelloWorld(int number) {
        this.number = number;
    }

    // main方法存放在方法区,局部变量在栈上
    public static void main(String[] args) {
        // 局部变量存放在虚拟机栈
        int localNumber = 10;

        // 对象存储在堆,引用变量存在栈中
        HelloWorld hello = new HelloWorld(localNumber);

        // 调用方法并传递引用
        hello.printGreeting();
    }

    // 实例方法也存放在方法区
    public void printGreeting() {
        System.out.println(greeting + " Number: " + number);
    }
}

执行过程分析

1.类加载

程序开始时,JVM 会通过类加载器(ClassLoader)加载 HelloWorld 类的字节码文件(HelloWorld.class)到方法区中。

  • 方法区(Java 8 以后叫元空间 Metaspace):存放类的信息,如类的字节码、静态变量、方法信息(main 方法、printGreeting 方法等),以及常量池(如字符串常量池存储 "Hello, World!")。
  • 静态变量 greeting 存放在方法区,main 方法的字节码也会存储在方法区。

2.JVM 启动 main 方法

JVM 启动后,它首先寻找 HelloWorld 类的 main 方法,执行这个方法是程序的入口。此时会创建一个用于 main 方法的栈帧(Stack Frame),这个栈帧会存放 main 方法中的局部变量。

int localNumber = 10;
  • 虚拟机栈(JVM Stack)main 方法的栈帧存放在虚拟机栈中。局部变量 localNumber 的值(10)也存储在这个栈帧中。

3.对象分配

执行 HelloWorld hello = new HelloWorld(localNumber); 时,JVM 会在堆内存中分配一个新的 HelloWorld 对象,存储这个对象的实例变量。

  • 堆内存(Heap)new HelloWorld(10) 会在堆中创建一个对象实例,并为 number 分配存储空间。number 的值(10)被初始化并存放在堆中。
  • hello 变量本身是一个引用,它存储在 main 方法的栈帧中,指向堆中的 HelloWorld 对象。

4.方法调用

当执行 hello.printGreeting(); 时,JVM 会为 printGreeting 方法创建一个新的栈帧,并将 hello 作为隐含的 this 传递给该方法。

  • 虚拟机栈(JVM Stack)printGreeting 方法的栈帧存储局部变量和操作数栈,包括引用 this(指向堆中的 HelloWorld 对象)。
  • printGreeting 中,JVM 会从堆内存中取出 number 的值(10),从方法区中的字符串常量池取出 "Hello, World!",并执行 System.out.println

5.输出操作

System.out.println(greeting + " Number: " + number);

这行代码通过 System.out 调用来输出内容到控制台。

最终,控制台会输出:

Hello, World! Number: 10

  • 方法区greeting 是一个静态变量,它在类加载时就已经存储在方法区。"Hello, World!" 存储在字符串常量池中。
  • 堆内存this.number 的值(10)从堆中获取。

6.垃圾回收(GC)

main 方法执行结束后,main 方法的栈帧被销毁,局部变量 hello 的引用也会随之消失。如果没有其他地方再引用堆中的 HelloWorld 对象,那么垃圾回收器(GC)会认为它是不可达对象,从而在合适的时候对该对象进行回收,释放它占用的堆内存。

内存区域的角色总结

1.方法区(元空间 Metaspace)

  • 存储类的元数据、静态变量和常量池信息。
  • 静态变量 greeting 和方法的字节码存储在这里。

2.堆内存(Heap Memory)

  • 存储所有对象实例和数组。
  • HelloWorld 对象实例存储在堆内存中,实例变量 number 也存在堆中。

3.虚拟机栈(JVM Stack)

  • 每个线程都会有一个独立的栈,用来存储方法调用的局部变量和操作数栈。
  • main 方法和 printGreeting 方法的栈帧存储在虚拟机栈中,局部变量如 localNumberhello 引用都在栈中。

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

  • 存储当前线程正在执行的字节码指令地址。
  • 线程切换时,程序计数器帮助恢复代码的执行位置。

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

  • 专门用于执行本地方法(如 JNI 调用的 C/C++ 代码),但在此例子中未涉及。

总结

通过这段代码,JVM 的执行逻辑可以清晰地展现出来:

  • 类加载器首先加载字节码到方法区。
  • 在堆内存中分配对象,引用保存在虚拟机栈中。
  • 方法的执行流程通过栈帧的创建和销毁来管理。
  • 最终,垃圾回收器会在内存中清理不再使用的对象。

这种分工明确的内存管理机制使得 JVM 能够高效运行,并保证内存的安全性和自动管理。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Springboot中的@ConditionalOnBean注解详细解读

    Springboot中的@ConditionalOnBean注解详细解读

    这篇文章主要介绍了Springboot中的@ConditionalOnBean注解详细解读,@ConditionalOnMissingBean注解两个类,一个Computer类,一个配置类,想要完成;如果容器中没有Computer类,就注入备用电脑Computer类,如果有Computer就不注入,需要的朋友可以参考下
    2023-11-11
  • IDEA2022中部署Tomcat Web项目的流程分析

    IDEA2022中部署Tomcat Web项目的流程分析

    这篇文章主要介绍了IDEA2022中部署Tomcat Web项目,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • springboot中@PostConstruct注解使用小结

    springboot中@PostConstruct注解使用小结

    本文主要介绍了springboot中@PostConstruct注解使用小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-01-01
  • postman 如何实现传递 ArrayList 给后台

    postman 如何实现传递 ArrayList 给后台

    这篇文章主要介绍了postman 如何实现传递 ArrayList给后台,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 使用SpringMVC响应json格式返回的结果类型

    使用SpringMVC响应json格式返回的结果类型

    这篇文章主要介绍了使用SpringMVC响应json格式返回的结果类型,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 详解JAVA生成将图片存入数据库的sql语句实现方法

    详解JAVA生成将图片存入数据库的sql语句实现方法

    这篇文章主要介绍了详解JAVA生成将图片存入数据库的sql语句实现方法的相关资料,这里就是实现java生成图片并存入数据库的实例,需要的朋友可以参考下
    2017-08-08
  • Spring Boot运行部署过程图解

    Spring Boot运行部署过程图解

    这篇文章主要介绍了Spring Boot运行部署过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • java获取各种路径的基本方法

    java获取各种路径的基本方法

    这篇文章主要为大家详细介绍了java获取各种路径的基本方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • JAVA SpringBoot统一日志处理原理详解

    JAVA SpringBoot统一日志处理原理详解

    这篇文章主要介绍了SpringBoot的统一日志处理原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-09-09
  • 一文秒懂logstash收集springboot日志的方法

    一文秒懂logstash收集springboot日志的方法

    通过这篇文章带你了解logstash收集springboot日志的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04

最新评论