Dúvida sobre gerar JAR

O meu programa tem um método para gerar um .jar. Primeiro o programa compila os .java e depois gera o jar.

Para compilar eu uso este código:

        try {
            Runtime cmd = Runtime.getRuntime();
            File[] files = new File("C:\\Users\\Andreia\\Documents\\novoPrograma1"
                    ).listFiles();

            for (File f : files) {
                cmd.exec("javac.exe "
                        + f.getAbsolutePath());
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }

E para gerar o JAR:

         try {            
            Runtime cmd = Runtime.getRuntime();

            Process processo = cmd.exec("jar -cvfm " 
                    + "C:\\Users\\Andreia\\Documents\\MeuJar.jar "
                    + "C:\\Users\\Andreia\\Documents\\META-INF\\manifest.mf "
                    + "novoPrograma1\\");

        } catch (IOException e) {
            e.printStackTrace();
        }

Mas eu tenho dois problemas.

  1. Eu chamo o método para compilar e em seguida o método para gerar o JAR, mas se houver muitos arquivos para compilar, quando cria o JAR ficam faltando alguns arquivos, pois não dá tempo de compilar todos.
    Não sei como verificar se todos os arquivos já foram compilados antes de chamar o método para gerar o JAR.

  2. O JAR criado só é concluído depois que eu fecho o meu programa.
    Eu não sei porque isso acontece!

se vc usar o proprio IDE do eclipse da para se fazer bem simples , sem precisar de codigo hahaha…e sim de pensamento lol

Dona Andréa, seria possível você usar o javax.tools em vez do javac.exe?
Só tem um probleminha - requer Java 6 ou superior.
http://docs.oracle.com/javase/6/docs/api/javax/tools/package-summary.html#package_description

[quote=entanglement]Dona Andréa, seria possível você usar o javax.tools em vez do javac.exe?
Só tem um probleminha - requer Java 6 ou superior.
http://docs.oracle.com/javase/6/docs/api/javax/tools/package-summary.html#package_description

Já tentei usar o javax.tools e funcionou, mas como eu disponibilizo o meu software para download não gostaria que ele ficasse dependente de libs, porq fica mais pesado para baixar!

Hum… certo. Então só tem um probleminha, que é o de você ter feito isto:

    for (File f : files) {  
        cmd.exec("javac.exe "  
                + f.getAbsolutePath());  
    } 

Obviamente, há dois problemas aqui.

a) Você está supondo que o javac.exe está no path do cidadão que vai usar o seu pacote (acho que está OK)
b) Você não está esperando a execução do javac.exe para passaro ao comando depois do for. É por isso que você reclama que de vez em quando os arquivos não estão completamente compilados.

Provavelmente você vai ter de dar uma olhadinha naquele famoso artigo:

Casualmente, o exemplo que ele dá é com o javac.exe mesmo :slight_smile:

De qualquer maneira, a presença de javax.tools não depende exatamente de um download mas sim de
a) o fulano ter o JDK instalado, e
b) a versão do Java ser 6.0 ou superior.

tenta usar um metodo sincronizado para ver se fica certo, a lib e tao grande assim ??

Métodos sincronizados não resolvem o problema dela.
O problema dela é que ela não está esperando o javac.exe terminar, e isso não se resolve com um “synchronized”.

[quote=Andr?a]O meu programa tem um método para gerar um .jar. Primeiro o programa compila os .java e depois gera o jar.

Para compilar eu uso este código:

        try {
            Runtime cmd = Runtime.getRuntime();
            File[] files = new File("C:\\Users\\Andreia\\Documents\\novoPrograma1"
                    ).listFiles();

            for (File f : files) {
                cmd.exec("javac.exe "
                        + f.getAbsolutePath());
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }

E para gerar o JAR:

         try {            
            Runtime cmd = Runtime.getRuntime();

            Process processo = cmd.exec("jar -cvfm " 
                    + "C:\\Users\\Andreia\\Documents\\MeuJar.jar "
                    + "C:\\Users\\Andreia\\Documents\\META-INF\\manifest.mf "
                    + "novoPrograma1\\");

        } catch (IOException e) {
            e.printStackTrace();
        }

Mas eu tenho dois problemas.

  1. Eu chamo o método para compilar e em seguida o método para gerar o JAR, mas se houver muitos arquivos para compilar, quando cria o JAR ficam faltando alguns arquivos, pois não dá tempo de compilar todos.
    Não sei como verificar se todos os arquivos já foram compilados antes de chamar o método para gerar o JAR.

  2. O JAR criado só é concluído depois que eu fecho o meu programa.
    Eu não sei porque isso acontece!
    [/quote]

Olá, você pode fazer assim:


public boolean makeClass() {
      try {
            Runtime cmd = Runtime.getRuntime();
            File[] files = new File("C:\\Users\\Andreia\\Documents\\novoPrograma1"
                    ).listFiles();

            for (File f : files) {
                cmd.exec("javac.exe "
                        + f.getAbsolutePath());
            }
            return true;
        } catch (IOException ex) {
            ex.printStackTrace();
        }
}

public void makeJarFile() {
    try {
            Runtime cmd = Runtime.getRuntime();
            File[] files = new File("C:\\Users\\Andreia\\Documents\\novoPrograma1"
                    ).listFiles();

            for (File f : files) {
                cmd.exec("javac.exe "
                        + f.getAbsolutePath());
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
}

if (makeClass) {
     makeJarFile();
}

Godzilla, você não enxergou ainda o problema dela. O problema da Andréa é realmente não esperar o javac.exe acabar. Não adianta ir metendo um monte de try/catch que não é isso que vai resolver (e pior, seu código nem compila porque não tem um “return false” depois do try).

entanglement, eu li o artigo mais ou menos. Não sei inglês e traduzi no google Tradutor, mas não entendi muito bem.
Ainda não sei como fazer para saber se o javac.exe já terminou de executar, no caso de compilar os arquivos.
E por que quando eu gero o .jar ele não termina de criar o JAR até que eu feche o meu programa?

Mude a estrutura do seu programa para que o método de criação do Jar
seja chamado através de um evento após a compilação do último arquivo
através da implementação do pattern observer, também conhecido como Listener,
veja os links abaixo:
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Observable.html
http://elope.wordpress.com/2006/04/07/tutorial-on-observer-pattern-2/

Se você quiser uma outra solução mais simples, recomendo criar um único método
que executa os dois comandos sequencialmente criando um array com os dois comandos.

String[] comandos = {"javac *.java", "jar -cmf meuPrograma.jar *.class"}; Runtime.getRuntime().exec(commandos);

Assim naturalmente os comandos seriam executados na ordem após a finalização de cada
um.

[quote=entanglement]De qualquer maneira, a presença de javax.tools não depende exatamente de um download mas sim de
a) o fulano ter o JDK instalado, e
b) a versão do Java ser 6.0 ou superior. [/quote]

entanglement, eu me confundi. Eu tava me referindo a lib tools.jar.

Mas javax.tools eu usei também, mas dava erro na hora de compilar os arquivos dentro do pacote!
Não consegui achar a solução e passei a usar javax.exec!

Olá, me diga uma coisa, qual a logica de compilar um monte de classes e jerar um jar, cujo precisa de todas as classes compiladas. Releia novamente as duas questões que ela coloca acima.

1.: Isto acontece por que você esta chamando os dois metodos um em seguida do outro, sem aguardar o primeiro que compila as classes terminar o seu trabalho. E com isso claro que o mesmo nao consegue colocar todas as classes necessarias dentro do arquivo .jar, a [u]SUGESTÃO[/u], veja [quote]entanglement[/quote], foi apenas uma sugestão, que éla deveria aguardar o primeiro metodo terminar o seu trabalho e só depois disso chamar o outro, o que eu sugestionei foi que ela chama-se um metodo que retorna um true ou false, para que o segundo metodo so deve ser chamado quando o primeiro terminar o serviço, e se seu retorno fosse verdadeiro.

Gostaria de pedir desculpas por ter colocado uma sugestão com o código errado, pois somente peguei o codigo que já existia e fiz uma sugestão para clarear a ideia. Fui infeliz na ajuda, caso o conteudo que postei não for ajudar, por favor desconsiderem as postagens.

Att, André Dalcin

Galera, consegui resolver o meu problema. Estou usando o Runtime para compilar os .java e para gerar o JAR uso JarOutputStream.

O código para gerar o jar esta aqui: http://ateoriadadesevolucao.blogspot.com/2012/06/criar-arquivo-jar-com-jaroutputstream.html
Com esse código eu consigo colocar pacotes dentro do JAR.

Para quem quiser ver como ficou o programa, pode baixar aqui:
http://ateoriadadesevolucao.blogspot.com/p/software-j-planet.html