Classe de pacotes diferentes não executando

7 respostas
T

Olá pessoal. Na minha máquina, eu tenho os seguintes diretórios:

/home/secreto/Java/Testes/app
/home/secreto/Java/Testes/util

No primeiro (app) tenho a seguinte classe (SomeApp.java):
package app;

public class SomeApp
{
	public static void main(String [] args){
		byte[] bytes = new byte[256];
		util.BitUtils.process(bytes);
	}
}
No segundo (util) tenho a seguinte classe (BitUtils)
package util;

public class BitUtils
{
	public static void process(byte[] b){}
}

Para compilar, eu fui até dentro do diretório app e executei o comando: javac SomeApp.java -cp /home/secreto/Java/Testes/ Compilou normalmente.
OBS: Caso não use o parâmetro -cp com esse caminho que especifiquei, o compilador reclama de não ter achado a classe BitUtils.

O problema é que na hora de executar, está dando uma java.lang.NoClassDefFoundError. Para a execução, eu entro no diretório app (que é onde está a classe SomeApp.class que contém o método main) e dou o comando: java SomeApp -cp /home/secreto/Java/Testes/ , mas sempre gera esse erro de NoClassDefFoundError. Não sei onde posso estar errando. Também já tentei executar assim: java SomeApp e assim: java SomeApp -cp /home/secreto/Java/Testes/app e nada também.

Alguém sabe o que pode estar acontecendo?
Obrigado!

7 Respostas

pmlm

Tens de indicar todo o caminho, com o nome da package.

Na directoria Testes:

java app.SomeApp

T

Olá pmlm. Isso de fato funcionou, mas, não há como executá-lo de dentro do diretório app? (ou de qualquer outro diretório da minha máquina).

pmlm

java app.SomeApp -cp /home/secreto/Java/Testes/

T

ok, agora a última pergunta :lol: Tem como executar sem usar app.SomeApp ???

pmlm

Não colocando na package app? :slight_smile:

T

Não. Ainda na package app. Tem como executar o programa sem usar app.SomeApp?

rmala_ti

Algumas considerações que fazendo testes eu cheguei:
(pode ser óbvio mas não sabia disso)

Considerando a estrutura:

/home/
   secreto/
        java/
           testes/     //---> testes é raiz para app e util
                 app/
                    SomeApp.java
                 util/
                    BitUtils.java

A) Comando-> javac:
* Não leva em consideração se tem ou não package declarado na classe;
* se tiver a opção "-d" junto ao classpath, o package poderá ser usado;
* O classpath não serve para localizar a classe a ser COMPILADA;
* O classpath na linha de comando/ambiente serve para informar onde estão as classes que SomeApp vai precisar;
* o pacote declarado na instrução import é usado pelo classpath para encontrar classes que a Classe a ser compilada irá precisar;

Situação 1: SomeApp não depende de outra classe:

package app;  //para javac package não tem relevância 
   
 public class SomeApp  
 {  
     public static void main(String [] args){}  
}
Neste caso é possível fazer algo como:
javac SomeApp.java;  //executado em app
javac /home/secreto/java/testes/app/SomeApp.java  //de qualquer diretório pois o caminho é absoluto

Situação 2: SomeApp depende de util.BitUtils:
* o classpath tem que conter o caminho até o diretório raiz do pacote util, que neste caso é testes para que possa localizar util e depois a classe BitUtis

package app;  //para javac package não tem relevância 
   
 public class SomeApp  
 {  
     public static void main(String [] args){
       byte[] bytes = new byte[256];
       util.BitUtils.process(bytes); //javac precisa encontrar (via classpath) a classe util.BitUtils
    }  
}
Neste caso o classpath de linha de comando/ambiente deverá conter o caminho até a classe util.BitUtils
javac /home/secreto/java/testes/app/SomeApp.java //erro, javac não encontra util.BitUtils
javac -cp . /home/secreto/java/testes/app/SomeApp.java //erro se executar dentro de util, dentro de teste funciona (. é o diretório atual)

Mas informando ao classPath onde util.BitUtils se encontra o código funcionará:

javac -cp ../. /home/secreto/java/testes/app/SomeApp.java // executando dentro de util ou app
javac -cp . /home/secreto/java/testes/app/SomeApp.java // executando dentro de testes

B) Comando-> java:

* Leva em consideração se tem package declarado na classe, e deve usar nomeDoPacote.NomeDaClasse
* O classpath na linha de comando/ambiente serve para informar onde estão a raiz dos pacotes que SomeApp vai precisar

Situação 1: classe a ser executada não tiver a instrução package e não usar nenhuma outra classe:
pode-se executar a classe diretamente no diretório que a classe.class se encontra:

java NomeClass

Situação 2: classe a ser executada tiver a instrução package

package app;  //para java package tem relevância 
   
 public class SomeApp  
 {  
     public static void main(String [] args){
       byte[] bytes = new byte[256];
       util.BitUtils.process(bytes); //java precisa encontrar (via classpath) a classe util.BitUtils
    }  
}
- Tentar executar essa classe no diretório app dessa forma:
java SomeApp
java ../SomeApp
Dá exeção SomeApp java.lang.NoClassDefFoundError: SomeApp (wrong name: app/SomeApp)

Então como executar?

Para executar a classe em app é obrigatório:
1º) incluir o classpath até o diretório raiz do pacote (testes)
2º) incluir o nome da classe: Atenção o nome da classe não é SomeApp. Deve incluir o package assim: app.SomeApp

retorna ao diretório anterior (raiz do pacote) e inclui o nome da classe
java -cp .. app.SomeApp //executando em app (.. volta para testes)
caminho absoluto até a raiz do pacote e nome da classe
java -cp /home/secreto/java/testes/ app.SomeApp //executando de qualquer local pois o caminho é absoluto até a raiz do pacote
Incluir o caminho absoluto até app não funciona:
java -cp /home/secreto/java/testes/app SomeApp //app não é raiz do pacote app
ou
java -cp /home/secreto/java/testes/app app.SomeApp //app não é raiz do pacote app

* o classpath tem que ser até o diretório raiz do pacote, que neste caso é testes e incluir o nome da classe app.SomeApp

E se SomeApp dependesse de outra classe?

/home/
   secreto/
        java/ // ---> java é raiz para testes
           testes/     //---> testes é raiz para app e util
                   OtherTestes.java 
                 app/
                    SomeApp.java
                 util/
                    BitUtils.java
package app;  //para java package tem relevância 
   
 public class SomeApp  
 {  
     public static void main(String [] args){
       byte[] bytes = new byte[256];
       
       util.BitUtils.process(bytes); //java precisa encontrar (via classpath) a classe util.BitUtils
       
       testes.OtherTestes.other(); //java precisa encontrar (via classpath) a classe testes.OtherTestes
    }  
}
Para javac: *Agora javac terá que encontrar através do classpath tanto util.BitUtils quanto testes.OtherTestes
javac -cp ../.:../../. /home/secreto/java/testes/app/SomeApp.java // funciona
Para java
java -cp ../;../../ app.SomeApp //executando em app
../ : localiza a raiz de util.BitUtils que é testes ../../ : localiza a raiz de testes.OtherTestes que é java
java -cp ../;. app.SomeApp //executando em testes
../ : localiza a raiz de testes.OtherTestes que é java . : localiza a raiz de util.BitUtils que é testes (já estamos em testes então . informa que é o diretório atual)

Bom foi assim que eu entendi.

Pode haver algum erro de conceito mas pra mim ficou claro dessa forma.

Abraços.

Criado 8 de janeiro de 2010
Ultima resposta 25 de fev. de 2010
Respostas 7
Participantes 3