通过字节码分析switch语句的执行

简介: 通过字节码分析switch语句的执行

先看一段代码

public class Test {
    public static void main(String[] args) {
        int i = 7;
        switch (i) {
            case 1:
                System.out.println("1");
            default:
                System.out.println("2");
            case 3:
                System.out.println("3");
        }
    }
}

运行结果
2
3


通过javap -c Test.class查看字节码文件

Compiled from "Test.java"
public class com.rsms.iot.service.Test {
  public com.rsms.iot.service.Test();
    Code:
       0: aload_0                //加载一个对象引用到操作数栈,在这里第一个变量是this,所以是将this引用压到操作数栈
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V (构造方法、私有方法和父类中的方法)
       4: return
  public static void main(java.lang.String[]);
    Code:
       0: bipush        7    //将操作数7压到操作数栈中
       2: istore_1     //将整形数字存储到本地变量中
       3: iload_1      //i代表int,从局部变量数组中加载一个对象引用到操作数栈的栈顶
       4: lookupswitch  { // 2   
                     1: 32   //为1匹配32行
                     3: 48   //同上
               default: 40   //同上
          }
      32: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      35: ldc           #3                  // String 1
      37: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      40: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      43: ldc           #5                  // String 2
      45: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      48: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      51: ldc           #6                  // String 3
      53: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      56: return
}


先分析下字节码文件(局部变量表和操作数栈都属于当前栈帧,内存模型我在CSDN一篇博客中整理过:https://mp.csdn.net/postedit/68945933


0:aload_0   会将this变量压到操作数栈中


0: bipush   初始化将变量推送至操作数栈栈顶


2: istore_1 将整形变量存储到本地局部变量表中位置为1的变量中


3: iload_1  将局部变量表中位置为1的变量的引用压到操作数栈中(个人理解是每次调用都会将变量的引用进行一次操作数栈的压栈操作),比如如下代码会有一次istore_1指令,两次iload_1指令。


int i = 7;
System.out.println(i);
System.out.println(i);


image.png


指令执行图示


从字节码文件可以看出,即使default在中间,编译后还是会在最后。所以匹配不到1、3时执行default,跳转到40行,40print执行之后,由于没有break语句,所以会顺序往下执行,会继续执行40行之后的所有语句。


相关文章
|
网络协议 Shell Linux
【Shell 命令集合 网络通讯 】Linux 追踪数据包在网络中的路径 traceroute命令 使用指南
【Shell 命令集合 网络通讯 】Linux 追踪数据包在网络中的路径 traceroute命令 使用指南
408 0
|
安全 关系型数据库 MySQL
揭秘MySQL海量数据迁移终极秘籍:从逻辑备份到物理复制,解锁大数据迁移的高效与安全之道
【8月更文挑战第2天】MySQL数据量很大的数据库迁移最优方案
1373 17
|
开发框架 JavaScript 前端开发
对 Electron 架构的理解
对 Electron 架构的理解
364 0
|
Java Serverless Nacos
nacos常见问题之serverless应用引擎连接异常如何解决?
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
|
存储 机器学习/深度学习 人工智能
DeepSpeed + Kubernetes 如何轻松落地大规模分布式训练
DeepSpeed + Kubernetes 如何轻松落地大规模分布式训练
|
数据可视化 图形学
R可视乎|圆环图
对于饼图,上一次学习《R语言数据可视化之美》的时候主要利用graphics包和ggplot包(可见R可视乎|饼图)。这几天的学习中发现还有一个更加简便的方法——ggpie包。接下来做简单描述,然后进入圆环图的学习。
667 0
R可视乎|圆环图
|
存储 缓存 大数据
Linux进程控制
Linux进程控制
212 0
Linux进程控制