Skip to content

Most visited

Recently visited

navigation

Configure aplicativos com mais de 64 K métodos

A plataforma Android continua crescendo, e o tamanho dos aplicativos para Android também. Quando um aplicativo e as bibliotecas às quais ele faz referência alcançam determinado tamanho, ocorrem erros de compilação que indicam que o aplicativo chegou ao limite da arquitetura de compilação de aplicativos Android. Versões anteriores do sistema de compilação reportam esse erro da seguinte forma:

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

Versões mais recentes do sistema de compilação do Android exibem um erro diferente que indica o mesmo problema:

trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

Ambas as condições de erro exibem um número em comum: 65.536. Esse número é importante, pois representa o total de referências que podem ser invocadas pelo código em um só arquivo de bytecode Dalvik Executable (DEX). Esta página explica como superar esse limite, ativando uma configuração de aplicativos denominada multidex, que permite que os aplicativos compilem e leiam vários arquivos DEX.

Sobre o limite de 64 K referências

Arquivos de aplicativo Android (APK) contêm arquivos de bytecode executáveis no formato de arquivos Dalvik Executable (DEX). Esses arquivos DEX são compostos pelo código compilado usado para executar o aplicativo. A especificação do formato Dalvik Executable limita o total de métodos que podem ser referenciados em um só arquivo DEX a 65.536 — inclusive os métodos de estrutura do Android, os métodos de biblioteca e os métodos do seu próprio código. No contexto da ciência da computação, o termo Kilo, K, denota 1.024 (ou 2^10). Como 65.536 equivale a 64 X 1.024, esse limite é chamado de “limite de 64 K referências”.

Compatibilidade com multidex antes do Android 5.0

Versões da plataforma anteriores ao Android 5.0 (nível de API 21) usam o tempo de execução da Dalvik para executar o código do aplicativo. Por padrão, a Dalvik limita os aplicativos a um único arquivo de bytecode classes.dex por APK. Para superar essa limitação, você pode usar a biblioteca de suporte a multidex, que se torna parte do arquivo DEX principal do seu aplicativo e gerencia o acesso aos arquivos DEX adicionais e ao código que eles contêm.

Observação: se o seu projeto estiver configurado para multidex com minSdkVersion 20 ou inferior e você implantá-lo em dispositivos de destino com o Android 4.4 (API de nível 20) ou uma versão anterior, o Android Studio desativará o Instant Run.

Compatibilidade com multidex para Android 5.0 e versões posteriores

O Android 5.0 (API de nível 21) e versões posteriores usam um tempo de execução chamado ART, que oferece suporte nativo para o carregamento de vários arquivos DEX de arquivos APK. O ART executa a pré-compilação no momento da instalação do aplicativo, que verifica a presença de arquivos classesN.dex e os compila em um único arquivo .oat para execução pelo dispositivo Android. Portanto, se o minSdkVersion for 21 ou posterior, a biblioteca de suporte multidex não será necessária.

Para obter mais informações sobre o tempo de execução do Android 5.0, leia ART e Dalvik.

Observação: ao usar o Instant Run, o Android Studio configurará automaticamente o aplicativo para multidex se minSdkVersion for definido como 21 ou posterior. Como o Instant Run só funciona com a versão de depuração do seu aplicativo, ainda será necessário configurar a compilação de lançamento para multidex para evitar o limite de 64 K.

Evitar o limite de 64 K

Antes de configurar seu aplicativo para permitir o uso de 64 K ou mais referências a métodos, tome providências para reduzir o total de referências chamadas pelo código do seu aplicativo, incluindo métodos definidos pelo código do aplicativo ou pelas bibliotecas incluídas. As seguintes estratégias podem ajudar a não atingir o limite de referências do DEX:

O uso dessas técnicas pode ajudar a necessidade de ativar multidex no aplicativo, além de diminuir o tamanho geral do APK.

Configurar o aplicativo para multidex

Para definir o uso de uma configuração multidex no aplicativo, é necessário fazer as seguintes modificações no projeto do aplicativo, dependendo da versão mínima de Android compatível com o aplicativo.

Se minSdkVersion for definido como 21 ou posterior, bastará definir multiDexEnabled como true no arquivo build.gradle do módulo, como mostrado aqui:

android {
    defaultConfig {
        ...
        minSdkVersion 21 
        targetSdkVersion 26
        multiDexEnabled true
    }
    ...
}

No entanto, se minSdkVersion for definido como 20 ou inferior, será necessário usar a biblioteca de suporte do multidex da seguinte maneira:

Agora, ao compilar o aplicativo, as ferramentas de compilação do Android construirão um arquivo DEX principal (classes.dex) e os arquivos de apoio DEX (classes2.dex, classes3.dex e assim por diante) conforme a necessidade. Em seguida, o sistema de compilação empacotará todos os arquivos DEX no APK.

Em tempo de execução, as APIs do multidex usam um carregador de classes especial para pesquisar todos os arquivos DEX disponíveis para os métodos (em vez de pesquisar apenas o arquivo principal classes.dex).

Limitações de biblioteca de suporte a multidex

A biblioteca de suporte a multidex tem algumas limitações que você deve conhecer e testar quando incorporá-la na configuração de compilação do seu aplicativo:

Declarar as classes necessárias no arquivo DEX principal

Ao criar cada arquivo DEX de um aplicativo multidex, as ferramentas de compilação tomam decisões complexas para determinar as classes necessárias no arquivo DEX principal para que o aplicativo seja iniciado corretamente. Se qualquer classe necessária durante a inicialização não for fornecida no arquivo DEX principal, o aplicativo falhará com o erro java.lang.NoClassDefFoundError.

Isso não deve ocorrer para código acessado diretamente no código do aplicativo, porque as ferramentas de compilação reconhecem esses caminhos de código. Mas é possível que isso ocorra quando os caminhos de compilação são menos visíveis, como quando uma biblioteca usada tem dependências complexas. Por exemplo, se o código usar introspecção ou invocação de métodos Java no código nativo, essas classes poderão não ser reconhecidas como necessárias no arquivo DEX principal.

Portanto, se você receber java.lang.NoClassDefFoundError, deverá especificar manualmente essas classes adicionais no arquivo DEX principal, declarando-as com a propriedade multiDexKeepFile ou multiDexKeepProguard no tipo de compilação. Se uma classe for correspondida no arquivo multiDexKeepFile ou multiDexKeepProguard, ela será adicionada ao arquivo DEX principal.

Propriedade multiDexKeepFile

O arquivo especificado em multiDexKeepFile deve conter uma classe por linha no formato com/example/MyClass.class. Por exemplo, você pode criar um arquivo denominado multidex-config.txt como este:

com/example/MyClass.class
com/example/MyOtherClass.class

Em seguida, você pode declarar esse arquivo para um tipo de compilação da seguinte forma:

android {
    buildTypes {
        release {
            multiDexKeepFile file 'multidex-config.txt'
            ...
        }
    }
}

Lembre-se de que o Gradle lê caminhos relativos ao arquivo build.gradle. Portanto, o exemplo acima funcionará se multidex-config.txt estiver no mesmo diretório que o arquivo build.gradle.

Propriedade multiDexKeepProguard

O arquivo multiDexKeepProguard usa o mesmo formato que o ProGuard e é compatível com toda a gramática do ProGuard. Para obter mais informações sobre o formato e a gramática do ProGuard, consulte a seção Keep Options no manual do ProGuard.

O arquivo especificado em multiDexKeepProguard deve conter opções -keep em qualquer sintaxe válida do ProGuard. Por exemplo: -keep com.example.MyClass.class. Você pode criar um arquivo denominado multidex-config.pro como este:

-keep class com.example.MyClass
-keep class com.example.MyClassToo

Ou, se você quiser especificar todas as classes de um pacote, o arquivo será assim:

-keep class com.example.** { *; } // All classes in the com.example package

Em seguida, você pode declarar esse arquivo para um tipo de compilação da seguinte forma:

android {
    buildTypes {
        release {
            multiDexKeepProguard 'multidex-config.pro'
            ...
        }
    }
}

Otimizar o multidex em compilações de desenvolvimento

Uma configuração de multidex exige um tempo de processamento de compilação significativamente maior, pois o sistema de compilação deve tomar decisões complexas sobre quais classes devem ser incluídas no arquivo DEX principal e quais podem ser incluídas nos arquivos DEX secundários. Isso significa que compilações incrementais usando multidex são normalmente mais demoradas e podem retardar o processo de desenvolvimento.

Para reduzir os tempos de compilação mais longos das saídas multidex, crie duas variações de compilação usando productFlavors: uma de desenvolvimento e outra de lançamento, com valores diferentes para minSdkVersion.

Para a variação de desenvolvimento, defina minSdkVersion como 21. Essa configuração ativa um recurso de compilação denominado pre-dexing, que gera saída multidex muito mais rapidamente usando um formato ART disponível apenas no Android 5.0 (API de nível 21) ou posterior. Para a variação de lançamento defina minSdkVersion da forma adequada ao nível mínimo de compatibilidade real. Essa configuração gera um APK multidex que é compatível com mais dispositivos, mas que demora mais para ser compilado.

O exemplo de configuração de compilação a seguir demonstra como configurar essas variáveis em um arquivo de compilação do Gradle:

android {
    defaultConfig {
        ...
        multiDexEnabled true
    }
    productFlavors {
        dev {
            // Enable pre-dexing to produce an APK that can be tested on
            // Android 5.0+ without the time-consuming DEX build processes.
            minSdkVersion 21
        }
        prod {
            // The actual minSdkVersion for the production version.
            minSdkVersion 14
        }
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                                                 'proguard-rules.pro'
        }
    }
}
dependencies {
    compile 'com.android.support:multidex:1.0.1'
}

Após concluir essa alteração de configuração, você poderá usar a variação devDebug do aplicativo para compilações incrementais, combinando os atributos da variação de produto dev com o tipo de compilação debug. Será criado um aplicativo depurável com multidex ativado e ProGuard desativado (porque minifyEnabled é false por padrão). Com essas configurações, o Android Plugin para Gradle fará o seguinte:

  1. Executar pre-dexing: compilar cada módulo de aplicativo e cada dependência como arquivo DEX separado.
  2. Incluir cada arquivo DEX no APK sem modificação (sem redução de código).
  3. O mais importante: os arquivos DEX do módulo não serão combinados. Portanto, o cálculo demorado para determinar o conteúdo do arquivo DEX principal será evitado.

Essas configurações proporcionam compilações rápidas e incrementais, pois somente os arquivos DEX dos módulos modificados serão calculados e empacotados novamente em compilações subsequentes. Contudo, o APK dessas compilações somente pode ser usado para testes em dispositivos com Android 5.0. No entanto, ao implementar a configuração como variação, você preserva a capacidade de executar compilações normais com o nível de API mínimo e redução de código do ProGuard apropriados para o lançamento.

Você também pode compilar as outras variações, incluindo a compilação de uma variação prodDebug, mais demorada, mas que pode ser usada para testes fora do ambiente de desenvolvimento. Na configuração mostrada, a variação prodRelease seria a versão final de teste e lançamento. Para obter mais informações sobre o uso de variações de compilação, consulte Configurar variações de compilação.

Dica: agora que já tem variações de compilação distintas para necessidades de multidex diferentes, você também pode oferecer um arquivo de manifesto diferente para cada variação (para que apenas o manifesto para a API de nível 20 ou anterior altere o nome da tag <application>) ou criar uma subclasse Application para cada variação (para que apenas o manifesto para a API de nível 20 ou anterior estenda a classe MultiDexApplication ou chame MultiDex.install(this)).

Testar aplicativos multidex

Nenhuma configuração adicional é necessária na criação de testes de instrumentação de aplicativos multidex. O AndroidJUnitRunner é fornecido já compatível com multidex, desde que você use MultiDexApplication ou modifique o método attachBaseContext() no seu objeto personalizado Application e chame MultiDex.install(this) para ativar o multidex.

Como alternativa, você pode modificar o método onCreate() em AndroidJUnitRunner:

public void onCreate(Bundle arguments) {
    MultiDex.install(getTargetContext());
    super.onCreate(arguments);
    ...
}

Observação: o uso de multidex para criar um APK de teste não é atualmente permitido.

This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)