在撰寫Java程式的時候,常常會需要引入別人提供的Jar檔案。這些Jar檔案所包的Package,名稱可能會重複,造成編譯失敗,或是執行時候拋出型態不合的例外。此時除了反編譯Jar檔案,手動改掉Package名稱再重新編譯的方法外,還有一個更好的選擇,那就是使用JarJar直接下指令更改Jar檔案的Package名稱。



通常我們在命名Java的Package時,會把自己的網址倒過來寫,例如本站的網址為「magiclen.org」,所以本站所寫的Java程式,Package名稱就會以「org.magiclen」當開頭來命名。如果大家都照著這個規則開發Java程式的話,應該不會有重複問題才對的呀!我們都知道網址不可能會重複的嘛!事實上,Package名稱之所以會重複,不照規則命名只是其中一項原因。

拿Android開發環境來說,Android SDK本身包含了Apache和JSON的函式庫(Library),也就是說,在正常情況下,我們無法引入自己習慣使用的Apache或是JSON的函式庫版本,而被迫要遷就使用Android所提供的函式庫版本。如果執意將Jar引入到Android專案的話,就會有文章一開始提到的問題。因此,為了解決這個問題,我們必須將引入的Jar檔中的Package名稱給改掉,此時,就得借助JarJar的力量了。

JarJar

JarJar本身就是一支Java程式,可以到官網下載可執行的Jar檔,直接在命令列使用。

以下的JarJar命令,可以查看Jar檔內所含的Package名稱:

java -jar jarjar.jar strings

以Google Gson的Jar檔案為例,可以看到以下的資訊:

從strings的內容可以知道這個Jar檔的Package名稱都是以「com.google.gson」開頭。

要更改Jar檔的Package名稱,可以使用以下命令:

java -jar jarjar.jar process rulesFile inJar outJar

rulesFile為一個文字檔案路徑,inJar為要改名的Jar檔案路徑,outJar為改完後輸出的Jar檔案路徑。

rulesFile有三種指令,分別如下:

rule用來取代Package的名稱。

rule pattern result

zap用來移除符合名稱的Package。

zap pattern

keep只會保留符合的Package名稱,其他的則會刪除。如果和zap一起使用,將會在zap執行完之後才執行。

keep pattern

pattern為要比對的字串,可以使用「*」和「**」來表示任意的Package名稱。「*」可以代表一層的Package,「**」可以代表多層的Package。

result為要取代成的字串,可以使用「@1」、「@2」這類的符號表示要使用第幾個pattern的「*」或「**」所代表的字串。

如果要將Jar檔內的「com.google.gson」名稱全都替換成「org.magiclen」,可以撰寫以下的rulesFile:

rule com.google.** org.magiclen.@1

執行JarJar的process命令後,就可以得到已修正過Package名稱的Jar檔案啦!