Java字节码揭秘——第三部分

本文通过一个简单的Java异常处理示例,展示了try-catch-finally结构的工作原理,并深入探讨了其对应的字节码指令及异常表,揭示了JVM如何执行异常处理逻辑。

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

接上一部份:

 

以下是一个简单的异常处理例子:
 
public class ExFun
{
        public static void main(String[] args)
        {
               try
               {
                       System.out.println("In try block");
                       throw new Exception();
               }
               catch (java.io.IOException ioEx)
               {
                       System.out.println("In catch IOException block");
                       System.out.println(ioEx);
               }
               catch (Exception ex)
               {
                       System.out.println("In catch Exception block");
                       System.out.println(ex);
               }
               finally
               {
                       System.out.println("In finally block");
               }
        }
}
 
字节码为:
 
Compiled from "ExFun.java"
public class ExFun extends java.lang.Object
        SourceFile: "ExFun.java"
        minor version: 0
        major version: 50
        Constant pool:
               (snipped for simplicity)
{
public ExFun();
        (snipped for simplicity)
 
public static void main(java.lang.String[]);
        Code:
               Stack=2, Locals=3, Args_size=1
               0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
               3: ldc #3; //String In try block
               5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
               8: new #5; //class java/lang/Exception
               11: dup
               12: invokespecial #6; //Method java/lang/Exception."<init>":()V
               15: athrow
               16: astore_1
               17: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
               20: ldc #8; //String In catch IOException block
                22: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
               25: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
               28: aload_1
               29: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
               32: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
               35: ldc #10; //String In finally block
               37: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
               40: goto 81
               43: astore_1
               44: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
               47: ldc #11; //String In catch Exception block
               49: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
               52: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
               55: aload_1
               56: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
               59: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
               62: ldc #10; //String In finally block
               64: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
               67: goto 81
               70: astore_2
               71: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
               74: ldc #10; //String In finally block
               76: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
               79: aload_2
               80: athrow
               81: return
        Exception table:
               from to target type
               0 16 16 Class java/io/IOException
               0 16 43 Class java/lang/Exception
               0 32 70 any
               43 59 70 any
               70 71 70 any
        LineNumberTable: (snipped)
        StackMapTable: (snipped)
}
 
try ”块内的操作符是在 0~16 的范围内, Java 源代码的“ catch ”块是被编在异常 (Exception) 表的开始两行 (0( 来自 )~16( 目标 )~16( 类型 ) java.io.IOException 0~6~43 java.lang.Exception) catch 的操作符偏移量分别是 16 43 。也需要注意的是,异常表的最后三行表明了方法的其他地方抛出异常的情况 ( 在异常块内部也一样 ) ,必须跳转到操作符 70 处来进行 finally 块的处理。而且需要注意的是,每个 catch 块都会对应一个 finally 块,所以 finally 块在字节码中重复出现了两次。这只是一个简单的例子,让我们看见了 javac 编译产生的字节码输出。
 
JVM 字节码集合有 212 个操作符, 46 个保留字为后续扩展使用。完全的集合可以通过 JVM规范 来了解。

The Java Virtual Machine Specification(2nd Edition) JVM规范(第二版)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值