上篇文章提到过在Class结构表中,属性表存在于Class表,字段表和方法表中,是为了 「描述额外的信息」 。
❝属性表在《JAVA虚拟机规范》中并没有像其他数据一样做严格的限制,我们甚至可以自己实现一个编译器往Class结构的属性表中注入额外的属性信息,虚拟机运行时会忽略掉它识别不了的属性。
❞
属性表属性总览
这张图中按Class结构,字段表,方法表这三个维度进行了区分标注,将 「三者共有的属性」 提取到最顶部的 「黄色椭圆」 中, 「蓝色」 代表各自属性表 「额外用到的属性」 , 「红色」 代表 「Code属性中引用的其他属性的集合」 。
引自《深入理解JAVA虚拟机》,读者也可以看这下面的两张图:
属性结构
首先表结构中的前两个字节说明该属性是叫什么名字,也就是什么类型的属性,最终指向常量池中的CONSTANT_Utf8_info类型的常量。
❝eg:Code,ConstantValue,SourceFile。。。等
❞
接着用四个字节描述属性值的长度,也就是说明属性值所占用的字节数;
❝除了第一个属性名称信息和该属性描述的属性长度,其他的就是属性值了,因此该值(属性值长度)固定为 整个属性表长度-6个字节
❞
最后列出属性信息,有多少属性信息呢?前四个字节已经列出了这个属性包含多少个属性,因此最后描述各个属性的信息。
前两个属性是所有属性都共有的,之后就不进行讲解了。
常见属性
Code
❝只有方法内有方法体的方法表才会有这项属性,像抽象方法,非defult接口方法是没有这个属性的(没有方法体)
❞
「该属性用于存放 操作数栈最大深度, 本地变量表最大占用存储空间, 方法中Catch块定义的异常类型和数量, 编译后方法体的字节码指令和指令长度, 还有其他属性」
首先先看下Code属性表的结构:
1.「max_stack操作数栈最大深度」
先看下之前的这篇文章,Java程序运行是基于栈的操作,就是说的该项属性。
通过指令从本地变量表中拿数据放到栈顶;将数据从栈顶保存到本地变量中;对栈顶两个值进行运算后将结果压入栈顶;将栈顶的值作为返回结果return.....等等这些都是通过操作数据结构栈来完成的。
❝这项属性描述了方法中操作数栈的最大深度,虚拟机运行时会根据这项属性来分配栈帧中操作数栈的最大深度。
❞
2.「max_locals局部变量表所需空间」
局部变量表最大占用的存储空间,存储的单位用的是Slot(变量槽),一个 Slot占用空间大小为32位。
存储范围:比如方法的参数,Catch块中定义的异常类型,方法体中定义的局部变量。
❝对于方法参数来说,根据实例方法(通过对象才能访问)和静态方法(通过类名就可以直接访问)又有不同;实例方法的参数中第一个是this,该变量会在编译时加入,而静态方法则没有这个变量。
❞
存储空间:对于小于32位的数据类型用一个变量槽,大于32位的用多个变量槽存储(比如小于64位的数据类型double和long用两个变量槽存储)。优化:对变量限定作用域,如果变量超出了作用域范围,那么存储该变量的Slot进行存储其他的变量,也就是重用变量槽。
❝根据同时生存的最大局部变量数量和类型计算出max_locals的大小。
❞
3.「code_length,code属性用于表述方法体编译后的字节码指令长度和字节码指令流」
❝字节码指令流,一个字节代表一条指令,即每条指令就是一个u1类型的单字节;u1数据类型取值范围是0X00~0XFF,对应十进制为0到255。即u1可以表达256条指令,目前使用的大约只有200条
❞
❝方法体中不允许超过65535条字节码指令,如果超出了编译器拒绝编译;但是code_length用的是u4长度值,可以达到2的32次幂,相当于指令长度只用了一半(u2长度)。
❞
4.「exception_table_length,exception_table用于描述方法块中Catch块定义的异常数量和类型」
❝如果方法体内部没有catch块则length为0,后面的字节不描述exception_table
❞
在这里插入图片描述
❝Exception table:
from to target type
0 5 10 Class java/lang/Exception
0 5 21 any
10 16 21 any
❞
Exceptions
该属性和上面提到的exception_table描述的信息不一样,exception_table是描述方法体中Catch块中定义的异常数量和类型;而该项属性是描述方法throws的异常数量和类型,通俗来说就是调用该方法需要catch的异常,也叫作受查异常。
❝因此上面的excepitons_table描述方法体内部Catch的异常,Exceptions描述方法抛出的异常
❞
结构:
LineNumberTable
❝用于描述Java代码行号和字节码行号的对应关系,该项属性可选择是否输出
❞
❝用处:当执行某段字节码指令抛出异常时可以根据这个对应关系,提示开发者Java代码对应的行号。
❞
结构
-
JAVA
+关注
关注
19文章
2957浏览量
104535 -
Class
+关注
关注
0文章
53浏览量
19708 -
JVM
+关注
关注
0文章
157浏览量
12206
发布评论请先 登录
相关推荐
评论