NoClassDefFoundError ao tentar executar o meu frasco com java.exe -jar ... o que está errado?
-
05-07-2019 - |
Pergunta
Tenho uma aplicação que eu estou tentando envolver em uma jarra para a implantação mais fácil. A aplicação compila e funciona muito bem (em um Windows janela cmd) quando executado como um conjunto de classes acessível a partir do CLASSPATH. Mas quando eu jar-se minhas aulas e tentar executá-lo com java 1.6 na mesma janela cmd, eu começar a receber exceções:
C:\dev\myapp\src\common\datagen>C:/apps/jdk1.6.0_07/bin/java.exe -classpath C:\myapp\libs\commons -logging-1.1.jar -server -jar DataGen.jar
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
at com.example.myapp.fomc.common.datagen.DataGenerationTest.<clinit>(Unknown Source)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
... 1 more
O engraçado é que, a LogFactory ofender parece estar em commons-logging-1.1.jar, que está no caminho de classe especificado. O arquivo jar (sim, é realmente lá):
C:\dev\myapp\src\common\datagen>dir C:\myapp\libs\commons-logging-1.1.jar
Volume in drive C is Local Disk
Volume Serial Number is ECCD-A6A7
Directory of C:\myapp\libs
12/11/2007 11:46 AM 52,915 commons-logging-1.1.jar
1 File(s) 52,915 bytes
0 Dir(s) 10,956,947,456 bytes free
O conteúdo do arquivo-commons-logging 1.1.jar:
C:\dev\myapp\src\common\datagen>jar -tf C:\myapp\libs\commons-logging-1.1.jar
META-INF/
META-INF/MANIFEST.MF
org/
org/apache/
org/apache/commons/
org/apache/commons/logging/
org/apache/commons/logging/impl/
META-INF/LICENSE.txt
META-INF/NOTICE.txt
org/apache/commons/logging/Log.class
org/apache/commons/logging/LogConfigurationException.class
org/apache/commons/logging/LogFactory$1.class
org/apache/commons/logging/LogFactory$2.class
org/apache/commons/logging/LogFactory$3.class
org/apache/commons/logging/LogFactory$4.class
org/apache/commons/logging/LogFactory$5.class
org/apache/commons/logging/LogFactory.class
... (more classes in commons-logging-1.1 ...)
Sim, commons-logging tem a classe LogFactory. E, finalmente, o conteúdo do meu jar manifesto:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.5
Created-By: 10.0-b23 (Sun Microsystems Inc.)
Main-Class: com.example.myapp.fomc.common.datagen.DataGenerationTest
Class-Path: commons-logging-1.1.jar commons-lang.jar antlr.jar toplink
.jar GroboTestingJUnit-1.2.1-core.jar junit.jar
Isso tem me perplexo, e quaisquer colegas de trabalho que eu grampeado por mais de um dia agora. Só para abater as respostas, pelo menos por agora, soluções de terceiros para isso são, provavelmente, devido a restrições de licenciamento e políticas da empresa (por exemplo .: ferramentas para criar exe de ou embalagem até frascos). O objetivo final é criar um frasco que pode ser copiada de minha caixa de Windows desenvolvimento para um servidor Linux (com todos os frascos dependentes) e usado para preencher um banco de dados (assim classpaths pode acabar sendo diferente entre ambientes de desenvolvimento e de implantação). Qualquer pistas para este mistério seria muito apreciada!
Solução
A opção -jar é mutuamente exclusiva de -classpath. Veja um velho descrição aqui
jar
Executar um programa encapsulado em um arquivo JAR. O primeiro argumento é o nome de um arquivo JAR em vez de um nome de classe de inicialização. Para que esta opção funcione, o manifesto do arquivo JAR deve conter uma linha da forma Main-Classe: classname. Aqui, identifica classname a classe tendo o método void main (String [] args) public static que serve como ponto de partida de sua aplicação.
Veja a página de referência ferramenta do frasco ea trilha Jar do Tutorial Java para obter informações sobre como trabalhar com arquivos JAR e manifesta-arquivo JAR.
Quando você usa esta opção, o arquivo JAR é a fonte de todas as classes de usuário e outras configurações de caminho de classe de usuário são ignoradas.
Um hack rápido e sujo é acrescentar o seu classpath para o classpath de inicialização:
-Xbootclasspath / a: caminho
Especifique um caminho separados por dois pontos de directires, arquivos JAR, e ZIP para anexar ao caminho de classe de inicialização padrão.
No entanto, como @ Dan diz, com razão, a solução correta é para garantir o seu JARs manifesto contém o classpath para todos os JARs ele vai precisar.
Outras dicas
Você pode omitir a opção -jar
e iniciar o arquivo jar como esta:
java -cp MyJar.jar;C:\externalJars\* mainpackage.MyMainClass
Este é o problema que está ocorrendo,
Se o arquivo JAR foi carregado de "C: \ java \ apps \ appli.jar", e seu arquivo de manifesto tem o Class-Path: referência "lib / other.jar", o carregador de classe irá procurar em "C : \ java \ apps \ lib \" para "other.jar". Ele não vai olhar para a entrada do arquivo JAR "lib / other.jar".
Solução: -
- clique direito no projeto, selecione Export.
- Selecione Java pasta e nela selecione Arquivo JAR Runnable em vez de arquivo JAR.
- Selecione as opções apropriadas e na seção Biblioteca de Manipulação de seleccionar a opção 3 ou seja (Copie exigido bibliotecas em uma sub-pasta ao lado do JAR gerado).
[ Editar = 3ª opção gera uma pasta, além do frasco, opção 2 ( "Pacote exigido bibliotecas em JAR gerado") também pode ser usado como você tem o frasco. ]
- Clique em Concluir e seu JAR é criado na posição especificada juntamente com uma pasta que contém os JARS mencionados no arquivo de manifesto.
-
abrir o terminal, dar o caminho adequado para o seu jar e executá-lo usando este comando java -jar abc.jar
Agora, o que vai acontecer é o carregador de classe vai olhar na pasta correta para os JARS referenciados já que agora eles estão presentes na mesma pasta que contém seu aplicativo JAR..There não é excepção "java.lang.NoClassDefFoundError" jogado agora .
Isso funcionou para mim ... espero que funcione para você também !!!
Se você usar bibliotecas externas em seu programa e você tenta embalar todos juntos em um arquivo jar não é tão simples, por causa de problemas de caminho de classe etc.
Eu prefiro usar OneJar para este problema.
Eu tive o mesmo problema com o meu jar a solução
- Crie o arquivo MANIFEST.MF:
Manifest-Version: 1.0
Sealed: true
Class-Path:. lib / jarX1.jar lib / jarX2.jar lib / jarX3.jar
Main-Class: com.MainClass
- clique direito no projeto, selecione Export.
Selecione Exportar todas as pastas outpout para o projeto verificado
- selecione usando existente manifesto da área de trabalho e selecione o arquivo MANIFEST.MF
Isso funcionou para mim :)
Eu descobri quando eu estou usando um manifesto que a listagem de frascos para a necessidade classpath ter um espaço após a listagem de cada frasco por exemplo "Required_lib / sun / pop3.jar required_lib / sun / smtp.jar". Mesmo que seja a última na lista.