androidandroid-jetpack-composeproguardandroid-r8

Unreadable exception stack trace in Jetpack Compose


i am facing some weird exception stack traces when i enable minification. The weird thing is that it happens only inside setContent.

release {
      isDebuggable = false
      isMinifyEnabled = true
      isShrinkResources = true
      proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
      signingConfig = signingConfigs.getByName(signingCfg)
    }
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      throw InvalidClassException("Test Exception")
      Content()
    }
  }

This code outputs something like:

Caused by: java.io.InvalidClassException: Test Exception
                    at g4.a.h(Unknown Source:31)
                    at h0.c.h(Unknown Source:53)
                    at androidx.compose.ui.platform.k1.a(Unknown Source:24)
                    at s.l0.h(Unknown Source:163)
                    at h0.c.h(Unknown Source:53)
                    at y9.z.b(Unknown Source:151)
                    at androidx.compose.ui.platform.l1.a(Unknown Source:282)
                    at y.v.a(Unknown Source:38)
                    at y.v.h(Unknown Source:15)
                    at h0.c.h(Unknown Source:53)
                    at y9.z.b(Unknown Source:151)
                    at androidx.compose.ui.platform.w0.a(Unknown Source:484)
                    at androidx.compose.ui.platform.f3.a(Unknown Source:170)
                    at androidx.compose.ui.platform.f3.h(Unknown Source:27)
                    at h0.c.h(Unknown Source:53)
                    at y9.z.a(Unknown Source:216)
                    at androidx.compose.ui.platform.f3.a(Unknown Source:144)
                    at androidx.compose.ui.platform.f3.h(Unknown Source:15)
                    at h0.c.h(Unknown Source:53)
                    at d5.a.O(Unknown Source:14)
                    at a0.q.q(Unknown Source:117)
                    at a0.q.k(Unknown Source:10)
                    at a0.x.n(Unknown Source:33)
                    at a0.e2.a(Unknown Source:33)
                    at a0.x.o(Unknown Source:8)
                    at a0.x.g(Unknown Source:2)
                    at androidx.compose.ui.platform.g3.invoke(SourceFile:24)
                    at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(Unknown Source:6)
                    at androidx.compose.ui.platform.WrappedComposition.g(Unknown Source:8)

If i throw the exception outside of setContent, i get a readable exception.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    throw InvalidClassException("Test Exception") // I get a proper exception stack trace
    setContent {   
      Content()
    }
  }

I have tried to update all compose related dependencies, currently i use:

agp = 8.2.0
kotlinCompilerExtensionVersion = "1.5.12"
kotlin = 1.9.23

But without any luck. The only way how to "fix" this is to set isMinifyEnabled = false.

It seems like some exception related to R8/ Proguard.


Solution

  • Please have a look at the official documentation of isMinifyEnabled:

    To make your app as small and fast as possible, you should optimize and minify your release build with isMinifyEnabled = true.

    Doing so enables shrinking, which removes unused code and resources; obfuscation, which shortens the names of your app’s classes and members; and optimization, which applies more aggressive strategies to further reduce the size and improve the performance of your app.

    Your code is being obfuscated when you use isminifyEnabled = true, which means that all classes, methods, and field names are replaced by some random letters. The error log you posted is exactly as expected in that sense.

    The error log seems normal when you throw before setContent because the program crashes before any obfuscated code specific to your App is executed and thus does not appear in the stacktrace.
    The onCreate method itself cannot be obfuscated, because it overrides the onCreate in android.app.Activity. If it got obfuscated, your App would no longer work. In general, methods overriding Android library methods will not be obfuscated.

    To decode an obfuscated stacktrace, read this section in the documentation.