Mobile Development 27 min read

Why We Switched from Proguard to R8 in WeChat Android: Benefits, Challenges, and Solutions

This article explains how WeChat Android moved from Proguard to R8, detailing the performance and size gains, the new build workflow, the numerous optimization pitfalls encountered, and the concrete fixes applied to ensure stable releases and smaller Tinker patches.

WeChat Client Technology Team
WeChat Client Technology Team
WeChat Client Technology Team
Why We Switched from Proguard to R8 in WeChat Android: Benefits, Challenges, and Solutions

Author: chrispaul, from the WeChat client team

Background

In previous versions, WeChat Android used Proguard to build release packages because:

Proguard optimization was stable.

ApplyMapping could guarantee correctness.

Combined with AutoDex it generated sufficiently small Tinker patches.

However Proguard also has obvious drawbacks:

Kotlin version upgrades are incompatible with Proguard, forcing Proguard version upgrades.

Proguard version upgrades increase compilation time beyond 30 minutes.

Historical keep rules prevent optimal package size.

With AGP upgrades, Google’s R8 becomes the default to obtain better APK performance.

Advantages of R8

Compared with Proguard, R8 offers:

Better support for Kotlin.

Build time: although we have incremental Proguard compilation, full‑build time with R8 is about 15 minutes, at least half of Proguard’s time.

Enabling R8 optimization reduces the APK size by at least 14 MB, which is the main reason for switching.

APK Build Process

AGP 7.2.2 Gradle 7.5

1. Build with Proguard

Explanation:

Proguard generates optimized Java bytecode and provides obfuscation.

During patch generation, ApplyMapping guarantees consistent obfuscation between builds.

AutoDex ensures that the Dalvik bytecode of successive builds is placed in the same dex sequence to produce the smallest possible Tinker patch.

2. After enabling R8

R8 skips the dex step and directly generates Dalvik bytecode. Because most WeChat releases use Tinker patches, R8 integration must provide ApplyMapping‑like capability and AutoDex‑like dex layout. R8 already supports ApplyMapping but does not provide dex re‑ordering, so supporting both ApplyMapping and dex layout is the key work.

Core Issues

When we first enabled R8 and ApplyMapping in WeChat, we encountered many runtime crashes, which can be divided into two categories:

Problems in the Optimize phase.

Crashes caused by the obfuscate phase after enabling ApplyMapping.

The following sections describe the most troublesome problems and their solutions.

Problem 1: Optimize Phase

1. Field access modified

We disabled field optimization with a !field/* rule, but R8 does not understand it, causing a field that should stay private to become public. The fix is to add -allowaccessmodification or change the subclass access to public.

2. InvokeDynamic causes class merging

Kotlin’s implicit interface calls generate invoke‑dynamic instructions, which R8 merges into a single class. Adding the compiler flag -Xsam-conversions=class prevents Kotlin from generating invoke‑dynamic, thus avoiding the merge.

3. Strong‑reference fields are shrunk

R8 shrinks strong‑reference fields that are used to keep callbacks alive. Adding a keep rule such as:

-keepclassmembers class * {
    private com.tencent.mm.ui.statusbar.StatusBarHeightWatcher$OnStatusBarHeightChangeCallback mStatusBarHeightCallback;
}

4. R8 line‑number optimization inflates Tinker DexDiff

Even a tiny code change can increase the patch size by ~20 MB because R8 optimizes line numbers at the end of the build. Three possible solutions are:

Remove debug info (harder to trace crashes).

Reuse previous line‑number results during ApplyMapping (maintenance heavy).

From API 26 onward, use instruction‑offset based line tables and compile with minSdkVersion 26 to drop line numbers entirely. We adopted this third solution.

5. Parameter optimization

R8 removes unused parameters, causing mismatched mappings. Example mapping snippet (omitted for brevity).

6. ProtoNormalizer creates duplicate methods

Horizontal/vertical merge can cause the same method to appear in different classes with identical mappings. Disabling this optimization adds ~1 MB to the APK.

7. Out‑Of‑Line optimization blocks Tinker patches

Out‑of‑line merges reuse a single method implementation across classes, but Tinker’s loader classes are kept with a keep rule that out‑of‑line does not respect. Disabling the optimization adds < 100 KB.

8. EnumUnBoxing causes inconsistent mapping

R8 unboxes enum classes, generating helper classes. We disable this as with Proguard, costing ~100 KB.

Obfuscated Phase

1. Activity classes get obfuscated

We kept public activities with -keep public class * extends android.app.Activity, but R8 only keeps public types, leaving non‑public activities obfuscated. Changing the rule to -keep class * extends android.app.Activity solves the issue.

2. ApplyMapping introduces many obfuscation problems

Three categories:

Duplicate methods leading to “Failure to verify dex file … Out‑of‑order method_ids”.

Interface methods missing implementations, causing AbstractMethodError.

Inner‑class access violations, causing IllegalAccessError.

These require case‑by‑case analysis and cannot be solved by a single switch.

We also describe the R8 ApplyMapping workflow with a diagram (image omitted).

Mapping interfaces, classes, default interface methods, minify classes, methods, fields, and the reservation logic are explained with code excerpts.

DexLayout

Android’s 65 535 limit on type/field/method IDs forces multi‑dex splitting, which affects patch size. AutoDex used to handle this, but after switching to R8 we re‑implemented Redex’s Interdex algorithm in C++ and used dexlib2 to analyze each class’s methods, fields, and types.

Conclusion

R8 is now stable in the latest WeChat Android version, with most issues resolved. It brings noticeable benefits in package size and cold‑start performance on low‑end devices. Feel free to discuss.

Reference: https://r8.googlesource.com/r8

For more WeChat client technology and development experience, follow the WeChat client technology team public account.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

AndroidR8build optimizationDEXProGuard
WeChat Client Technology Team
Written by

WeChat Client Technology Team

Official account of the WeChat mobile client development team, sharing development experience, cutting‑edge tech, and little‑known stories across Android, iOS, macOS, Windows Phone, and Windows.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.