Skip to content

Fix IncompatibleClassChangeError when hardening Compose apps with --k…#186

Merged
luoyesiqiu merged 2 commits into
luoyesiqiu:mainfrom
blackandwhiteforzj:fix/keep-classes-compose-incompatibleclasschange
Jun 16, 2026
Merged

Fix IncompatibleClassChangeError when hardening Compose apps with --k…#186
luoyesiqiu merged 2 commits into
luoyesiqiu:mainfrom
blackandwhiteforzj:fix/keep-classes-compose-incompatibleclasschange

Conversation

@blackandwhiteforzj

Copy link
Copy Markdown

Root cause

With --keep-classes, splitDex re-partitions each dex with dexlib2 (read →
write), splitting classes into a separate "keep" dex and reorganizing the
remaining dex. This changes the dex membership/type tables of Compose classes
and breaks ART's cross-dex linking of interface default-method calls (e.g.
DrawScope), causing IncompatibleClassChangeError.
Without -K, dexes are not re-partitioned (only clinit injection + byte-level
method extraction, both of which preserve class layout), so Compose works fine.

Fix

Skip splitting entirely for any dex that contains "keep-in-place" classes
(currently Landroidx/compose/):

  • DexUtils.dexContainsKeepInPlace(File) detects such dexes.
  • AndroidPackage.extractDexCode skips splitDex for them; they still go
    through method extraction (matched classes are skipped as before), keeping
    the original class layout intact.
  • Dexes without Compose classes are still split, preserving the -K startup
    optimization.
    The prefix list (KEEP_IN_PLACE_PREFIXES) is easy to extend if other
    frameworks hit the same issue.

@luoyesiqiu luoyesiqiu merged commit e69c356 into luoyesiqiu:main Jun 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants