Search code examples
javaandroidgradleproguardandroid-proguard

Proguard produce runtime error because of specific third party library


recently I finished building a big project in Android, and the last requirement before publish was that it will be compiled with Proguard enabled, which I thought will be the easy part in the project, but turned out to be quite of hellish experience for me.

In the project I used several third party libraries, at least from my current checking, it seems all of them are working fine with my Proguard config.

The problematic library is JWT: JSON Web Token for Java and Android, which doesn't have documentation about how to config it with Proguard, and I tried so many different configurations, but none solved this problem.

The error occurs only when I put this line in the code (calling a class from this library):

Jwts.builder();

And the error as follows:

java.lang.ExceptionInInitializerError at io.jsonwebtoken.Jwts.builder(ProGuard:116) at com.cineworld.app.screen_options.webpage.PurchaseWebPage.GenerateToken(ProGuard:216) at com.cineworld.app.screen_options.webpage.PurchaseWebPage.onCreateView(ProGuard:142) at android.app.Fragment.performCreateView(Fragment.java:1699) at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:885) at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1057) at android.app.BackStackRecord.run(BackStackRecord.java:682) at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435) at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441) at android.os.Handler.handleCallback(Handler.java:725) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5041) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.ExceptionInInitializerError at io.jsonwebtoken.impl.DefaultJwtBuilder.(ProGuard:42) at io.jsonwebtoken.Jwts.builder(ProGuard:116)  at com.cineworld.app.screen_options.webpage.PurchaseWebPage.GenerateToken(ProGuard:216)  at com.cineworld.app.screen_options.webpage.PurchaseWebPage.onCreateView(ProGuard:142)  at android.app.Fragment.performCreateView(Fragment.java:1699)  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:885)  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1057)  at android.app.BackStackRecord.run(BackStackRecord.java:682)  at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435)  at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441)  at android.os.Handler.handleCallback(Handler.java:725)  at android.os.Handler.dispatchMessage(Handler.java:92)  at android.os.Looper.loop(Looper.java:137)  at android.app.ActivityThread.main(ActivityThread.java:5041)  at java.lang.reflect.Method.invokeNative(Native Method)  at java.lang.reflect.Method.invoke(Method.java:511)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)  at dalvik.system.NativeStart.main(Native Method)  Caused by: java.lang.ExceptionInInitializerError at com.a.a.c.ad.(ProGuard:209) at io.jsonwebtoken.impl.DefaultJwtBuilder.(ProGuard:42)  at io.jsonwebtoken.Jwts.builder(ProGuard:116)  at com.cineworld.app.screen_options.webpage.PurchaseWebPage.GenerateToken(ProGuard:216)  at com.cineworld.app.screen_options.webpage.PurchaseWebPage.onCreateView(ProGuard:142)  at android.app.Fragment.performCreateView(Fragment.java:1699)  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:885)  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1057)  at android.app.BackStackRecord.run(BackStackRecord.java:682)  at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435)  at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441)  at android.os.Handler.handleCallback(Handler.java:725)  at android.os.Handler.dispatchMessage(Handler.java:92)  at android.os.Looper.loop(Looper.java:137)  at android.app.ActivityThread.main(ActivityThread.java:5041)  at java.lang.reflect.Method.invokeNative(Native Method)  at java.lang.reflect.Method.invoke(Method.java:511)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)  at dalvik.system.NativeStart.main(Native Method)  Caused by: java.lang.NoSuchFieldError: PUBLIC_ONLY at java.lang.Class.getDeclaredAnnotation(Native Method) at java.lang.Class.getAnnotation(Class.java:260) at com.a.a.c.f.ac.(ProGuard:172) at com.a.a.c.ad.(ProGuard:209)  at io.jsonwebtoken.impl.DefaultJwtBuilder.(ProGuard:42)  at io.jsonwebtoken.Jwts.builder(ProGuard:116)  at com.cineworld.app.screen_options.webpage.PurchaseWebPage.GenerateToken(ProGuard:216)  at com.cineworld.app.screen_options.webpage.PurchaseWebPage.onCreateView(ProGuard:142)  at android.app.Fragment.performCreateView(Fragment.java:1699)  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:885)  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1057)  at android.app.BackStackRecord.run(BackStackRecord.java:682)  at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435)  at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441)  at android.os.Handler.handleCallback(Handler.java:725)  at android.os.Handler.dispatchMessage(Handler.java:92)  at android.os.Looper.loop(Looper.java:137)  at android.app.ActivityThread.main(ActivityThread.java:5041)  at java.lang.reflect.Method.invokeNative(Native Method)  at java.lang.reflect.Method.invoke

Can someone guide me to the proper way to handle this problem?


Solution

  • If you want to simply prevent an entire Java package from being obfuscated because it's too time consuming to figure out the one thing that's going wrong, try adding this to your proguard rules file:

    -keep class io.jsonwebtoken.** {
      public protected private *;
    }
    

    The rules are typically in your project's proguard-rules.pro file.