使用 ASM 插入 FrameNode

insert FrameNode with ASM

如何在字节码中插入该帧节点?

FRAME FULL [java/lang/String [C java/lang/String T I I [C] []

我的第一次尝试是:

mn.instructions.insertBefore(random, new FrameNode(Opcodes.F_FULL, 1 /**IDK**/,
    new Object[]{ "java/lang/String", "[C", "java/lang/String", "T", "I", "I", "[C]" },
    1/**IDK**/, new Object[] { "[C]","[]" }));

效果不佳。输出:

    FRAME FULL [[java/lang/String] [java/lang/String]

一个栈帧由一些局部变量和操作数栈上的一些值组成。您要重现的内容显然是将该状态转换为形式为

的人类可读字符串的结果

FRAME FULL [<em>局部变量类型列表</em>] [<em>操作数堆栈时间类型列表</em>]

您要做的第一件事是从输出格式中识别括号,这需要了解包含的类型签名,因为以左括号开头的签名如 [C 表示数组类型,即字符数组。换句话说,一些左括号是类型签名的一部分,其他是输出格式的一部分,而右括号始终是输出格式的一部分,从不出现在类型签名中。

然后,当您确定了两组中的类型签名后,提供局部变量和操作数堆栈项的适当计数。在你的情况下你有:

FRAME FULL // frame type
[          // start local variables
  java/lang/String
  [C
  java/lang/String
  T
  I
  I
  [C
] // seven local variables specified
[ // start of operand stack
] // empty operand stack

但是你必须开始考虑类型项的含义,不幸的是,这不能从打印输出中推导出来,仅仅复制相同的打印输出并不一定意味着正确代码。

也就是说,项目 TI 可以分别引用具有完整限定名称 TI 的 classes,其中将 "T""I" 传递给 FrameNode 的情况是正确的。然而,它们更可能指的是非class堆栈帧类型‹top›int,必须使用预定义的Integer ASM 中的常量:

new FrameNode(Opcodes.F_FULL, 7, new Object[] {
    "java/lang/String", "[C", "java/lang/String",
    Opcodes.TOP, Opcodes.INTEGER, Opcodes.INTEGER, "[C" }, 0, new Object[0]);