evant / gradle-retrolambda

A gradle plugin for getting java lambda support in java 6, 7 and android
Apache License 2.0
5.3k stars 449 forks source link

Proguard requirements for obfuscated libraries #237

Closed kustra closed 7 years ago

kustra commented 7 years ago

I'm developing a closed source library that I'm obfuscating using proguard before uploading it to Maven. The library is using Java 6 syntax, so no retrolambda.

When I try to use this library in my app (using retrolambda and Java 8 syntax), I run into the same issue as described in #31, but with my own library, and not Google's support libs. If I include a non-obfuscated version of my library in the app, it works fine. If I include -noverify in my JVM args, it also works fine, but I'm not exactly comfortable with this solution.

Since I have access to the Proguard file of the library, we might as well try to figure out what's causing the issue. Please find the file below. We're using the proguard-android-optimize.txt as the default proguard config.

# Keep attributes
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-renamesourcefileattribute SourceFile

# Keep classes that are referenced on the AndroidManifest
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider

# Remove debug logs:
-assumenosideeffects class android.util.Log {
    public static boolean isLoggable(java.lang.String, int);
    public static int d(...);
    public static int v(...);
}

# Java native methods
-keepclasseswithmembernames,includedescriptorclasses class * {
    native <methods>;
}

# Maintain enums
-keepclassmembers class * extends java.lang.Enum {
    <fields>;
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# Keep serializable classes compatible
-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 <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

# Keep the R
-keepclassmembers class **.R$* {
    public static <fields>;
}

# Keep Javascript interface classes
-keepclassmembers class * {
    @android.webkit.JavascriptInterface <methods>;
}

# Library dependencies
-keep class com.squareup.okhttp.** { *; }

# SDK code
-keep public class com.mylib.service.network.* { public protected *; }
-keep public class com.mylib.other.package.** { public protected *; }

-keepclassmembers public class com.mylib.service.MylibAndroidService {
    *;
}

Do you see anything that looks suspicious? Is there any requirement for an obfuscated library to be usable in an app using retrolambda?

Thank you

evant commented 7 years ago

Sorry, I don't know what in proguard would cause issues. Is it possible you can reproduce with a similar proguard config on a sample lib? If so you can post an issue with the jar to https://github.com/orfjackal/retrolambda to get help figuring out why it's failing.

kustra commented 7 years ago

The issue turned out to be reproducible with just a few lines of code. Here's the relevant issue: https://github.com/orfjackal/retrolambda/issues/124 Will keep this issue updated with the results.

evant commented 7 years ago

Thanks, might want to include retrolambda's output, you can get it by running gradle with --info

kustra commented 7 years ago

The issue has been resolved. I ended up adding retrolambda to the library as well, and using it to produce Java 6 bytecode instead of Java 7, which caused the error. See the related retrolambda issue for details.