在Java 6版本之后JVM在class文件中引入了栈图(StackMapTable)属性。作用是为了提高JVM在类型检查的验证过程的效率,以下简称StackMapTable为栈图。 栈图结构位于Code属性(指Classfile的Code属性)的属性表( attributes
table)结构中。在字节码的Code属性中最多包含一个StackMapTable属性。在Java 7版本之后把栈图作为字节码文件中的强制部分。 本来程序员是不需要关心JVM中的JIT编译器的细节,也不用知道编译原理或者数据流、控制流的细节。但栈图强制了,如果要生成bytecode,必须准确知道每个字节码指令对应的局部变量和操作数栈的类型。这是因为Java7在编译的时期做了一些验证期间要做的事情,那就是类型检查,也就是栈图包含的内容。
想想都比较抓狂,但是JVM做的这一点点性能优化对整体性能提升也没起到什么卵用。Java的验证在类加载的时候只会运行一次,而占据了大部分时间的操作是IO的消耗,而不是验证过程。即使现在有了栈图,验证过程依然会执行,栈图的存在只是节省了一部分的验证时间。并且JVM的设计者还必须兼容没有栈图的验证的实现,因为Java7以前版本是没有强制栈图这个概念的,然而Java8依然延续了栈图的字节码结构。
jvm8的规范中(https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.4),栈图的标准结构如下:
StackMapTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_entries;
stack_map_frame entries[number_of_entries];
}