Dex: method ID kann nicht ausgeführt werden, nicht in [0, 0xffff]: 65536

344

Ich habe schon verschiedene Versionen der Dex-Erros gesehen, aber diese ist neu. Reinigen / Neustarten usw. wird nicht helfen. Bibliotheksprojekte scheinen intakt zu sein und die Abhängigkeit scheint korrekt verknüpft zu sein.

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

oder

Cannot merge new index 65950 into a non-jumbo instruction

oder

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

tl; dr : Die offizielle Lösung von Google ist endlich da!

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

Nur ein kleiner Tipp, Sie müssen dies wahrscheinlich tun, um zu verhindern, dass beim Dexen nicht genügend Speicherplatz zur Verfügung steht.

dexOptions {
        javaMaxHeapSize "4g"
}

Es gibt auch einen Jumbo-Modus, der dies weniger zuverlässig beheben kann:

dexOptions {
        jumboMode true
}

Update: Wenn Ihre App fett ist und Sie zu viele Methoden in Ihrer Haupt-App haben, müssen Sie Ihre App möglicherweise gemäß den Anforderungen neu organisieren

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

Edison
quelle
1
Verwenden Sie eine API, die auf Ihrem aktuellen Gerät nicht verfügbar ist?
rekire
Es ist da, weil ein anderes Projekt gut auf dieselbe API-Version abzielt.
Edison
Sie verwenden also irgendwann eine API, die nicht verfügbar ist? Prüfen Sie mit einer solchen Zeile, if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)dass Sie diese Funktion nicht aufrufen, wenn sie nicht verfügbar ist?
rekire
Ja, das mache ich. Das Projekt wurde schon früher gut gebaut. Das sollte auch ein Laufzeitfehler sein, selbst wenn ich die Zeile verpasst habe.
Edison
Es ist wahrscheinlich eine der Abhängigkeiten ist durcheinander. (macht gerade eine Mischung aus Maven + Project Lib)
Edison

Antworten:

379

Update 3 (03.11.2014)
Google hat endlich die offizielle Beschreibung veröffentlicht .


Update 2 (31.10.2014) Das
Gradle-Plugin v0.14.0 für Android bietet Unterstützung für Multi-Dex. Zum Aktivieren müssen Sie es nur in build.gradle deklarieren :

android {
   defaultConfig {
      ...
      multiDexEnabled  true
   }
}

Wenn Ihre Anwendung Android vor 5.0 unterstützt ( dh wenn Sie minSdkVersion20 Jahre oder jünger sind ), müssen Sie die Anwendung ClassLoader auch dynamisch patchen , damit Klassen aus sekundären Dexes geladen werden können. Glücklicherweise gibt es eine Bibliothek , die das für Sie erledigt. Fügen Sie es den Abhängigkeiten Ihrer App hinzu:

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

Sie müssen den ClassLoader-Patchcode so schnell wie möglich aufrufen. MultiDexApplicationIn der Dokumentation der Klasse werden drei Möglichkeiten vorgeschlagen (wählen Sie eine davon aus , eine, die für Sie am bequemsten ist):

1 - Deklarieren Sie die MultiDexApplicationKlasse als Anwendung in Ihrer AndroidManifest.xml :

<?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 - Lassen Sie Ihre ApplicationKlasse die MultiDexApplication- Klasse erweitern:

public class MyApplication extends MultiDexApplication { .. }

3 - Aufruf MultiDex#installvon Ihrer Application#attachBaseContextMethode:

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

Update 1 (17.10.2014):
Wie erwartet wird die Multidex-Unterstützung in Version 21 der Android Support Library ausgeliefert. Sie finden die Datei android-support-multidex.jar im Ordner / sdk / extras / android / support / multidex / library / libs.


Multi-Dex-Unterstützung löst dieses Problem. Mit dx 1.8 können bereits mehrere Dex-Dateien generiert werden.
Android L wird Multi-Dex nativ unterstützen, und die nächste Überarbeitung der Support-Bibliothek wird ältere Versionen zurück zu API 4 abdecken.

Es wurde in dieser Android Developers Backstage-Podcast-Episode von Anwar Ghuloum angegeben. Ich habe ein Transkript (und eine allgemeine Multi-Dex-Erklärung) des relevanten Teils veröffentlicht.

Alex Lipov
quelle
2
Blog-Post ist ein Sparer! : D
Nadavfima
39
Etwas für Eclipse-Benutzer?
Muhammad Babar
52
@ MuhammadBabar Es gibt Android Studio für Eclipse-Benutzer.
VipulKumar
2
@MohammedAli Sicher, vermeiden Sie es, wenn Sie können. Aber was sollten Sie tun, wenn Ihre App wirklich zu viele Methoden enthält und Sie bereits alle Tricks wie den von Ihnen erwähnten ausprobiert haben? In Bezug auf die Build-Zeit - es gibt eine Lösung dafür, zumindest für Entwicklungs-Builds - siehe meine Antwort hier: stackoverflow.com/a/30799491/1233652
Alex Lipov
2
Unter Qt für Android hatte ich zur Laufzeit Probleme mit meiner App, als ich die SDKs von Facebook + Twitter zusammen integrierte, selbst nachdem ich die Multidex-Unterstützung aktiviert hatte (dieser eine Fehler verursachte mir Albträume :) java.lang.ClassNotFoundException: Didn't find class "org.qtproject.qt5.android.QtActivityDelegate" on path: DexPathList[[],nativeLibraryDirectories=[/vendor/lib, /system/lib]]. Es stellte sich heraus, dass mein Fehler darin bestand, dass ich die zusätzlichen Schritte für die Android-Unterstützung vor 5.0 nicht angewendet habe. Nachdem dies gesagt wurde, löste Option 3 es und ich hatte keine ClassNotFoundExceptionProbleme mehr . Danke, @Alex Lipov!
Rob
78

Wie bereits erwähnt, haben Sie zu viele Methoden (mehr als 65 KB) in Ihrem Projekt und Ihren Bibliotheken.

Verhindern Sie das Problem: Reduzieren Sie die Anzahl der Methoden mit Play Services 6.5+ und support-v4 24.2+

Da die Google Play-Dienste mit ihren über 20.000 Methoden häufig einer der Hauptverdächtigen bei der "Verschwendung" von Methoden sind . Mit Google Play-Diensten Version 6.5 oder höher können Sie Google Play-Dienste mithilfe einer Reihe kleinerer Client-Bibliotheken in Ihre Anwendung aufnehmen. Wenn Sie beispielsweise nur GCM und Karten benötigen, können Sie nur diese Abhängigkeiten verwenden:

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

Die vollständige Liste der Unterbibliotheken und ihrer Verantwortlichkeiten finden Sie im offiziellen Google-Dokument .

Update : Seit Support Library v4 v24.2.0 wurde es in folgende Module aufgeteilt:

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

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

Beachten Sie jedoch, dass bei Verwendung support-fragmentAbhängigkeiten zu allen anderen Modulen bestehen (dh wenn Sie diese verwenden, android.support.v4.app.Fragmentgibt es keinen Vorteil).

Hier finden Sie die offiziellen Versionshinweise für support-v4 lib


Aktivieren Sie MultiDexing

Seit Lollipop (auch bekannt als Build Tools 21+) ist es sehr einfach zu handhaben. Der Ansatz besteht darin, das Problem mit 65.000 Methoden pro Dex-Datei zu umgehen, um mehrere Dex-Dateien für Ihre App zu erstellen. Fügen Sie Ihrer Gradle-Build-Datei Folgendes hinzu ( dies stammt aus dem offiziellen Google-Dokument für Anwendungen mit mehr als 65.000 Methoden ):

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

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

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

Der zweite Schritt besteht darin, entweder Ihre Anwendungsklasse vorzubereiten oder, wenn Sie die Anwendung nicht erweitern, Folgendes MultiDexApplicationin Ihrem Android-Manifest zu verwenden:

Fügen Sie dies entweder Ihrer Application.java hinzu

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

oder verwenden Sie die bereitgestellte Anwendung aus der 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>

Verhindern Sie OutOfMemory mit MultiDex

Als weiterer Tipp: Wenn Sie OutOfMemorywährend der Erstellungsphase auf Ausnahmen stoßen, können Sie den Heap mit vergrößern

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

das würde den Heap auf 4 Gigabyte setzen.

In dieser Frage finden Sie weitere Informationen zum Problem mit dem Dex-Heapspeicher.


Analysieren Sie die Ursache des Problems

Um die Quelle der Methoden zu analysieren, kann das Gradle-Plugin https://github.com/KeepSafe/dexcount-gradle-plugin in Kombination mit dem von gradle bereitgestellten Abhängigkeitsbaum mit z

.\gradlew app:dependencies

In dieser Antwort und Frage finden Sie weitere Informationen zur Anzahl der Methoden in Android

Patrick Favre
quelle
Ich habe die Play Services 6.5+ -Lösung verwendet und sie hat perfekt funktioniert. Unglaublich nützlicher Tipp. Vielen Dank!
Hoang Nguyen Huu
Ich würde mehr Stimmen abgeben, wenn ich könnte - das Ausschneiden aller anderen Play Services-Inhalte, die wir nicht verwendet haben, hat dieses Problem behoben, ohne auf Multi-Dex zurückgreifen zu müssen, was negative Auswirkungen auf die Leistung beim Erstellen hat.
Sean Barbeau
1
Als du so sehr mit Tränen in meinen Augen. Du hast mich gerettet
Schlaflosigkeit
Ich habe die Client-Bibliothek für GCM verwendet, da ich nur den gcm-Dienst vom Play-Dienst verwende. Jetzt wurde mein Problem damit behoben. Vielen Dank! um meine Zeit zu sparen.
Ankit
57

Ihr Projekt ist zu groß. Sie haben zu viele Methoden. Es können nur 65536 Methoden pro Anwendung vorhanden sein. siehe hier https://code.google.com/p/android/issues/detail?id=7147#c6

Blobbie
quelle
Aha. Ich habe viele Abhängigkeiten für dieses Projekt. Es funktioniert gut, bevor ich Maven verwendet habe. Vielleicht hat Maven unnötige Abhängigkeiten hinzugefügt. Wird noch einmal überprüfen.
Edison
5
Genauer gesagt kann es nur 65.536 Methoden pro ausführbarer Dalvik-Datei (Dex) geben. Und eine Anwendung (APK) kann mehr als eine Dex-Datei haben, beispielsweise mit benutzerdefiniertem Laden.
Dennis Sheil
7
Es ist wirklich peinlich Fehler für Android! Wie auch immer, in meinem Fall habe ich Jar entfernt, der in den Bibliotheken war und nicht verwendet wurde, und die App kompiliert
David
Zeit, mein Projekt aufzuräumen: /
Decoy
1
Eine schnelle Lösung wäre, Proguard auch mit den Debug-Builds zu verwenden
Aleb
12

Der folgende Code hilft, wenn Sie Gradle verwenden. Ermöglicht das einfache Entfernen nicht benötigter Google-Dienste (vorausgesetzt, Sie verwenden sie), um den Schwellenwert von 65.000 wieder zu unterschreiten. Alle Gutschriften für diesen Beitrag: https://gist.github.com/dmarcato/d7c91b94214acd936e42

Edit 2014-10-22 : Es gab viele interessante Diskussionen über das Wesentliche, auf das oben Bezug genommen wurde. TLDR? Schauen Sie sich diese an: https://gist.github.com/Takhion/10a37046b9e6d259bb31

Fügen Sie diesen Code am Ende Ihrer build.gradle-Datei ein und passen Sie die Liste der nicht benötigten Google-Dienste an:

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
quelle
Liebe es! def benötigt, da Unternehmen wie Google die Pakete weiter aufblasen.
Edison
1
Schön - das hat den Job genau getroffen. Kein Ärger und keine Sorge!
Slott
Hinweis: Diese gelöschten Google Play Services-Gläser in meinem Android SDK in Android Studio! Eine schlechte Idee, da es nicht einfach ist, zu Originalgläsern zurückzukehren. Der Autor sollte das Skript ändern, um die Jars im Build-Verzeichnis zu ändern.
Inder
@inder: Ich hatte dieses Problem nicht. Allerdings musste ich cleanjedes Mal eine Aktion durchführen, wenn ich mit den Ausschlüssen Affen machte (wir verwenden Analysen).
Johnny Lambada
Wie kann man dies von Release Builds ausschließen?
user1324936
6

Ich habe ein Beispielprojekt freigegeben, das dieses Problem mithilfe des Build-Skripts custom_rules.xml und einiger Codezeilen löst.

Ich habe es in meinem eigenen Projekt verwendet und es läuft einwandfrei auf 1M + Geräten (von Android-8 bis zum neuesten Android-19). Ich hoffe es hilft.

https://github.com/mmin18/Dex65536

mmin
quelle
1
Danke für die Skripte. Sie sollten auf ART achten. Das Gerät konvertiert möglicherweise nur Ihren Standard-Dex und nicht die sekundären. Proguard-Lösungen sollten bevorzugt werden.
Edison
2
Wenn ich die Projekte in die Eclipse importiere und ausführe, gibt es einen Fehler. "Dex: Methoden-ID kann nicht in [0, 0xffff]: 65536 ausgeführt werden". Können Sie die Verwendung des Projekts
erklären
6

Konfrontierte das gleiche Problem und löste es, indem ich meine build.gradle-Datei im Abschnitt Abhängigkeiten bearbeitete und entfernte:

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

Und ersetzen durch:

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
quelle
Perfekt! Ich benutze nur die Google Drive API und das funktioniert.
Vedavis
5

Versuchen Sie, den folgenden Code in build.gradle hinzuzufügen, es hat bei mir funktioniert -

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

Die perfekte Lösung hierfür wäre die Zusammenarbeit mit Proguard. wie Aleb im Kommentar erwähnt. Dadurch wird die Größe der Dex-Datei um die Hälfte verringert.

shimi_tap
quelle
1
Einverstanden, mit einem immer größeren Google Play Services Jar vor allem * (18k Methoden für sich)
Edison
2

Sie können Probleme (Dex-Dateireferenzen) mit Android Studio analysieren:

Build -> APK analysieren ..

Klicken Sie im Ergebnisbereich auf die Datei classes.dex

Und du wirst sehen:

Geben Sie hier die Bildbeschreibung ein

alexshr
quelle
0

Gradle + Proguard-Lösung:

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
quelle
0

Entfernen Sie eine JAR-Datei aus dem Libs-Ordner und kopieren Sie sie in einen anderen Ordner. Gehen Sie zu _Project Properties> Java Build Path auswählen, Libraries auswählen, Select External Jar hinzufügen, Wählen Sie die entfernte JAR-Datei zu Ihrem Projekt aus. Klicken Sie auf Speichern. Dies wird unter Referenziert hinzugefügt Bibliothek statt Libs-Ordner. Bereinigen Sie nun Ihr Projekt und führen Sie es aus. Sie müssen keinen Code für MultDex hinzufügen. Es hat einfach bei mir funktioniert.

Lakshmanan
quelle
0

Ich hatte heute das gleiche Problem, für das, was funktioniert hat, unten steht

Für ANDROID STUDIO ... Sofortlauf aktivieren

Unter Datei-> Einstellungen-> Erstellen, Ausführen, Bereitstellen-> Sofortausführung-> Aktivieren Sie Sofortausführung für Hot-Swap aktivieren ...

Ich hoffe es hilft

Abdul Waheed
quelle
1
Dies funktionierte für mich - ich habe einfach "Ausführen aktivieren" deaktiviert, auf "Übernehmen" geklickt, es wieder aktiviert und es hat wieder funktioniert.
MrBigglesworth