属性表中的每个属性都有固定的格式,如下图所示:

Code属性是整个Class文件中最重要的属性,只作用于方法表,在Code属性中存储了Java方法体经过编译后Java的字节码指令,Code属性的结构如下:

操作数栈的最大深度。虚拟机运行的时候需要根据这个值来分配栈帧中的操作栈深度。
局部变量表所需要的空间,单位是Slot,对于int、byte和returnAddress不超过32位的数据类型采用1个Slot来存储,而double和long等64位的数据类型采用两个Slot存储。
方法中的参数(实例方法还有一个隐藏的this),显示异常处理参数(try-catch中的异常)、方法体中的局部变量都需要用局部变量表存储。
code_length存储了字节码指令的长度,虽然长度是4个字节(表面也就是说字节码指令的长度可以达到2^32-1),但实际上Java虚拟机规定了方法体中的字节码指令最多有65535条。
code就存储了具体的字节码指令,具体的字节码指令我们可以不用强记,在使用的时候根据字节码去查表就可以,下图是其中一部分字节码指令:

显示异常(受检查的异常)中的个数(try-catch中的异常)。
这是受检查的异常的具体信息,这个字段不一定存在(如果没有try-catch),下图是显示异常的具体结构:

当代码在start_pc和end_pc之间出现了类型为catch_type(指向常量池中一个CONSTANT_Class_info型常量的索引)的异常时,便转到handler_pc进行处理,如果catch_type为0,代表任何异常都需要转到handler_pc处进行处理。
public class ClassTest {
public int inc() {
int m;
try {
m = 1;
return m;
} catch (Exception e) {
m = 2;
return m;
} finally {
m = 3;
}
}
}
下图是这段方法的Code属性:

通过源码我们知道这段方法体大约有三种执行方式,一种是无任何异常返回1,另一种是有Exception及子类异常返回2,另外是抛出未受检查的异常。
下面我们站在字节码执行的角度上来看一下这段方法是如何执行的,首先我们看一下无异常的情况:
关于字节码的含义大家可以去查表,这里就不一一解释了,无异常执行的字节码为0-7,下面我们来详解一下7个步骤:
通过上述分析,我们可以看出无异常时,返回的值为1
首先我们通过查看受检查异常表发现,如果0-4字节码指令将会转到第8个字节码指令去执行,也就是说代码所执行的字节码指令为0-4,8-16,下面我们来分析一下当出现Exception是8-16的字节码指令:
通过查看受检查异常表可以发现,在我们代码任何阶段发生未受检查的异常时,都会转到17个字节码指令执行,也就是说我们代码会执行17-23个字节码指令: