一个项目的主要目的
Label
LineNumberTable
属性存在,用于在
LocalVariableTable
属性存在,对于较新的类文件,它们的类型注释记录在
RuntimeVisibleTypeAnnotations
try
块,所以它是一个基本块,但对于其他字节码来说,它不需要保留。
看见
-
visitLocalVariable(java.lang.String name, java.lang.String descriptor, java.lang.String signature, Label start, Label end, int index)
-
visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, java.lang.String descriptor, boolean visible)
-
visitTryCatchBlock(Label start, Label end, Label handler, java.lang.String type)
因为局部变量的范围可能跨越最后一个
return
指令,可能在最后一条指令之后遇到标签,这就是您的情况。你在注射毒品
bipush 7, invokestatic #13
之后
返回
指令,导致无法访问的代码。
显然,你也在使用
COMPUTE_FRAMES
允许ASM从头开始重新计算堆栈映射帧的选项,但由于未知的初始堆栈状态,无法为无法访问的代码计算帧。ASM通过将无法访问的代码替换为
nop
指示,然后是单个
athrow
陈述对于这个序列,可以指定一个有效的初始堆栈帧,并且它对执行没有影响(因为代码是不可访问的)。
没有
阿思罗
指令跨越五个字节,与被替换的指令大小相同
bipush 7,invokestatic#13号
顺序有问题。
通过指定
ClassReader.SKIP_DEBUG
到它的
accept
method
. 然后,您的示例只得到一个报告的标签,即与
if
陈述但你必须处理好
visitJumpInsn
以标识条件代码的开头。
因此,要识别所有基本块,必须处理所有分支指令,即通过
visitLookupSwitchInsn
,和
visitTableSwitchInsn
,以及所有结束指令,即。
阿思罗
返回
. 此外,您需要处理所有
visitTryCatchBlock
电话。如果需要在单个过程中识别分支指令的潜在目标,请使用
visitFrame
对于51(Java7)或更高版本的类文件,所有分支目标都必须使用帧,而不是标签。
顺便说一下,当您注入的都是加载常量和调用静态方法(在可到达的位置)的序列时,Id使用
COMPUTE_MAXS
计算\u帧