Proguard warnings despite kept classes - java

I'm using Proguard to shrink my code. My strategy is to enable it and then follow the warnings to keep anything it complains about. If there are outside libraries, I try to follow the Proguard instructions the authors make available. Many instructions include a -dontwarn flag. If I disable the -dontwarn flag, I will get warnings. If we are keeping most classes via -keep flag, why do warnings still come up?
Example:
-keep class javax.** { *; }
# for butterknife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
#butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
#butterknife.* <methods>;
}
Warning:butterknife.internal.ButterKnifeProcessor: can't find referenced class javax.annotation.processing.AbstractProcessor
Warning:butterknife.internal.ButterKnifeProcessor: can't find referenced class javax.annotation.processing.ProcessingEnvironment
Warning:butterknife.internal.ButterKnifeProcessor: can't find referenced class javax.lang.model.element.TypeElement
Warning:butterknife.internal.ButterKnifeProcessor: can't find referenced class javax.lang.model.element.Element
Warning:butterknife.internal.ButterKnifeProcessor: can't find referenced class javax.annotation.processing.Filer
Warning:butterknife.internal.ButterKnifeProcessor: can't find referenced class javax.tools.JavaFileObject
...

There are many warnings in ProGuard meaning different things. This particular one:
Warning:A: can't find referenced class B
Means that while ProGuard was processing class A it encountered reference to class B. But class B wasn't included as a source (-injars class_path) or as a library (-libraryjars class_path).
First note that for this particular warning in case of standard Android build chain adding -keep rules will not help. ProGuard transitively keeps referenced code.
This warning can happen for several reasons. Often a library X can contain code that uses another library Y. And X uses Y optionally - only when Y is present on the classpath, X doesn't enforce presence of Y. This way ProGuard is unable to find classes from Y.
To get rid of the warnings you have to either add Y as a dependency or ignore the relevant warnings.
In case of ButterKnife the situation is slightly different. Butterknife uses annotation processing. And it contains both the library and annotation processor in one dependency (latest version 7.0.1). So class butterknife.internal.ButterKnifeProcessor is still present in the compiled classes (even though it's work is already finished - used during java compilation). And ProGuard tries to process it. ProGuard fails to find the missing classes because they were used only during annotation processing and are not present for ProGuard processing.
In this case it's really necessary to ignore the warnings.

Related

Resolve many proguard warning

I saw a lot of warnings when connected, more than 5 thousand, I found information that I should solve problems in a similar way
-keep class com.google.android.gms.** { *; }
-dontwarn com.google.android.gms.**
But I have too many classes, I do not believe what I need to add all this one by one, it will take a lot of time and nerves
What are possible solutions? Maybe it can be simplified
I have more than 5 thousand such warnings
1>PROGUARD : warning : com.google.android.gms.internal.zzal: can't find superclass or interface org.apache.http.client.methods.HttpEntityEnclosingRequestBase
1>PROGUARD : warning : android.arch.core.internal.FastSafeIterableMap: can't find referenced class android.support.annotation.RestrictTo$Scope
1>PROGUARD : warning : android.arch.lifecycle.ClassesInfoCache: can't find referenced class android.support.annotation.Nullable
You have to manually fix all warnings, by applying proguard rules.
Your program code contains copies or better versions of Android runtime classes in the package com.google.android.gms If that's ok:
-dontwarn com.google.android.gms.**
-dontnote com.google.android.gms.**
And so on...
ProGuard manual > Troubleshooting

ProGuard SimException

I'm trying to get ProGuard to work, after roughly 4 hours of randomly trying options to try and get this amazing software to work.
My project is using LibGDX and KryoNet. This is my current ProGuard configuration:
-verbose
-dontobfuscate
-dontwarn android.support.**
-dontwarn com.badlogic.gdx.backends.android.AndroidFragmentApplication
-dontwarn com.badlogic.gdx.utils.GdxBuild
-dontwarn com.badlogic.gdx.jnigen.BuildTarget*
-dontwarn com.badlogic.gdx.graphics.g2d.freetype.FreetypeBuild
-keepclassmembers class com.badlogic.gdx.backends.android.AndroidInput* {
<init>(com.badlogic.gdx.Application, android.content.Context, java.lang.Object, com.badlogic.gdx.backends.android.AndroidApplicationConfiguration);
}
# Kryo
-dontwarn sun.reflect.**
-dontwarn java.beans.**
-dontwarn sun.nio.ch.**
-dontwarn sun.misc.**
-keep class com.esotericsoftware.kryo.** {*;}
-keep class com.esotericsoftware.** {*;}
-keep class java.beans.** { *; }
-keep class sun.reflect.** { *; }
-keep class sun.nio.ch.** { *; }
This does not compile. It throws multiple of the following errors: Uncaught translation error: com.android.dx.cf.code.SimException: local variable type mismatch: attempt to set or access a value of type float using a local variable of type int. This is symptomatic of .class transformation tools that ignore local variable information.
I found some information about this error: Compile with Proguard gives SimException: "local variable type mismatch".
The solution given was to edit some main-rules.xml file from ANT, but I'm using Gradle. A comment was posted with a fix for Gradle : to add project.tasks.withType(com.android.build.gradle.tasks.Dex) { additionalParameters=['--no-locals'] }. But apparently the Dex class is removed, so this no longer works.
I read this is a bug in ProGuard, and that obfuscating should fix it. But when I remove the -dontobfuscate line, my app does not start anymore: java.lang.UnsatisfiedLinkError: No implementation found for void com.a.a.c.a.k.g() (tried Java_com_a_a_c_a_k_g and Java_com_a_a_c_a_k_g__).
Does anyone know how to work around these issues?
The problem might be related to a specific optimization of ProGuard.
You can disable it like that:
-optimizations !code/allocation/variable
Furthermore you can also remove the LocalVariableTable and LocalVariableTypeTable attributes which do not seem to be updated properly (and are not needed in an application anymore). For this you would need to enable obfuscation though and then use something like:
-keepattributes !LocalVariable*,**
This rule would keep all attributes but the LocalVariable related ones.
The obfuscation problem with libGDX might be solved by this rule:
# Keep names - Native method names. Keep all native class/method names.
-keepclasseswithmembers,includedescriptorclasses class * {
native <methods>;
}

Proguard - Error: A JNI error has occured

I've been trying to use ProGuard to obfuscate an application of mine. I have disabled every option exception for obfuscate. Loader is my main class.
The screenshot below is the result when I try to run my obfuscated jar.
No errors were given while obfuscating either.
My config
-injars 'C:\Users\Corsair\Desktop\obfuscate\Example.jar'
-outjars 'C:\Users\Corsair\Desktop\obfuscate\ExampleOut.jar'
-libraryjars 'C:\Program Files\Java\jre1.8.0_91\lib\rt.jar'
-dontskipnonpubliclibraryclassmembers
-dontshrink
-dontoptimize
-dontusemixedcaseclassnames
-dontpreverify
-dontnote
-dontwarn
-verbose
-keep class Loader
If this is the only configuration that you are using, also native methods will get obfuscated. As a result, their name will not match the ones in the native library anymore, and thus you will see an error like this when trying to load the library using System.loadLibrary.
You need to add at least a rule like this:
-keepclasseswithmembernames,includedescriptorclasses class * {
native <methods>;
}
This will instruct ProGuard to keep all native methods in any class it processes.
Edit:
Additional rules that are needed to get it working:
Remove -dontpreverify, preverify is needed for Java 7+
Keep the main method
This will keep the main method:
-keep class Loader {
public static void main(...);
}
You have to exclude certain classes from obfuscating like bean classes, callback classes and native classes. In the official examples the following is mentioned:
Processing native methods
If your application, applet, servlet, library, etc., contains native methods, you'll want to preserve their names and their classes' names, so they can still be linked to the native library.
-keepclasseswithmembernames,includedescriptorclasses class * {
native <methods>;
}
Note: We don't want to preserve all classes or all native methods; we just want to keep the relevant names from being obfuscated.
Processing callback methods
If your application, applet, servlet, library, etc., contains callback methods, which are called from external code (native code, scripts,...), you'll want to preserve them, and probably their classes too. They are just entry points to your code, much like, say, the main method of an application.
-keep class mypackage.MyCallbackClass {
void myCallbackMethod(java.lang.String);
}
Processing bean classes
If your application, applet, servlet, library, etc., makes extensive use of introspection on bean classes to find bean editor classes, or getter and setter methods, then configuration may become painful. There's not much else you can do than making sure the bean class names, or the getter and setter names don't change
Helpful: to use wildcards in class names and method signatures
-keep class mybeans.** {
void set*(***);
void set*(int, ***);
boolean is*();
boolean is*(int);
*** get*();
*** get*(int);
}
Also some other scenarios (Ressources, Serialization classes) can lead to problems. Please refer to the whole guide for these
ProGuard Official: Examples

Configuring ProGuard for android-eclipse project with multiple jars

I want to use ProGuard for my android app, but I have some trouble with it. When I build an unsigned apk via android tools (in eclipse) I got following errors:
Warning: com.millennialmedia.android.NVASpeechKit$7: can't find referenced class com.nuance.nmdp.speechkit.Recognizer
[...] //more warnings of the same type as above
You should check if you need to specify additional program jars.
Warning: there were 170 unresolved references to classes or interfaces.
You may need to specify additional library jars (using '-libraryjars').
java.io.IOException: Please correct the above warnings first.
at proguard.Initializer.execute(Initializer.java:321)
at proguard.ProGuard.initialize(ProGuard.java:211)
at proguard.ProGuard.execute(ProGuard.java:86)
at proguard.ProGuard.main(ProGuard.java:492)
I'm using 5 jar files within my app, which are all located in the libs-folder and are added to the build-path (So they propably appear in 'Referenced Libraries' as well as 'Android Private Libraries' again). Additionally, I put a so-library in libs/armeabi...
My proguard - file look pretty normal, yet:
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontpreverify
-dontskipnonpubliclibraryclasses
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** e(...);
}
What should I do to fix this error?
regards
PS: I know that proguard can delete/change some important things (like class-files,..). So, will I notice such 'errors' by exceptions immediately when starting my app or do I have to check every detail and navigate to any part of my app at runtime to make sure that it runs as it should?
EDIT:
I'm using following jars:
alljoyn.jar (there's also a path varibale in linked resources to the alljoyn-sdk)
peergroupmanager.jar
android-support-v4.jar
MMSDK.jar
GoogleAdMobAdsSdk-6.4.1.jar
From http://docs.millennialmedia.com/android-SDK/AndroidFAQ.html
I am using ProGuard with my Android application, what should I do to ensure my Millennial ads still work?
To make sure you still receive ads while using ProGuard, add the following snippet to your proguard.cfg file.
-keepclassmembers class com.millennialmedia.android.* {
public *;
}
-keep class com.millennialmedia.android.**
When using ProGuard and not SpeechKit, add the following line to their proguard-project.txt:
-dontwarn com.millennialmedia.android.NVASpeechKit*

Proguard: keepclassmembers inside a Namespace

I'm trying to obfuscate my Android app. After obfuscating, there are a few things broken, so I need to keep all classmembernames inside a special namespace.
what did't worked was
-keepclassmembers class my.namespace.to.keep** {*;}
any suggestion? It is no Problem if the whole class is kept or only its members.
You don't tell in what way it didn't work, but you may need to specify -keep instead of -keepclassmembers.
You can specify -printseeds to see which classes and class members are matched by the -keep options.

Categories

Resources