NoClassDefFoundError ao tentar executar o meu frasco com java.exe -jar ... o que está errado?

StackOverflow https://stackoverflow.com/questions/250166

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!

Foi útil?

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: -

  1. clique direito no projeto, selecione Export.
  2. Selecione Java pasta e nela selecione Arquivo JAR Runnable em vez de arquivo JAR.
  3. 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. ]

  1. 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.
  2. 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

  1. 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

  1. clique direito no projeto, selecione Export.

Selecione Exportar todas as pastas outpout para o projeto verificado

  1. 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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top