我试图修改一个已编译的类(源代码不可用),例如,我想some.packageName.SomeClass java.lang.Object所有引用更改为some.packageName.SomeClass

引用指的是:

  • 栏位类型
  • 方法返回类型
  • 方法参数类型
  • 方法主体中的变量类型
  • 静态类引用(例如java.lang.Object.class
  • 通用类型参数
  • 等等。

基本上,通过此示例,修改后的类应该不能直接访问java.lang.Object类,而只能通过some.packageName.SomeClass进行some.packageName.SomeClass 请注意,示例类可以是jre中的任何任意类。 提供的替代品将完全符合预期的性能。

使用BCEL或Javassist是否可以? 如果没有,是否有其他库提供实现此目标的功能?

===============>>#1 票数:1

我没有尝试过,但是javassist和ASM当然可以在类中更改常量池。 这是此类引用存储在类文件中的地方。

===============>>#2 票数:1 已采纳

我使用ASM,这非常简单。 我有一个org.objectweb.asm.commons.Remapper的实现, 它将类的名称和描述符更改为新的。

例如,一种方法如下所示:

@Override
public String mapDesc(String desc) {
    return super.mapDesc(StringUtil.fixDesc(desc, renamed));
}

描述如下: Lcom / example / Class; 我输入到fixDesc中的“重命名”字段是我进行的类映射的映射,其中包含旧值到新值。 因此,如果我想将com / example / AAA设置com / example / BBB,则将之前和之后的值输入到映射中,然后像这样调用重新映射器:

/**
 * Given a map of ClassNodes and mappings, returns a map of class names to
 * class bytes.
 */
public static Map<String, byte[]> process(Map<String, ClassNode> nodes, Map<String, MappedClass> mappings) {
    Map<String, byte[]> out = new HashMap<String, byte[]>();
    RemapperImpl mapper = new RemapperImpl(mappings);
    for (ClassNode cn : nodes.values()) {
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
        ClassVisitor remapper = new ClassRemapper(cw, mapper);
        cn.accept(remapper);
        out.put(mappings.get(cn.name).getNewName(), cw.toByteArray());
    }
    return out;
}

  ask by Juan Garcia translate from so

未解决问题?本站智能推荐: