jvm signature 属性_【JVM学习笔记】异常表的重要作用以及locals属性的含义

本文详细分析了一段Java代码的字节码,解释了`work`方法中异常表的结构和作用,说明了在遇到多个`catch`块时,JVM如何处理`finally`语句,并对比了不同JDK版本中异常处理的差异。内容涵盖了字节码的`stack`、`locals`、`args_size`等参数含义,以及异常表的条目信息,对于理解Java异常处理机制有帮助。
摘要由CSDN通过智能技术生成

有如下代码

public classTest {public voidwork() {try{

InputStream is= new FileInputStream("test.txt");

ServerSocket serverSocket= new ServerSocket(9999);

serverSocket.accept();

}catch(FileNotFoundException e) {

}catch(IOException e) {

}catch(Exception e) {

}finally{

System.out.println("finally block");

}

}

}

javap -verbose -p Test 结果如下

D:\workspace-learn\common-learn\learn-classloader\target\classes\com\learn\jvm>javap -verbose -p Test

警告: 二进制文件Test包含com.learn.jvm.Test

Classfile /D:/workspace-learn/common-learn/learn-classloader/target/classes/com/learn/jvm/Test.class

Last modified 2019-9-5; size 1075 bytes

MD5 checksum 744e2b9632f4d7f2d38d6b77b4225cc2

Compiled from "Test.java"

public class com.learn.jvm.Test

SourceFile: "Test.java"

minor version: 0

major version: 51

flags: ACC_PUBLIC, ACC_SUPER

Constant pool:

#1 = Methodref #15.#35 // java/lang/Object."":()V

#2 = Class #36 // java/io/FileInputStream

#3 = String #37 // test.txt

#4 = Methodref #2.#38 // java/io/FileInputStream."":(Ljava/lang/String;)V

#5 = Class #39 // java/net/ServerSocket

#6 = Methodref #5.#40 // java/net/ServerSocket."":(I)V

#7 = Methodref #5.#41 // java/net/ServerSocket.accept:()Ljava/net/Socket;

#8 = Fieldref #42.#43 // java/lang/System.out:Ljava/io/PrintStream;

#9 = String #44 // finally block

#10 = Methodref #45.#46 // java/io/PrintStream.println:(Ljava/lang/String;)V

#11 = Class #47 // java/io/FileNotFoundException

#12 = Class #48 // java/io/IOException

#13 = Class #49 // java/lang/Exception

#14 = Class #50 // com/learn/jvm/Test

#15 = Class #51 // java/lang/Object

#16 = Utf8

#17 = Utf8 ()V

#18 = Utf8 Code

#19 = Utf8 LineNumberTable

#20 = Utf8 LocalVariableTable

#21 = Utf8 this

#22 = Utf8 Lcom/learn/jvm/Test;

#23 = Utf8 work

#24 = Utf8 is

#25 = Utf8 Ljava/io/InputStream;

#26 = Utf8 serverSocket

#27 = Utf8 Ljava/net/ServerSocket;

#28 = Utf8 StackMapTable

#29 = Class #47 // java/io/FileNotFoundException

#30 = Class #48 // java/io/IOException

#31 = Class #49 // java/lang/Exception

#32 = Class #52 // java/lang/Throwable

#33 = Utf8 SourceFile

#34 = Utf8 Test.java

#35 = NameAndType #16:#17 // "":()V

#36 = Utf8 java/io/FileInputStream

#37 = Utf8 test.txt

#38 = NameAndType #16:#53 // "":(Ljava/lang/String;)V

#39 = Utf8 java/net/ServerSocket

#40 = NameAndType #16:#54 // "":(I)V

#41 = NameAndType #55:#56 // accept:()Ljava/net/Socket;

#42 = Class #57 // java/lang/System

#43 = NameAndType #58:#59 // out:Ljava/io/PrintStream;

#44 = Utf8 finally block

#45 = Class #60 // java/io/PrintStream

#46 = NameAndType #61:#53 // println:(Ljava/lang/String;)V

#47 = Utf8 java/io/FileNotFoundException

#48 = Utf8 java/io/IOException

#49 = Utf8 java/lang/Exception

#50 = Utf8 com/learn/jvm/Test

#51 = Utf8 java/lang/Object

#52 = Utf8 java/lang/Throwable

#53 = Utf8 (Ljava/lang/String;)V

#54 = Utf8 (I)V

#55 = Utf8 accept

#56 = Utf8 ()Ljava/net/Socket;

#57 = Utf8 java/lang/System

#58 = Utf8 out

#59 = Utf8 Ljava/io/PrintStream;

#60 = Utf8 java/io/PrintStream

#61 = Utf8 println

{

public com.learn.jvm.Test();

flags: ACC_PUBLIC

Code:

stack=1, locals=1, args_size=1

0: aload_0

1: invokespecial #1 // Method java/lang/Object."":()V

4: return

LineNumberTable:

line 14: 0

LocalVariableTable:

Start Length Slot Name Signature

0 5 0 this Lcom/learn/jvm/Test;

public void work();

flags: ACC_PUBLIC

Code:

stack=3, locals=4, args_size=1

0: new #2 // class java/io/FileInputStream

3: dup

4: ldc #3 // String test.txt

6: invokespecial #4 // Method java/io/FileInputStream."":(Ljava/lang/String;)V

9: astore_1

10: new #5 // class java/net/ServerSocket

13: dup

14: sipush 9999

17: invokespecial #6 // Method java/net/ServerSocket."":(I)V

20: astore_2

21: aload_2

22: invokevirtual #7 // Method java/net/ServerSocket.accept:()Ljava/net/Socket;

25: pop

26: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;

29: ldc #9 // String finally block

31: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

34: goto 84

37: astore_1

38: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;

41: ldc #9 // String finally block

43: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

46: goto 84

49: astore_1

50: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;

53: ldc #9 // String finally block

55: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

58: goto 84

61: astore_1

62: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;

65: ldc #9 // String finally block

67: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

70: goto 84

73: astore_3

74: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;

77: ldc #9 // String finally block

79: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

82: aload_3

83: athrow

84: return

Exception table:

from to target type

0 26 37 Class java/io/FileNotFoundException

0 26 49 Class java/io/IOException

0 26 61 Class java/lang/Exception

0 26 73 any

37 38 73 any

49 50 73 any

61 62 73 any

73 74 73 any

LineNumberTable:

line 17: 0

line 18: 10

line 19: 21

line 27: 26

line 28: 34

line 20: 37

line 27: 38

line 28: 46

line 22: 49

line 27: 50

line 28: 58

line 24: 61

line 27: 62

line 28: 70

line 27: 73

line 29: 84

LocalVariableTable:

Start Length Slot Name Signature

10 16 1 is Ljava/io/InputStream;

21 5 2 serverSocket Ljava/net/ServerSocket;

0 85 0 this Lcom/learn/jvm/Test;

StackMapTable: number_of_entries = 5

frame_type = 101 /* same_locals_1_stack_item */

stack = [ class java/io/FileNotFoundException ]

frame_type = 75 /* same_locals_1_stack_item */

stack = [ class java/io/IOException ]

frame_type = 75 /* same_locals_1_stack_item */

stack = [ class java/lang/Exception ]

frame_type = 75 /* same_locals_1_stack_item */

stack = [ class java/lang/Throwable ]

frame_type = 10 /* same */

}

在上图中看到work方法的 stack=3, locals=4, args_size=1,其中size = 1表示参数个数为一个,即this,locals=4表示有4个局部变量,分别为 this,is,serverSocket,和 e,虽然有三个catch块,但是程序运行时只可能进入其中某一个,所以只有一个e

对异常表的解读

异常表的第一行为例,表示在[0,25]行这个范围内如果发生FileNotFoundException,将会跳转到字节码第37行,如下图

astore_1表示把一个引用赋值给局部变量e

Java字节码对于异常的处理方式:

统一采用异常表的方式来对异常进行处理

在jdk1.4.2之前的版本中,并不是使用异常表的方式来对异常进行处理的,而是采用特定的指令方式

当异常处理存在finally块时,现代化的jvm采取的处理方式是将finally语句块的字节码拼接到每一个catch块后面,换句话说,程序中存在多少个catch块,就会在每个catch块后面重复多少个finally语句块的字节码

最后,如果方法后面throws了异常,则字节码里方法会多出一个属性,是这样的:

很简单,知道即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值