1. Introdução

Um programa Java segue uma linha tradicional de tradução e execução, assim como a linguagem C também faz. No entanto, Java foi inventado com objetivos diferentes como: funcionar o mais rapidamente possível e em qualquer plataforma, mesmo que para isso tenhamos um declínio no tempo de execução.

A figura abaixo mostra as etapas seguidas nos processos de tradução e execução dos programas Java.

Etapas de Tradução para programas Java

Figura 1: Etapas de Tradução para programas Java

A primeira diferença que podemos notar para o processo de tradução e execução das linguagens de programação é que no Java temos que ao invés de compilar para a linguagem de montagem assembly de um computador destino, tem-se uma compilação para instruções fáceis de interpretar: bytecode Java. Esse conjunto de instruções é muito próximo da linguagem Java. Assim essa etapa de compilação torna-se um tanto trivial, de forma que não se tem nem mesmo uma fase de otimização que normalmente é feita por qualquer compilador. Todos os programas Java são distribuídos na forma binária desses bytecodes. Portanto, o bytecode é um formato de código intermediário entre o código fonte escrito pelo programador em linguagem Java e o código de máquina que o computador consegue executar.

Deve-se ressaltar que um programador Java não precisa codificar em bytecodes e nem mesmo ser um perfeito entendedor desse código para se tornar um bom programador, da mesma forma que um programador C não precisa conhecer linguagem de montagem assembly para entender uma linguagem C. Mesmo que existam montadores que permitem a escrita de bytecodes diretamente, eles raramente são utilizados. Atualmente existem diversos compiladores que transformam códigos em linguagem Java para bytecodes como o javac da Sun, Jikes da IBM, GCJ da GNU, entre diversos outros.

No restante do artigo verificaremos melhor como funciona cada uma das etapas do processo de tradução até a execução de um programa Java.

2. Java Virtual Machine

A Java Virtual Machine ou JVM é um interpretador Java que carrega e executa os aplicativos Java que estão em bytecodes, convertendo esses bytecodes em código executável de máquina. Um interpretador nada mais é do que um programa que simula um conjunto de instruções. Dessa forma, não temos uma etapa de montagem separada. A JVM também possui outras funções como o gerenciamento de aplicativos na medida em que eles são executados.

A portabilidade é a grande vantagem dessa interpretação. Os mais diversos tipos de dispositivos hoje possuem uma versão da Java Virtual Machine (JVM) para executar os programas Java, desde os telefones celulares até navegadores (browsers) para web. Por este motivo é que o Java é considerado independente de plataforma, pois basta possuirmos uma versão da JVM para os programas escritos em Java poderem funcionar em qualquer plataforma de hardware e software. Mais informações sobre o funcionamento interno da Java Virtual Machine são encontradas na sua especificação oficial em http://docs.oracle.com/javase/specs/jvms/se7/html/index.html ou no livro do Joshua Engel que se encontra na bibliografia do artigo.

No entanto, sabe-se que se por um lado a interpretação ajuda em alguns pontos, mas prejudica em outros como o desempenho. Para se ter uma ideia, o fator de atraso é de 10 vezes comparando-se a programas compilados em C, por exemplo.

Porém, sabe-se que com o avanço incrível da tecnologia temos que programas interpretados tornaram-se viáveis atualmente.

No intuito de preservar a portabilidade e aumentar a velocidade, novas técnicas foram desenvolvidas, como compiladores Just-In-Time que será visto na próxima seção.

3. Compiladores Just-In-Time (JIT)

Compiladores Just-In-Time foram o próximo passo no desenvolvimento do Java. Compiladores Just-In-time são compiladores que traduziam enquanto o programa estava sendo executado. Esses compiladores nada mais fazem do que traçar o perfil do programa em execução para descobrir onde estão os métodos principais do programa, e depois os compilam para o conjunto de instruções nativo em que a máquina virtual está executando. A parte compilada é salva para a próxima vez em que o programa for executado, de modo que a execução possa ser feita mais rapidamente da próxima vez em que ele for executado.

Este equilíbrio entre interpretação e compilação evoluiu bastante com o passar do tempo, de modo que os programas Java executados com frequência sofrem pouquíssimo trabalho extra da interpretação.

Um dado importante que deve ser ressaltado é que pesquisas atuais relatam que a lacuna de desempenho entre Java e C ou Java e C++ está se fechando cada vez mais devido a velocidade cada vez maior dos computadores (assim os compiladores conseguem fazer mais) e os melhores meios inventados pelos pesquisadores para compilar Java durante a execução.

4. Conclusão

Neste artigo vimos que um programa Java é primeiro compilado para uma versão binária dos bytecodes Java e que após isso ele está pronto para ser executado no interpretador Java Virtual Machine (JVM). A JVM por sua vez link-edita os métodos desejados na biblioteca Java enquanto o programa está sendo executado. No entanto, também vimos que para conseguirmos um melhor desempenho, a JVM pode chamar o compilador Just-In-Time (JIT), que compila métodos seletivamente para a linguagem nativa da máquina em que está executando.

Bibliografia

  • Organização e Projeto de Computadores. David Patterson, John Hennessy. Elsevier, 2005.
  • Organização Estruturada de Computadores. Tenenbaum. Addison Wesley, 2010.
  • JVM Specification
  • Engel, Joshua. Programming for the Java Virtual Machine. Reading, Massachusetts: Addison-Wesley
  • Dahm, M., Byte Code Engineering, Proceedings JIT’99, Springer, 1999.