2016-05-24 24 views
1

我正在尝试修改已编译的类(源代码不可用),例如,我想将所有对java.lang.Object的引用更改为some.packageName.SomeClass更改已编译类中的所有类引用

通过引用我的意思是:

  • 字段类型
  • 方法返回类型
  • 方法的参数类型
  • 超类型
  • 变量类型的方法体
  • 静态类引用(例如java.lang.Object.class
  • 基因RIC类型参数
  • 等等

基本上,通过本实施例中,修饰的类should't能够直接访问java.lang.Object类,而只能通过some.packageName.SomeClass。请注意,示例类可以是jre中的任意类,也可以不是。提供的替代品的行为与原预期完全相同。

这可能通过使用BCEL或Javassist?如果没有,是否有任何其他库提供用于实现此目标的功能?

+0

为什么会有人想修改一个编译的类? –

+0

@Vishal Kamat,如果你想不出为什么,那就意味着你不需要。在某些情况下它可能很有用,例如,添加一个额外的方法并在没有源代码的类上实现一个接口。在我的情况只是一个沙箱测试。 –

+0

在这种情况下,AOP是你的朋友。很多东西在做它只是你提到的 –

回答

1

我还没有尝试过,但javassist和ASM肯定可以改变类中的常量池。这是将这些引用存储在类文件中的地方。

+0

只需修改常量池就足够了吗?除了反射之外,还有其他的方式,常量池中没有引用的类在其他类中仍然可见吗? –

+0

所有课程/领域/方法参考经过不断游泳池 – Nikem

+0

我会试一试 –

0

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

例如其中一种方法是这样的:

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

的描述如下所示:LCOM /示例/类;。我将这个字段'重命名为',我将其添加到fixDesc中,这是一个包含旧值到新值的类映射的映射。所以,如果我想使COM /例子/ AAACOM /例子/ 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; 
} 
相关问题