介紹
ProGuard是一個Java類文件壓縮器、優化器、混淆器和預校驗器。在壓縮步驟會發現並移除無用的類、字段、方法和屬性。 在優化步驟會分析和優化Method(方法)的字節碼。在混淆步驟會使用短且沒有意義的名字來重命名剩餘的類、字段和方法。 這些前面的步驟會使代碼更小、更高效、更難反向工程。最後的預校驗步驟會給這些類添加Java Micro版本須要的預校驗信息或爲Java 6減小啓動時間的預校驗信息。
這些步驟每個都是可選的。例如,ProGuard也能夠在一個程序中僅僅用來列出無效代碼; 或用於在Java 6中預校驗類文件提升效率。 html
ProGuard 一般讀取input jars(或 wars, ears, zips,或 目錄)。而後壓縮、優化、混淆和預校驗它們。 壓縮步驟以後,能夠執行多個優化過程。ProGuard把這些處理過的結果生成一個或多個output jars (或 wars, ears, zips, 或 目錄)。 輸入可能包含資源文件,他們的名字和內容能夠可選地被更新成反射混淆以後的類的名字。 app
ProGuard 要求input jars中的library jars (or wars, ears, zips, or directories) 被指明。這些在本質上是你編譯代碼要用到的庫。ProGuard用它們來重構類的依賴,並在必要的時候作適當的處理。 這些library jars始終未被改變,你應該一直把它們放在你最終程序的類路徑中。 函數
入口點
爲了決定哪些代碼須要被維持原樣和哪些代碼能夠被移除或混淆,你必須在你的代碼中指定一個或多個
入口點。 這些入口點一般是含有 main 方法的類、applets、midlets等等。
- 在 壓縮步驟, ProGuard 從這些入口點啓動並遞歸決定哪些類和類方法是有用的。而剩餘的全部的其它類和類方法會被廢棄。
- 在 優化步驟, ProGuard 進一步優化代碼。不是入口點的類和方法能夠被設置爲private、static或final,無用的參數可能被移除,而且一些方法可能會被內聯。
- 在 混淆步驟, ProGuard 重命名不是入口點的類和方法的名字。整個過程當中保持這些入口點以確保他們還能經過他們的原始名字被訪問到。
- 預校驗步驟 是惟一不須要知道入口點的步驟
在 使用 章節 描述了必要的-keep選項 而 示例 章節 則提供了大量的示例. 優化
反射
反射和檢討一樣存在全部自動代碼處理所帶來的特殊問題。對ProGuard而言, 在你代碼中被建立或被動態執行的類和類成員也必需要看成入口點指定。例如:Class.forName()構造在運行時可能會引用任何類。 一般難以預測哪些類必須被保留(保留它們的原始名字),例如類名稱可能會從配置文件中讀取。所以你必須在你的ProGuard配置中指定它們,使用簡單的-keep選項。
不過,ProGuard已經爲你指出並處理如下方案: spa
- Class.forName("SomeClass")
- SomeClass.class
- SomeClass.class.getField("someField")
- SomeClass.class.getDeclaredField("someField")
- SomeClass.class.getMethod("someMethod", new Class[] {})
- SomeClass.class.getMethod("someMethod", new Class[] { A.class })
- SomeClass.class.getMethod("someMethod", new Class[] { A.class, B.class })
- SomeClass.class.getDeclaredMethod("someMethod", new Class[] {})
- SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class })
- SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class, B.class })
- AtomicIntegerFieldUpdater.newUpdater(SomeClass.class, "someField")
- AtomicLongFieldUpdater.newUpdater(SomeClass.class, "someField")
- AtomicReferenceFieldUpdater.newUpdater(SomeClass.class, SomeType.class, "someField")
類和類成員名稱固然能夠不一樣,可是構造函數應該每一個字符都相同,爲了ProGuard可以認出它們。在壓縮階段被引用的類和類成員會被 保留,而混淆階段字符串參數會被適當地更新。
此外,若是有必要保持某些類或類成員,ProGuard會提供一些建議。例如:ProGuard會提示相似"(SomeClass)Class.forName(variable).newInstance()"。 這可能表示類或接口SomeClass的實現可能須要被保留。你隨後能夠相應地修改你的配置。 .net
爲了產生合適的結果,你至少應該對你正在處理的代碼有所瞭解。代碼混淆進行了大量的反射,可能會產生失敗和錯誤,尤爲是沒有內部代碼的必要信息。 翻譯
Copyright © 2002-2011
Eric Lafortune 翻譯:
大坤.