Todos os programas têm um ambiente de tempo de execução. Nós tendemos a esquecer isso, mas está lá. Lib padrão para C que envolve chamadas do sistema para o sistema operacional. O Objective-C tem seu tempo de execução que envolve todas as suas mensagens.
Com Java, o tempo de execução é a JVM. A maioria das implementações de Java com as quais as pessoas estão familiarizadas é semelhante à HotSpot JVM, que é um interpretador de código de bytes e compilador JIT.
Esta não precisa ser a única implementação. Não há absolutamente nada a dizer que você não pode criar um tempo de execução padrão para Java e compilar o código no código da máquina nativo e executá-lo no tempo de execução que lida com chamadas para novos objetos em mallocs e acesso a arquivos nas chamadas do sistema na máquina. E é isso que o compilador Ahead Of Time (AOT em vez de JIT) faz. Chamar esse tempo de execução que você vai ... você poderia chamá-lo de uma implementação JVM (e não seguir a especificação JVM) ou um ambiente de tempo de execução ou lib padrão para Java. Está lá e faz essencialmente a mesma coisa.
Isso poderia ser feito reimplementando javac
para atingir a máquina nativa (foi o que o GCJ fez). Ou pode ser feito com a tradução do código de byte gerado pelo código de javac
máquina (ou byte) para outra máquina - é isso que o Android faz. Com base na Wikipedia, é o que o Excelsior JET também faz ("O compilador transforma o código de byte Java portátil em executáveis otimizados para o hardware e sistema operacional (SO) desejado"), e o mesmo vale para o RoboVM .
Existem complicações adicionais com o Java, o que significa que é muito difícil fazer isso como uma abordagem exclusiva. O carregamento dinâmico de classes ( class.forName()
) ou objetos com proxy requer uma dinâmica que os compiladores AOT não fornecem facilmente e, portanto, suas respectivas JVMs também devem incluir um compilador JIT (Excelsior JET) ou um intérprete (GCJ) para manipular classes que não podem ser pré-compiladas nativo.
Lembre-se, a JVM é uma especificação , com muitas implementações . A biblioteca padrão C também é uma especificação com muitas implementações diferentes.
Com o Java8, um bom trabalho foi feito na compilação do AOT. Na melhor das hipóteses, só é possível resumir a AOT em geral dentro dos limites da caixa de texto. No entanto, no JVM Language Summit de 2015 (agosto de 2015), houve uma apresentação: Java Goes AOT (vídeo do youtube). Este vídeo tem 40 minutos de duração e aborda muitos dos aspectos técnicos mais profundos e benchmarks de desempenho.
gcj
exemplo executável mínimoVocê também pode observar uma implementação de código aberto como
gcj
(agora obsoleta). Por exemplo, arquivo Java:Em seguida, compile e execute com:
Agora você é livre para descompilar e ver como funciona.
file Main.o
diz que é um arquivo elfo.readelf -d Main | grep NEEDED
diz que depende das bibliotecas dinâmicas:Portanto, libgcj.so deve estar onde a funcionalidade Java é implementada.
Você pode descompilar com:
e veja exatamente como é implementado.
Parece muito com C ++, muitos nomes desconfortáveis e chamadas de funções polimórficas indiretas.
Gostaria de saber como a coleta de lixo entra em ação. Vale a pena examinar: /programming/7100776/garbage-collection-implementation-in-compiled-languages e outras linguagens compiladas com o GC como o Go.
Testado no Ubuntu 14.04, GCC 4.8.4.
Veja também https://en.wikipedia.org/wiki/Android_Runtime , a espinha dorsal do Android 5 em diante, que faz o AOT completo para otimizar aplicativos Android.
fonte