Tidak dapat menjalankan dex: ID metode tidak dalam [0, 0xffff]: 65536

344

Saya telah melihat berbagai versi dex erros sebelumnya, tetapi yang ini baru. clean / restart dll tidak akan membantu. Proyek perpustakaan tampaknya masih utuh dan ketergantungan tampaknya terhubung dengan benar.

Unable to execute dex: method ID not in [0, 0xffff]: 65536
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536

atau

Cannot merge new index 65950 into a non-jumbo instruction

atau

java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

tl; dr : Solusi resmi dari Google akhirnya tiba!

http://developer.android.com/tools/building/multidex.html

Hanya satu tip kecil, Anda mungkin perlu melakukan ini untuk mencegah kehabisan memori ketika melakukan dex-ing.

dexOptions {
        javaMaxHeapSize "4g"
}

Ada juga mode jumbo yang dapat memperbaikinya dengan cara yang kurang andal:

dexOptions {
        jumboMode true
}

Pembaruan: Jika aplikasi Anda gemuk dan Anda memiliki terlalu banyak metode di dalam aplikasi utama Anda, Anda mungkin perlu meng-org ulang aplikasi Anda sesuai

http://blog.osom.info/2014/12/too-many-methods-in-main-dex.html

Edison
sumber
1
Apakah Anda menggunakan api yang tidak dapat digunakan pada perangkat saat ini?
rekire
Itu ada di sana, karena proyek lain membangun penargetan yang baik dengan versi API yang sama.
Edison
Jadi Anda menggunakan API di beberapa titik yang tidak tersedia? Apakah Anda memeriksa dengan garis seperti if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)itu Anda tidak memanggil fungsi ini jika tidak tersedia?
rekire
Ya saya lakukan. Proyek ini dibangun dengan baik sebelumnya. Juga, itu harus menjadi kesalahan runtime bahkan jika saya melewatkan garis.
Edison
Mungkin salah satu dependensi kacau. (melakukan campuran maven + project lib sekarang)
Edison

Jawaban:

379

Pembaruan 3 (11/3/2014)
Google akhirnya merilis deskripsi resmi .


Pembaruan 2 (31/10/2014)
Plugin Gradle v0.14.0 untuk Android menambahkan dukungan untuk multi-dex. Untuk mengaktifkan, Anda hanya perlu mendeklarasikannya di build.gradle :

android {
   defaultConfig {
      ...
      multiDexEnabled  true
   }
}

Jika aplikasi Anda mendukung Android sebelum 5.0 (yaitu, jika Anda minSdkVersionberusia 20 atau di bawah) Anda juga harus secara dinamis menambal ClassLoader aplikasi , sehingga akan dapat memuat kelas dari dexes sekunder. Untungnya, ada perpustakaan yang melakukan itu untuk Anda. Tambahkan ke dependensi aplikasi Anda:

dependencies {
  ...
  compile 'com.android.support:multidex:1.0.0'
} 

Anda perlu memanggil kode tambalan ClassLoader sesegera mungkin. dokumentasiMultiDexApplication kelas menyarankan tiga cara untuk melakukan itu (pilih salah satu dari mereka , satu yang paling nyaman bagi Anda):

1 - Deklarasikan MultiDexApplicationkelas sebagai aplikasi di AndroidManifest.xml Anda :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.multidex.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

2 - Mintalah Applicationkelas Anda memperluas kelas MultiDexApplication :

public class MyApplication extends MultiDexApplication { .. }

3 - Panggilan MultiDex#installdari Application#attachBaseContextmetode Anda :

public class MyApplication {
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
        ....
    }
    ....
}

Pembaruan 1 (10/17/2014):
Seperti yang diharapkan, dukungan multidex dikirimkan dalam revisi 21 dari Perpustakaan Dukungan Android. Anda dapat menemukan android-support-multidex.jar di / sdk / ekstra / android / support / multidex / library / libs folder.


Dukungan multi-dex memecahkan masalah ini. dx 1.8 sudah memungkinkan menghasilkan beberapa file dex.
Android L akan mendukung multi-dex secara asli, dan revisi berikutnya dari perpustakaan dukungan akan mencakup rilis yang lebih lama kembali ke API 4.

Hal itu dinyatakan dalam ini Android Developers Backstage episode podcast oleh Anwar Ghuloum. Saya telah memposting transkrip (dan penjelasan multi-dex umum) dari bagian yang relevan.

Alex Lipov
sumber
2
posting blog adalah penghemat! : D
nadavfima
39
Apa saja untuk pengguna gerhana?
Muhammad Babar
52
@MuhammadBabar Ada studio Android untuk pengguna Eclipse.
VipulKumar
2
@MohammedAli Tentu, hindari menggunakannya jika Anda bisa. Tapi apa yang harus Anda lakukan jika Anda benar-benar memiliki terlalu banyak metode dalam aplikasi Anda, dan Anda sudah mencoba semua trik seperti yang Anda sebutkan? Mengenai waktu pembangunan - ada solusi untuk ini, setidaknya untuk pembangunan sedang - lihat jawaban saya di sini: stackoverflow.com/a/30799491/1233652
Alex Lipov
2
Di Qt untuk Android, saya mengalami masalah saat runtime untuk aplikasi saya ketika mengintegrasikan Facebook + Twitter SDK bersama-sama, bahkan setelah mengaktifkan dukungan multidex (kesalahan yang satu ini khususnya memberi saya mimpi buruk :) java.lang.ClassNotFoundException: Didn't find class "org.qtproject.qt5.android.QtActivityDelegate" on path: DexPathList[[],nativeLibraryDirectories=[/vendor/lib, /system/lib]]). Ternyata kesalahan saya adalah saya tidak menerapkan langkah-langkah tambahan untuk dukungan Android sebelum versi 5.0. Dengan itu, opsi # 3 menyelesaikannya, dan saya tidak punya ClassNotFoundExceptionmasalah lagi . Terima kasih, @Alex Lipov!
merampok
78

Seperti yang telah dinyatakan, Anda memiliki terlalu banyak metode (lebih dari 65k) dalam proyek dan lib Anda.

Cegah Masalah: Kurangi jumlah metode dengan Play Services 6.5+ dan support-v4 24.2+

Karena seringkali layanan Google Play adalah salah satu tersangka utama dalam metode "wasting" dengan metode 20k + -nya . Layanan Google Play versi 6.5 atau yang lebih baru, adalah mungkin bagi Anda untuk memasukkan layanan Google Play dalam aplikasi Anda menggunakan sejumlah pustaka klien yang lebih kecil. Misalnya, jika Anda hanya membutuhkan GCM dan peta, Anda dapat memilih untuk menggunakan dependensi ini saja:

dependencies {
    compile 'com.google.android.gms:play-services-base:6.5.+'
    compile 'com.google.android.gms:play-services-maps:6.5.+'
}

Daftar lengkap sub perpustakaan dan tanggung jawabnya dapat ditemukan di google doc resmi .

Pembaruan : Karena Perpustakaan Dukungan v4 v24.2.0 itu dibagi menjadi beberapa modul berikut:

support-compat, support-core-utils, support-core-ui, support-media-compatDansupport-fragment

dependencies {
    compile 'com.android.support:support-fragment:24.2.+'
}

Namun perlu dicatat, jika Anda menggunakan support-fragment, itu akan memiliki dependensi ke semua modul lainnya (mis. Jika Anda menggunakan android.support.v4.app.Fragmenttidak ada manfaat)

Lihat di sini catatan rilis resmi untuk dukungan-v4 lib


Aktifkan MultiDexing

Karena Lollipop (alias membangun alat 21+) sangat mudah ditangani. Pendekatannya adalah mengatasi metode 65k per masalah file dex untuk membuat beberapa file dex untuk aplikasi Anda. Tambahkan berikut ini ke file build gradle Anda ( ini diambil dari google doc resmi pada aplikasi dengan lebih dari 65k metode ):

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.1'
}

Langkah kedua adalah mempersiapkan kelas Aplikasi Anda atau jika Anda tidak memperpanjang penggunaan Aplikasi MultiDexApplicationdalam Manifes Android Anda:

Tambahkan ini ke Application.java Anda

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

atau gunakan aplikasi yang disediakan dari mutlidex lib

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

Cegah OutOfMemory dengan MultiDex

Sebagai tip selanjutnya, jika Anda mengalami OutOfMemorypengecualian selama fase build Anda bisa memperbesar heap

android {
    ...
    dexOptions {
        javaMaxHeapSize "4g"
    }
}

yang akan mengatur tumpukan menjadi 4 gigabytes.

Lihat pertanyaan ini untuk detail lebih lanjut tentang masalah memori tumpukan dex.


Analisis sumber Masalah

Untuk menganalisis sumber metode, plugin gradle https://github.com/KeepSafe/dexcount-gradle-plugin dapat membantu dalam kombinasi dengan pohon dependensi yang disediakan oleh gradle dengan eg

.\gradlew app:dependencies

Lihat jawaban dan pertanyaan ini untuk informasi lebih lanjut tentang penghitungan metode di android

Patrick Favre
sumber
Saya telah menggunakan solusi Play Services 6.5+ dan berfungsi dengan baik. Tip bermanfaat yang luar biasa. Terima kasih banyak!
Hoang Nguyen Huu
Saya akan lebih banyak memilih jika saya bisa - menghapus semua hal Layanan Play lainnya yang tidak kami gunakan memperbaiki masalah ini, tanpa harus menggunakan multi-dex, yang memiliki implikasi kinerja negatif ketika membangun.
Sean Barbeau
1
Terima kasih banyak dengan air mata di mataku. Anda menyelamatkan saya
insomnia
Saya menggunakan pustaka klien untuk GCM, karena saya hanya menggunakan layanan gcm dari layanan play, sekarang ini memperbaiki masalah saya dengan ini. Terima kasih! untuk menghemat waktu saya.
Ankit
57

Proyek Anda terlalu besar. Anda memiliki terlalu banyak metode. Hanya ada 65536 metode per aplikasi. lihat di sini https://code.google.com/p/android/issues/detail?id=7147#c6

blobbie
sumber
Saya melihat. Saya punya banyak dependensi untuk proyek ini. Itu membangun dengan baik sebelum saya pindah untuk menggunakan pakar, mungkin pakar menambahkan dependensi yang tidak perlu. Akan mengecek.
Edison
5
Untuk lebih spesifik, hanya ada 65.536 metode per file executable (dex) Dalvik. Dan aplikasi (APK) dapat memiliki lebih dari satu file dex dengan hal-hal seperti pemuatan kustom.
Dennis Sheil
7
Ini benar-benar bug yang memalukan untuk android! Bagaimanapun, Dalam kasus saya, saya menghapus Jar yang ada di libs dan tidak digunakan, dan aplikasi dikompilasi
David
Saatnya membersihkan proyek saya: /
Umpan
1
Perbaikan cepat akan menggunakan Proguard juga dengan build debug
aleb
12

Kode di bawah ini membantu, jika Anda menggunakan Gradle. Memungkinkan Anda dengan mudah menghapus layanan Google yang tidak dibutuhkan (dengan anggapan Anda menggunakannya) untuk kembali di bawah ambang batas 65 ribu. Semua kredit untuk posting ini: https://gist.github.com/dmarcato/d7c91b94214acd936e42

Sunting 2014-10-22 : Ada banyak diskusi menarik tentang inti yang dirujuk di atas. TLDR? lihat yang ini: https://gist.github.com/Takhion/10a37046b9e6d259bb31

Rekatkan kode ini di bagian bawah file build.gradle Anda dan sesuaikan daftar layanan google yang tidak Anda butuhkan:

def toCamelCase(String string) {
    String result = ""
    string.findAll("[^\\W]+") { String word ->
        result += word.capitalize()
    }
    return result
}

afterEvaluate { project ->
    Configuration runtimeConfiguration = project.configurations.getByName('compile')
    ResolutionResult resolution = runtimeConfiguration.incoming.resolutionResult
    // Forces resolve of configuration
    ModuleVersionIdentifier module = resolution.getAllComponents().find { it.moduleVersion.name.equals("play-services") }.moduleVersion

    String prepareTaskName = "prepare${toCamelCase("${module.group} ${module.name} ${module.version}")}Library"
    File playServiceRootFolder = project.tasks.find { it.name.equals(prepareTaskName) }.explodedDir

    Task stripPlayServices = project.tasks.create(name: 'stripPlayServices', group: "Strip") {
        inputs.files new File(playServiceRootFolder, "classes.jar")
        outputs.dir playServiceRootFolder
        description 'Strip useless packages from Google Play Services library to avoid reaching dex limit'

        doLast {
            copy {
                from(file(new File(playServiceRootFolder, "classes.jar")))
                into(file(playServiceRootFolder))
                rename { fileName ->
                    fileName = "classes_orig.jar"
                }
            }
            tasks.create(name: "stripPlayServices" + module.version, type: Jar) {
                destinationDir = playServiceRootFolder
                archiveName = "classes.jar"
                from(zipTree(new File(playServiceRootFolder, "classes_orig.jar"))) {
                    exclude "com/google/ads/**"
                    exclude "com/google/android/gms/analytics/**"
                    exclude "com/google/android/gms/games/**"
                    exclude "com/google/android/gms/plus/**"
                    exclude "com/google/android/gms/drive/**"
                    exclude "com/google/android/gms/ads/**"
                }
            }.execute()
            delete file(new File(playServiceRootFolder, "classes_orig.jar"))
        }
    }

    project.tasks.findAll { it.name.startsWith('prepare') && it.name.endsWith('Dependencies') }.each { Task task ->
        task.dependsOn stripPlayServices
    }
}
mcm
sumber
Suka! Def diperlukan karena perusahaan seperti Google terus menggembungkan paket.
Edison
1
Bagus - ini berhasil. Tidak ada hasswle dan tidak perlu khawatir!
slot
Catatan: stoples layanan google play yang dihapus ini di Android SDK saya di Android Studio! Ide yang buruk karena tidak mudah untuk kembali ke toples asli. Penulis harus memodifikasi skrip untuk mengubah toples di direktori build.
inder
@inder: Saya tidak punya masalah itu. Namun, saya harus melakukan cleansetiap kali saya menggunakan pengecualian (kami menggunakan analitik).
JohnnyLambada
bagaimana cara mengecualikan ini dari rilis build?
user1324936
6

Saya telah membagikan contoh proyek yang menyelesaikan masalah ini menggunakan custom_rules.xml build script dan beberapa baris kode.

Saya menggunakannya pada proyek saya sendiri dan dijalankan tanpa cacat pada perangkat 1M + (dari android-8 ke android-19 terbaru). Semoga ini bisa membantu.

https://github.com/mmin18/Dex65536

mmin
sumber
1
Terima kasih untuk skripnya. Anda harus waspada terhadap ART. Perangkat hanya dapat mengkonversi dex default Anda dan bukan yang sekunder. Solusi proguard harus lebih disukai.
Edison
2
Ketika saya mengimpor proyek ke Eclipse dan menjalankannya memberikan kesalahan. "Tidak dapat menjalankan dex: ID metode tidak dalam [0, 0xffff]: 65536". Bisakah Anda menjelaskan penggunaan proyek
Karacago
6

Menghadapi masalah yang sama dan menyelesaikannya dengan mengedit file build.gradle saya di bagian dependensi, menghapus:

compile 'com.google.android.gms:play-services:7.8.0'

Dan menggantinya dengan:

compile 'com.google.android.gms:play-services-location:7.8.0'
compile 'com.google.android.gms:play-services-analytics:7.8.0' 
Luis Miguel Ballestas
sumber
Sempurna! Saya hanya menggunakan Google Drive API dan ini berfungsi.
vedavis
5

Coba tambahkan kode di bawah ini di build.gradle, itu berhasil untuk saya -

compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
    multiDexEnabled true
}
Sunita
sumber
2

Solusi sempurna untuk ini adalah bekerja dengan Proguard. seperti yang disebutkan aleb dalam komentar. Ini akan mengurangi ukuran file dex hingga setengahnya.

shimi_tap
sumber
1
Setuju, dengan toples layanan bermain google yang semakin besar terutama * (metode 18k dengan sendirinya)
Edison
2

Anda dapat menganalisis masalah (referensi file dex) menggunakan Android Studio:

Bangun -> Analisis APK ..

Pada panel hasil klik pada file classes.dex

Dan Anda akan melihat:

masukkan deskripsi gambar di sini

alexshr
sumber
0

solusi gradle + proguard:

afterEvaluate {
  tasks.each {
    if (it.name.startsWith('proguard')) {
        it.getInJarFilters().each { filter ->
            if (filter && filter['filter']) {
                filter['filter'] = filter['filter'] +
                        ',!.readme' +
                        ',!META-INF/LICENSE' +
                        ',!META-INF/LICENSE.txt' +
                        ',!META-INF/NOTICE' +
                        ',!META-INF/NOTICE.txt' +
                        ',!com/google/android/gms/ads/**' +
                        ',!com/google/android/gms/cast/**' +
                        ',!com/google/android/gms/games/**' +
                        ',!com/google/android/gms/drive/**' +
                        ',!com/google/android/gms/wallet/**' +
                        ',!com/google/android/gms/wearable/**' +
                        ',!com/google/android/gms/plus/**' +
                        ',!com/google/android/gms/topmanager/**'
            }
        }
    }
  }
}
Oleg Khalidov
sumber
0

Hapus beberapa file jar dari folder Libs dan salin ke folder lain, Dan Pergi ke _Proyek Properti> Pilih Java Build Path, Pilih Perpustakaan, Pilih Tambah Jar eksternal, Pilih jar Dihapus untuk proyek Anda, Klik simpan, ini akan ditambahkan di bawah Dirujuk Perpustakaan bukannya folder Libs. Sekarang bersihkan dan Jalankan proyek Anda. Anda tidak perlu menambahkan kode apa pun untuk MultDex. Itu hanya bekerja untuk saya.

Lakshmanan
sumber
0

Saya menghadapi masalah yang sama hari ini apa yang berhasil di bawah

Untuk ANDROID STUDIO ... Aktifkan Jalankan Instan

Di File-> Preferences-> Build, Execution, Deployment-> Instant Run-> Centang Aktifkan Instant run untuk hot swap ...

Semoga ini bisa membantu

Abdul Waheed
sumber
1
Ini berfungsi untuk saya - Saya cukup menonaktifkan Aktifkan Jalankan, klik Terapkan, aktifkan kembali, dan itu berfungsi lagi.
MrBigglesworth