调用ClassNode.accept()传入ClassWriter时抛出IllegalArgumentException求助
问题原因
你出现该异常的核心原因是LDC指令支持的常量类型有严格限制,你直接将Pattern实例赋值给LdcInsnNode的cst字段,而Pattern不属于Java字节码常量池支持的可存储类型,ASM在生成字节码写入常量池时校验不通过就会抛出该异常。
Java规范中LDC指令仅支持加载以下类型的常量:
- 基本类型包装类(
Integer、Float、Long、Double) StringClassMethodType、MethodHandle(Java 7及以上版本支持)DynamicConstant(Java 11及以上版本支持)
你之前的修改操作在操作ClassNode阶段不会触发校验,只有调用classNode.accept(classWriter)生成最终字节码时,ASM才会校验常量类型合法性,所以异常才会在你标注的行抛出,和ClassWriter与ClassVisitor的继承关系无关。
解决方案
你需要将原来的单条LDC指令,替换为调用Pattern.compile("")的指令序列,示例修改代码如下:
for (MethodNode methodNode : classNode.methods){ for (AbstractInsnNode abstractInsnNode : methodNode.instructions.toArray()){ if (abstractInsnNode.getOpcode() == Opcodes.LDC){ LdcInsnNode ldc = (LdcInsnNode) abstractInsnNode; if (ldc.cst.toString().equals("[a-zA-Z0-9_]+")){ // 移除原有加载字符串的LDC指令 methodNode.instructions.remove(ldc); // 构造新的指令序列 InsnList newInsns = new InsnList(); // 加载空字符串常量 newInsns.add(new LdcInsnNode("")); // 调用Pattern.compile静态方法生成Pattern实例 newInsns.add(new MethodInsnNode( Opcodes.INVOKESTATIC, "java/util/regex/Pattern", "compile", "(Ljava/lang/String;)Ljava/util/regex/Pattern;", false )); // 将新指令插入到原LDC指令的位置 methodNode.instructions.insertBefore(abstractInsnNode, newInsns); } } } }
注意事项
替换后栈顶的元素类型从String变为Pattern,你需要确认原代码后续对该值的使用逻辑和类型匹配,否则会出现字节码校验错误。
内容的提问来源于stack exchange,提问作者Lux
相关产品推荐
相关产品推荐

