- Megjelent: 2012. június 23
Mielőtt Java programod terjesztésébe kezdesz, gondoskodnod kell róla, hogy mások minnél nehezebben tudják visszafejteni - és így ellopni - a nagy munkával megírt forráskódot.
Két obfuscator programot is kipróbáltam:
A ProGuard tapasztalataim szerint egyszerűbben beépíthető a NetBeans-be és könnyebben konfigurálható, ezért ennek a menetét ismertetem.
Platform
Figyelj rá, hogy ha a legújabb Java platfomot használod, nem biztos, hogy a ProGuard támogatja, így valami hasonló hibaüzenetet fogsz kapni:
Can't read [C:\Program Files\Java\jdk1.7.0\jre\lib\rt.jar]
(Can't process class [com/oracle/net/Sdp$1.class] (Unsupported version number [51.0] for class format))
A 4.7-es verziótól mindegyik támogatja a Java 7-et, és tényleg működik is vele (kipróbáltam).
Telepítés NetBeans-hez
-
Töltsd le a ProGuard legújabb verzióját. A letöltő oldal itt érhető el.
- Közvetlen letöltés: proguard4.8.zip
- Csomagold ki az állományt
- A lib alkönyvtárban található JAR fájlokat másold be egy tetszőleges könyvtárba
- Jegyezd meg a könytár nevét, mert később szükség lesz rá!
Ha ez megvan, a NetBeans projekted build.xml fájljába másold be a következő ANT szkriptet. A szkriptben félkövéren kiemelt elérési útvonalat értelemszerűen módosítsd, mielőtt a build gombra kattintasz a NetBeans-ben!
<target name="-post-jar">
<property name="proguard.jar.path" value="/path/to/proguard/proguard.jar" />
<taskdef resource="proguard/ant/task.properties"
classpath="${proguard.jar.path}" />
<echo message="Obfuscating ${dist.jar}..."/>
<mkdir dir="${build.dir}/obfuscated"/>
<proguard printmapping="${build.dir}/obfuscated/${application.title}.map"
renamesourcefileattribute="SourceFile" ignorewarnings="true">
<!-- Specify the input jars, output jars, and library jars. -->
<injar file="${dist.jar}" />
<outjar file="${build.dir}/obfuscated/${application.title}.jar" />
<libraryjar path="${javac.classpath}" />
<libraryjar file="${java.home}/lib/rt.jar" />
<libraryjar file="${java.home}/lib/jce.jar" />
<!-- Keep some useful attributes. -->
<keepattribute name="InnerClasses" />
<keepattribute name="SourceFile" />
<keepattribute name="LineNumberTable" />
<keepattribute name="Deprecated" />
<keepattribute name="*Annotation*" />
<keepattribute name="Signature" />
<keepattribute name="Exceptions" />
<!-- Preserve all public classes, and their public and protected fields and methods. -->
<keep access="public">
<field access="public protected" />
<method access="public protected" />
</keep>
<!-- Preserve all .class method names. -->
<keepclassmembernames access="public">
<method type ="java.lang.Class"
name ="class$"
parameters="java.lang.String" />
<method type ="java.lang.Class"
name ="class$"
parameters="java.lang.String,boolean" />
</keepclassmembernames>
<!-- 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.
With this code serializable classes will be backward compatible -->
<keepnames implements="java.io.Serializable"/>
<keepclassmembers implements="java.io.Serializable">
<field access ="final"
type ="long"
name ="serialVersionUID" />
<field access ="!static !transient"
name ="**"/>
<field access ="!private"
name ="**"/>
<method access ="!private"
name ="**"/>
<method access ="private"
type ="void"
name ="writeObject"
parameters="java.io.ObjectOutputStream" />
<method access ="private"
type ="void"
name ="readObject"
parameters="java.io.ObjectOutputStream" />
<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>
<copy file="${build.dir}/obfuscated/${application.title}.jar" tofile="${dist.jar}" overwrite="true"/>
<delete dir="${build.dir}/obfuscated"/>
</target>