【深入浅出-JVM】(70):StackMapTable 属性

栈映射帧(stack map frame) ,用于class 文件类型校验

结构

StackMapTable_attribute {
    u2 attribute_name_index; //恒为 StackMapTable
    u4 attriubte_length;
    u2 number_of_entries;
    stack_map_frame entries[number_of_entries];
}

union stack_map_frame {
    same_frame; 
    same_locals_1_stack_item_frame;
    same_locals_1_statck_item_frame_extended;
    chop_frame;
    same_frame_extended;
    append_frame;
    full_frame;
}
  • frame_type = SAME ;/ 0-63 / 与上一个比较位置的局部变量表相同,且操作数栈为空,这个值也是隐含的 offset_delta
  • frame_type = SAME_LOCALS_1_STACK_ITEM; / 64-127 / 当前帧与上一帧有相同的局部变量,操作数栈中的变量数目为 1,隐式 offset_delta 为 frame_type - 64
  • frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; / 247 /
  • frame_type = CHOP / 248- 250 /
  • frame_type = SAME_FRAME_EXTENDED / 251 / 局部变量信息和上一个帧相同,且操作数栈为空
  • frame_type = APPEND ; / 252-254 / 当前帧比上一帧多了k个局部变量,且操作数栈为空,其中 k = frame_type -251
  • frame_type = FULL_FRAME;/ 255 / 局部变量表和操作数栈做完整记录

例子

stackMapTable 含义

package com.mousycoder.mycode.thinking_in_jvm;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-08-26 10:23
 */
public class StackMapTableTest {

    public static void append(){
        int i = 0;
        int j = 0;
        if (i > 0) {
            i++;
        }
    }
}

从stackmaptable信息中可知,有一条栈映射帧的记录,该记录表示帧类型为 append,偏移量为11,查 LineNumberTable 偏移量为 11 的行号为16,函数结尾,到函数结尾,局部变量表中的数据比前一帧多 253-251=2 个局部变量,且类型都是int,就是例子中i,j.前一帧就是函数调用时的局部变量(调用时 append() 无参数,且为静态函数,局部变量表为空)

栈帧减少

package com.mousycoder.mycode.thinking_in_jvm;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-08-26 11:30
 */
public class StackMapTest1 {
    public static void chop(){
        int i = 0;
        int j = 0;
        if (i > 0) {
            long k = 0;
            if (j == 0) {
                k++;
            }
            int t = 0;
        }
    }
}

第一帧为append,偏移量为 18的位置多了 3 个局部变量,int,int,long. 查看LineNumberTable 源码 17 行以前,有 i,j,k。第2 帧为chop,比上一帧少了 251-250= 1个局部变量 k,代码偏移量得 18+2+1=21,查看LineNumberTable 对应代码19 行,此时局部变量 k,t已过作用域。

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章