I have an Android App that works well in debug mode, but that has some kind of memory leak in release mode. Basically, it is really slow and the following line appears repeatedly in logcat:
dalvikvm D WAIT_FOR_CONCURRENT_GC blocked 91ms
If I don't obfuscate, don't shrink and don't optimize in proguard, then the release works. If I do one of them, I have this error. I use the following lines:
-dontshrink
-dontoptimize
-dontobfuscate
I am using multiple external libraries that use some native (i.e. JNI) code, and I have no idea what could be wrong.
How can I identify where the issue comes from?
Can I tell proguard to optimize/shrink/obfuscate only one package, so that I can try to isolate the problem?
You can tell Proguard to not interfere with, I mean obfuscate, packages and subpackages using instructions like this in the proguard config file:
-keep class com.google.** { *; }
-keep class okio.** { *; }
You can also tell it to keep classes annotated with a specific annotation using:
-keep class com.your.annotation
-keep #com.your.annotation class * { *; }
The first keep instruction makes sure it doesn't remove the annotation itself, and the second keeps anything annotated with it.
The full Proguard manual with other examples can be found here.
Related
I'm facing some issues when compiling the release version of my app.
I'm currently using Room and I have my model classes are under:
com.example.room.entity
and in order to let the app working I'm using a proguard rule
-keepattributes *Annotation*,SourceFile,LineNumberTable
-keep class com.example.room.entity.**.* { *; }
Once I build the version and I execute on my phone the app crash and I can see
Caused by java.lang.ClassNotFoundException
com.roommate.example.room.entity.UserEntity
The output of -printusage shows me that the the class I'm trying to preserve is somewhat touched by R8.
What can I do to enforce my rules?
Try to change second line to:
-keep class com.roommate.example.room.entity.** { *; }
I've configured:
-keep ,allowoptimization,allowobfuscation,allowshrinking public class org.jf.dexlib2.dexbacked.** {
*;
}
but still getting the warning:
Note: the configuration keeps the entry point 'com.trusteer.trf.dex_parser { int get_strings_count(org.jf.dexlib2.dexbacked.DexBackedDexFile); }', but not the descriptor class 'org.jf.dexlib2.dexbacked.DexBackedDexFile'
I am using proguard version 4.7 (in Android SDK)
What should I do?
You have told Proguard to keep a certain method void foo(Bar bar); but to obfuscate the descriptor class Bar.
This is only a problem if you are going to invoke the method from an external source as the signature will be changed by the obfuscation (if you use Proguard to obfuscate a library and then use that library in another app).
So have the following choices:
Configure Proguard to also keep Bar.
Use the -dontnote directive to tell Proguard not to print notes like this.
Note: the configuration keeps the entry point '...', but not the descriptor class '...'
Your configuration contains a -keep option to preserve the given method (or field), but no -keep option for the given class that is an argument type or return type in the method's descriptor. You may then want to keep the class too. Otherwise, ProGuard will obfuscate its name, thus changing the method's signature. The method might then become unfindable as an entry point, e.g. if it is part of a public API. You can automatically keep such descriptor classes with the -keep option modifier includedescriptorclasses (-keep,includedescriptorclasses ...). You can switch off these notes by specifying the -dontnote option.
Add this line in your 'proguard-rules.pro' file to fix this problem .
-ignorewarnings
From the docuemnts:
allowshrinking Specifies that the entry points specified in the -keep
option may be shrunk, even if they have to be preserved otherwise.
That is, the entry points may be removed in the shrinking step, but if
they are necessary after all, they may not be optimized or obfuscated
So it appears that you need to remove the allowshrinking modifier.
In my case this problem appears when I add to build.gradle
minifyEnable true
Official instructions: https://flutter.dev/docs/deployment/android
Bug https://github.com/flutter/flutter/issues/19250
Sample proguard-rules.pro file:
#Flutter Wrapper
-ignorewarnings
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.** { *; }
-keep class io.flutter.util.** { *; }
-keep class io.flutter.view.** { *; }
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
I did some digging in the docs. You have not supplied your whole configuration file, but I'm guessing that that com.trusteer.trf.dex_parser is set to both keep and not to obfuscate.
This means that there is a refrence from com.trusteer.trf.dex_parser to a class called org.jf.dexlib2.dexbacked.DexBackedDexFile that was either shrunk or obfuscated. This means that the link is now broken - dex_parser can't import DexBackedDexFile.
So either disable shrinking and obfuscation for DexBackedDexFile, or allow optimization and obfuscation on dex_parser.
I added Crashlytics to my android app (via Idea plugin).
When my app starts I get next error:
java.lang.AbstractMethodError: abstract method not implemented
at io.fabric.sdk.android.ActivityLifecycleManager$ActivityLifecycleCallbacksWrapper$1.onActivityStarted(ActivityLifecycleManager.java)
at android.app.Application.dispatchActivityStarted(Application.java:199)
at android.app.Activity.onStart(Activity.java:1048)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:536)
I completely can't figure out why this happens. Maybe someone faced with this issue?
As mentioned above (by Chris), proguard stripping out something it isn't able to discern as being used. And it really stripping Crashlytics/Fabric classes.
For avoid this, just need add these lines to proguard config file:
-keep class com.crashlytics.** { *; }
-keep class io.fabric.** { *; }
-dontwarn com.crashlytics.**
I've seen a couple questions regarding this issue, but they are for older versions of Netty.
I have tried their answers, switching org.jboss.netty out with io.netty, but the same error occurs.
I'm trying to compile an Android app that uses Netty 5.0.0Alpha2 (build #16) with Proguard enabled.
Without Proguard, the app runs fine.
As soon as I enable Proguard, I get this exception when it tries to use Netty:
java.lang.IllegalStateException: unknown type parameter 'I': class io.netty.channel.SimpleChannelInboundHandler
at io.netty.util.internal.TypeParameterMatcher.find0(Unknown Source)
at io.netty.util.internal.TypeParameterMatcher.find(Unknown Source)
at io.netty.channel.SimpleChannelInboundHandler.<init>(Unknown Source)
at io.netty.channel.SimpleChannelInboundHandler.<init>(Unknown Source)
...
This is my Proguard config:
# billing
-keep class com.android.vending.billing.**
# butterknife
-dontwarn butterknife.internal.**
-keep class **$$ViewInjector {
*;
}
-keepnames class * {
#butterknife.InjectView *;
}
# admob
-keep public class com.google.android.gms.ads.** {
public *;
}
-keep public class com.google.ads.** {
public *;
}
# logging
-assumenosideeffects class android.util.Log
# netty (partial)
-dontwarn io.netty.**
-dontwarn sun.**
I have tested it without the -dontwarn options to see if the warnings would point me in the right direction, but it's all missing optional dependencies like slf4j and Tomcat.
I have also tried excluding all the Netty classes like so:
-keep class io.netty.** {
*;
}
...but that does not appear to fix it either.
I have fixed this issue with some carefully* applied Proguard rules after reading through parts of the rather huge Netty sources:
-keepattributes Signature,InnerClasses
-keepclasseswithmembers class io.netty.** {
*;
}
-keepnames class io.netty.** {
*;
}
My original exception was caused by the type variables being removed from the bytecode, which Netty uses via reflection. Signature in -keepattributes keeps this information.
You get a slightly different exception if you only do Signature on -keepattributes - adding InnerClasses fixes this one by bringing back even more information in the class files.
Later, I got java.lang.NoSuchFieldException: ctl; that's what -keepnames is for. This way, the field is still called ctl like Netty expects.
Finally, some members (like ctl, seen earlier) were being removed by Proguard because Netty only uses them via reflection. The final rule, -keepclasseswithmembers, makes sure Proguard doesn't remove them.
If you take this approach, I strongly recommend you use only the Netty jars you need, instead of the -all jar. Switching from -all to just the required Netty jars brought my method count way down after I had gone past the 65k limit. Reducing your jars requires bit of trial-and-error though as the separation is unclear and there's not really any resources saying what's what.
* not carefully at all, I just slapped rules into the file and removed them if they did nothing. There's probably a better way to do this that doesn't keep this information in the entire program, but instead just Netty.
Una's answer keep too many classes, which makes my app 1MB larger than usual. So I use the rules below:
# netty
-keepclassmembernames class io.netty.buffer.AbstractByteBufAllocator {
*;
}
-keepclassmembernames class io.netty.buffer.AdvancedLeakAwareByteBuf {
*;
}
-keep public class io.netty.util.ReferenceCountUtil {
*;
}
Background
I am developing an Android application that relies on multiple external libraries (8 added as library project dependencies, 14 added as jar dependencies).
Some of these jar libraries are closed source an have already been obfuscated and some of them rely pretty heavily on reflection.
The application uses ZXing for QR code scanning/recognition and, without Proguard optimization, ZXing is quite slow (at least on Android).
At first, I only needed to optimize the com.google.zxing.** package using Proguard. In order to do that I've added the following Proguard options in my config file (the best I could figure out from this question):
-keep class !com.google.zxing.** { *; }
-keep interface !com.google.zxing.** { *; }
-keep enum !com.google.zxing.** { *; }
-dontwarn !com.google.zxing.**
I exported my application and it works like a charm.
Problem
Now, I want to use Proguard to obfuscate the application's classes.
I've tried changing the above to:
-keep class !(com.google.zxing.**, com.example.app.**) { *; }
-keep interface !(com.google.zxing.**, com.example.app.**) { *; }
-keep enum !(com.google.zxing.**, com.example.app.**) { *; }
-dontwarn !(com.google.zxing.**, com.example.app.**)
-keep com.example.app.activities.** { *; }
-keep com.example.app.receivers.** { *; }
-keep com.example.app.services.** { *; }
-keep com.example.app.views.** { *; }
The problem is that Proguard does not accept !(package.one.**, second.package.**) { *; } as a valid option for a -keep rule.
Another approach would be to put a -keep rule for every package in my application.
This approach has two big disadvantages:
adding or swapping libraries would require changing the Proguard config file
it makes updating libraries a pain, as some of them are obfuscated and, when recompiled by the library's developer, will change package names.
Obviously, I would like to avoid this approach as much as possible (because of the high number of external libraries).
Question
Is it possible to use Proguard to obfuscate just two packages, without defining a -keep rule for each of the other packages in my app? If so, how can I do this?
The correct syntax is a comma-separated list without any parentheses:
-keep class !com.google.zxing.**,!com.example.app.** { *; }
See the ProGuard manual > Usage > Filters.
Note that this single line already implies the two other lines for interfaces and enums. You can imply the -keep options for all subpackages by not letting the last wildcard match subpackages:
-keep class !com.google.zxing.**,!com.example.app.* { *; }