R8开启minifyEnabled时发布构建报ExceptionInInitializerError求助
问题描述
构建Release版本时触发ExceptionInInitializerError错误,Debug版本或添加-dontobfuscate标记后问题消失。错误堆栈如下:
java.lang.ExceptionInInitializerError at androidx.fragment.app.FragmentHostCallback.<init>(SourceFile:4) at androidx.fragment.app.FragmentHostCallback.<init>(SourceFile:2) at androidx.fragment.app.FragmentActivity$HostCallbacks.<init>(SourceFile:2) at androidx.fragment.app.FragmentActivity.<init>(SourceFile:2) at androidx.appcompat.app.AppCompatActivity.<init>(SourceFile:1) at main.MainActivity.<init>(SourceFile:1) Caused by: java.lang.RuntimeException: Shaking error: Missing method in androidx.fragment.app.FragmentManager: void <clinit>() at androidx.fragment.app.FragmentManager.<clinit>(Unknown Source:9) at androidx.fragment.app.FragmentHostCallback.<init>(SourceFile:4) at androidx.fragment.app.FragmentHostCallback.<init>(SourceFile:2) at androidx.fragment.app.FragmentActivity$HostCallbacks.<init>(SourceFile:2) at androidx.fragment.app.FragmentActivity.<init>(SourceFile:2) at androidx.appcompat.app.AppCompatActivity.<init>(SourceFile:1) at main.MainActivity.<init>(SourceFile:1)
当前配置
Proguard规则(proguard-rules.pro)
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable -keepattributes *Annotation* -keepattributes RuntimeVisibleAnnotations,AnnotationDefault -keepattributes SourceFile,LineNumberTable -renamesourcefileattribute SourceFile -if @kotlinx.serialization.Serializable class ** -keepclassmembers class <1> { static <1>$Companion Companion; } -if @kotlinx.serialization.Serializable class ** { static **$* *; } -keepclassmembers class <2>$<3> { kotlinx.serialization.KSerializer serializer(...); } -if @kotlinx.serialization.Serializable class ** { public static ** INSTANCE; } -keepclassmembers class <1> { public static <1> INSTANCE; kotlinx.serialization.KSerializer serializer(...); } -keep @kotlinx.android.parcel.Parcelize public class * -keep @kotlinx.parcelize.Parcelize public class * -keep class retrofit2.** { *; } -keepclasseswithmembers class * { @retrofit2.http.* <methods>; } -keep class okhttp3.** { *; } -keep interface okhttp3.** { *; }
Gradle构建配置
defaultConfig { minSdk 24 targetSdk 32 } buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } }
核心疑问
如何确定哪些类/方法被Proguard剥离了?
解决方案与排查步骤
一、先修复当前的FragmentManager错误
从错误日志看,androidx.fragment.app.FragmentManager的静态初始化方法(<clinit>)被Proguard的优化规则移除了。这是因为你使用了proguard-android-optimize.txt,其中的优化规则会主动移除它认为“无用”的静态初始化逻辑,但FragmentManager的<clinit>是框架初始化必需的。
直接在Proguard规则里添加以下配置即可修复:
-keep class androidx.fragment.app.FragmentManager { static <clinit>(); }
或者更稳妥的方式,添加AndroidX Fragment库的官方Proguard规则:
-keep class androidx.fragment.app.** { *; } -keep interface androidx.fragment.app.** { *; }
二、排查被剥离的类/方法的具体步骤
1. 查看Proguard自动生成的映射文件
构建Release版本后,在app/build/outputs/mapping/release/目录下会生成几个关键文件:
mapping.txt:记录原始类/方法名与混淆后名称的映射usage.txt:最关键,明确标注了Proguard移除的所有类、方法、字段,被移除的内容会标记为[removed]seeds.txt:记录被Proguard保留的类/方法/字段
直接打开usage.txt,搜索目标类名(比如FragmentManager),就能看到它的哪些成员被标记为移除。
2. 启用Proguard详细日志
在proguard-rules.pro开头添加以下规则,生成更详细的移除记录:
-verbose -printusage build/outputs/mapping/release/custom_usage.txt
构建后打开custom_usage.txt,可以看到更细致的代码移除逻辑,方便精准定位问题。
3. 反编译APK验证
用APK反编译工具(比如jadx)打开Release版本的APK,查看目标类的代码结构,确认是否存在被怀疑移除的方法或字段。如果不存在,说明确实被Proguard移除了。
三、额外建议
- 对于AndroidX库,尽量不要手动编写Proguard规则,大部分主流库会在aar包中自带
proguard.txt,Gradle会自动导入这些规则 proguard-android-optimize.txt的优化强度比默认的proguard-android.txt更高,容易误删框架必需的代码,建议先测试默认规则是否能正常工作
内容的提问来源于stack exchange,提问作者arshcaptano
相关产品推荐
相关产品推荐

