JVM工作原理与实战(十六):运行时数据区-Java虚拟机栈

简介: JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了运行时数据区、Java虚拟机栈等内容。

一、运行时数据区

Java虚拟机(JVM)在运行Java程序期间,会创建并维护一系列内存区域,这些区域总称为运行时数据区。这些区域根据其用途和特性,被严格定义并管理。《Java虚拟机规范》详细规定了这些区域的作用和行为,以确保所有Java虚拟机实现的一致性和正确性。

线程不共享区域:

  • 程序计数器:用于存储当前线程执行的字节码指令地址。这个区域是每个线程独有的,不共享。
  • Java虚拟机栈:每个线程在创建时都会创建一个虚拟机栈,每个方法调用都会创建一个栈帧,用于存储局部变量、操作数栈、动态链接和方法出口信息。
  • 本地方法栈:与虚拟机栈相似,本地方法栈为native方法提供服务。

线程共享区域:

  • 方法区:用于存储已被JVM加载的类信息、常量、静态变量以及即时编译器编译后的代码等数据。
  • :堆是所有线程共享的区域,用于动态分配内存。所有的对象实例以及数组都应当在堆上分配。

image.gif

二、Java虚拟机栈

Java虚拟机栈是Java技术中至关重要的部分,它负责管理方法调用中的基本数据。在执行Java程序时,Java虚拟机栈是线程私有的,即每个线程都拥有自己的Java虚拟机栈,并且随着线程的创建而创建,随着线程的销毁而回收。


Java虚拟机栈,运用栈式数据结构对方法调用过程中的基本数据进行管理。遵循先进后出(First In Last Out)的原则,每一个方法调用都会对应一个独立的栈帧(Stack Frame)进行数据存储。

1.栈帧的组成

Java虚拟机栈的核心组成部分是栈帧,每一个方法的调用都会对应一个栈帧。这个栈帧存储了该方法的所有信息,包括局部变量、操作数栈、动态链接、方法出口等。

  • 局部变量表:这是在运行过程中存放所有局部变量(包括方法参数)的区域。在编译成字节码文件时,就可以确定局部变量表的内容。每个槽(slot)可以存放一个值,如果该值为long或double类型,则该槽会占用两个槽的空间。此外,实例方法的局部变量表中序号为0的位置存放的是this指针,它指向当前调用方法的对象。
  • 操作数栈:这是执行指令时存放临时数据的区域。操作数栈是实现中间计算结果交换和保存的主要场所,同时它也是函数调用的主要数据交互通道。函数作为参数传递时,就将其放在操作数栈上传递。
  • 帧数据:这部分主要包含动态链接、方法出口、异常表的引用等。动态链接保存了符号引用与运行时常量池的内存地址的映射关系。方法出口则指出了方法正常或异常结束时,当前栈帧应如何被弹出。异常表则是用于处理代码中异常的信息,包含了异常捕获的生效范围以及异常发生后跳转到的字节码指令位置。

image.gif

2.局部变量表

局部变量表是存储在栈帧中的一块区域,它的作用是在方法执行过程中存放所有的局部变量。这些变量在编译成字节码文件时就可以确定其内容。

案例:

public class Demo1 {
    public static void test() {
        int i = 0;
        long j = 1;
    }
}
image.gif

字节码:

0 iconst_0
1 istore_0
2 lconst_1
3 lstore_1
4 return
image.gif

局部变量表(Nr.表示编号;起始PC、长度表示生效范围):

image.gif

案例分析图:

image.gif

栈帧中的局部变量表是一个数组,数组中的每个位置称之为槽(slot)。每个槽可以存放一个值,long和double类型的数据会占用两个槽的空间,其他类型的数据则占用一个槽。

局部变量表(序号表示槽的起始编号):

image.gif

在实例方法中,序号为0的位置专门用于存储当前调用方法的对象引用,即this指针。在运行时,该位置将存储实例对象的内存地址,以便于访问和操作对象的属性和方法。

案例:

public class Demo1 {
    public void test() {
        int i = 0;
        long j = 1;
    }
}
image.gif

局部变量表:

image.gif

方法参数也会保存在局部变量表中,其顺序与方法中参数定义的顺序一致。

局部变量表保存的内容有:实例方法的this对象、方法的参数、方法体中声明的局部变量等。为了节省空间,局部变量表中的槽是可以复用的,一旦某个局部变量不再生效,当前槽就可以再次被使用。

案例:

public class Demo1 {
    public void test(int x,int y) {
        int i = 0;
        long j = 1;
    }
}
image.gif

局部变量表:

image.gif

3.操作数栈

操作数栈是栈帧中虚拟机在执行指令过程中用来存放临时数据的一块区域。它是一种栈式的数据结构,如果一条指令将一个值压入操作数栈,则后面的指令可以弹出并使用该值。在编译期就可以确定操作数栈的最大深度,从而在执行时正确地分配内存大小。

案例:

public class Demo1 {
    public void test() {
        int i = 0;
        int j = i + 1;
    }
}
image.gif

字节码文件信息:

image.gif

字节码:

0 iconst_0
1 istore_1
2 iload_1
3 iconst_1
4 iadd
5 istore_2
6 return
image.gif

字节码分析:

0 iconst_0 将常量0放入操作数栈
1 istore_1 从操作数栈取出放入局部变量表1号位置
2 iload_1 将局部变量表1中的数据放入操作数栈
3 iconst_1 将常量1放入操作数栈
4 iadd 将操作数栈顶部的两个数据进行累加,结果放入栈中
5 istore_2 从操作数栈取出放入局部变量表2号位置
6 return 方法结束,返回

4.帧数据

当当前类的字节码指令引用了其他类的属性或方法时,需要将符号引用(编号)转换成对应的运行时常量池中的内存地址。动态链接就保存了编号到运行时常量池的内存地址的映射关系。这样在执行时就可以快速地找到对应的内存地址。

image.gif

方法出口指的是方法在正确或异常结束时,当前栈帧会被弹出,同时程序计数器应该指向上一个栈帧中的下一条指令的地址。所以在当前栈帧中,需要存储此方法出口的地址。这样在方法结束时,就可以快速地返回到上一个方法的执行位置。


异常表主要用于存储代码中异常的处理信息,它不仅涵盖了异常捕获的有效范围,还包含了try代码块和catch代码块执行后的字节码指令跳转位置。通过异常表,虚拟机能够精确地定位异常发生的位置,并采取适当的处理措施,从而确保程序的稳定性和可靠性。

案例:

public class Demo1 {
    public void test() {
        try {
            int i = 0;
        } catch (Exception e) {
            int j = 1;
        } finally {
            int k = 2;
        }
    }
}
image.gif

字节码文件信息:

image.gif

字节码:

0 iconst_0
 1 istore_1
 2 iconst_2
 3 istore_1
 4 goto 21 (+17)
 7 astore_1
 8 iconst_1
 9 istore_2
10 iconst_2
11 istore_1
12 goto 21 (+9)
15 astore_3
16 iconst_2
17 istore 4
19 aload_3
20 athrow
21 return
image.gif

总结

JVM是Java程序的运行环境,负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了运行时数据区、Java虚拟机栈等内容,希望对大家有所帮助。

相关文章
|
2月前
|
存储 监控 Java
JVM实战—8.如何分析jstat统计来定位GC
本文详细介绍了使用jstat、jmap和jhat等工具分析JVM运行状况的方法,以及如何合理优化JVM性能。内容涵盖新生代与老年代对象增长速率、Young GC和Full GC的触发频率及耗时等关键指标的分析。通过模拟BI系统和计算系统的案例,展示了如何根据实际场景调整JVM参数以减少FGC频率,提升系统性能。最后汇总了常见问题及其解决方案,帮助开发者更好地理解和优化JVM运行状态。
JVM实战—8.如何分析jstat统计来定位GC
|
2月前
|
缓存 监控 算法
JVM实战—10.MAT的使用和JVM优化总结
本文详细探讨了JVM内存管理与性能优化的关键问题。首先分析了线上大促活动引发的老年代内存泄漏及频繁FGC问题,通过MAT工具定位到本地缓存未正确处理的原因,并提出使用Ehcache等框架解决。接着讨论了百万级数据误处理导致的频繁FGC案例,深入剖析String.split()方法在特定JDK版本下的内存消耗问题,并给出多线程并发处理大数据量的优化建议。文章还总结了JVM运行原理、GC机制以及YGC和FGC的触发条件,明确了正常系统GC频率指标。最后提供了JVM性能优化的整体思路,包括新系统开发时的参数预估、压测后的调整策略以及线上系统的监控方法,同时列举了常见的FGC原因及对应解决方案。
200 79
JVM实战—10.MAT的使用和JVM优化总结
|
2月前
|
消息中间件 缓存 Java
JVM实战—11.OOM的原因和模拟以及案例
本文详细探讨了Java系统中内存溢出(OutOfMemory,简称OOM)问题的成因与解决方法。首先分析了线上系统因OOM挂掉的常见场景及处理思路,接着深入讲解了JVM中可能发生OOM的三大区域:Metaspace(类信息存储区)、栈内存(线程执行方法时使用)和堆内存(对象存储区)。针对每个区域,文章通过具体代码示例模拟了内存溢出的情况,如动态生成过多类导致Metaspace溢出、无限递归调用引发栈内存溢出以及高负载下堆内存不足等问题。最后结合实际案例,如大数据处理系统因Kafka故障未正确处理数据缓存而导致OOM,以及无限循环调用或未缓存动态代理类引发的问题,给出了预防和改进措施。
234 64
JVM实战—11.OOM的原因和模拟以及案例
|
2月前
|
存储 监控 Java
JVM实战—7.如何模拟GC场景并阅读GC日志
本文主要介绍了:如何动手模拟出频繁Young GC的场景、JVM的Young GC日志应该怎么看、编写代码模拟动态年龄判定规则进入老年代、编写代码模拟S区放不下部分进入老年代、JVM的Full GC日志应该怎么看。
118 16
JVM实战—7.如何模拟GC场景并阅读GC日志
|
2月前
|
SQL 缓存 监控
JVM实战—9.线上FGC的几种案例
本文详细探讨了JVM性能优化中的几个关键案例与问题。首先分析了如何优化每秒十万QPS的社交APP,通过增加Survivor区大小和优化内存碎片解决频繁Full GC的问题。接着讨论了垂直电商后台系统FGC的深度优化,定制JVM参数模板以降低GC频率。还探讨了不合理设置JVM参数导致频繁FGC的情况,并提出了解决方案。此外,针对线上系统每天数十次FGC的问题,定位到大对象是主要原因,并通过调整新生代大小等参数优化。同时,分析了电商大促活动中因System.gc()调用导致系统卡死的现象,建议禁用显式GC。
180 10
JVM实战—9.线上FGC的几种案例
|
2月前
|
SQL 前端开发 Java
JVM实战—13.OOM的生产案例
本文详细探讨了多种线上系统中引发OOM(内存溢出)问题的原因及排查方法。内容涵盖:1)每秒仅上百请求的系统因RPC超时时间设置过长导致QPS激增而OOM;2)Jetty服务器NIO机制因堆外内存管理不当引发内存溢出;3)微服务架构下RPC调用因类定义不一致导致超大byte[]数组占用内存;4)SQL语句缺少WHERE条件查询大量数据引发OOM;5)日志分析系统因堆内存不足与递归操作耗尽内存;6)类加载器过多导致内存使用过高被OS杀死进程;7)数据同步系统频繁OOM的排查与解决;8)总结JVM参数优化、GC问题定位及OOM分析方法。
JVM实战—13.OOM的生产案例
|
2月前
|
缓存 监控 Java
JVM实战—12.OOM的定位和解决
本文详细探讨了JVM内存管理中的常见问题及其解决方案,包括如何监控和报警系统的OOM异常、在内存溢出时自动Dump内存快照、解决Metaspace区域内存溢出、栈内存溢出(StackOverflowError)以及堆内存溢出(OutOfMemoryError: Java heap space)。针对每种情况,文章提供了具体的解决思路、示例代码、GC日志分析及内存快照分析方法。通过搭建系统监控体系、调整JVM参数和使用工具如MAT,可以有效定位和解决各类内存问题,优化系统性能并避免崩溃风险。
JVM实战—12.OOM的定位和解决
|
2月前
|
缓存 Linux 调度
【YashanDB数据库】VMware虚拟机使用默认安装,在掉电之后数据库无法启动
VMware虚拟机使用默认安装,在掉电之后数据库无法启动
|
2月前
|
IDE 测试技术 数据库
【YashanDB知识库】使用vmware虚拟机安装的YashanDB,本机无法访问
在 VMware 虚拟机中安装并测试 YashanDB,数据库及虚拟机运行正常,但本地 IDE 工具无法连接虚拟机中的数据库。问题可能与 VMware 网络适配器配置或网络模式(如 NAT、桥接)有关,导致网络通信异常。需检查虚拟机网络设置、IP 地址配置以及防火墙规则,确保本地与虚拟机间网络连通性。目前无明确修复版本。
|
1月前
|
Linux 虚拟化 iOS开发
Windows Server 2008 R2 OVF (2025 年 4 月更新) - VMware 虚拟机模板
Windows Server 2008 R2 OVF (2025 年 4 月更新) - VMware 虚拟机模板
77 29
Windows Server 2008 R2 OVF (2025 年 4 月更新) - VMware 虚拟机模板