I just found that ProGuard removed a .wait() call which I used to synchronize threads, which lead to a race condition which lead to a day of happy debugging :) Anyway...
I tracked it down to following piece of proguard configuration:
-assumenosideeffects public class android.util.Log {
<methods>;
}
I want to understand WHY this happened. I am not sure why assuming that removal of Log class has no side effects leads to removal of .wait() on different class/object.
I saw ProGuard optimization also remove #wait() calls where Eric explains that such things may happen. However, he doesn't explain why.
Also, I found example how to remove Logs here (http://proguard.sourceforge.net/index.html#manual/examples.html). So, I can replace this piece of proguard of configuration (but it's not the point of this question).
Your original configuration matches all methods of Log (explicit or inherited), including Object#wait(). It tells ProGuard that the wait() method has no side-effects and that it can be removed without harming the program. This is obviously not true, as you have noticed. With -assumenosideeffects, you should always explicitly list the methods that are safe to remove.
Related
I've been obfuscating my apps for a long while, with the following settings I took like mantras, because they were Google's recommendations
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
However, the other day I commented this line by mistake, the app got built correctly, and "apparently" works. I've made a lot of tests and couldn't made it crash.
So I wonder if those disabled optimization settings are needed ...
as of today's Android SDK and latest Proguard versions, I only target devices from Android 4.0.3 onwards (15), and use Proguard 5.1.
and for applications that don't do exotic stuff and have a properly written proguard.cfg instructing to keep the relevant problematic classes, etc.
Most answers here releated to this very issue have conflicting information, and are related to pretty old API versions.
One by one:
!code/simplification/arithmetic
I found a discussion on Google Groups where they say that simplification/arithmethic is not needed for SDK's after Android Donut. I assume then, I can safely enable this optimization.
!class/merging/*
It looks like proguard makes a good job in my projects with this optimization turned on:
[proguard] Number of vertically merged classes: 296
[proguard] Number of horizontally merged classes: 445
Are there other side effects besides the stack traces being incorrect? I mean, side effects related to the application crashing rather than to debug issues. I found this related question but it doesn't conclude wether it is safe or not.
!field/* and !code/simplification/cast
I read in this question answered by ProGuard's author that those were included to avoid bugs with older Proguard versions. So is it safe to activate them on Proguard 5.1?
General advice: there's no guarantee that optimizations won't work, but there's always a risk. What the default Android proguard settings are attempting to do is provide a configuration that minimizes that risk, hence why they appear so conservative for your specific situation.
Enabling those optimizations just means that if something crashes, you can't be as certain as to the root cause. In general, the proguard step has less strong guarantees about what the outputs should be relative to the inputs, which is a source of non-determinism in your program. Small changes in code can result in significantly different changes in runtime behaviour, and it's not possible to know until you actually run the program, depending on your config.
In summary, if you can run your APK, and it all works - then great, the optimizations work for you. But, they're not guaranteed to.
So is it safe to activate them on Proguard [5.1]?
It's a high risk move and I can give you an example where it causes a problem.
We're using ProGuard 5.2.1 and we're hitting a bug when reenabling the field/* optimization (more specifically, field/removal/writeonly seems to be causing the problem). Our code uses protobuf and enabling that optimization causes ProGuard to fail with this message on the third pass of optimizations:
Optimizing...
Unexpected error while evaluating instruction:
Class = [com/google/protobuf/FieldSet$1]
Method = [()V]
Instruction = [308] isub
Exception = [java.lang.IllegalArgumentException] (Value "com/google/protobuf/WireFormat$JavaType!" is not an integer value [proguard.evaluation.value.TypedReferenceValue])
Unexpected error while performing partial evaluation:
Class = [com/google/protobuf/FieldSet$1]
Method = [()V]
Exception = [java.lang.IllegalArgumentException] (Value "com/google/protobuf/WireFormat$JavaType!" is not an integer value [proguard.evaluation.value.TypedReferenceValue])
Warning: Exception while processing task java.io.IOException: java.lang.IllegalArgumentException: Value "com/google/protobuf/WireFormat$JavaType!" is not an integer value [proguard.evaluation.value.TypedReferenceValue]
This is to say that the fact that these optimizations have been disabled for so many years means that they probably haven't been as well maintained as others. Luckily this was caught at compile time but re-enabling some of these optimizations (e.g. horizontally merging classes via class/merging/*) might easily break your app in certain versions/builds of Android without being properly reported back to you "the developer" (e.g. it might crash dexopts or fail to install altogether with VerifyError).
I am trying to use proguard to obfuscate the code of my Android app.
My problem is that some screen of my app work fine, some others show a blank screen (not entirely blank though, for example my top title bar display correctly, but the rest of the content is blank).
I have started with the basic settings:
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
Then, in proguard-project.txt, I have tried to add:
-keep class {my.package.name}.** { *; }
No change
Then
-dontskipnonpubliclibraryclassmembers
No change
Then
-dontobfuscate
which obviously solved the problem but then there is no point since I want to obfuscate my code.
Any idea?
Look at the output ProGuard creates; it will tell you what classes got renamed and what classes got deleted (because they appear to be unused). You will need to modify your config to nether rename nor delete these classes of course. Typically, you can find an interaction between your AndroidManifest.xml and the pieces that are missing after obfuscation (and your logcat might even tell you what is missing). Less likely is that use of reflection led ProGuard to not realize the importance of keeping these things in tact.
If you decide you need full obfuscation for the things that are being altered yet are necessary, you'll need to create thin object proxys that are safe from obfuscation and know how to get to the real classes.
Android app submission says, remove any logging before submission. Have a few question on this one
Is System.out.println considered as logging? How can I disable it across the app without having to remove it on by one
Tried android:debuggable="false" inside manifest, but eclipse says "Avoid hardcoding the debug mode; leaving it out allows debug and release builds to automatically assign one"
I have some third party jar files that shows Log statement when I test my app. How can I remove them, considering I don't have the source.
Suggestions are highly appreciated.
I'm sure you've come across the fact that you can do the if(GLOBAL_VALUE) trick, because your logs are already there!
Therefore, my suggestions is to use Proguard; http://developer.android.com/tools/help/proguard.html
The following proguard.cfg chunk instructs to remove Log.d calls.
-assumenosideeffects class android.util.Log {
public static *** d(...);
}
You can do it for other calls like Log.i, Log.e, etc based on the value you put there!
As for your Jar, if it is referencing the Android Log system, ProGuard should take care of that.
I am developing an android application where i am using a lot of Logs for printing values at console for debugging purpose. Now i am using Log.i() method in Android. Now actually what the problem , before i have to give to testing team, i have to remove all logs. When the number of classes in the project is small, i can remove it manually. But when the project contains 40 to 50 classes, it is humanly impossible to go to all classes and remove it manually. So is there any settings is availaible in eclipse so that i can remove or disable all logs by changing a single settings or configuration or else is there any jar file that helps for debugging much more easier than Log.i() method. Any suggestion or guidance is highly appreciable
Thanks inAdvance
the logs will be kept on the phone and any user/developer can check them out by installing apps like Catlog even without using adb! This is a problem as you stand to give unnecessary and at times, confidential data to users/other developers.
Simple way to solve this?
a. Use Proguard to automatically block all logs, more information in this stackoverflow thread
Here you can automatically block all logs at the bytecode level in Proguard
-assumenosideeffects class android.util.Log {
public static int v(...);
}
The above, for example would remove any verbose logging, more in this thread
b. I use a if(DEBUG) Log.i for all my logs, so that with one change of the boolean DEBUG i can switch on/off all logs
This answer referred from this link
Android hide logs in the application when upload to market
I've been using Log.whatever() calls to Log various bits of information as I've been developing my Android app. As I prepare to publish my app to the Android Marketplace, I'm trying to figure out what I need to remove.
According to the Android developer Dev Guide, before publishing, they suggest:
Deactivate any calls to Log methods in the source code.
How does one deactivate the Log methods? Obviously I could go through and erase them all (which is a bit of a pain) but is there some other way to deactivate Log calls that I'm unaware of?
Also, what danger is there to having Log calls in a published application? Can anyone install Eclipse, plugin in their phone and enable Debug mode and see all the same LogCat information that I see as I'm developing?
Also the Dev Guide suggests:
Remove the android:debuggable="true" attribute from the <application> element of the manifest.
I was unaware of this flag until now. What does it do exactly? I've been developing and debugging my app just fine up to this point and this flag is not set to true or false for in my Manifest.
Yes, anyone can install the Android SDK (with or without Eclipse) to view all log messages on your device.
I don't recommend completely removing your logging code, but instead wrap it, such as: if (DEBUG) Log.d(...) where DEBUG is some static boolean you define in a convenient place. I prefer to create a utility class so that all log calls across various classes can be enabled/disabled at once.
Simplest chnages for that would be to define one custom Class say MyLog, now replace all the calls of Log.d() to MyLog.d().
Now inside your class you can have one flag that can enable or disable logs.
hope this helps.
A good practice is to use something like if (DEBUG) Log.whatever, and then simply make DEBUG false.
There is no real danger except that you may expose some underlying implementaion which may expose glitches and hackable points in you app. The real problem is the performance penalty that you will get from logging too much.
As for android:debuggable="true", search for it in here
Finally, yes, Logcat logs are global and can be seen by anyone using the Android SDK.
Yes logs can be seen by anyone. Not only that, apps can collect logs programmatically: http://www.cuteandroid.com/five-android-logcat-related-open-source-apps-for-developers
So make sure you don't expose sensitive data as many apps collect logs - mine do in case of unhandled exceptions / crashes.
Yep, most certainly. Everyone can see them.
If you don't want that to happen, delete them from your code. It's quite normal though. I see a lot of apps using logs, and odds are that almost none of your users will be using that to check your logs.
I would recommend not wrapping your Log statements; depending on the size of your application that could take a while, will probably result in a fair bit of extra code and is just a hassle IMHO.
Instead I found configuring Proguard to automatically optimize your code and strip out Log statements when exporting an app release to be much easier. It will also obfuscate specified areas slowing down any reverse engineers that are trying to break your app.
If you do decide to go with Proguard you can put something like the following in your proguard-project.txt file to strip out log statements.
-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(...);
}