JVM之虚拟机栈

本文深入探讨了Java虚拟机栈的工作原理,包括方法执行的动态内存模型,栈帧的入栈与出栈过程,以及栈内存消耗导致的StackOverflowError异常。通过具体代码示例,解释了局部变量表、操作数栈和动态链接的概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.基本概念

      虚拟机栈描述的是java方法执行的动态内存模型:每个方法从执行都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从执行到结束,都对应一个栈帧的在虚拟机栈中的入栈和出栈。特点:线程私有。

Class Text{
    public static void sleep(){
        goBed();
        Boolean isSleep = true;
        if(isSleep){
             System.out.println("Sleep....");
        }
         int number1 = 1;
         int number2 = 2;
        int number3 = number1 + number2;
    }
    public static void goBed(){
        Boolean isGobed = true;
        if(isGobed){
            System.out.println("goBed....");
        } 
    }
    
    public static void main(String[] args){
        sleep();
    }
}

 

   以上述程序为模板其虚拟机栈运行如图

 

    虚拟机栈遵循LIFO的思想,当main被调用时入栈,当main调用sleep时栈帧2入栈,依次类推。

    当goBed函数执行完,栈帧3出栈,依次类推。

    每次的栈帧入栈操作对应着虚拟机栈的内存消耗,当栈的内存消耗完时,方法则不能进行调用这时便会出现stackOverFlowError,即内存溢出。

    常规下栈的内存是多少呢,每个机器的默认栈内存不大一样大概2m左右,可以通过定义数组的大小进行估算。当然也可以自己设置栈内存的大小(在后面栈溢出问题将演示).

    栈里面的变量表和操作数栈他们之间的联系是什么。以栈帧3为类。

   操作数栈是一个用来保存执行过程中的运算值的功能(LIFO)

   如图是一个概念演示。

    returnAddress类型是为字节码指令jsr、jsr_w和ret服务的,它指向了一条字节码指令的地址。在Class文件中的常量池持中存有大量的符号引用。字节码中的方法调用指令就以常量池中指向方法的符号引用作为参数。这些符号引用一部分在类的加载阶段(解析)或第一次使用的时候就转化为了直接引用(指向数据所存地址的指针或句柄等),这种转化称为静态链接。而相反的,另一部分在运行期间转化为直接引用,就称为动态链接。 

import java.lang.Integer

public Test{
    
}

java文件编译时不知道Integer类的真实地址,它加入用Integer这个名词来代替的话,这个Integer就可以理解为符号引用,当Test类被装载器装载时,通过虚拟机就可以获得Integr真实的地址,这真实地址就是直接引用。

### JVM 虚拟机的概念和作用 #### 1. JVM 虚拟机的定义 JVM 虚拟机是 Java 虚拟机中用于存储方法执行时相关数据结构的一部分内存区域。每个线程在创建时都会分配一个虚拟机,其生命周期与线程一致[^3]。虚拟机由多个帧(Stack Frame)组成,每个帧对应一次方法调用。 #### 2. 帧的组成 帧是虚拟机的基本组成部分,它包含以下内容: - **局部变量表**:用于存储方法中的局部变量,包括基本数据类型、对象引用等[^4]。 - **操作数**:用于存储常量和对象地址,是方法执行过程中临时数据存放的地方[^4]。 - **动态链接**:负责解析方法内调用其他方法的名字,并将其映射为具体的一段代码。 - **方法出口**:用于在方法执行完毕后返回到线程的具体位置[^4]。 #### 3. JVM 虚拟机的作用 JVM 虚拟机的主要作用是支持方法的执行,包括以下几个方面: - **存储方法执行过程中的局部变量**:通过局部变量表保存方法内的变量信息。 - **提供方法调用和返回的支持**:通过帧实现方法的调用和返回逻辑[^4]。 - **管理线程的执行状态**:每个线程拥有独立的虚拟机,确保线程之间的隔离性[^3]。 #### 4. 异常处理 JVM 规范定义了两种常见的异常情况: - 如果线程请求分配的容量超过虚拟机允许的最大容量,则抛出 `StackOverflowError` 异常[^2]。 - 如果虚拟机可以动态扩展,但在尝试扩展时无法申请到足够的内存,或者在创建新线程时没有足够的内存来创建对应的虚拟机,则抛出 `OutOfMemoryError` 异常[^2]。 #### 5. 示例代码 以下是一个简单的 Java 方法调用示例,展示了虚拟机的工作原理: ```java public class Example { private int num = 0; public void methodA() { System.out.println("methodA()"); methodB(); } public void methodB() { System.out.println("methodB()"); num++; } public static void main(String[] args) { Example example = new Example(); example.methodA(); } } ``` 在上述代码中: - 当调用 `methodA()` 时,会创建一个新的帧,其中包含局部变量表、操作数等。 - 在 `methodA()` 内部调用 `methodB()` 时,又会创建一个新的帧,压入虚拟机中。 - 方法执行完毕后,帧被弹出,控制权返回到上一层方法。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值