Runtime é uma camada de software que gerencia a execução do código de um aplicativo móvel: aloca memória, trata exceções, executa coleta de lixo e despacha chamadas de métodos. Sem runtime, nenhum aplicativo pode executar — é a camada intermediária entre o código compilado e o sistema operacional. De acordo com Android Developer Documentation, 2025, o ambiente de execução é um elemento chave da plataforma que determina desempenho e compatibilidade.
Pontos principais
Runtime é a infraestrutura que garante a execução do programa após sua inicialização. No contexto do desenvolvimento móvel, runtime inclui o carregador de classes, alocador de memória, coletor de lixo, despachador de métodos e tratador de exceções. Sem essa camada intermediária, o sistema operacional não pode executar bytecode Dalvik ou mensagens Objective-C.
As plataformas móveis usam diferentes implementações de runtime. Android usa ART (Android Runtime) com compilação híbrida AOT/JIT. O iOS usa Objective-C Runtime — um sistema dinâmico baseado em passagem de mensagens e identificadores SEL. Ambas as abordagens resolvem o mesmo problema: executar o código do desenvolvedor em um dispositivo específico com máximo desempenho.
De acordo com o Google I/O 2024, o Android Runtime processa mais de 10 bilhões de métodos por dia em dispositivos ao redor do mundo. O desempenho do runtime afeta diretamente a velocidade de inicialização do aplicativo, a suavidade das animações e o consumo de bateria. Cada chamada de método, cada alocação de memória e cada ciclo de coleta de lixo passam pela camada de runtime.
Runtime system inclui cinco componentes principais: carregador de classes, gerenciador de memória, interpretador ou compilador, despachador de métodos e sistema de segurança. Cada componente executa uma função estritamente definida no processo de execução do código.
Quando um usuário inicia um aplicativo, o ClassLoader carrega arquivos DEX (Android) ou binários Mach-O (iOS) na RAM. No Android, esta etapa inclui verificação de bytecode: o runtime verifica se o código não contém instruções inseguras, não ultrapassa limites de arrays e respeita os tipos. A verificação é uma etapa crítica de segurança que impede a execução de código malicioso.
Gerenciador de memória aloca e libera memória para objetos. No Android ART, é usado um coletor de lixo concorrente com coleta geracional: objetos jovens são verificados com mais frequência, objetos velhos com menos. Objective-C Runtime usa Automatic Reference Counting (ARC), onde o compilador insere chamadas retain/release automaticamente.
Despachador de métodos determina qual implementação de método será chamada. Em linguagens estáticas (Kotlin, Swift), o despacho é feito via vtable — uma tabela de métodos virtuais. Em linguagens dinâmicas (Objective-C), a mensagem passa pelo objc_msgSend, que procura a implementação na classe e suas superclasses. O resultado é armazenado em cache no method cache para acelerar chamadas repetidas.
Android Runtime (ART) é uma máquina virtual que executa bytecode DEX de aplicativos Android. O ART substituiu o Dalvik no Android 5.0 Lollipop, introduzindo compilação AOT: o aplicativo é compilado em código de máquina uma vez durante a instalação. Isso eliminou a sobrecarga da compilação JIT em cada inicialização.
A partir do Android 7.0 Nougat, o ART usa uma abordagem híbrida. Durante a instalação, a compilação JIT é realizada apenas para métodos usados com frequência (hot methods), o restante do código é interpretado. Um processo em segundo plano (profile-guided optimization) analisa quais métodos são chamados com mais frequência e os compila AOT durante o tempo ocioso do dispositivo. Isso reduz o tempo de instalação enquanto garante alto desempenho.
O ART também inclui um compilador AOT (dex2oat) que converte arquivos DEX em binários ELF com código de máquina ARM64. A compilação é realizada com três níveis de otimização: quicken (rápida), optimize (média) e everything (completa). Por padrão, o Android usa optimize, equilibrando entre velocidade de compilação e desempenho do código.
class RuntimeExample {
fun measureExecutionTime() {
val start = System.nanoTime()
// Chamada de método compilado pelo ART
processData()
val end = System.nanoTime()
println("Tempo de execução: ${end - start} ns")
}
}
No exemplo acima, System.nanoTime() é um método nativo cuja chamada é despachada através do runtime ART para o kernel Linux. O ART converte bytecode Kotlin em instruções ARM64 que são executadas pelo processador do dispositivo. Este processo ocorre de forma transparente para o desenvolvedor, mas sua otimização é uma tarefa chave da equipe Android Platform.
Profile-guided optimization é um mecanismo do ART que coleta perfis de uso de métodos. O arquivo profiles/
O desenvolvedor pode habilitar baseline profiles em seu projeto Gradle. São anotações manuais que informam ao ART quais métodos compilar AOT imediatamente após a instalação. Baseline profiles reduzem a primeira inicialização em 40% sem esperar pela criação de perfil em segundo plano.
Objective-C Runtime é uma biblioteca dinâmica que fornece execução de código Objective-C no iOS e macOS. Seu núcleo é a função objc_msgSend, que implementa passagem de mensagens: em vez de uma chamada de método direta, o objeto envia uma mensagem com um seletor, e o runtime determina qual implementação deve executar.
Cada objeto Objective-C contém um ponteiro isa para sua classe, e a classe tem uma dispatch table que mapeia seletores (SEL) para implementações (IMP). Quando um método é chamado, objc_msgSend percorre a cadeia: classe → superclasse → NSObject, até encontrar a IMP. Se nenhuma implementação for encontrada, o runtime invoca o forwarding mechanism, que pode interceptar a mensagem ou gerar uma exceção.
Objective-C Runtime também suporta method swizzling — substituir a IMP de um seletor existente em tempo de execução. Este é um mecanismo poderoso usado em bibliotecas AOP e ferramentas de monitoramento, mas requer cautela devido ao seu impacto em todo o aplicativo.
@interface RuntimeDemo : NSObject
- (void)printClassInfo;
@end
@implementation RuntimeDemo
- (void)printClassInfo {
// objc_getClass — função do runtime
Class cls = objc_getClass("RuntimeDemo");
unsigned int count;
Method *methods = class_copyMethodList(cls, &count);
NSLog("Número de métodos: %d", count);
}
@end
O código demonstra acesso direto à API do Objective-C Runtime: objc_getClass obtém o objeto de classe pelo nome, class_copyMethodList recupera a lista de todos os métodos. Isso é reflexão em ação — acesso a metadados de classe em tempo de execução. Esta abordagem é usada no XCTest para registro dinâmico de testes.
Ponteiro isa é um ponteiro para a classe do objeto, armazenado nos primeiros 8 bytes de cada objeto. A partir do iOS 12, a Apple introduziu isa-swizzling para otimização: os bits inferiores do isa codificam informações adicionais sobre o estado do objeto. Tagged pointers são outra otimização onde valores de até 60 bits (NSNumber, NSDate) são armazenados diretamente no ponteiro, sem alocar um objeto no heap. Isso reduz a carga do gerenciador de memória em 30%.
JIT (Just-In-Time) e AOT (Ahead-Of-Time) são duas abordagens para compilar bytecode em código de máquina. JIT compila código durante a execução do aplicativo, analisando pontos quentes e otimizando-os em tempo real. AOT compila todo o código antecipadamente — durante a instalação do aplicativo ou no lado do desenvolvedor.
| Característica | JIT | AOT |
|---|---|---|
| Tempo de compilação | Durante a execução | Durante instalação/build |
| Tamanho APK/IPA | Menor (apenas bytecode) | Maior (código de máquina) |
| Velocidade de inicialização | Menor (compilação necessária) | Maior (código pronto) |
| Otimização por dispositivo | Sim (adaptativa) | Limitada (genérica) |
| Consumo de RAM | Maior (compilador na memória) | Menor |
A abordagem híbrida do ART (Android 7+) é considerada ideal: o aplicativo usa um interpretador para métodos raramente chamados, JIT para métodos hot e AOT para métodos do profile-guided optimization. O iOS, por contraste, usa AOT estrito via LLVM: Swift e Objective-C são compilados em código de máquina na etapa de build no Xcode.
De acordo com Apple Developer Documentation, 2024, o Swift runtime adiciona cerca de 15 MB ao tamanho do aplicativo. Flutter usa sua própria Dart VM, onde a compilação JIT funciona em modo debug para hot reload, e AOT em modo release para máximo desempenho. React Native usa Hermes — um motor JavaScript com compilação AOT que reduz o tempo de inicialização em 50%.
ARM64 Runtime é o nível no qual o código de máquina interage com o processador do dispositivo. A maioria dos dispositivos móveis modernos funciona em processadores ARM64 (aarch64). O runtime traduz bytecode ou chamadas nativas em instruções ARM64 que a CPU executa.
Registradores ARM64 principais usados pelo runtime: x0–x7 (parâmetros de funções), x8 (resultado indireto), x30 (endereço de retorno), sp (stack pointer), fp (frame pointer). O ART gera código que segue o ARM64 Procedure Call Standard: todas as chamadas de método passam pelo protocolo definido pela arquitetura do processador.
Entender a ABI ARM64 é importante para otimização de desempenho: inline caching, predição de branch e alinhamento de código na memória afetam diretamente a velocidade do runtime. Ferramentas de perfilamento (Android Studio Profiler, Instruments) mostram quais seções de código passam mais tempo no runtime — otimizá-las traz o maior ganho.
// Exemplo de assembly ARM64 gerado pelo ART
// Chamada de método com dois parâmetros
mov x0, x23 // self (this)
mov x1, x24 // param1
mov x2, x25 // param2
bl methodEntryPoint // chamada via runtime
str x0, [sp, #8] // salvar resultado
Neste exemplo, instruções ARM64 mov passam argumentos para os registradores x0–x2, bl chama o ponto de entrada do método, e str salva o valor de retorno. O runtime gera tais instruções para cada chamada de método, otimizando a sequência através de devirtualization e inlining.
Runtime overhead é o custo inevitável do despacho dinâmico. Cada chamada de método através do runtime requer: busca da implementação na dispatch table, verificação de tipos, chamada da IMP e retorno do resultado. Medições mostram que o runtime adiciona 10–50 ns por chamada em Objective-C e 5–20 ns no ART.
Para reduzir a sobrecarga, os desenvolvedores usam monomorphic inlining (ART) e method caching (Objective-C). Kotlin/Native e Swift compilam diretamente para ARM64, eliminando completamente a camada de runtime, mas perdendo capacidades dinâmicas — reflexão, swizzling, carregamento dinâmico de classes.
Perguntas frequentes
SDK (Software Development Kit) é um conjunto de ferramentas para desenvolvimento de aplicativos (compilador, bibliotecas, utilitários). Runtime é o ambiente no qual o aplicativo já desenvolvido é executado no dispositivo. O desenvolvedor precisa do SDK, o usuário precisa do runtime.
Não — o runtime é parte do sistema operacional e não pode ser substituído pelo usuário. ART está incorporado no Android Framework, Objective-C Runtime no iOS. O desenvolvedor pode escolher a linguagem (Kotlin/Native sem runtime) ou usar máquinas virtuais como Dart VM no Flutter.
Sim, o runtime afeta o consumo de energia. Garbage collection no ART e Swift runtime usam CPU, o que aumenta o consumo de bateria. Otimizações como concurrent GC e tagged pointers no iOS reduzem o impacto do runtime na bateria em 20–30%.
Runtime error é um erro que ocorre durante a execução: null pointer exception, index out of bounds, divisão por zero. Ao contrário de erros em tempo de compilação, eles não são detectados durante o build. São capturados através de blocos try-catch ou crash reporting (Firebase Crashlytics, Sentry).
Swift runtime é mais leve que Objective-C: não suporta dispatch dinâmico por padrão, usa value types (struct) sem alocação no heap e não tem message forwarding. Métodos Swift são chamados diretamente via vtable a menos que marcados como @objc dynamic. Isso dá um ganho de velocidade de até 5x em benchmarks.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também