You need to enable JavaScript to run this app. 调用ClassNode.accept()传入ClassWriter时抛出IllegalArgumentException求助
优惠活动
大模型
产品
解决方案
定价
更多

调用ClassNode.accept()传入ClassWriter时抛出IllegalArgumentException求助

问题原因

你出现该异常的核心原因是LDC指令支持的常量类型有严格限制,你直接将Pattern实例赋值给LdcInsnNode的cst字段,而Pattern不属于Java字节码常量池支持的可存储类型,ASM在生成字节码写入常量池时校验不通过就会抛出该异常。

Java规范中LDC指令仅支持加载以下类型的常量:

  • 基本类型包装类(Integer、Float、Long、Double)
  • String
  • Class
  • MethodType、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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 17:42:03