使用ProGuard合并多個jar檔案

來源:互聯網
上載者:User

ProGuard(http://proguard.sourceforge.net/)對jar檔案可以進行縮減,最佳化和混淆等操作。縮減jar檔案將多個輸入jar檔案(injar參數)合成一個輸出jar檔案(outjar參數)。最佳化執行與編譯器最佳化類似的操作。基本的混淆操作將變數名、方法名等替換為較短的別名。 這裡利用ProGuard的第一個功能(縮減)將多個jar檔案合成一個jar檔案,並剔除這些檔案中用不到的類。

注意:在縮減和混淆操作中,為保證結果的正確,ProGuard能夠自動處理Class.forName("MyClass") 和 MyClass.class這樣的結構,因而不會將類MyClass剔除或混淆; 在某些情況下,如果ProGuard不能作出決定會警告使用者。

例如有一個應用程式myapp.jar, 該應用程式用到Apache commons-lang3-3.0庫,但是只用到個別的類,為了避免在發布時將Apache commons-lang3-3.0庫和myapp.jar一起發布,可以通過ProGuard的縮減功能將這兩個jar檔案合并成一個jar:myapp-dist.jar(註:不清楚這樣做是否違反了Apache的license約定)。

執行build.xml的run target之前的目錄結構:
./src/org/test/proguard/Main.java
./commons-lang3-3.0/commons-lang3-3.0.jar
./lib/proguard.jar
./build.xml
./manifest.mf

執行完build.xml的run任務之後的目錄結構:
./src/org/test/proguard/Main.java
./commons-lang3-3.0/commons-lang3-3.0.jar
./lib/proguard.jar

./build/org/test/proguard/Main.class
./out/myapp.jar
./lib/myapp-dist.jar

./build.xml
./manifest.mf
其中./build/org/test/proguard/Main.class是compile target產生的;./out/myapp.jar是jar target產生的;./lib/myapp-dist.jar是shrink target產生的,這個檔案就是合并之後的jar檔案。



檔案清單:
myapp.jar/Main.java:
package org.test.proguard;import org.apache.commons.lang3.StringUtils; public class Main {public static void main(String[] args) {String text = "ThisIsAVeryLongLongText";String shorttext = StringUtils.abbreviate(text, 15);System.out.println(text);System.out.println(shorttext);}}


build.xml: (注: 沒有使用ProGuard的最佳化和混淆功能:optimize="off" obfuscate ="off")

<?xml version="1.0" encoding="UTF-8"?><project name="proguard" default="run" basedir="./"><property name="package.dir" value="org/test/proguard"/><property name="javahome" value="/usr/local/jdk1.5.0_16" /><property name="jdk.lib.dir" value="${javahome}/lib" /><property name="jre.lib.dir" value="${javahome}/jre/lib" /><property name="proguard.lib" value="./lib" /><property name="commons.lang.lib" value="./commons-lang3-3.0/" /><property name="src.dir" value="./src" /><property name="build.dir" value="./build" /><property name="out.dir" value="./out" /><property name="dist.dir" value="./lib" /><property name="manifest.file" value="manifest.mf"/><property name="outjar.file" value="myapp.jar"/><property name="distjar.file" value="${dist.dir}/myapp-dist.jar"/><path id="lib.path"><fileset dir="${jdk.lib.dir}"><include name="**/*.jar" /></fileset><fileset dir="${jre.lib.dir}"><include name="**/*.jar" /></fileset><fileset dir="${proguard.lib}"><include name="**/*.jar" /></fileset><fileset dir="${commons.lang.lib}"><include name="**/*.jar" /></fileset></path><target name="clean"><tstamp/><delete includeEmptyDirs="true" quiet="yes"><fileset dir="${build.dir}" /><fileset dir="${out.dir}" /></delete></target><target name="compile" depends="clean"> <mkdir dir="${build.dir}" /><javac srcdir="${src.dir}/${package.dir}" destdir="${build.dir}" debug="yes"><classpath refid="lib.path" /></javac></target><target name="jar" depends="compile">     <mkdir dir="${out.dir}" />   <jar jarfile="${out.dir}/${outjar.file}" manifest="${manifest.file}">      <fileset dir="${build.dir}">        <include name="**/*"/>      </fileset>   </jar>   </target><target name="shrink" depends="jar">  <taskdef resource="proguard/ant/task.properties" classpathref="lib.path"/>  <proguard optimize="off" obfuscate ="off" printseeds="on"            printmapping="out.map"            renamesourcefileattribute="SourceFile">    <!-- Specify the input jars, output jars, and library jars. -->    <injar  file="${out.dir}/${outjar.file}" />  <injar  file="${commons.lang.lib}/commons-lang3-3.0.jar" />      <outjar file="${distjar.file}" />    <libraryjar file="${java.home}/lib/rt.jar" />    <!-- libraryjar file="junit.jar"           / -->    <!-- libraryjar file="servlet.jar"         / -->    <!-- libraryjar file="jai_core.jar"        / -->    <!-- ...                                   / -->       <!-- Preserve line numbers in the obfuscated stack traces. -->    <keepattribute name="LineNumberTable" />    <keepattribute name="SourceFile" />    <!-- Preserve all annotations. -->    <keepattribute name="*Annotation*" />    <!-- Preserve all public applications. -->    <keepclasseswithmembers access="public">      <method access    ="public static"              type      ="void"              name      ="main"              parameters="java.lang.String[]" />    </keepclasseswithmembers>    <!-- Preserve all native method names and the names of their classes. -->    <keepclasseswithmembernames>      <method access="native" />    </keepclasseswithmembernames>    <!-- Preserve the methods that are required in all enumeration classes. -->    <keepclassmembers extends="java.lang.Enum">      <method access="public static"              type="**[]"              name="values"              parameters="" />      <method access="public static"              type="**"              name="valueOf"              parameters="java.lang.String" />    </keepclassmembers>    <!-- Explicitly preserve all serialization members. The Serializable         interface is only a marker interface, so it wouldn't save them.         You can comment this out if your library doesn't use serialization.         If your code contains serializable classes that have to be backward         compatible, please refer to the manual. -->    <keepclassmembers implements="java.io.Serializable">      <field  access    ="static final"              type      ="long"              name      ="serialVersionUID" />      <field  access    ="static final"              type      ="java.io.ObjectStreamField[]"              name      ="serialPersistentFields" />      <method access    ="private"              type      ="void"              name      ="writeObject"              parameters="java.io.ObjectOutputStream" />      <method access    ="private"              type      ="void"              name      ="readObject"              parameters="java.io.ObjectInputStream" />      <method type      ="java.lang.Object"              name      ="writeReplace"              parameters="" />      <method type      ="java.lang.Object"              name      ="readResolve"              parameters="" />    </keepclassmembers>    <!-- Your application may contain more items that need to be preserved;         typically classes that are dynamically created using Class.forName -->  </proguard></target><target name="run" depends="shrink">   <!--run: java -jar lib/app-dist.jar -->  <java jar="${distjar.file}" fork="yes">    </java></target></project>


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.