I use
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
public static int w(...);
public static int d(...);
public static int e(...);
public static java.lang.String getStackTraceString(java.lang.Throwable);
}
However when I decompile, I see the one and only custom string I used in a Log.d line in decompiled jar file. How can that be possible? Doesn't Proguard remove Log.d lines completely?
This is relevant if proguard optimization is enabled i.e. your proguard.config is this
proguard.config=${sdk.dir}/tools/proguard/proguard-android-optimize.txt:proguard-project.txt
Just for clarification, it's my understanding optimisation 'has' to been enabled for the log calls to be stripped.
You could try using a Log wrapper class (like this one) to wrap android.util.Log. I used this approach due to a note from Eric (a.k.a Mr Proguard) in this answer about how Proguard inspects the code. So this ends up with a simpler call to Log.d(tag, string) rather than Log.d(tag, string + value+ String)
Or use DexGuard IIRC is has some explicit function for log removal. --
[update: sorry my bad it's not a explicit function DexGuard uses the same config as you noted. I guess I was thinking the fact the decompiled code is more mangled with DexGuard.]
Related
I have an android app I have been developing, and it's now ready to launch. It works great running from eclipse unsigned. When I export a signed copy and run it, an NPE occurs. I've tried creating the signed version with the latest supplied proguard files (proguard-android.txt and proguard-android-optimize.txt). No difference with either. The only mods I've made via my local proguard config file is to leave line numbers so I can get a decent stack trace.
The NPE is what has me scratching my head. I use a lock object for synchronization, and I initialize it in the definition of the object and also during stream initialization:
public class HttpRequest extends NetworkRequest {
private transient Object lock = new Object();
<snip>
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();
lock = new Object();
}
In my debugging version, lock is never null, but in my signed version, when I go to use the lock object, it's null, consistently. I can only assume proguard is doing something I don't want, but this is the first time I've delved into proguard so I'm a bit out of my element.
Can anyone suggest how I can debug this further?
Proguard does three things: shrink, optimize, obfuscate.
In the shrink step, it cuts out any unused program code. What may be happening to you is that Proguard may be stripping away the readObject method because it appears to be unused. I would expect there to be a keep-rule for that method out of the box, but apparently there isn't, or at least not in the Android SDK.
One way to verify that would be to assemble your app with -dontobfuscate in the proguard config, then extracting the classes.dex file from the APK package and running dexdump classes.dex and looking for the presence or absence of the readObject method.
Ultimately, to ensure the readObject method is preserved, you would add the following rule to your ProGuard config:
-keepclassmembers class * implements java.io.Serializable {
private void readObject(java.io.ObjectInputStream);
}
Updated by mvsjes2 to add the config that actually worked for me:
-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
I know that removing logger calls with Proguard works for Android applications.
How can one accomplish this in standard Java application?
import java.util.logging.Logger;
public class Clazz {
private static final Logger LOGGER = Logger.getLogger(Clazz.class.getName());
public void foo() {
LOGGER.info("bar");
}
}
in my Proguard configuration I have the following:
-assumenosideeffects class java.util.logging.Logger { *; }
-whyareyoukeeping class java.util.logging.Logger
which gives the following output when running:
[proguard] java.util.logging.Logger
[proguard] is a library class.
I understand that it's a library but I want to strip all calls to it anyway. Is this possible with Proguard? If not, why? How come this works so conveniently for Android, does the logger field or lack of it have something to do with this?
You should be able to remove logging calls like this, assuming you haven't disabled optimization -- it's the optimization step that removes unnecessary and unwanted calls. ProGuard can't remove the Logger class itself, since it is a run-time library class, as you've seen.
You mustn't use a wildcard for matching the methods though, since this includes essential methods like wait() and finalize() (affecting all classes). You'll have to enumerate the methods that you want to remove. For instance:
-assumenosideeffects class java.util.logging.Logger {
void info(java.lang.String);
}
I tried ProGuard with NetBeans to obfuscate the class. After decompiling I see that it's only renaming local variables names.
Can anyone help explain to me how to refactor all variables names including public members. I can do that myself in NetBeans but it'll take forever. Also, ProGuard is obfuscating everything, even the libraries; I want to obfuscate only my classes. It doesn't matter if libraries are obfuscated or not.
For example, my global class contains variables like this:
public class D {
public static boolean doneSplash = false;
public static boolean bossActive = false;
.....
Is there a way to make it like ...
public class D {
public static boolean asdsa6d = false;
public static boolean xgrrret7 = false;
.....
Can anyone help?
use proguard gui and uncheck following option
skip non public library class
skip non public library class members
I know I'm throwing a pretty stupid question, but I promise I did try to search around the settings and around google and the webs and no luck, so I guess I should just ask.
I saw in quite a few open-source projects the following line:
if(DEBUG){
// do some logging
}
I perfectly understand what the line is doing, I just can't seem to repeat it.
There's no declaration of boolean DEBUG; anywhere in the code, and I couldn't figure out a place on the project properties to define a system wide variable to be replaced on the compiling (into byte code). And as far as I know, if it's a reference to a class constant it was supposed to be Log.DEBUG or something similar.
Can anyone solve this mystery for me?
thanks.
You really should look at the import section of the class.
It is probably a static import, like this :
A.java
public class A {
public static boolean DEBUG = false;
}
B.java
import static A.DEBUG;
public class B {
public void myMethod() {
if (DEBUG) {
// do something
}
}
}
You are in front of a public static field, look in import list and pick the original class or, use the inline help from Eclipse as said in comments
i am optimizing a jar with proguard, but it crashes after optimization.
here is my proguard task:
<proguard>
-injars ${dist}/${jarname}
-outjars ${dist}-proguard/${jarname}
-target 5
-libraryjars '${java.home}/lib/rt.jar'
-dontobfuscate
-optimizationpasses 4
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
-keep public class * {
public static void main(java.lang.String[]);
}
</proguard>
as soon as i put in the -dontoptimize option, it works.
according to the stack of the exception it crashes when accessing a static public member of a class with a nullpointer. here is the code:
public static Texture ring, dust, spikering, thinring, crystal, clouds;
public static void init() {
Field [] fields = TexturePool.class.getDeclaredFields();
for (Field field : fields) {
if(field.getType() == Texture.class) {
field.set( null, /*imagine new object here*/ );
}
}
}
thanks!
ok, i just found out myself. i think the optimization completely optimized that classmembers away, since they are not directly accessed in this class. if i specify the option:
-keepclassmembers public class com.package.** {
public static * ;
}
it works even with optimization.
According to Best Java Obfuscation Application For Size Reduction:
"I was always able to fix the problem by not using the Proguard argument "-overloadaggressively"."
Perhaps you should try the same?
EDIT: The problem could easily be that an assignment is optimized away. The initializations happening in the source code, where a field is defined, is actually done by the compiler in a static code blokc. Appears that the optimizations tinker with that. What happens with fewer optimization passes?
I had the same issue with ProGuard optimizing away class fields that were modified using reflection API only. However, the suggested answer didn't work for me as there were too many classes scattered throughout the code base to specify class filter.
Instead, disabling field optimization did the trick for me:
-optimizations !field/*