18 Nisan 2018 Çarşamba

ProGuard

Giriş
ProGuard şu 3 temel işlevi yerine getiriyor. Shrinking, Optimization ve Obfuscation
1.The shrinking step recursively determines which classes and class members are used. All classes and class members not used are discarded .If your application is distributed with a third party library then the number of classes, fields and methods that are not actually used could be quite significant.

2.The optimization step, optimizes the code and in particular: merges classes, removes attributes irrelevant to execution, sorts local variables, collapses method body inline, removes unused constant, optimizes code statement like if, for, switch and in general makes the code more compact and less user friendly.

3.The obfuscation step renames with meaningless name classes and class members that are not entry points. In this process keeping the entry points ensures that they can still be accessed by their original names. Every java project has at least one entry point: for example the class that contains the main for a java application or every class that contains public API for a java library. In general an entry point is a class that, if obfuscated, will prevent the library or the application from working properly.
ProGuard maven plugini ile de çalıştırılabiliyor. Ben maven-antrun-plugin olarak çalıştırılmasını gördüm. Her iki durumda da package safhasında -yani jar oluştururken - çalıştırılıyor.

Obfuscation
Elimizde şöyle bir kod olsun.
public class Superclass {
    private int intValue;
}

public class Subclass extends Superclass {
    private String stringValue;
}
Obfuscation işleminden sonra kod şu hale gelir.
public class A {
    private int a;
}

public class B extends A {
    private String b;
}
maven Kullanmak - Yeni Yöntem
maven ProGuard plugin yazısına taşıdım.

antrun Kullanmak - Eski Yöntem
Obfuscat işlemine dahil edilecek jar'ları vermek için pom.xml'de şöyle yaparız.
<plugin>
  <artifactId>maven-antrun-plugin</artifactId>
  <execution>
    <id>obfuscate</id>
    <phase>package</phase>
    <goals>
      <goal>run</goal>
    </goals>
    <configuration>
      <tasks>
        <ant antfile="build.xml">
          <target name="obfuscate"/>
        </ant>
      </tasks>
    </configuration>
  </execution>
</plugin>
build.xml
Bu dosyada ant tarafından çalıştırılacak komut yazılır. Komut şöyledir
<taskdef resource="proguard/ant/task.properties"
classpath="${basedir}/proguard-base-6.0.3.jar;${basedir}/proguard-anttask-6.0.3.jar;"/>

 obfuscate edilecek jar dosyalarını belirtiriz. Ayrıca bu dosyada ismi obf.pro olan ve kuralları içeren dosyaya atıfta bulunuruz.

1. libraryjars
Obfuscate edilmeyecek jar dosyalarını belirtir. Kendi sınıfım üçüncü taraf bir sınıftan kalıtıyorsa bu jar'ı belirtmem gerekiyor, yoksa ProGuard hata veriyor.
Örnek
Şöyle yaparız.
<librayjar path ="foo.jar"/> 
Örnek
Java sınıflarınından kalıtım olduğu için şu satır mutlaka lazım. build.xml'de ben şöyle yaprım.
<librayjar path ="${java.home}/lib"/>
Bazıları bu dizindeki jar'ları ayrı ayrı da veriyor. pom içinde şöyle yaparız.
 <!--  Java Runtime -->
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jsse.jar</lib>
<lib>${java.home}/lib/jce.jar</lib>
.pro dosyasında şöyle yaparız.
-libraryjars <java.home>/lib/rt.jar
2. Eğer kendi sınıfımda  üçüncü taraf bir sınıf üye eleman olarak kullanılıyorsa bu jar'ı <libraryjar...> olarak dahil etmeme gerek yok. Bu alan obfuscate edilmiyor.

3. injars
Obfuscate edilecek jar dosyalarını belirtir.
Örnek
Şöyle yaparız.
-injars log4j-api-2.10.0.jar(!META-INF/versions/**)


proguard.conf
Kuralları içerir.

dontwarn
Şöyle yaparız.
-dontwarn com.fasterxml.jackson.databind.**
-keep
Belli bir metoda sahip sınıfları korumak için şöyle yaparız.
-keep public class * { 
    public static void main(java.lang.String[]); 
}
-keepattributes
Şöyle yaparız.
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile
-keepclass
Belirtilen isim alanındaki sınıfları muhafaza etmek için kullanılır. Üçüncü taraf  (third party) kütüphaneleri obfuscate etmeye gerek olmaz. Hatta bu kütüphanelerin içini bilmek mümkün olmadığı için obfuscate etmemek daha iyi. Bu iş için kullanılabilir.
Örnek
Şöyle yaparız.
-keep class * implements java.sql.Driver
Örnek
Şöyle yaparız.
-keep class android.support.** { *; }
Örnek
Şöyle yaparız.
-keep class commons-io.** { *; }
-keep class commons-codec.** { *; }
-keep class commons-collections.** { *; }
-keep class commons-dbcp.** { *; }
-keep class postgresql.** { *; }
Örnek
Şöyle yaparız.
-keep class okio.** { *; }
-keepclassmembers
Belirtilen sınıftan veya arayüzden kalıtan sınıfın, üye alan veya üye metodlarını muhafaza eder.
Örnek
Serializable arayünden kalıtan sınıfları korumak için şöyle yaparız.
 -keepclassmembers class * implements java.io.Serializable { 
   private 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(); 
}
Örnek
Enum'ları korumak için şöyle yaparız.
// Preserve the special static methods that are required in all enumeration classes.

-keepclassmembers class * extends java.lang.Enum {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
Örnek
Spring sınıflarındaki @Autowired anotasyonlarının bozulmaması için şöyle yaparız.
-dontshrink
-verbose

-optimizationpasses 3 

-keepdirectories
-keep class * extends *
-keep interface * extends *

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

-keepclassmembers class * {
    @org.springframework.beans.factory.annotation.Autowired *;
}
-keepclasseswithmembernames
Şöyle yaparız.
// Preserve all native method names and the names of their classes.

-keepclasseswithmembernames class * {
    native <methods>;
}
-keepinterface
Belli bir arayüzü korumak için şöyle yaparız.
-keep interface com.somepackage.SomeClass$someInterface
keepnames
Şöyle yaparız.
-keepnames interface com.fasterxml.jackson.** {*;}
keepparameternames
Şöyle yaparız.
-keepparameternames

1 yorum:

  1. Merhaba Java projemde jar alıp proguard ui da kullandım ancak hata aldı dontwarn i nereye yazmamız gerekiyor

    YanıtlaSil