No Android 8.0 e versões mais recentes, a ART Tooling Interface (ART TI) expõe alguns componentes internos do tempo 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 componentes internos do ambiente de execução são expostos a agentes carregados no processo do ambiente de execução.
Eles se comunicam com o ART por meio de chamadas diretas e callbacks. Ambiente de execução
oferece suporte a vários agentes para que diferentes preocupações de criação de perfil ortogonal possam
ficar separadas. Os agentes podem ser fornecidos no início do ambiente de execução (quando
dalvikvm
ou app_process
são invocadas) ou anexadas a
um processo já em execução.
Porque a capacidade de instrumentar e modificar o comportamento do app e do tempo de execução é muito eficiente, duas medidas de segurança foram integradas à ART TI:
- Primeiro, o código que expõe a interface do agente, JVMTI, é implementado como plug-in do ambiente de execução, não um componente principal do ambiente de execução. O carregamento do plug-in pode ser para impedir que os agentes encontrem as partes da interface pontos.
- Segundo, a classe
ActivityManager
e o processo do ambiente de execução só permitem que os agentes anexar a apps depuráveis. Os apps depuráveis foram desconectados por seus desenvolvedores sejam analisados e instrumentados, e não são distribuídos para usuários finais. A Google Play Store não permite a distribuição de itens depuráveis apps. Isso garante que apps normais (incluindo os componentes principais) não possam ser instrumentados ou manipulados.
Design
O fluxo geral e a interconexão em um app instrumentado são mostrados em Figura 1.
O plug-in ART libopenjdkjvmti
expõe a ART TI, que é
projetada para acomodar as necessidades e restrições da plataforma:
- A redefinição de classe é baseada em arquivos
Dex
, contendo apenas um definição de classe única, em vez de arquivos de classe. - As APIs de linguagem Java para instrumentação e redefinição não são expostas.
A 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 da 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 no ambiente de execução inicial. Portanto, lembre-se de que um ambiente de execução iniciado manualmente permite que modificações sem medidas de segurança. Isso permite testes de ART.
Observação: isso não se aplica a apps normais (incluindo o sistema servidor) em um dispositivo. Os aplicativos são bifurcados de um zigoto já executado, e um processo do 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 da JVMTI ainda não tiver sido carregado, anexar um agente carregará os o plug-in e a biblioteca do agente.
Um agente só pode ser anexado a um app em execução marcado como
debuggable (parte do manifesto do app, com atributo
O valor android:debuggable
foi definido como true
no app
). Tanto a classe ActivityManager
quanto a ART apresentam
antes de permitir a anexação de um agente. O ActivityManager
verifica as informações atuais do app (derivadas da classe PackageManager)
dados de classe) para o status depurável, 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 os agentes no processo atual para que o agente
podem se vincular diretamente a ela e se comunicar com ela. O ART em si é agnóstico
com relação ao local específico de origem do agente. A string é usada
para uma chamada dlopen
. Permissões do sistema de arquivos e políticas do SELinux
restringir o carregamento real.
Para fornecer agentes que podem ser executados por um app depurável, faça o seguinte:
- Incorpore o agente no diretório da biblioteca do APK do app.
- Usar
run-as
para copiar o agente nos dados do app diretório.
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" é visível publicamente. Esse comando anexa uma instância JVMTI agente para 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 aos agentes (código nativo). As mais importantes recursos incluem:
- Como redefinir uma classe.
- Rastrear a alocação de objetos e a coleta de lixo.
- Iterando todos os objetos de uma pilha, seguindo a árvore de referência do objetos.
- Inspeção de pilhas de chamadas do Java.
- Suspender (e retomar) todas as linhas de execução.
Recursos diferentes podem estar disponíveis em diferentes versões do Android
Compatibilidade
Esse recurso precisa da compatibilidade principal com o ambiente de execução, disponível apenas no Android 8.0 e superiores. Os fabricantes de dispositivos não precisam fazer mudanças 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 são anexados a apps depuráveis e falham ao anexar e não depuráveis.
- Testa todas as APIs da JVMTI implementadas
- Testa se a interface binária dos agentes é estável
Outros testes foram adicionados ao Android 9 e versões mais recentes e estão incluídos nos testes de CTS para essas versões.