ProGuard使用简介

**### ProGuard使用简介 **

背景简介:

ProGuard是一个压缩、优化和混淆Java字节码文件的免费的工具,它可以删除无用的类、字段、方法和属性。可以删除没用的注释,最大限度地优化字节码文件。它还可以使用简短的无意义的名称来重命名已经存在的类、字段、方法和属性,增加项目被反编译的难度。

下载地址:http://proguard.sourceforge.net/

用法简介

命令: java -jar proguard.jar options ...

常用选项说明:

Input/Output 选项

-include filename 简写:@filename 递归读取指定的文件名的配置选项,文件名支持 示例:-include lib/an粗体notations.pro; 该名称可以包含Java系统属性(或Ant属性,使用Ant时),由尖括号,“<”和“>”分隔。 例如,<java.home> /lib/rt.jar会自动扩展为类似/usr/local/java/jdk/jre/lib/rt.jar。 同样,<user.home>扩展到用户的主目录,而<user.dir>被扩展为当前工作目录

-injars class_path 指定即将被混淆的jar文件(或者aars, wars, ears, zips, apks, 或者文件目录)的路径 示例: -in.jar(!images/**) #匹配jar包中所有非images目录下的文件 -injars project(.class) #匹配project目录下的所有class文件

-outjars class_path 指定混淆后输出的jar文件(或者aars, wars, ears, zips, apks, 或者文件目录)的路径 指定输出路径时,必须避免覆盖输入文件。

-libraryjars class_path 指定injar依赖的库文件,可以是jar文件(或者aars, wars, ears, zips, apks, 或者文件目录),这些文件不会包含到outjars中。

-skipnonpubliclibraryclasses 配置此选项将在读取library jar时跳过non-public classes ,会让proguard在执行过程中效率更快,如果跳过的非公共类对injars文件有影响,proguard会打出警告。

**-dontskipnonpubliclibraryclasses **
指定不去忽略非公共的库类。

**-dontskipnonpubliclibraryclassmembers **
指定不去忽略非公共的库类的成员。

-keepdirectories [directory_filter] 保留输出jar文件(或者aars, wars, ears, zips, apks, 或者文件目录)的目录信息,默认情况下,proguard为了减小文件大小,目录信息会被删除。单数如果class需要以类似“mypackage.MyClass.class.getResource("")”的方法查找,则必须保留相应包下的目录信息。例如:-keepdirectories mydirectory/**表示保留mydirectory目录及其子目录下的所有类的目录信息。

Keep 选项

-keep [,modifier,...] class_specification 指定不不混淆的类,成员或方法

-keepclassmembers _{modifier} {class_specification} _ 保护指定类的成员,如果此类受到保护他们会保护的更好

-keepclasseswithmembers _{class_specification} _
保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。

-keepnames _{class_specification} _
保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除) -keepclassmembernames _{class_specification} _
保护指定的类的成员的名称(如果他们不会压缩步骤中删除) -keepclasseswithmembernames _{class_specification} _
保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后) -printseeds _{filename} _
列出类和类的成员-keep选项的清单,标准输出到给定的文件

Shrinking 选项

**-dontshrink **
不压缩输入的类文件,不配置的话默认压缩,除了在keep选项中设置的类和成员外,所有的类和类成员都将被移除。

-printusage _{filename} _ 在压缩有效的情况下,将输入类文件中的僵尸代码列表打印到标准输出文件中。

-whyareyoukeeping _{class_specification} _
配置该选项后会在压缩步时,打印出配置类或成员被保留的原因的细节

Optimization 选项

**-dontoptimize **
不优化输入的类文件,默认开启优化

-optimizationpasses n 制定优化执行的次数,默认一次,多次优化执行时,发现没有可改进的,则优化结束。

-assumenosideeffects {class_specification}
指定不被调用的的方法,优化时会删除该方法。例如:指定System.currentTimeMillis()方法,不被调用的情况下可以删除。

**-allowaccessmodification **
优化时允许访问并修改有修饰符的类和类的成员

Obfuscation 选项

**-dontobfuscate ** 不混淆输入的类文件

**-printmapping **_{filename} _ 将混淆前和混淆后的类和类成员打印到制定文件中

**-applymapping **_{filename} _
重用映射文件,一般用于增量混淆,例如: -injars proguardgui.jar -outjars proguardgui_out.jar -libraryjars proguard.jar -libraryjars <java.home>/lib/rt.jar -applymapping proguard.map

-keep public class proguard.gui.ProGuardGUI { public static void main(java.lang.String[]); }

-obfuscationdictionary _{filename} _
使用给定文件中的关键字作为要混淆方法的名称

**-overloadaggressively ** 混淆时应用侵入式重载

**-useuniqueclassmembernames **
确定统一的混淆类的成员名称来增加混淆

-flattenpackagehierarchy_ {package_name}_
重新包装所有重命名的包并放在给定的单一包中

-repackageclass _{package_name} _ 重新包装所有重命名的类文件中放在给定的单一包中

-dontusemixedcaseclassnames
混淆时不会产生形形色色的类名

**-keepattributes {attribute_name,...} ** 保护给定的可选属性,例如 -keepattributes Exceptions,InnerClasses,Signature,Deprecated, SourceFile,LineNumberTable,Annotation,EnclosingMethod

LineNumberTable:保留方法的行号 LocalVariableTable:保留局部变量的名称和类型 SourceFile:保留被编译源文件的名称,在堆栈追踪时会显示 Deprecated:表明方法,成员或类已经过期 Signature: 保留类,字段或方法的签名,编译器可能需要这些信息来正确编译使用泛型的编译库类。代码可以通过反射来访问此签名 Annotation:保留被注解过的类或成员 InnerClasses:保留内部类信息 Exceptions:保留类捕获的异常

-renamesourcefileattribute [string] 指定一个字符串常量被放入的SourceFile属性的类文件(和SourceDir属性)。请注意,属性必须存在,该属性必须显式的使用-keepattributes指令被保留。例如,你想保留异常,源文件行数信息时,设置-renamesourcefileattribute SourceFile。只有当混淆时适用。

-keepparameternames 保留参数的名称和方法,该选项可以保留调试级别的属性。

支持Ant编译

版本要求 Jdk1.8+; ant 1.8+ 官方说明: ProGuard can be run as a task in the Java-based build tool Ant (version 1.8 or higher)

配置文件示例

build.xml
<!-- This Ant build file illustrates how to process applications,
     by including a ProGuard-style configuration file.
     Usage: ant -f applications1.xml -->

<project name="Applications" default="obfuscate" basedir="../..">

<target name="obfuscate">
  <taskdef resource="proguard/ant/task.properties"
           classpath="lib/proguard.jar" />

  <proguard configuration="examples/applications.pro" />

</target>

</project>


applications.pro


#
# This ProGuard configuration file illustrates how to process applications.
# Usage:
#     java -jar proguard.jar @applications.pro
#

# Specify the input jars, output jars, and library jars.

-injars  in.jar
-outjars out.jar

-libraryjars <java.home>/lib/rt.jar
#-libraryjars junit.jar
#-libraryjars servlet.jar
#-libraryjars jai_core.jar
#...

# Save the obfuscation mapping to a file, so you can de-obfuscate any stack
# traces later on. Keep a fixed source file attribute and all line number
# tables to get line numbers in the stack traces.
# You can comment this out if you're not interested in stack traces.

-printmapping out.map
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable

# Preserve all annotations.

-keepattributes *Annotation*

# You can print out the seeds that are matching the keep options below.

#-printseeds out.seeds

# Preserve all public applications.

-keepclasseswithmembers public class * {
    public static void main(java.lang.String[]);
}

# Preserve all native method names and the names of their classes.

-keepclasseswithmembernames,includedescriptorclasses class * {
    native <methods>;
}

# Preserve the special static methods that are required in all enumeration
# classes.

-keepclassmembers,allowoptimization enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 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 application doesn't use serialization.
# If your code contains serializable classes that have to be backward 
# compatible, please refer to the manual.

-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

# Your application may contain more items that need to be preserved; 
# typically classes that are dynamically created using Class.forName:

# -keep public class mypackage.MyClass
# -keep public interface mypackage.MyInterface
# -keep public class * implements mypackage.MyInterface

支持Maven编译 Maven支持proguard需要用到第三方插件,proguard官方推荐: IDFC Maven ProGuard Plug-in 网址:http://mavenproguard.sourceforge.net/ 版本要求 Maven 3.1 Jdk版本根据依赖的proguard版本决定 配置文件示例 在pom.xml文件中加入proguard插件配置:

<plugin>
	<groupId>com.idfconnect.devtools</groupId>
	<artifactId>idfc-proguard-maven-plugin</artifactId>
	<version>1.0.1</version>
         <executions>
              <execution>
                  <phase>package</phase>
                   <goals>
                          <goal>obfuscate</goal>
                    </goals>
               </execution>
         </executions>
	<configuration>
		<inputFile>${project.build.outputDirectory}</inputFile>
	<libraryJarPaths>
	<libraryJarPath>${java.home}/lib/rt.jar</libraryJarPath>
	         </libraryJarPaths>
	         <excludeManifests>false</excludeManifests>
	         <excludeMavenDescriptor>false</excludeMavenDescriptor>
		 <outputArtifacts>
			<outputArtifact>
				 < file>${project.build.finalName}.${project.packaging}</file>
		    </outputArtifact>
		 </outputArtifacts>
	</configuration>
          <dependencies>
               <dependency>
                    <groupId>net.sf.proguard</groupId>
                    <artifactId>proguard-base</artifactId>
                    <version>4.9</version>
               </dependency>
          </dependencies>
	</plugin>

除了plugin之外的配置,还有一个.pro的配置文件(存放在${basedir}/src/main/config/${project.artifactId}-maven.pro)。 如果需要指定配置文件目录,则通过以下配置实现: <proguardIncludeFile> ${basedir}/src/main/config/${project.artifactId}-maven.pro </proguardIncludeFile>

#Pro文件示例:
#保留调试信息(异常信息源码行数)
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
#混淆时不要形成混合大小写类名
-dontusemixedcaseclassnames
#保留调试级别的属性
-keepparameternames

# 保留注解信息,签名信息,异常信息,内部类信息

-keepattributes *Annotation*,Signature,Exceptions,InnerClasses
#指定混淆时方法和属性名替换字典文件
-obfuscationdictionary shakespeare.txt

# 保留所有共有和保护类型的属性和方法
-keep public class * {
    public protected *;
}
#保留枚举类方法
-keepclassmembers,allowoptimization enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
#保留所有实现序列化的类的素有属性
-keepclassmembers class * implements java.io.Serializable {
   private <fields>;
}
#保留com.test.web包下所有条件了@Autowired注解的素有属性
-keepclassmembers class com.test.web.** {
   @org.springframework.beans.factory.annotation.Autowired <fields>;
}

配置异常及解决

1.spring java.lang.IllegalArgumentException: Name for argument type [java.lang.String] 的错误 原因: 这个错误主要是因为action的参数标注默认是debug级别,比如 @RequestMapping(value = "/security/login", method = RequestMethod.POST) public ModelAndView login(@RequestParam String userName, @RequestParam String password, HttpServletRequest request) {此时userName的级别时debug级别,而在proguard编译时是忽略了这些标注,导致请求时就会找不到userName的参数。

解决方法: 编译脚本中添加-keepparameternames保留调试属性

2.找不到使用@Autowired注入的service类 混淆时proguard会对jar包进行优化,以期减少其大小。默认情况下,proguard会删除jar中的目录元素,导致ClassLoader().getResource()方法找不到对应的资源。只需要在使用时 加上 -keepdirectories 选项即可。

转载于:https://my.oschina.net/u/147528/blog/472237

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值