Java字节码方法表与属性表详解
继续跟着上一次【https://www.cnblogs.com/webor2006/p/9502507.html】的那10个代表code的字节分析,如下:


而这些字节其实对应的信息是它:

所以问题就来了,aload_0不是助记符信息么,怎么就能够跟字节码文件中的字节对应上呢?所谓助记符其实也就是帮忙我们去记忆的符合,在底层其实也是对应的一个个十六进制的数字的,其它aload_0对应的就是2A这个十六进制数字,凭什么这么说?因为有jclasslib这么好的工具能帮我们对应上,将鼠标放在助记符上发现是一个可以点的链接,如下:

点一下“aload_0”发现居然链到了oracle的官网上的说明上去了,如下:



所以第一个字节已经分析完了,确实是跟助记符对应上了,接着来分析第二个字节:

而在jsclasslib中对应的第二个助记符是“invokespecial”,点击链到官网看一下:

而它的作用可以理解成就是调用父类的方法,很明显对于咱们自定义的子类肯定会去调用父类的构造方法,而这个助记符是有参数的:

其实也就是往后的两个字节就是该助记符所对应的参数,如下:

对应常量池为:

也就是构造方法嘛,如jsclasslib所示:

接下来继续往下走一个字节:

又对应aload_0,如下:

接着再往后看一个字节:

其实它就是对应下一个助记符,如下:

为啥如此任性呢,因为点击查看一下说明就晓了啦:

为啥要push一个1呢?实际就是给咱们定义的成员变量a赋值,如下:

可见,该变量的赋值是在默认构造函数中进行的,而不是直接进行赋值的,这也就是分析字节码文件的好处,可以更加真实的发现底层细节。
接下来再数一个字节:

当然它又对应另一个助记符喽,如下:

点击看一下官网说明:

接下来该助记符是携带有参数的,所以再往后数两个字节:

对应常量池:

也就是给MyTest1的成员变量a赋值为1。
接下来再数一个字节:

对应于如下助记符:

点击确认一下:

至此整个构造方法就已经执行完了。发现通过分析字节码也能获得不少新知识嘛,仅通过这个构造函数的执行流程就能知道了对于我们定义的成员变量原来是在构造方法中进行赋值而非直接赋值的,还是挺有价值的。
好,方法的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时,表示处理所有的异常。
接下来就到属性相关的东东了,如下:

所以往下数2个字节:

说明该方法有两个属性,往下数两个字节则是第一个属性的名字索引,如下:

也就是对应第10的常量池,为:

该属性用来表示code数组中的字节码和Java代码行数之间的关系。这个属性可以用来在调试的时候定位代码执行的行数。而该属性的结构为:

其中attribute_name_index就是常量索引10,接下来数4个字节则是属性的长度attribute_length,如下:

也就是属性的长度为10,也就是接下来10个字节则为LineNumberTable的属性信息,如下:

看一下jclasslib:

下面具体来分析一下这10个字节,根据结构体来看:

先2个字节表示属性表有几对映射,如下:

说明有两对映射,然后再回到结构体中,每对映射的内容为:

每对占4个字节,先看第一对映射:

也就是start_pc=0;line_number=3,对应于jclasslib:

由于咱们源代码木有构造方法,所以字节码对应源代码就在第3行,如下:

接下来看第二对映射:

也就是start_pc=4;line_number=4,对应于jclasslib:

因为成员变量的赋值是在构造方法中完成的,所以对应第4行代码:

好,方法的第一个属性已经完了,接下来以同样的顺序来查看方法的第二个属性信息了,走2个字节来看属性名称索引,如下:

对应第11个常量池索引,如下:

它的结构跟LineNumberTable差不多的,往后数四个字节则是局部变量表所占的长度:


长度为12,如jclasslib所示:

然后往后数12个字节则是局部变量的具体信息,首先两个字节则为局部变量的个数,如下:

呃~~构造方法哪来的局部变量呢,好奇怪,先不管先来把其它字节分析完,再往后四个字节表示start_pc和length,如下:

如jclasslib所示:

接下来则为局部变量的索引为0,也就是第一个局部变量:

再往后两个字节则是局部变量对应常量池的索引,如下:


再接下来两个字节则是对该局部变量的一个描述常量索引,如下:


所以对应jclasslib中可以看到:

那思考一下为啥在构造方法中会有一个this的局部变量呢?我们知道在所有方法中我们都能使用this关键字来访问当前的对象,而从字节层面来讲其实this是作为方法的第一个参数传进来的,也就是说对于Java的一个实例方法而言最少会有一个this的局部变量存在!
还剩最后两个字节则为stackmaptable信息,JDK1.6加入的,主要做校验检查的,因为0嘛所以后面肯定木有相关的信息了,这里就直接忽略,如下:

Java字节码方法表与属性表详解的更多相关文章
- Java字节码(.class文件)格式详解(一)
原文链接:http://www.blogjava.net/DLevin/archive/2011/09/05/358033.html 小介:去年在读<深入解析JVM>的时候写的,记得当时还 ...
- Java线程通讯方法之wait()、nofity() 详解
Java线程通讯方法之wait().nofity() 详解 本文将探讨以下问题: synchronized 代码块使用 notify()与notifyAll()的区别 Java wait(),noti ...
- JVM Java字节码方法表与属性
方法表 1.methods_count method_info,前三个字段和field_info一样 2.方法的属性结构 方法中的每个属性都是一个attribut_info结构 JVM定义了部分at ...
- Java字节码方法表与属性表深度剖析
方法表: 在上一次咱们已经分析到了字段信息了,如下: 紧接着就是方法相关的信息了: 而它展开之后的结构为: 所以往后数2个字节,看一下方法的总数: 3个方法,可咱们只定义了两个方法呀: 因为编译器会为 ...
- Java字节码方法表结构深度剖析
继续上一次[https://www.cnblogs.com/webor2006/p/9459681.html]的字节码分析,这次来分析一下最为复杂的方法表的信息,如下: 而上一次分析到了属性表的位置在 ...
- Java线程阻塞方法sleep()和wait()精炼详解
版权声明:因为个人水平有限,文章中可能会出现错误,如果你觉得有描述不当.代码错误等内容或者有更好的实现方式,欢迎在评论区告诉我,即刻回复!最后,欢迎关注博主!谢谢 https://blog.csdn. ...
- Java字节码操纵框架ASM小试
本文主要内容: ASM是什么 JVM指令 Java字节码文件 ASM编程模型 ASM示例 参考资料汇总 JVM详细指令 ASM是什么 ASM是一个Java字节码操纵框架,它能被用来动态生成类或者增强既 ...
- 从 HelloWorld 看 Java 字节码文件结构
很多时候,我们都是从代码层面去学习如何编程,却很少去看看一个个 Java 代码背后到底是什么.今天就让我们从一个最简单的 Hello World 开始看一看 Java 的类文件结构. 在开始之前,我们 ...
- 空手套白狼,硬阅java字节码class文件
如下,是一些java字节码也就是原始的class文件,当应用部署到线上之后,我们能够看到的也就是这样的字样了.那么怎样解呢?就让我们一起,来解读解读字节码吧! Offset A B C D E F C ...
随机推荐
- charles 开始/暂停记录
本文参考:charles 开始/暂停记录 1.1. stop/start recording 和 2.1 recording settings 是常用的功能了:这里需要注意就是后面的session1代 ...
- vue路由传参的三种方式
方式一 通过query方式传参 这种情况下 query传递的参数会显示在url后面 this.$router.push({ path: '/detail', query: { id: id } }) ...
- 【计算机视觉】Selective Search for Object Recognition论文阅读3
Selective Search for Object Recoginition surgewong@gmail.com http://blog.csdn.net/surgewong 在前 ...
- thinkphp5 验证器 validate 和 layer
首先tp5的验证器使用特方便 设置规则即可通用 首先页面html(layer 配合) 毕竟是后端 尽量用一些成熟的前台框架 之前用boostrap $.ajax({ url:'/index/Regi ...
- C#使用Castle实现AOP面向切面编程
Castle.Core 本质是创建继承原来类的代理类,重写虚方法实现AOP功能.个人觉得比Autofac用着爽 使用方式比较简单,先新建一个控制台项目,然后在Nuget上搜索Castle.Core并安 ...
- opencv根据摄像头名称获取索引值
OpenCV的VideoCapture是一个视频读取与解码的API接口,支持各种视频格式.网络视频流.摄像头读取. 针对一般摄像头的读取,opencv为了实现跨平台读取摄像头时是使用的摄像头索引, V ...
- 1、1通过maven建立spring boot项目(不用联网)
1.把以前spring boot项目的pom.xml导入进来 2.修改pom.xml 里面项目名改成自己项目名 3.复制配置文件 spring: datasource: url: jdbc:mysq ...
- Selenium绕过登录的实现
1.使用命令行启动Chrome:Mac:/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome -remote-debugging ...
- Python笔记002-Python编程基础概念
第二章(1):Python编程基础概念 1. Python 程序的构成 Python 程序有模块组成.一个模块对应 Python 源文件,一般后缀名是:.py. 模块有语句组成.运行 Python程序 ...
- Python3 和 Python2的区别
目录 print Python2.7的print不是一个function Python3里的print是一个function. Unicode Python 2 有 ASCII str() 类型,un ...