O Android Runtime (ART) é o tempo de execução padrão para dispositivos que executam o Android 5.0 (nível 21 da API) e versões mais recentes. Esse ambiente de execução oferece vários recursos que melhoram o desempenho e a estabilidade da plataforma e dos apps Android. Saiba mais sobre os novos recursos do ART em Introdução ART.
No entanto, algumas técnicas que funcionam na Dalvik não funcionam no ART. Isso documento informa o que você deve observar ao migrar um aplicativo seja compatível com o ART. A maioria dos aplicativos deve funcionar apenas quando executados com ARTE.
Solução de problemas de coleta de lixo (GC)
Na Dalvik, é útil que os apps chamem explicitamente
System.gc()
para solicitar a coleta de lixo (GC). Ela deve ser
muito menos necessário com o ART, especialmente se você invocar a coleta de lixo
para impedir o uso do tipo GC_FOR_ALLOC
ou para reduzir a fragmentação. É possível verificar qual ambiente de execução está em uso
chame System.getProperty("java.vm.version")
. Se o ART estiver em uso, o valor da propriedade
é "2.0.0"
ou superior.
O ART usa o coletor de cópia simultânea (CC, na sigla em inglês) que compacta a pilha Java simultaneamente. Por isso, você deve evitar o uso de técnicas incompatíveis com a GC com compactação (como salvar ponteiros em objetos dados da instância). Isso é especialmente importante para apps que usam o Java Native Interface (JNI). Para mais informações, consulte Como evitar problemas de JNI.
Prevenção de problemas de JNI
A JNI do ART é um pouco mais rígida do que a do Dalvik. É uma boa ideia para usar o modo CheckJNI para detectar problemas comuns. Se o app usar C/C++ consulte o seguinte artigo:
Depuração JNI do Android com CheckJNI
Verificação do código JNI para problemas de coleta de lixo
O coletor de cópia simultânea (CC, na sigla em inglês) pode mover objetos na memória para compactação. Se você usar código C/C++, não executar operações incompatíveis com a GC com compactação. Nós aprimoramos CheckJNI para identificar possíveis problemas, conforme descrito na JNI mudanças de referência local no ICS).
Uma área a ser observada em particular é o uso de
Get...ArrayElements()
e Release...ArrayElements()
. Em ambientes de execução com GC sem compactação, os
As funções Get...ArrayElements()
normalmente retornam uma referência ao
memória real que apoia o objeto de matriz. Se você alterar uma das
elementos de matriz retornados, o objeto da matriz é alterado (e os argumentos
como Release...ArrayElements()
são geralmente ignorados). No entanto, se
a GC com compactação estiver em uso, as funções Get...ArrayElements()
poderão
retornar uma cópia da memória. Se você usar indevidamente a referência quando a GC com compactação for
em uso, isso pode levar à corrupção da memória ou outros problemas. Exemplo:
- Se você fizer alterações nos elementos da matriz retornados, deverá chamar o método
a função
Release...ArrayElements()
apropriada quando terminar, para garantir que as alterações feitas sejam copiadas corretamente para o objeto de matriz. - Quando você liberar os elementos da matriz de memória, será necessário usar os elementos
dependendo das alterações feitas:
- Se você não tiver feito alterações nos elementos da matriz, use
Modo
JNI_ABORT
, que libera a memória sem copiar. volta para o objeto de matriz subjacente. - Se você fez alterações na matriz e não precisa da referência
mais, use o código
0
, que atualiza o objeto da matriz e libera a cópia da memória). - Se você tiver feito alterações na matriz que quer confirmar e quiser
para manter a cópia da matriz, use
JNI_COMMIT
, que atualiza o objeto de matriz subjacente e retém a cópia).
- Se você não tiver feito alterações nos elementos da matriz, use
Modo
- Quando você chamar
Release...ArrayElements()
, retorne o mesmo ponteiro que foi retornado originalmente porGet...ArrayElements()
. Para exemplo, não é seguro incrementar o ponteiro original (para percorrer o elementos de matriz retornados) e, em seguida, passar o ponteiro incrementado paraRelease...ArrayElements()
: Passar esse ponteiro modificado pode fazer a memória errada a ser liberada, resultando na corrupção da memória.
Tratamento de erros
A JNI do ART gera erros em diversos casos nos quais o Dalvik não faz. (Uma vez novamente, você pode capturar muitos desses casos testando com CheckJNI.
Por exemplo, se RegisterNatives
for chamado com um método que
não existe (talvez porque o método tenha sido removido por uma ferramenta como
ProGuard), o ART agora gera um NoSuchMethodError
corretamente:
08-12 17:09:41.082 13823 13823 E AndroidRuntime: FATAL EXCEPTION: main 08-12 17:09:41.082 13823 13823 E AndroidRuntime: java.lang.NoSuchMethodError: no static or non-static method "Lcom/foo/Bar;.native_frob(Ljava/lang/String;)I" 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.Runtime.nativeLoad(Native Method) 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.Runtime.doLoad(Runtime.java:421) 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.Runtime.loadLibrary(Runtime.java:362) 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:526)
O ART também registra um erro (visível no logcat) se RegisterNatives
for
chamados sem métodos:
W/art ( 1234): JNI RegisterNativeMethods: attempt to register 0 native methods for <classname>
Além disso, as funções JNI GetFieldID()
e
GetStaticFieldID()
agora gera NoSuchFieldError
corretamente.
em vez de simplesmente retornar nulo. Da mesma forma, GetMethodID()
e
GetStaticMethodID()
agora gera NoSuchMethodError
corretamente
Isso pode levar a falhas do CheckJNI devido às exceções não processadas ou aos
exceções sendo geradas para autores de chamadas de código nativo em Java. Assim,
particularmente importante para testar aplicativos compatíveis com ART com o modo CheckJNI.
O ART espera que os usuários dos métodos JNI CallNonvirtual...Method()
(como CallNonvirtualVoidMethod()
) para usar a declaração de método
, não uma subclasse, conforme exigido pela especificação JNI.
Prevenção de problemas de tamanho da pilha
O Dalvik tinha pilhas separadas para o código Java e nativo, com uma biblioteca Java
de 32 KB e um tamanho de pilha nativo padrão de 1 MB. O ART tem um sistema
para uma melhor localidade. Normalmente, a pilha Thread
da ART
deve ser aproximadamente o mesmo da Dalvik. No entanto, se você explicitamente
definir tamanhos de pilha, pode ser necessário revisar esses valores para aplicativos em execução
ARTE.
- Em Java, revise as chamadas para o construtor
Thread
que especificam uma pilha explícita. tamanho. Por exemplo, será necessário aumentar o tamanho seStackOverflowError
ocorrer. - Em C/C++, revise o uso de
pthread_attr_setstack()
epthread_attr_setstacksize()
para linhas de execução que também executam código Java via JNI Confira um exemplo do erro registrado quando um app tenta chamar a JNIAttachCurrentThread()
quando o tamanho do pthread é muito pequeno:F/art: art/runtime/thread.cc:435] Attempt to attach a thread with a too-small stack (16384 bytes)
Mudanças no modelo de objeto
A Dalvik permitiu incorretamente que a subclasse modificasse os métodos privados do pacote. O ART enviará um aviso nestes casos:
Before Android 4.1, method void com.foo.Bar.quux() would have incorrectly overridden the package-private method in com.quux.Quux
Se você pretende substituir o método de uma classe em um pacote diferente, declare a
como public
ou protected
.
Object
agora tem campos privados. Apps que refletem sobre os campos
nas hierarquias de classe devem ter cuidado para não tentar olhar para
campos de Object
. Por exemplo, se você iterar uma classe
como parte de um framework de serialização, pare quando
Class.getSuperclass() == java.lang.Object.class
em vez de continuar até que o método retorne null
.
O proxy InvocationHandler.invoke()
agora recebe null
se não houver
em vez de uma matriz vazia. Esse comportamento foi documentado anteriormente, mas
não são processados corretamente na Dalvik. As versões anteriores do Mockito têm dificuldades com
portanto, use uma versão atualizada do Mockito ao realizar testes com o ART.
Correção de problemas de compilação de AOT
A compilação Java Ahead-Of-Time (AOT) do ART deve funcionar para todos os padrões
o código-fonte. A compilação é feita por
Ferramenta dex2oat
caso você encontre algum problema relacionado
dex2oat
durante a instalação, entre em contato com nossa equipe (consulte Como informar problemas) para que possamos corrigi-los o mais rápido possível
possível. Algumas observações necessárias:
- O ART realiza uma verificação de bytecode mais rígida no momento da instalação do que a Dalvik. O código produzido por ferramentas de compilação Android deve funcionar normalmente. No entanto, alguns as ferramentas de pós-processamento (especialmente ferramentas que realizam ofuscação) podem produzir arquivos inválidos que são tolerados pela Dalvik, mas rejeitados pelo ART. Fomos trabalhar com fornecedores de ferramentas para encontrar e corrigir esses problemas. Em muitos casos, obter as versões mais recentes de suas ferramentas e gerar novamente os arquivos DEX pode corrigir esses para solucionar problemas fáceis e de produção.
- Alguns problemas típicos que são sinalizados pelo verificador do ART:
- controle de fluxo inválido
monitorenter
/monitorexit
desequilibrado- tamanho de lista de tipo de parâmetro 0
- Alguns apps têm dependências no arquivo
.odex
instalado. em/system/framework
,/data/dalvik-cache
ou no diretório de saída otimizado deDexClassLoader
. Esses agora são arquivos ELF e não uma forma estendida dos arquivos DEX. Enquanto o ART tenta seguir as mesmas regras de nomenclatura e bloqueio do Dalvik, os apps não devem depender o formato do arquivo. o formato está sujeito a alterações sem aviso prévio.Observação: no Android 8.0 (nível 26 da API) e superior, o diretório de saída otimizado
DexClassLoader
foi descontinuado. Para mais informações, consulte a documentação daDexClassLoader()
construtor.
Informar problemas
Se você tiver problemas que não são causados por JNI do app, informe
usando o Issue Tracker do Android Open Source Project em https://code.google.com/p/android/issues/list.
Inclua um "adb bugreport"
e um link para o app no Google
Play Store, se disponível. Caso contrário, se possível, anexe um APK que reproduza
o problema. Os problemas, inclusive os anexos, são públicos
visíveis.