当前位置: 首页 > 知识库问答 >
问题:

使用ASM修改Java字节码引发ClassFormatError:LocalVariableTable中的长度XXX无效

步联
2023-03-14

我正在使用ASM(tree和util),并且遇到了一个奇怪的异常

Exception in thread "main" java.lang.ClassFormatError: Invalid length 65526 in LocalVariableTable in class file 

我正在尝试编辑一个。class文件的字节码,以生成一个新的字节码。我有一个for循环,里面有一些if分支,我试图修改它。我在下面发布了两个for循环的代码,最初的一个和想要生成的。

初始

int[] ar = new int[]{1,2,3,4,5};
int[] ar2 = new int[]{8,9,9,94,3,2};
MyClass myar = new MyClass(ar);
MyClass myar2 = new MyClass(ar2);
int sum=0;
for(int i=0; i<ar.length; i++)
  if(ar[i]>3) {
    if(ar2[i]>8) {
      sum+=(ar[i]+ar2[i]);
    }
  }
}
int[] ar = new int[]{1,2,3,4,5};
int[] ar2 = new int[]{8,9,9,94,3,2};
MyClass myar = new MyClass(ar);
MyClass myar2 = new MyClass(ar2);
int sum=0;
for(int i=0; i<ar.length; i++)
  int[] temp = callAFunctionToDoSthing(myar, myar2);
  if(temp[0]>3) {
    if(temp[1]>8) {
      sum+=(temp[0]+temp[1]);
    }else i+=1;
  }else i+=2;
}

编辑:

IntInsnNode bp7 = (IntInsnNode) aload17.getNext();
instructions.remove(bp7.getNext());
instructions.remove(bp7.getNext());
instructions.remove(bp7.getNext());
instructions.remove(bp7.getNext());
instructions.remove(bp7.getNext());
InsnList l4 = new InsnList();
LabelNode l45Ins = new LabelNode();
l4.add(new JumpInsnNode(Opcodes.IF_ICMPGT, l45Ins));
LabelNode l46Ins = new LabelNode();
l4.add(l46Ins);
l4.add(new LineNumberNode(178, l46Ins));
l4.add(new VarInsnNode(Opcodes.ALOAD, 20));
l4.add(new InsnNode(Opcodes.ICONST_0));
instructions.insert(bp7, l4);

共有1个答案

虞祯
2023-03-14

我终于想出了如何解决上面的问题。问题出在LabelNodes上。正如您在问题的编辑部分所看到的,我删除了LabelNode39,并插入了一个新的LabelNode。我也是在main的Return语句之后的最后一个LabelNode中完成的。不过,ASM无法检测到我插入的新LabelNode并用它替换旧的LabelNode。更具体地说,我在LocalVariableTable中的全局作用域变量在程序的最后一个标签上完成。虽然,当我删除LabelNode时,他们得到了一个非常大的数字,导致程序崩溃。为了解决这个问题,我简单地使用了初始版本中相同的LabelNodes,并且只有在没有其他选择的情况下才在我想要的程序中插入new。当然,我仍然编辑了LinenumberNode来镜像我想要的行。对于上面的示例,解决该问题的代码如下

IntInsnNode bp7 = (IntInsnNode) aload17.getNext();
instructions.remove(bp7.getNext());

LabelNode l39 = (LabelNode) bp7.getNext();
LineNumberNode lnl39 = (LineNumberNode) l39.getNext();
lnl39.line = 178;
instructions.remove(lnl39.getNext());
instructions.remove(lnl39.getNext());

InsnList l4 = new InsnList();
LabelNode l45Ins = new LabelNode();
l4.add(new JumpInsnNode(Opcodes.IF_ICMPGT, l45Ins));
instructions.insert(bp7, l4);

InsnList l5 = new InsnList();
l5.add(new VarInsnNode(Opcodes.ALOAD, 20));
l5.add(new InsnNode(Opcodes.ICONST_0));
instructions.insert(lnl39, l5);
 类似资料:
  • 我想在Java中测试一些方法/类。为此,我编写了一个Java代理,它只检测我选择的几个类。 我使用以下代码来获取加载的类并筛选其中的一些类: null

  • 本文向大家介绍postgresql 修改字段长度的操作,包括了postgresql 修改字段长度的操作的使用技巧和注意事项,需要的朋友参考一下 使用数据库postgresql的时候,有时会遇到字段长度扩展的情况,由于之前已经有数据了,所以只能修改字段长度,不能通过删除再增加的方式。 可以使用如下方式进行 通过上面的一句话就可以把你的表中相应的字段的长度修改为3000. 补充:PostgreSQL字

  • 本文向大家介绍java字节码框架ASM的深入学习,包括了java字节码框架ASM的深入学习的使用技巧和注意事项,需要的朋友参考一下 一、什么是ASM ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class文件里,这些

  • 正如文件所说: 公共接口操作码 定义JVM操作码、访问标志和数组类型代码。此接口没有定义所有JVM操作码,因为某些操作码会自动处理。例如,xLOAD和xSTORE操作码会在可能的情况下自动替换为xLOAD_n和xSTORE_n操作码。因此,xLOAD_n和xSTORE_n操作码不会在此接口中定义。LDC也是如此,必要时自动替换为LDC_W或LDC2_W、WIDE、GOTO_W和JSR_W。 问题:

  • 我的问题是,当我上传一个文件超过我在脚本中设置的限制(5 MB)时,它会在网站顶部显示此警告: 警告:第0行未知中32485176字节的POST内容长度超过了20971520字节的限制 例如,在这里,我上传了一个文件超过(30 MB),但当我上传一个文件超过(5 MB),小于30(或没有那么大)它不显示警告,只显示我想要的代码错误: 我正在localhost,这个错误每次都出现,我知道如何通过修改

  • 在Swift2.2中,我们如何找出字符串的长度(字节)? 我知道一个出路是使用