2014-06-20 63 views
0

我有一個名爲StaticInitializer.class的類文件,該文件成功地進行了模糊處理。 當我反編譯它時,我得到以下結果,其中IDE給出編譯器錯誤「Cannot return from within an initializer」。刪除「return」聲明可解決問題。 但事實上,我想知道的是,如果在靜態初始化器中有return語句,混淆的類文件如何正常工作。反編譯的混淆代碼「無法從初始化程序中返回」

java文件的編譯和運行階段之間是否存在不匹配,混淆是否會將其作爲混淆的一種方式進行檢測和使用?

反編譯的代碼

public class StaticInitializer { 


    static { 

     int a=12; 
     int b=34; 
     return ; 
    } 

} 

被修改: 繼運行表明,混淆類文件是與JDK 1.5

javap -c StaticInitializer.class 
major version: 49 

J2SE 8 = 52, J2SE 7 = 51編譯, J2SE 6.0 = 50,

J2SE 5.0 = 49,

JDK 1.4 = 48, JDK 1.3 = 47, JDK 1.2 = 46, JDK 1.1 = 45

+2

反編譯器不是神靈。他們可以犯錯誤。 – BackSlash

+0

在以前版本的Java中(直到Java 7),可以通過靜態塊而不是主要方法來運行應用程序。他們刪除了所有可以執行此操作的'伎倆'或'黑客',也許這會對其產生影響。另外:由於BackSlash指出:反編譯器可能會犯錯誤。大多數反編譯器都是Java的幾個版本,而不是最新的最新限制,這就是爲什麼它可能認爲return語句是一個有效的語句。 – Stultuske

+1

@Stultuske你仍然可以這樣做([DEMO](http://ideone.com/REAXnL)),因爲在類被調用之前,靜態塊會被執行,***之前***任何其他方法。即使你不能,一個'static'塊中的return也不是一個有效的語句。 – BackSlash

回答

2

反編譯器是從未100%精確,因爲有很多種方法編程任何代碼行。 ALSO JAD(當我們說Java的反編譯器,它幾乎與JAD同義)不支持JDK 1.5及更高版本。它不再被開發或維護。

同樣看着反編譯的代碼,它給了你錯誤,因爲從Java 7開始,它在加載類之前查找主要方法。這是從以前的Java版本的變化,因此您的靜態塊不執行。在以前的版本中,行爲是JRE用於在加載類後以及在執行靜態塊之後查找main方法。所以它可以在以前的版本中使用,但不能在新版本的java中使用。但是由於JAD不再維護,它可能會顯示過時的有效代碼。

1

但實際上我想知道的是,如果混淆的類文件在靜態初始化器中有返回語句,它是如何正常工作的。

每個方法都必須返回,包括一個靜態初始化器。在字節碼級別,有(且必須是)return操作碼。無論出於何種原因,您使用的反編譯器在將字節碼轉換回Java代碼時並未省略return語句,因此在不允許顯式返回的上下文中最終得到return語句。這可能與您的課程被混淆無關。有趣的是,一些反編譯器(如Procyon)沒有明確地忽略來自初始化塊的return語句。通常不需要,因爲它們試圖刪除所有多餘的語句。由於不允許使用明確的return,因此從Java代碼編譯的靜態初始化程序應該只包含一個return,並且它始終是多餘的,因此總是被刪除。通過在主體中插入新的return操作碼,混淆器可能會鼓勵生成無效的Java代碼。