ART TI

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.

Fluxo e interconexão em um app instrumentado
Figura 1. Fluxo e interconexão de um app instrumentado

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.