Release build ClassNotFoundException not in debug: cause and file?

Tests R8 shrinking awareness: release-only obfuscation removes classes loaded by reflection. Check proguard-rules.pro first and add a -keep rule. Red flag: blaming multidex or disabling minification rather than writing a targeted keep rule.
What's really being asked
This question tests whether you understand the difference between debug and release Android builds regarding code shrinking. Specifically, it checks if you know that R8 runs by default in release builds to shrink, obfuscate, and optimize code, and that this process can break dynamic class loading mechanisms like reflection, JNI, or serialization where class names are referenced as strings. It also checks if you know the standard location for keep rules.
The full answer
First, state that R8 code shrinking and obfuscation is enabled in release but typically disabled in debug. Second, explain that ClassNotFoundException in release almost always means the class was removed as dead code or renamed by obfuscation because R8 cannot trace the reference, usually due to reflection, ServiceLoader, Gson, or JNI usage. Third, name proguard-rules.pro as the first file to investigate, though you might also mention consumer-rules.pro if the issue is in a library module. Fourth, describe the fix: adding a targeted -keep rule to preserve the class name and members, such as -keep class com.example.MyClass, and then rebuilding. Optionally mention using -keepnames if you only need to prevent renaming but not removal.
The mistakes people make
Blaming multidex is a red flag because multidex issues manifest differently and are unrelated to code shrinking. Suggesting you disable minification or shrinkResources in build.gradle to fix the symptom rather than the cause shows a lack of understanding of release optimization. Confusing ProGuard with R8 is minor but outdated; saying you would look at build.gradle first instead of the rules file misses the point. Another red flag is suggesting you deobfuscate the stack trace before fixing the crash; while mapping.txt is useful for reading logs, it does not fix the underlying missing class.
What usually comes next
An interviewer might ask how you would identify the missing class if the stack trace is obfuscated, in which case you would use the mapping.txt file from the build outputs. They might ask for the difference between -keep, -keepnames, and -keepclassmembers, so you should know that -keep preserves the entire class from shrinking and obfuscation, -keepnames only prevents renaming if the class is kept, and -keepclassmembers preserves members but not the class name. They might also ask how library modules expose their own rules, which is via consumerProguardFiles pointing to consumer-rules.pro.
A concrete example
Suppose you use Gson to deserialize JSON into a data class com.example.model.User that has no direct constructor calls in your Kotlin code. In debug, the class exists and Gson finds it via reflection. In release, R8 sees no static references to User and removes it or renames it to something like a.b.c. The app crashes with ClassNotFoundException. You open proguard-rules.pro and add a -keep rule for com.example.model.User, or better, for the entire com.example.model package, then rebuild the release APK.
Interview question
An app crashes with ClassNotFoundException in release but not debug. The class is only referenced via reflection. What is the most appropriate first step to fix it?
- a.Inspect proguard-rules.pro and add a targeted -keep rule for the reflected classCorrect
- b.Deobfuscate the stack trace using mapping.txt to identify the missing class name
- c.Enable multidex in build.gradle because the app has exceeded the DEX method limit
- d.Disable minification and shrinkResources in build.gradle to match debug behavior
Why? this is the answer
R8 removes or renames classes it cannot statically trace, such as those loaded via reflection, so the correct fix is to add a -keep rule in proguard-rules.pro. Disabling minification is a tempting distractor because it stops the crash, but it sacrifices release optimizations instead of solving the underlying issue.
Just read this? Test yourself on what you have been reading.
Read the original → developer.android.com
- #android
- #r8
- #code-shrinking
- #release-builds
- #classnotfoundexception
Put your scrolling time to good use
Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on android — each one lists the topics its interview covers.
See open roles