2016-05-24 30 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; 
} 
相關問題