使用ASM重命名类会在已编译的jar上引发ClassCastException和AbstractMethodError

时间:2019-03-02 13:42:12

标签: java java-bytecode-asm

我正在尝试使用ASM ClassRemapper将所有类从已编译的.jar重命名为新名称,几乎所有工作正常,我的应用程序正常运行,直到因ClassCastException或{{1}而崩溃}

AbstractMethodError

我认为我在方法中遗漏了一些东西,但是找不到。

ClassRemapper adapter = new ClassRemapper(classWriter, new Remapper() { @Override public String mapType(String s) { return super.mapType(getNewName(s)); } @Override public String mapFieldName(String owner, String name, String descriptor) { Type type = Type.getType(descriptor); descriptor = descriptor.replace(type.getClassName(), getNewName(type.getClassName())); return super.mapFieldName(getNewName(owner), name, descriptor); } @Override public String map(String internalName) { return getNewName(internalName); } @Override public String mapDesc(String descriptor) { Type type = Type.getType(descriptor); descriptor = descriptor.replace(type.getClassName(), getNewName(type.getClassName())); return super.mapDesc(descriptor); } @Override public String mapMethodDesc(String methodDescriptor) { Type methodType = Type.getMethodType(methodDescriptor); List<Type> types = new LinkedList<>(); for (Type argumentType : methodType.getArgumentTypes()) types.add(Type.getType(argumentType.getDescriptor().replace(argumentType.getClassName(), getNewName(argumentType.getClassName())))); Type returnType = Type.getReturnType(methodDescriptor); returnType = Type.getReturnType("()" + returnType.getDescriptor().replace(returnType.getClassName(), getNewName(returnType.getClassName()))); return super.mapMethodDesc(Type.getMethodDescriptor(returnType, types.toArray(new Type[0]))); } }); 基本上是getNewName(string)

1 个答案:

答案 0 :(得分:1)

您不必要地覆盖方法mapMethodDescmapTypeClassRemapper,执行转换(尽管不能正确处理数组类型),然后调用{{1 }}已经处理所有情况,例如跳过原始类型并分解数组类型,并为普通引用类型调用map(String internalName)。根据实际的重命名方案,多次应用它可能会导致问题。

同样,当您不想重命名字段时,无需覆盖mapFieldName。无论您是否转换所有者类型,继承的实现都将简单地返回原始名称(它还能做什么)。但是,这种过时的覆盖是无害的。

这简化了整个适配器的工作

ClassRemapper adapter = new ClassRemapper(classWriter, new Remapper()
{
    @Override
    public String map(String internalName)
    {
        return getNewName(internalName);
    }
});