No Android 8.0 e versões mais recentes, a interface de ferramentas do ART (ART TI) expõe alguns elementos internos do ambiente de execução e permite que criadores de perfil e depuradores influenciem o comportamento de execução dos apps. Isso pode ser usado para implementar ferramentas de desempenho de última geração fornecidas para implementar agentes nativos em outras plataformas.
Os elementos internos do ambiente de execução são expostos a agentes que foram carregados no processo de execução.
Eles se comunicam com o ART por chamadas diretas e callbacks. O ambiente de execução
oferece suporte a vários agentes para que diferentes problemas de perfil ortogonal possam
ser separados. Os agentes podem ser fornecidos no início da execução (quando
dalvikvm
ou app_process
são invocados) ou anexados a
um processo que já está em execução.
Como a capacidade de instrumentar e modificar o comportamento do app e do ambiente de execução é muito poderosa, duas medidas de segurança foram integradas ao ART TI:
- Primeiro, o código que expõe a interface do agente, JVMTI, é implementado como um plug-in de execução, não um componente principal do ambiente de execução. O carregamento de plug-ins pode ser restringido para que os agentes não consigam encontrar nenhum dos pontos da interface.
- Em segundo lugar, a classe
ActivityManager
e o processo de execução só permitem que os agentes se conectem a apps depuráveis. Os apps depuráveis foram aprovados pelos desenvolvedores para análise e instrumentação e não são distribuídos para os usuários finais. A Google Play Store não permite a distribuição de apps depuração. Isso garante que apps normais (incluindo componentes principais) não possam ser instrumentados ou manipulados.
Design
O fluxo geral e a interconexão em um app instrumentado são mostrados na Figura 1.

O plug-in ART libopenjdkjvmti
expõe o TI do ART, que foi
projetado para acomodar as necessidades e restrições da plataforma:
- A redefinição de classe é baseada em arquivos
Dex
, contendo apenas uma definição de classe, em vez de arquivos de classe. - As APIs da linguagem Java para instrumentação e redefinição não são expostas.
O ART TI também oferece suporte aos criadores de perfil do Android Studio.
Carregar ou anexar um agente
Para anexar um agente na inicialização do ambiente de execução, use este comando para carregar o plug-in JVMTI e o agente fornecido:
dalvikvm -Xplugin:libopenjdkjvmti.so -agentpath:/path/to/agent/libagent.so …
Não há medidas de segurança em vigor quando um agente é carregado na inicialização do ambiente de execução. Portanto, lembre-se de que um ambiente de execução iniciado manualmente permite a modificação completa sem medidas de segurança. Isso permite o teste do ART.
Observação: isso não se aplica a apps normais (incluindo o servidor do sistema) em um dispositivo. Os apps são bifurcados de um zigoto já em execução, e um processo de zigoto não pode carregar agentes.
Para anexar um agente a um app que já está em execução, use este comando:
adb shell cmd activity attach-agent [process] /path/to/agent/libagent.so[=agent-options]
Se o plug-in JVMTI ainda não tiver sido carregado, a anexação de um agente vai carregar o plug-in e a biblioteca do agente.
Um agente só pode ser anexado a um app em execução marcado como
depurável (parte do manifesto do app, com o atributo
android:debuggable
definido como true
no nó
do app). A classe ActivityManager
e o ART fazem
verificações antes de permitir que um agente seja anexado. A classe ActivityManager
verifica as informações atuais do app (derivadas dos dados da classe
PackageManager) para o status de depuração, e o ambiente de execução verifica o status atual,
que foi definido quando o app foi iniciado.
Locais dos agentes
O ambiente de execução precisa carregar agentes no processo atual para que o agente
possa se vincular e se comunicar diretamente com ele. O ART em si não tem conhecimento
sobre o local específico de onde o agente vem. A string é usada
para uma chamada dlopen
. As permissões do sistema de arquivos e as políticas do SELinux
restringem o carregamento real.
Para entregar agentes que podem ser executados por um app depurável, faça o seguinte:
- Incorpore o agente no diretório de biblioteca do APK do app.
- Use
run-as
para copiar o agente para o diretório de dados do app.
APIs
O método a seguir foi adicionado a android.os.Debug
.
/** * Attach a library as a jvmti agent to the current runtime, with the given classloader * determining the library search path. * Note: agents may only be attached to debuggable apps. Otherwise, this function will * throw a SecurityException. * * @param library the library containing the agent. * @param options the options passed to the agent. * @param classLoader the classloader determining the library search path. * * @throws IOException if the agent could not be attached. * @throws a SecurityException if the app is not debuggable. */ public static void attachJvmtiAgent(@NonNull String library, @Nullable String options, @Nullable ClassLoader classLoader) throws IOException {
Outras APIs do Android
O comando attach-agent fica visível publicamente. Esse comando anexa um agente JVMTI a um processo em execução:
adb shell 'am attach-agent com.example.android.displayingbitmaps \'/data/data/com.example.android.displayingbitmaps/code_cache/libfieldnulls.so=Ljava/lang/Class;.name:Ljava/lang/String;\''
Os comandos am start -P
e am
start-profiler/stop-profiler
são semelhantes ao comando attach-agent.
JVMTI
Esse recurso expõe a API JVMTI a agentes (código nativo). Os recursos importantes incluem:
- Redefinindo uma classe.
- Rastreamento da alocação de objetos e da coleta de lixo.
- Iterar sobre todos os objetos em uma pilha, seguindo a árvore de referência de objetos.
- Inspecionar pilhas de chamadas Java.
- Suspender (e retomar) todas as linhas de execução.
Diferentes recursos podem estar disponíveis em diferentes versões do Android.
Compatibilidade
Esse recurso precisa de suporte de execução principal que só está disponível no Android 8.0 e versões mais recentes. Os fabricantes de dispositivos não precisam fazer nenhuma mudança para implementar esse recurso. Ele faz parte do AOSP.
Validação
O CTS testa o seguinte no Android 8 e versões mais recentes:
- Testes que os agentes anexam a apps depuráveis e não conseguem se conectar a apps não depuráveis.
- Testa todas as APIs JVMTI implementadas
- Testa se a interface binária para agentes é estável
Outros testes foram adicionados ao Android 9 e versões mais recentes e incluídos nos testes de CTS para essas versões.