Sửa lỗi "The number of method references in a .dex file cannot exceed 64K" (DexIndexOverflowException)

intermediate📱 Android2026-05-06| Android Studio (mọi phiên bản), Gradle 3.x–8.x, Android API 19–34, dự án Java/Kotlin

Error Message

com.android.dex.DexIndexOverflowException: method ID not in [0, ffff]: 65536
#gradle#multidex#android-studio#build-error

TL;DR

Ứng dụng của bạn — bao gồm tất cả các thư viện được kéo vào — đã vượt quá 65.536 tham chiếu phương thức. Đó là giới hạn cứng của một file DEX đơn. Cách khắc phục phụ thuộc vào minSdk của bạn:

  • minSdk < 21: Bật MultiDex trong build.gradle và kế thừa MultiDexApplication.
  • minSdk ≥ 21: ART xử lý nhiều file DEX theo cách tự nhiên. Đặt multiDexEnabled true là xong.
  • Dù trường hợp nào, hãy bật tính năng thu gọn R8. Nó sẽ cắt giảm đáng kể số lượng tham chiếu trong các bản build release.

Lỗi cụ thể

AGPBI: {"kind":"error","text":"The number of method references in a .dex file cannot exceed 64K.",
"sources":[{}],"tool":"Dexer"}
...
com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

Lỗi này xảy ra trong quá trình build Gradle — cụ thể là ở bước dexing, sau khi quá trình biên dịch đã hoàn tất thành công. Thường xuất hiện ngay sau khi bạn thêm một dependency nặng: Firebase, Google Play Services, hoặc bộ Retrofit + OkHttp đầy đủ là những nguyên nhân phổ biến nhất.

Nguyên nhân

Định dạng DEX sử dụng chỉ mục 16-bit để tham chiếu các phương thức. Điều đó giới hạn tối đa chính xác 65.536 (0xFFFF + 1) — không có ngoại lệ. Các ứng dụng hiện đại vượt qua con số này nhanh hơn bạn nghĩ. Chỉ riêng Google Play Services đã từng tiêu tốn khoảng 20.000 tham chiếu; thêm Retrofit, Room và vài module Firebase là bạn đã vượt giới hạn trước khi viết một dòng logic nghiệp vụ nào.

Muốn kiểm tra tình trạng trước khi build thất bại? Hãy cài đặt plugin dexcount:

# build.gradle (project level)
buildscript {
    dependencies {
        classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:4.0.0'
    }
}

# build.gradle (app level)
apply plugin: 'com.getkeepsafe.dexcount'

Sau đó chạy ./gradlew assembleDebug — plugin sẽ in ra bảng phân tích số lượng phương thức theo từng package trong output build.

Cách khắc phục 1 — minSdk ≥ 21 (đơn giản nhất)

ART (Android 5.0+) tải nhiều file DEX ngay từ đầu mà không cần cấu hình thêm. Chỉ cần một flag duy nhất:

// app/build.gradle
android {
    defaultConfig {
        minSdk 21
        multiDexEnabled true
    }
}

Không cần dependency bổ sung. Không cần thay đổi class Application. Sync và rebuild là xong.

Cách khắc phục 2 — minSdk < 21 (hỗ trợ thiết bị cũ)

Các thiết bị Dalvik cũ hơn cần thư viện hỗ trợ MultiDex được kết nối thủ công.

Bước 1 — thêm dependency:

// app/build.gradle
android {
    defaultConfig {
        minSdk 16
        multiDexEnabled true
    }
}

dependencies {
    implementation 'androidx.multidex:multidex:2.0.1'
}

Bước 2 — cập nhật class Application của bạn.

Tùy chọn A — kế thừa trực tiếp từ MultiDexApplication (cách dễ nhất nếu bạn chưa có class base tùy chỉnh):

// Kotlin
class MyApp : MultiDexApplication() {
    // code hiện tại của bạn
}

// Java
public class MyApp extends MultiDexApplication {
    // code hiện tại của bạn
}

Tùy chọn B — override attachBaseContext thay thế (dùng cách này nếu bạn đã kế thừa từ class khác và không thể thay đổi class cha):

// Kotlin
class MyApp : SomeOtherBaseApp() {
    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }
}

// Java
@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}

Bước 3 — đăng ký trong AndroidManifest.xml nếu bạn chưa sử dụng Application mặc định:

<application
    android:name=".MyApp"
    ...>

Cách khắc phục 3 — thu gọn với R8 (áp dụng bất kể bạn chọn cách nào)

MultiDex giúp build thành công. Nhưng số lượng phương thức phình to vẫn gây hại — trên Android 4.x, việc tải nhiều file DEX khi khởi động lạnh có thể tốn thêm 200–500ms. R8 loại bỏ code thừa trước khi đến giai đoạn DEX:

// app/build.gradle
android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
                         'proguard-rules.pro'
        }
        debug {
            // Bật ở đây nếu bạn đang gần đến giới hạn 64K
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
                         'proguard-rules.pro'
        }
    }
}

R8 là mặc định trong AGP 3.4+. Với các cài đặt cũ hơn, thêm dòng này vào gradle.properties:

android.enableR8=true

Cách khắc phục 4 — kiểm tra lại các dependency

Đôi khi vấn đề thực sự là bạn đang import nhiều hơn những gì thực sự dùng. Một số thủ phạm phổ biến:

  • Bộ monolith Google Play Services: com.google.android.gms:play-services kéo vào mọi thứ (~36K tham chiếu). Chỉ import những gì cần — play-services-maps cho Maps, play-services-auth cho đăng nhập, v.v.
  • Dependency transitive trùng lặp: Chạy ./gradlew app:dependencies và tìm các thư viện xuất hiện ở nhiều phiên bản. Mỗi bản trùng lặp đều cộng vào tổng số đếm.
  • Thư viện support cũ: Nếu bạn vẫn dùng com.android.support, việc chuyển sang AndroidX thường giảm được số lượng tham chiếu — các artifact được viết lại nhỏ gọn hơn.
# Cây dependency đầy đủ cho bản build release
./gradlew app:dependencies --configuration releaseRuntimeClasspath

# Số lượng phương thức theo từng package (yêu cầu plugin dexcount)
./gradlew assembleDebug

Kiểm tra xem cách khắc phục đã hoạt động chưa

  • Chạy ./gradlew assembleDebug — lỗi DexIndexOverflowException phải biến mất.
  • Kiểm tra output build để tìm thông báo 1 DEX file written hoặc 2 DEX files written nhằm xác nhận MultiDex đã hoạt động.
  • Kiểm tra trên thiết bị hoặc emulator Android 4.x (nếu bạn hỗ trợ pre-21) và đảm bảo ứng dụng khởi động không bị lỗi ClassNotFoundException.
  • Mở Build → Analyze APK trong Android Studio để kiểm tra kích thước DEX và số lượng phương thức theo từng package.

Các vấn đề thường gặp sau khi bật MultiDex

  • Khởi động lạnh chậm trên Android < 5.0: Lần khởi chạy đầu tiên sẽ giải nén các file DEX phụ từ APK — quá trình này có thể mất 2–5 giây trên phần cứng cấu hình thấp. Sử dụng splash screen hoặc trì hoãn việc khởi tạo để che giấu độ trễ.
  • ClassNotFoundException khi chạy: Các class được tải trước class Application (ví dụ ContentProvider tùy chỉnh) có thể nằm trong DEX phụ. Ghim chúng vào DEX chính bằng multiDexKeepProguard hoặc multiDexKeepFile.
  • Incremental build vẫn thất bại: Cache DEX cũ có thể gây ra lỗi ảo sau khi bạn thêm MultiDex. Chạy ./gradlew clean và thực hiện full rebuild.
# Ghim một class vào DEX chính:
# app/build.gradle
android {
    defaultConfig {
        multiDexEnabled true
        multiDexKeepFile file('multidex-config.txt')
    }
}

# multidex-config.txt
com/example/MyContentProviderHelper.class

Related Error Notes