Reflection, Classpath e jar

0 respostas
argard

Oi, pessoal, quebrei a cabeça a tarde inteira para resolver mas não saiu. Saiu agora na hora que eu estava pedindo penico :stuck_out_tongue: , mas vamos lá, vou compartilhar o meu ex-problema =D.

Antes de tudo, estou utilizando o netbeans 6.7. Windows e Linux, o problema acontecia nos dois SOs.

O ex-problema:

Eu tenho um formulário, com 2 textareas, a primeira é para colocar o codigo java de uma classe qualquer e a segunda o resultado da compilação (em java) desse código, e dois butões, “COMPILA” e “EXECUTE”. Esse é o cenário.

Então o que acontecia, quando eu executava pelo netbeans, este com o classpath configurado, funcianava bem, no reflection não tinha problema pois a JVM achava os arquivos que foram compilados, no entanto quando eu executava o arquivo de distribution gerado, o jar file, com o comando java -jar nomejar.jar, dava um erro. Bem na hora de executar o invoke de um método da classe recém criada, a JVM não achava-a, dando ClassNotFoundException. Pesquisei muito e tive hit na resposta umas duas vezes, mas não caiu a ficha de como o URLClassLoader funcionava em si, dando sempre o mesmo problema. Eu tentava colocar no URLClassLoader o caminho completo do arquivo, ou seja, path/nomedoarquivo.class. Mas não funcionava de jeito algum. Assim fiquei matutando aqui e percebi que quando se usa URLClassLoader, você passa o(s) “CAMINHO(S)” das classes que você utilizará, não os fullpath da classe que queira usar. Ou seja

Se sua classe tive o seguinte fullpath: c:\caminho\AlgumaClasse.class . O URLClassLoader é criado com os caminhos das classes , como “c:\caminho”, para que assim quando for dado o loadClass(“AlgumaClasse”), ele retorne o seu novo tipo. A partir daí, criando-se uma nova instância da sua classe que será utilizada pelo invoke dos métodos.

Portanto era um problema que a solução estava embaixo do nariz, realmente simples mas incrivelmente chato e besta. Assim espero que isso possa ajudar alguém no futuro.

Abração

Segue o trecho do código para ficar mais rápido de entender :wink:

URLClassLoader classeLoader ;
            Class classe;
            File path = new File(".");

            //contadorClasses variavel inteira que vai incrementando após cada compilação
            //gerando Teste1.class, Teste2.class, Teste3.class, etc...

            //errado, pois o classpath utiliza um caminho, não o full path do arquivo
            //URL url = new File(path.getCanonicalPath() + "/Teste" + contadorClasses + ".class").toURL();

            //certo, pois define o caminho da sua nova classe que acabara de ser criada
            URL url = new File(path.getCanonicalPath()).toURL();

            
            jLabel2.setText(url.getPath());
            classeLoader = new URLClassLoader(new URL[]{url});
            classe = classeLoader.loadClass("Teste" + contadorClasses);
            Object instancia = classe.newInstance();

            Method metodoHello = classe.getDeclaredMethod("hello");
            metodoHello.setAccessible(true);
            metodoHello.invoke(instancia); //executa o metodo escrevendo no console o hello world

            Method metodoVolta1 = classe.getDeclaredMethod("volta1");
            metodoVolta1.setAccessible(true);
            Object i = metodoVolta1.invoke(instancia); //executa o metodo volta1 retorna um número inteiro
            txtResultados.append("\nO valor de i é " + (Integer) i); //mostra na textarea dos resultados o valor retornando
Criado 12 de dezembro de 2009
Respostas 0
Participantes 1