2015-09-22 10 views
19

Sto cercando di eseguire i test di strumentazione ma ottenere l'errore sotto mentre la conversione dex IMPREVISTO TOP-LEVEL ECCEZIONE:Troppi classi --main-dex-list, la capacità dex principale superati

com.android.dex.DexException: Too many classes in --main-dex-list, main dex capacity exceeded 
     at com.android.dx.command.dexer.Main.processAllFiles(Main.java:494) 
     at com.android.dx.command.dexer.Main.runMultiDex(Main.java:334) 
     at com.android.dx.command.dexer.Main.run(Main.java:244) 
     at com.android.dx.command.dexer.Main.main(Main.java:215) 
     at com.android.dx.command.Main.main(Main.java:106) 

:App:dexDebug FAILED 

Come risolvere questo problema in gradle?

+0

Probabilmente stai usando Google Play Services. Se utilizzi Android Studio, prova a utilizzare solo i sottocomponenti di cui hai bisogno (ad esempio annunci, giochi, ecc.), Non tutti in una volta. È un problema noto e difficilmente verrà risolto nel prossimo futuro. Il problema è che Dalvik supporta solo 65535 (2^16 - 1) classi. Una volta che tutti i dispositivi utilizzano l'ART nativa, non sarà più un problema. – GiantTree

risposta

16

Facciamo capire prima il problema:

Su dispositivi pre-Lollipop, solo il main dex viene caricato dal framework. Per supportare applicazioni multi-dex è necessario applicare esplicitamente una patch al programma di caricamento classe dell'applicazione con tutti i file dex secondari (ecco perché la classe Application deve estendere la classe MultiDexApplication o chiamare MultiDex#install).

Ciò significa che il dex principale dell'applicazione dovrebbe contenere tutte le classi che sono potenzialmente accessibili prima del patch del programma di caricamento classi.

Riceverai java.lang.ClassNotFoundException se il codice dell'applicazione proverà a fare riferimento a una classe che è stata inserita in uno dei tuoi file dex secondari prima di applicare correttamente il caricatore della classe dell'applicazione.

Ho il documented here come plugin decide quali classi devono essere impacchettate in main-dex.
Se la quantità totale di metodi a cui tali classi fanno riferimento supera il limite 65.536, la generazione non riuscirà con l'errore Too many classes in --main-dex-list, main dex capacity exceeded.

Posso pensare a tre possibili soluzioni per questo problema:

  1. (La soluzione più semplice, ma non è adatto per la maggior parte delle applicazioni ) Cambia la tua minSdkVersion a 21.
  2. Shrink vostra applicazione codice. Questo è stato discusso molte volte in precedenza (vedi here e here).
  3. Se nessuna delle soluzioni di cui sopra funziona per te, puoi provare a utilizzare my workaround per questo problema - Sto correggendo il plug-in gradle Android per non includere le classi di attività nel dex principale. È un po 'hacky, ma funziona bene per me.

Ci sono an issue in bug tracker Android per quanto riguarda questo errore. Speriamo che il team di Tools fornirà presto una soluzione migliore.


Aggiornamento (4/27/2016)

Versione 2.1.0 di Gradle plugin permette di filtrare principale-Dex classi della lista.
Avviso: questo sta utilizzando un api non supportato che verrà sostituito in futuro.

Ad esempio, per escludere tutte le classi di attività che si possono fare:

afterEvaluate { 
    project.tasks.each { task -> 
    if (task.name.startsWith('collect') && task.name.endsWith('MultiDexComponents')) { 
     println "main-dex-filter: found task $task.name" 
     task.filter { name, attrs -> 
     def componentName = attrs.get('android:name') 
     if ('activity'.equals(name)) { 
      println "main-dex-filter: skipping, detected activity [$componentName]" 
      return false 
     } else { 
      println "main-dex-filter: keeping, detected $name [$componentName]" 
      return true 
     } 
     } 
    } 
    } 
} 

È inoltre possibile controllare il mio example project che illustra questo problema (e si applica il filtraggio di cui sopra).


Aggiornamento 2 (7/1/2016)

Versione 2.2.0-alfa4 di plug Gradle (con build-tools V24), infine, risolve questo problema reducing multidex keep list to a minimum.
Il filtro non supportato (e non documentato) dalla versione 2.1.0 non deve essere più utilizzato. Ho aggiornato il mio sample project, dimostrando che la compilazione ha esito positivo senza alcuna logica di compilazione personalizzata.

+0

Ciao, ho dovuto usare anche la stessa patch. Ma qual è la causa principale di questo problema? E qualche idea su come evitarlo? –

+0

Ho modificato la mia risposta, per favore fatemi sapere se avete ulteriori domande. –

+0

Grazie ha aiutato molto. –

-1

Hai due scelte.

  1. uso ProGuard a spogliarsi numero di metodi
  2. uso funzione multidex

Il mio consiglio - andare con ProGuard, si richiede un minimo di a zero modifiche al codice sorgente

+3

MultiDex è già abilitato. Sembra essere diverso. –

12

Un altro modo per risolvere questo problema è quello di rimuovere le classi con annotazioni runtime dal file DEX principale:

android { 

    dexOptions { 
     keepRuntimeAnnotatedClasses false 
    } 

} 

Ciò è particolarmente utile per le applicazioni che utilizzano i quadri iniezione di dipendenza dal momento che anche per le annotazioni Dagger sono di solito tenuto in runtime.

+0

Grazie! Questo aiuta. Ho già avuto le seguenti opzioni dexOptions additionalParameters + = '--minimal-main-dex' additionalParameters + = '--set-max-idx-number = 50000' – hcpl

+0

Ciao! Hai mai avuto problemi o arresti anomali a causa di 'keepRuntimeAnnotatedClasses false'? – aleien

+0

@aleien no, tutto andava bene –

Problemi correlati