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

接着编译来看用javap -verbose来查看一下它的字节码信息:

  1. xiongweideMacBook-Pro:classes xiongwei$ javap -verbose com/jvm/bytecode/MyTest3.class
  2. Classfile /Users/xiongwei/Documents/workspace/IntelliJSpace/jvm_lectue/out/production/classes/com/jvm/bytecode/MyTest3.class
  3. Last modified Sep 26, 2018; size 1056 bytes
  4. MD5 checksum 67ac394f07ca1303eb0119b94486d428
  5. Compiled from "MyTest3.java"
  6. public class com.jvm.bytecode.MyTest3
  7. minor version: 0
  8. major version: 52
  9. flags: ACC_PUBLIC, ACC_SUPER
  10. Constant pool:
  11. #1 = Methodref #15.#35 // java/lang/Object."<init>":()V
  12. #2 = Class #36 // java/io/FileInputStream
  13. #3 = String #37 // test.txt
  14. #4 = Methodref #2.#38 // java/io/FileInputStream."<init>":(Ljava/lang/String;)V
  15. #5 = Class #39 // java/net/ServerSocket
  16. #6 = Methodref #5.#40 // java/net/ServerSocket."<init>":(I)V
  17. #7 = Methodref #5.#41 // java/net/ServerSocket.accept:()Ljava/net/Socket;
  18. #8 = Fieldref #42.#43 // java/lang/System.out:Ljava/io/PrintStream;
  19. #9 = String #44 // finally
  20. #10 = Methodref #45.#46 // java/io/PrintStream.println:(Ljava/lang/String;)V
  21. #11 = Class #47 // java/io/FileNotFoundException
  22. #12 = Class #48 // java/io/IOException
  23. #13 = Class #49 // java/lang/Exception
  24. #14 = Class #50 // com/jvm/bytecode/MyTest3
  25. #15 = Class #51 // java/lang/Object
  26. #16 = Utf8 <init>
  27. #17 = Utf8 ()V
  28. #18 = Utf8 Code
  29. #19 = Utf8 LineNumberTable
  30. #20 = Utf8 LocalVariableTable
  31. #21 = Utf8 this
  32. #22 = Utf8 Lcom/jvm/bytecode/MyTest3;
  33. #23 = Utf8 test
  34. #24 = Utf8 is
  35. #25 = Utf8 Ljava/io/InputStream;
  36. #26 = Utf8 serverSocket
  37. #27 = Utf8 Ljava/net/ServerSocket;
  38. #28 = Utf8 StackMapTable
  39. #29 = Class #47 // java/io/FileNotFoundException
  40. #30 = Class #48 // java/io/IOException
  41. #31 = Class #49 // java/lang/Exception
  42. #32 = Class #52 // java/lang/Throwable
  43. #33 = Utf8 SourceFile
  44. #34 = Utf8 MyTest3.java
  45. #35 = NameAndType #16:#17 // "<init>":()V
  46. #36 = Utf8 java/io/FileInputStream
  47. #37 = Utf8 test.txt
  48. #38 = NameAndType #16:#53 // "<init>":(Ljava/lang/String;)V
  49. #39 = Utf8 java/net/ServerSocket
  50. #40 = NameAndType #16:#54 // "<init>":(I)V
  51. #41 = NameAndType #55:#56 // accept:()Ljava/net/Socket;
  52. #42 = Class #57 // java/lang/System
  53. #43 = NameAndType #58:#59 // out:Ljava/io/PrintStream;
  54. #44 = Utf8 finally
  55. #45 = Class #60 // java/io/PrintStream
  56. #46 = NameAndType #61:#53 // println:(Ljava/lang/String;)V
  57. #47 = Utf8 java/io/FileNotFoundException
  58. #48 = Utf8 java/io/IOException
  59. #49 = Utf8 java/lang/Exception
  60. #50 = Utf8 com/jvm/bytecode/MyTest3
  61. #51 = Utf8 java/lang/Object
  62. #52 = Utf8 java/lang/Throwable
  63. #53 = Utf8 (Ljava/lang/String;)V
  64. #54 = Utf8 (I)V
  65. #55 = Utf8 accept
  66. #56 = Utf8 ()Ljava/net/Socket;
  67. #57 = Utf8 java/lang/System
  68. #58 = Utf8 out
  69. #59 = Utf8 Ljava/io/PrintStream;
  70. #60 = Utf8 java/io/PrintStream
  71. #61 = Utf8 println
  72. {
  73. public com.jvm.bytecode.MyTest3();
  74. descriptor: ()V
  75. flags: ACC_PUBLIC
  76. Code:
  77. stack=1, locals=1, args_size=1
  78. 0: aload_0
  79. 1: invokespecial #1 // Method java/lang/Object."<init>":()V
  80. 4: return
  81. LineNumberTable:
  82. line 9: 0
  83. LocalVariableTable:
  84. Start Length Slot Name Signature
  85. 0 5 0 this Lcom/jvm/bytecode/MyTest3;
  86.  
  87. public void test();
  88. descriptor: ()V
  89. flags: ACC_PUBLIC
  90. Code:
  91. stack=3, locals=4, args_size=1
  92. 0: new #2 // class java/io/FileInputStream
  93. 3: dup
  94. 4: ldc #3 // String test.txt
  95. 6: invokespecial #4 // Method java/io/FileInputStream."<init>":(Ljava/lang/String;)V
  96. 9: astore_1
  97. 10: new #5 // class java/net/ServerSocket
  98. 13: dup
  99. 14: sipush 9999
  100. 17: invokespecial #6 // Method java/net/ServerSocket."<init>":(I)V
  101. 20: astore_2
  102. 21: aload_2
  103. 22: invokevirtual #7 // Method java/net/ServerSocket.accept:()Ljava/net/Socket;
  104. 25: pop
  105. 26: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
  106. 29: ldc #9 // String finally
  107. 31: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
  108. 34: goto 84
  109. 37: astore_1
  110. 38: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
  111. 41: ldc #9 // String finally
  112. 43: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
  113. 46: goto 84
  114. 49: astore_1
  115. 50: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
  116. 53: ldc #9 // String finally
  117. 55: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
  118. 58: goto 84
  119. 61: astore_1
  120. 62: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
  121. 65: ldc #9 // String finally
  122. 67: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
  123. 70: goto 84
  124. 73: astore_3
  125. 74: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
  126. 77: ldc #9 // String finally
  127. 79: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
  128. 82: aload_3
  129. 83: athrow
  130. 84: return
  131. Exception table:
  132. from to target type
  133. 0 26 37 Class java/io/FileNotFoundException
  134. 0 26 49 Class java/io/IOException
  135. 0 26 61 Class java/lang/Exception
  136. 0 26 73 any
  137. LineNumberTable:
  138. line 13: 0
  139. line 14: 10
  140. line 15: 21
  141. line 23: 26
  142. line 24: 34
  143. line 16: 37
  144. line 23: 38
  145. line 24: 46
  146. line 18: 49
  147. line 23: 50
  148. line 24: 58
  149. line 20: 61
  150. line 23: 62
  151. line 24: 70
  152. line 23: 73
  153. line 24: 82
  154. line 25: 84
  155. LocalVariableTable:
  156. Start Length Slot Name Signature
  157. 10 16 1 is Ljava/io/InputStream;
  158. 21 5 2 serverSocket Ljava/net/ServerSocket;
  159. 0 85 0 this Lcom/jvm/bytecode/MyTest3;
  160. StackMapTable: number_of_entries = 5
  161. frame_type = 101 /* same_locals_1_stack_item */
  162. stack = [ class java/io/FileNotFoundException ]
  163. frame_type = 75 /* same_locals_1_stack_item */
  164. stack = [ class java/io/IOException ]
  165. frame_type = 75 /* same_locals_1_stack_item */
  166. stack = [ class java/lang/Exception ]
  167. frame_type = 75 /* same_locals_1_stack_item */
  168. stack = [ class java/lang/Throwable ]
  169. frame_type = 10 /* same */
  170. }
  171. 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关键字以及异常表的重要作用的更多相关文章

  1. 通过字节码分析this关键字以及异常表的作用

    1.创建MyTest3类 public class MyTest3 { public void test(){ try { InputStream is = new FileInputStream(& ...

  2. 通过字节码分析Java异常处理机制

    在上一次[https://www.cnblogs.com/webor2006/p/9691523.html]初步对异常表相关的概念进行了了解,先来回顾一下: 其源代码也贴一下: 下面来看一下jclas ...

  3. JVM-String比较-字节码分析

    一道String字符串比较问题引发的字节码分析 public class a { public static void main(String[] args)throws Exception{ } p ...

  4. Java并发编程原理与实战八:产生线程安全性问题原因(javap字节码分析)

    前面我们说到多线程带来的风险,其中一个很重要的就是安全性,因为其重要性因此,放到本章来进行讲解,那么线程安全性问题产生的原因,我们这节将从底层字节码来进行分析. 一.问题引出 先看一段代码 packa ...

  5. Python_Tips[2] -> 函数延后估值及字节码分析

    函数延后估值及字节码分析 在一个循环中定义了函数 f 但是并未对其进行调用,在循环结束后调用,此时i值为3故最终3个函数输出均为9.而非1, 4, 9. 这是由于在定义闭包函数 f 时,传入变量 i, ...

  6. Java字节码分析

    目录 Java字节码分析 查看字节码详细内容 javap 实例分析 Java字节码分析 对于源码的效率,但从源码来看有时无法分析出准确的结果,因为不同的编译器版本可能会将相同的源码编译成不同的字节码, ...

  7. 通过字节码分析java中的switch语句

    在一次做题中遇到了switch的问题,由于对switch执行顺序的不了解,在这里简单的通过字节码的方式理解一下switch执行顺序(题目如下): public class Ag{ static pub ...

  8. Java finally语句到底是在return之前还是之后执行(JVM字节码分析及内部体系结构)?

    之前看了一篇关于"Java finally语句到底是在return之前还是之后执行?"这样的博客,看到兴致处,突然博客里的一个测试用例让我产生了疑惑. 测试用例如下: public ...

  9. 字节码分析finally块对return返回值的影响

    直接进入主题.看如下代码: public int test(){ int i=0; try { i=1; return i; } catch (Exception e) { i=2; return i ...

随机推荐

  1. 20190722java学习习惯小结

    1.周一——周六: 学习: 周日: 巩固练习测试. 2.java 大数据. python 人工智能 .. 3.写技术博客! 4.python应用: 人工智能.web开发.自动化运维.数据分析.爬虫.游 ...

  2. 【数据库开发】在Windows上和Linux上配置MySQL的过程

    [数据库开发]在Windows上和Linux上配置MySQL的过程 标签(空格分隔): [编程开发] 首先是在Windows上尝试用QT进行MySQL数据库开发,结果总出现driver不能load的错 ...

  3. Andrew Ng机器学习课程13

    Andrew Ng机器学习课程13 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 引言:主要从一般的角度介绍EM算法及其思想,并推导了EM算法的收敛性.最后 ...

  4. easyui中combobox下拉内容进行分组

    需求:对combobox下拉内容进行分组. 效果样式: 代码: valueField:'paymethod_name', textField:'paymethod_name', data:[{ &qu ...

  5. SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题

    原文链接:https://segmentfault.com/a/1190000012879279 当前后端分离时,权限问题的处理也和我们传统的处理方式有一点差异.笔者前几天刚好在负责一个项目的权限管理 ...

  6. Calibre 和 Kindle 配合的使用方法

    1. 前言 使用"Calibre"软件,把网上下载的电子书转换成适合kindle阅读的格式. 2. 使用经验总结 2.1 首行缩进.段落间距设置 2.2 输出为mobi格式设置 2 ...

  7. docker&k8s-配置/常用命令

      kubectl delete deployment,ingress,svc demo-mml-jp-ylmopt-web-1 -n demo-mml  #删除预生产环境mml组ylmopt-web ...

  8. MySQL部分2

  9. Luogu5327 ZJOI2019语言(树上差分+线段树合并)

    暴力树剖做法显然,即使做到两个log也不那么优美. 考虑避免树剖做到一个log.那么容易想到树上差分,也即要对每个点统计所有经过他的路径产生的总贡献(显然就是所有这些路径端点所构成的斯坦纳树大小),并 ...

  10. codefroce 854 A.Fraction

    题解:贪心,每次从能够出发的飞机中取一个最大的就好啦,用一个队列维护一下~ ac代码: #include <cstdio> #include <iostream> #inclu ...