Infra - Linux

Desempenho e portabilidade: GCJ o compilador Java Livre

Com a repercussão gerada quando a Sun resolveu disponibilizar o código fonte do Java, resolvi testar o Java Livre. O projeto GCJ da GNU é um compilador Java totalmente livre, onde o desenvolvedor pode gerar bytecode ou código binário nativo. Não sou especialista em Java, mas fiquei surpreso ao executar os testes mencionados neste artigo.

por Alessandro de Oliveira Faria



Introdução e instalação:

O projeto GCJ é um compilador Java 100% livre no qual podemos gerar bytecodes ou binários nativos. Baseado em algumas pesquisas, cheguei a conclusão que existe suporte ao kit Java J2SE 1.4.2, mas não na API Swing. Mas acredito que esta não disponibilidade é apenas uma questão de tempo.

A Red Hat há algum tempo lançou uma versão do Eclipse que não depende da JVM, compilada com o GCJ, gera programas para execução nativa, como o compilador GCC. O Eclipse é um ambiente de desenvolvimento utilizado por programadores Java, C e C++.

Em aproximadamente em fevereiro de 2006, foi disponibilizada à comunidade a versão 4.1.0 do GCC com diversas mudanças.

O GCC possui front-ends para as linguagens C, C++, Objective C, Fortran, Java e Ada e suas respectivas bibliotecas. Sendo assim posso dizer que estamos mais próximo de um compilador livre para Java com capacidade de traduzir bytecodes ou código-fonte em Java para código executável nativo. Imagine a portabilidade do Java junto a performance do compilador C.

Instalação dos pacotes necessários:

Em minha distribuição SuSE bastou utilizar os pacotes gcc-java, libgcj e libgcj-devel, como no exemplo abaixo:

Para efeito de informação, a libgcj fornece para a aplicação os componentes em tempo de execução que seriam fornecidos pela JVM.

Compilando e testando um programa exemplo

Compilando um programa "OLA MUNDO".

Para compilar um programa em Java utilizamos o comando gcj. Abaixo alguns parâmetros utilizados na sintaxe de compilação:

  • -o : Nome do arquivo binário a ser gerado;
  • -c : Cria apenas o arquivo objeto;
  • -O : Compila com otimizações;
  • -g : Gera informações para o debug;
  • --main=Nome-Classe : Nome da classe utilizada para iniciar o programa.

Para iniciar, crie um programa "OLA MUNDO" em Java para efetuarmos os primeiros testes de compilação. Abaixo o conteúdo do programa BemVindo.java. Para quem preferir o download pode ser efetuado aqui.

// Olá mundo em java.
// Arquivo BemVindo.java.
public class BemVindo
{
   public static void main(String[] args)
        {
      System.out.println("Olá Mundo!");
   }
} 

Agora compilaremos o nosso primeiro programa informando o nome do arquivo binário (BemVindo), a classe main e no nome do arquivo fonte.

Pronto! Após a compilação, basta executar o programa BemVindo como no exemplo abaixo:

$ gcj -o BemVindo --main=BemVindo BemVindo.java
$ ./BemVindo
Olá Mundo! 

Gerando um bytecode com o programa "OLA MUNDO"

Para não gerar um código nativo e sim um bytecode, basta utilizar o parâmetro -C. O comando gij utiliza a biblioteca libgcj para proporcionar ao sistema uma máquina virtual. Vale à pena ressaltar que a variável ambiental CLASSPATH do Java é utilizada gij e gcj.

No exemplo abaixo geramos um bytecode e o executamos com o JVM da Sun e com o GIJ! Veja como é simples:

$ gcj -C BemVindo.java
$ ls BemVindo.class
BemVindo.class
$ gij BemVindo
Olá Mundo! 

Agora teste o bytecode gerado como JVM do Java:

$ java BemVindo
Olá Mundo! 

Outro ponto importantíssimo é que tanto gcj quanto o gij conseguem utilizar pacotes JAR na compilação e na execução de programa. O GCJ possui um utilitário similar ao jar, o fastjar, escrito inteiramente em C.

Para compilar aplicações com várias classes, basta utilizar o parâmetro -c, logo após cria o binário. Veja no exemplo abaixo:

$ gcj -c Classe1.java 
$ gcj -c Main.java 
$ ls 
Classe1.java 
Classe1.o 
Main.java 
Main.o 
$ gcj -o programa1 main=Main Classe1.o Main.o
$ ls 
programa1 
Classe1.java 
Classe1.o 
Main.java 
Main.o 
$ ./programa 
Testando a performance (compactando um vídeo mpeg)

Escolhi um programa em Java que compacta um arquivo MPEG para testar a performance de execução. O principal motivo que levou a esta escolha foi a compactação que exige um pouco de cálculo e a leitura e gravação em disco (assim conseguindo obter resultado com I/O).

Baixe o programa Glauber Brilhante no Viva o Linux e descompacte com o programa unzip como no exemplo abaixo:

$ unzip Zip.zip
Archive: Zip.zip
  inflating: Zip/Zipando.java 

O programa efetua a compactação de um programa informado pelo teclado. Como o objetivo é verificar a performance, efetuei algumas alterações para o código assumir sempre determinados valores. Abaixo menciono as linhas que a serem alteradas.

Quem preferir adquirir o código já alterado, efetue o download aqui.

Para efeito de informação, explicarei passo a passo as alterações. Primeiro entre na pasta criada Zip e edite o programa Zipando.java.

$ cd Zip/
$ vi Zipando.java 

Na linha 31 o programa solicita a digitação do nome do arquivo destino (arquivo zip a ser criado). Sendo assim comentei a linha 31 e atribui na linha 32 uma constante na variável SAIDA.

 
     31    // saida = leia.readLine();
     32    saida = "video.zip";
 

Já na linha 55 o programa solicita a digitação do tipo de informação a ser compactada 1=arquivo e 2=pasta. Novamente comentei a linha 55 e atribui na linha 56 o retorno da constante 1.

 
     55    //return leia.readLine();
     56    return "1";
 

Agora na linha 89 o programa solicita a digitação do nome do arquivo origem (nome caso utilizei o arquivo de vídeo tst.mpg). Então comentei a linha 89 e atribui na linha 90 uma constante na variável nome.

 
     89 // nome = leia.readLine();
     90  nome ="tst.mpg";
 

Agora compile com o gcj, gij e com o javac o nosso programinha, execute com o comando time para analisarmos os resultados como no exemplo abaixo:

ATENÇÃO: Ressalto que executei o programa 2 vezes para não criar falsos resultados em função do cache de disco.

Compilando e executando com o Java:

$ javac Zipando.java
$ time java Zipando
Zipando.java
Zipando arquivos ou pastas

Digite o nome do arquivo a ser gerado:
Selecione..compactacao de:
1. Arquivo
2. Pasta
Opcao:
Digite o nome do arquivo a ser zipado:
Compactando: tst.mpg

Arquivo zipado com sucesso! 
real    0m24.482s
user    0m19.613s
sys     0m1.380s

Compilando e executando com o gcj: 

$ gcj -o Zipando --main=Zipando Zipando.java
$ time ./Zipando
Zipando.java
Zipando arquivos ou pastas

Digite o nome do arquivo a ser gerado:
Selecione..compactacao de:
1. Arquivo
2. Pasta
Opcao:
Digite o nome do arquivo a ser zipado:
Compactando: tst.mpg

Arquivo zipado com sucesso! 
real    0m12.600s
user    0m10.565s
sys     0m1.172s

Compilando com o gcj e executando com o gij: 

$ gcj -C Zipando.java
$ time gij Zipando
Zipando.java
Zipando arquivos ou pastas

Digite o nome do arquivo a ser gerado:
Selecione..compactacao de:
1. Arquivo
2. Pasta
Opcao:
Digite o nome do arquivo a ser zipado:
Compactando: tst.mpg

Arquivo zipado com sucesso! 
real    0m13.225s
user    0m9.365s
sys     0m0.988s

Abaixo os resultados:

-----------------------------
! Execução        !  Tempo  !
! Java bytecode   ! 24.482s !
! Código nativo   ! 12.600s !
! gij bytecode    ! 13.225s !
-----------------------------

Quero deixar bem claro que o objetivo deste documento não é gerar polêmica, muito menos classificar como melhor ou pior determinada tecnologia, e sim disponibilizar os teste efetuados na NETi TECNOLOGIA junto a equipe de desenvolvimento e pesquisa da empresa.

Alessandro de Oliveria Faria (CABELO)
Analista de Negócios
http://www.netitec.com.br/alessandro

Alessandro de Oliveira Faria

Alessandro de Oliveira Faria - Sócio-proprietário da empresa NETi TECNOLOGIA fundada em Junho de 1996 (http://www.netitec.com.br), empresa especializada em desenvolvimento de software e soluções biométricas, Consultor Biométrico na tecnologia de reconhecimento facial, atuando na área de tecnologia desde 1986 assim propiciando ao mercado soluções em software nas mais diversas linguagens e plataforma, levando o Linux a sério desde 1998 com desenvolvimento de soluções open-source, membro colaborador da comunidade Viva O Linux, mantenedor da biblioteca open-source de vídeo captura entre outros projetos.