2010-12-14 103 views
2

後,我有一種奇怪的jar文件,它包含了一些類,當我使用JD反編譯,它表現出這樣的一段:的Java:奇怪的結果反編譯

public final void a(ak aa) { 
    this.jdField_a_of_type_Ak = aa; 
} 

public final void a(cn ccn) { 
    this.jdField_a_of_type_Cn = ccn; 
} 

public final cN a() { 
    return this.jdField_a_of_type_CN; 
} 

public final void a() { 
    super.b(); 
} 

public final boolean a() { 
    return this.jdField_a_of_type_Boolean; 
} 

我只是想知道爲什麼/的編譯器/混淆器可以產生這樣的類字節代碼,我的意思是方法簽名。有沒有人知道混淆器可以做到這一點?

+0

您已經顯示了5種方法 - 哪種方法簽名會打擾您? – 2010-12-14 08:25:44

+2

你是否問過重載類型(最後三個)? – 2010-12-14 08:26:23

+0

我的意思是最後三個'return'類型不包含在方法簽名中,所以這些方法都是重複的,對嗎? – secmask 2010-12-14 08:30:50

回答

6

As @Joachim Sauer correctly points out:與JLS在Java程序中相比,JVM規範對字節碼中方法重載的限制較少。

JVM Specification (Section 4.6, Methods)

在一個類文件中沒有兩個方法可以有相同的名稱和描述符(§4.3.3)。

和方法描述符包括返回類型:(4.3.3 Method Descriptors

MethodDescriptor:
        (ParameterDescriptor*) ReturnDescriptor

你在你的問題中提到的所有有不同的描述方法,所以他們沒問題:

public final void a(ak aa)  ->  (Lsomepkg1/ak;)V 
public final void a(cn ccn) ->  (Lsomepkg2/ccn;)V 
public final cN a()   -> ()Lsomepkg3/cN; 
public final void a()   -> ()V 
public final boolean a()  -> ()Z 

這是由混淆器巧妙利用。有效的字節碼程序不再具有「直接對應」的Java程序。例如ProGuard。下面是他們的手工一個片段:

-overloadaggressively

指定,同時混淆申請侵略性超載。只要參數和返回類型不同(不僅僅是它們的參數),多個字段和方法可以獲得相同的名稱,

有利用比如jsr字節碼指令或使用變量標識符是在Java語言中的保留字其他類似的技術。 Here是列出一些技術的網頁。


要回答明顯跟進的問題:如何在JVM知道在調用點調用哪個方法?

調用指令要求您指定對要調用的完整方法簽名(包括方法的返回類型)的引用。

1

...混淆器產生這樣的方法名稱/簽名,因爲這是它的工作。任何混淆器都應該爲此目的工作。

6

Java字節碼支持在Java源代碼中無效的構造。混淆器通過修改字節碼來使用這些構造來利用這一事實(雖然仍然給出與未混淆的字節碼相同的結果)。

+0

你能命名爲java-obfuscator軟件嗎? – secmask 2010-12-14 08:36:16

+0

@secmask,ProGuard會這樣做。看到我的答案。 – aioobe 2010-12-14 08:47:08

1

該類已編譯時沒有調試信息(至少缺少局部變量信息)並在稍後進行混淆。

一個基本的混淆策略是用新的無意義的名稱替換(幾乎)所有的包,類和方法名,以致於無法理解反編譯的代碼。

其他策略是混淆字符串並添加無法反編譯爲java代碼的字節碼結構。

您仍然可以爲混淆的類文件創建等效的Java源代碼,但只需付出極大的努力。