通过字节码分析this关键字以及异常表的重要作用
在之前的字节码分析中缺少对异常的介绍,这次主要来对字节码异常表相关的东东进行一个学习,下面先来编写一个相关异常的小程序:

接着编译来看用javap -verbose来查看一下它的字节码信息:
xiongweideMacBook-Pro:classes xiongwei$ javap -verbose com/jvm/bytecode/MyTest3.class
Classfile /Users/xiongwei/Documents/workspace/IntelliJSpace/jvm_lectue/out/production/classes/com/jvm/bytecode/MyTest3.class
Last modified Sep 26, 2018; size 1056 bytes
MD5 checksum 67ac394f07ca1303eb0119b94486d428
Compiled from "MyTest3.java"
public class com.jvm.bytecode.MyTest3
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #15.#35 // java/lang/Object."<init>":()V
#2 = Class #36 // java/io/FileInputStream
#3 = String #37 // test.txt
#4 = Methodref #2.#38 // java/io/FileInputStream."<init>":(Ljava/lang/String;)V
#5 = Class #39 // java/net/ServerSocket
#6 = Methodref #5.#40 // java/net/ServerSocket."<init>":(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
#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/jvm/bytecode/MyTest3
#15 = Class #51 // java/lang/Object
#16 = Utf8 <init>
#17 = Utf8 ()V
#18 = Utf8 Code
#19 = Utf8 LineNumberTable
#20 = Utf8 LocalVariableTable
#21 = Utf8 this
#22 = Utf8 Lcom/jvm/bytecode/MyTest3;
#23 = Utf8 test
#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 MyTest3.java
#35 = NameAndType #16:#17 // "<init>":()V
#36 = Utf8 java/io/FileInputStream
#37 = Utf8 test.txt
#38 = NameAndType #16:#53 // "<init>":(Ljava/lang/String;)V
#39 = Utf8 java/net/ServerSocket
#40 = NameAndType #16:#54 // "<init>":(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
#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/jvm/bytecode/MyTest3
#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.jvm.bytecode.MyTest3();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/jvm/bytecode/MyTest3; public void test();
descriptor: ()V
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."<init>":(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."<init>":(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
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
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
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
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
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
LineNumberTable:
line 13: 0
line 14: 10
line 15: 21
line 23: 26
line 24: 34
line 16: 37
line 23: 38
line 24: 46
line 18: 49
line 23: 50
line 24: 58
line 20: 61
line 23: 62
line 24: 70
line 23: 73
line 24: 82
line 25: 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/jvm/bytecode/MyTest3;
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 */
}
SourceFile: "MyTest3.java"
其中重点观注一下test()方法的信息:


其中stack表示这个方法运行的任何时刻所能达到的操作数栈的最大深度;local表示方法执行期间创建的局部变量的数目,包含用来表示传入的参数的局部变量。args_size表示方法的参数的总个数。
下面首先来解释一下为啥args_size等于1,很明显咱们这个方法是一个无参的定义,关于这个在之前的学习中已经解释过了,这里再巩固一下:对于Java类中的每一个实例方法(非static方法),其在编译后所生成的字节码当中,方法参数的数量总是会比源代码中方法的参数的数量多一个(this),它位于方法的第一个参数位置处;这样,我们就可以在Java的实例方法中使用this来去访问当前对象的属性以及其它方法。这个操作是在编译期间完成的,既由javac编译器在编译的时候将对this的访问转化为对一个普通实例方法参数的访问,接下来的运行期间,由JVM在调用实例方法时,自动向实例方法传入该this参数。所以,在实例方法的局部变量表中,至少会有一个指向当前对象的局部变量【也就是会存在于下面要分析的locals中】。
接着来看一下locals,为啥有4个局部变量呢?下面来分析一下:
1、当然就是隐含的this啦,上面分析stack中标明处有说明。
2、当然就是is喽,如下:
3、当然就是serverSocket喽:
4、那它倒底是啥呢?貌似咱们能见到局部变量就木有了,其实这个局部变量是位于catch当中的,如下:
也就是如果抛出了异常,那么最终这三个异常就会产生一个局部变量,如果不抛出异常,那么这个最多4个局部变量中最终只会使用3个局部变量。
最后再来看一下statck=3,也就是这个方法最多能往栈中压入3个元素,关于栈在之后还会详述的,这里有个基本印象。
接着来则到了该篇要讨论的核心话题:异常,对应方法的code属性中exception_table,这里存放的是处理异常的信息。每一个exception_table表项由start_pc、end_pc、handler_pc、catch_type组成,那这四个元素分别代表啥呢?下面来看一下:
- start_pc和end_pc表示在code数组中的从start_pc到end_pc处(包含start_pc,不包含end_pc)的指令抛出的异常会由这个表项来处理。
- handler_pc表示处理异常的代码的开始处。catch_type表示会被处理的异常类型,它指向常量池里的一个异常表。当catch_type为0时,表示处理所有的异常。
其实异常在字节码中是存在有goto语句的,也就是当发生异常则会goto到指定的位置进行异常处理,大至看一下:

具体异常相关的分析下次再继续。
通过字节码分析this关键字以及异常表的重要作用的更多相关文章
- 通过字节码分析this关键字以及异常表的作用
1.创建MyTest3类 public class MyTest3 { public void test(){ try { InputStream is = new FileInputStream(& ...
- 通过字节码分析Java异常处理机制
在上一次[https://www.cnblogs.com/webor2006/p/9691523.html]初步对异常表相关的概念进行了了解,先来回顾一下: 其源代码也贴一下: 下面来看一下jclas ...
- JVM-String比较-字节码分析
一道String字符串比较问题引发的字节码分析 public class a { public static void main(String[] args)throws Exception{ } p ...
- Java并发编程原理与实战八:产生线程安全性问题原因(javap字节码分析)
前面我们说到多线程带来的风险,其中一个很重要的就是安全性,因为其重要性因此,放到本章来进行讲解,那么线程安全性问题产生的原因,我们这节将从底层字节码来进行分析. 一.问题引出 先看一段代码 packa ...
- Python_Tips[2] -> 函数延后估值及字节码分析
函数延后估值及字节码分析 在一个循环中定义了函数 f 但是并未对其进行调用,在循环结束后调用,此时i值为3故最终3个函数输出均为9.而非1, 4, 9. 这是由于在定义闭包函数 f 时,传入变量 i, ...
- Java字节码分析
目录 Java字节码分析 查看字节码详细内容 javap 实例分析 Java字节码分析 对于源码的效率,但从源码来看有时无法分析出准确的结果,因为不同的编译器版本可能会将相同的源码编译成不同的字节码, ...
- 通过字节码分析java中的switch语句
在一次做题中遇到了switch的问题,由于对switch执行顺序的不了解,在这里简单的通过字节码的方式理解一下switch执行顺序(题目如下): public class Ag{ static pub ...
- Java finally语句到底是在return之前还是之后执行(JVM字节码分析及内部体系结构)?
之前看了一篇关于"Java finally语句到底是在return之前还是之后执行?"这样的博客,看到兴致处,突然博客里的一个测试用例让我产生了疑惑. 测试用例如下: public ...
- 字节码分析finally块对return返回值的影响
直接进入主题.看如下代码: public int test(){ int i=0; try { i=1; return i; } catch (Exception e) { i=2; return i ...
随机推荐
- ThinkPHP 5 文件上传及指定宽高生成缩略图公共方法
这个是非常常用的案例,ThinkPHP 5 文件上传及指定宽高生成缩略图公共方法/** * 单文件上传 * name:表单上传文件的名字 * ext: 文件允许的后缀,字符串形式 * path:文件保 ...
- 【数据库开发】MySQL命令大全
1.连接Mysql 格式: mysql -h主机地址 -u用户名 -p用户密码1.连接到本机上的MYSQL. 首先打开DOS窗口,然后进入目录mysql\bin,再键入命令mysql -u root ...
- 1234: 约瑟夫问题-输出最后的编号(Java)
WUSTOJ 1234: 约瑟夫问题-输出最后的编号 参考资料 约瑟夫问题--百度百科 Description n个人围成一圈,依次从1至n编号.从编号为1的人开始1至k报数,凡报数为k的人退出圈子, ...
- 跳转语句 break;continue; return; goto 区别用法
C语言是按顺序执行语句的语言——一个接一个.即使它有条件语句或循环语句,程序的流程也是自上而下的.没有顺序流的随机跳转或跳转.但我们的程序是为了满足任何现实世界的需求,一个接一个地执行永远不会很直接. ...
- spring cloud微服务实践二
在上一篇,我们已经搭建了spring cloud微服务中的注册中心.但只有一个注册中心还远远不够. 接下来我们就来尝试提供服务. 注:这一个系列的开发环境版本为 java1.8, spring boo ...
- Linux虚拟机常用命令
参考原文链接:(https://blog.csdn.net/fanyun_01/article/details/51083585) 一.Linux虚拟机常用命令 # virsh list //查看已打 ...
- 使用Duilib开发Windows软件(1)——HelloWorld
我使用的是网易版本: https://github.com/netease-im/NIM_Duilib_Framework 时间是2019-11-28,作者最新的提交如下图: 运行官方示例程序 下载完 ...
- Kconfig语法简介
背景: 上篇文章<添加自己的驱动程序到Linux内核树中>简单介绍了在Linux内核配置中添加自己的驱动选项.但是仅靠如此简单的配置有时候不能满足我们的要求. Target :hi3531 ...
- Linux 编译kernel有关Kconfig文件详解
ref : https://blog.csdn.net/Ultraman_hs/article/details/52984929 Kconfig的格式 下面截取/drivers/net下的Kconfi ...
- webapi IHttpActionResult无引用和config.MapHttpAttributeRoutes()无引用解决办法
1. 打开NuGet,打开方法 工具->库程序包管理器->程序包管理器控制台,如下图所示: 2. 输入如下命令Install-Package Microsoft.AspNet.WebApi ...