NoClassDefFoundError durante il tentativo di eseguire il mio jar con java.exe -jar ... cosa c'è che non va?

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

Domanda

Ho un'applicazione che sto cercando di avvolgere in un barattolo per una distribuzione più semplice. L'applicazione viene compilata ed eseguita correttamente (in una finestra cmd di Windows) quando viene eseguita come un insieme di classi raggiungibili da CLASSPATH. Ma quando accumulo le mie lezioni e provo a eseguirlo con java 1.6 nella stessa finestra cmd, comincio a ottenere eccezioni:

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

La cosa divertente è che LogFactory offensivo sembra essere in commons-logging-1.1.jar, che si trova nel percorso di classe specificato. Il file jar (sì, è davvero 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

Il contenuto del file 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 ...)

Sì, la registrazione comune ha la classe LogFactory. E infine, il contenuto del manifest del mio vaso:

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

Questo mi ha sconcertato e tutti i colleghi che ho assillato per più di un giorno ormai. Solo per cogliere le risposte, almeno per ora, le soluzioni di terze parti a questo sono probabilmente fuori a causa di restrizioni di licenza e politiche aziendali (ad esempio: strumenti per creare exe o confezionare barattoli). L'obiettivo finale è quello di creare un vaso che può essere copiato dalla mia finestra di Windows di sviluppo su un server Linux (con qualsiasi barattolo dipendente) e utilizzato per popolare un database (quindi i percorsi di classe potrebbero finire per essere diversi tra ambienti di sviluppo e distribuzione). Qualsiasi indizio su questo mistero sarebbe molto apprezzato!

È stato utile?

Soluzione

L'opzione -jar si esclude a vicenda da -classpath. Guarda una vecchia descrizione qui

  

-jar

     

Esegue un programma incapsulato in un file JAR. Il primo argomento è il nome di un file JAR anziché un nome di classe di avvio. Affinché questa opzione funzioni, il manifest del file JAR deve contenere una riga del modulo Main-Class: classname. Qui, classname identifica la classe che ha il metodo main statico vuoto vuoto (String [] args) che funge da punto di partenza dell'applicazione.

     

Vedere la pagina di riferimento dello strumento Jar e la traccia Jar del Tutorial Java per informazioni sull'uso dei file Jar e dei manifesti file Jar.

     

Quando si utilizza questa opzione, il file JAR è l'origine di tutte le classi utente e le altre impostazioni del percorso delle classi utente vengono ignorate.

Un trucco rapido e sporco è quello di aggiungere il tuo percorso di classe al percorso di classe bootstrap:

  

-Xbootclasspath / a: path

     

Specifica un percorso separato da due punti di direttori, archivi JAR e archivi ZIP da aggiungere al percorso di classe bootstrap predefinito.

Tuttavia, come @Dan dice giustamente, la soluzione corretta è assicurarsi che il tuo JARs Manifesto contenga il percorso di classe per tutti i JAR di cui avrà bisogno.

Altri suggerimenti

Puoi omettere l'opzione -jar e avviare il file jar in questo modo:

java -cp MyJar.jar; C: \ externalJars \ * mainpackage.MyMainClass

Questo è il problema che si sta verificando,

se il file JAR è stato caricato da " C: \ java \ apps \ appli.jar " ;, e il tuo file manifest ha il percorso di classe: riferimento " lib / other.jar " ;, il caricatore di classi cercherà in " C: \ java \ apps \ lib \ " per " altro.jar " ;. Non esaminerà la voce del file JAR " lib / other.jar " ;.

Soluzione: -

  1. Fai clic destro sul progetto, seleziona Esporta.
  2. Seleziona la cartella Java e in essa seleziona il file JAR eseguibile anziché il file JAR.
  3. Seleziona le opzioni appropriate e nella sezione Gestione libreria seleziona la terza opzione, ovvero (Copia le librerie richieste in una sottocartella accanto al JAR generato).

[ MODIFICA = la terza opzione genera una cartella oltre al vaso, la seconda opzione (" Librerie richieste dal pacchetto in JAR generato ") può anche essere usata quando hai il vaso. ]

  1. Fai clic su Fine e il tuo JAR viene creato nella posizione specificata insieme a una cartella che contiene i JAR menzionati nel file manifest.
  2. apri il terminale, dai il percorso corretto al tuo jar ed eseguilo usando questo comando java -jar abc.jar

    Ora ciò che accadrà è che il caricatore di classi cercherà nella cartella corretta i JAR referenziati poiché ora sono presenti nella stessa cartella che contiene la tua app JAR..Non c'è " java.lang.NoClassDefFoundError " eccezione generata ora.

Questo ha funzionato per me ... Spero che funzioni anche per te !!!

se usi librerie esterne nel tuo programma e provi a raggruppare tutte insieme in un file jar non è così semplice, a causa di problemi con il percorso di classe ecc.

Preferirei utilizzare OneJar per questo problema.

Ho avuto lo stesso problema con il mio vaso la soluzione

  1. Crea il file MANIFEST.MF:
  

Versione manifest: 1.0

     

Sigillato: vero

     

Percorso di classe:. lib / jarX1.jar lib / jarX2.jar lib / jarX3.jar

     

Classe principale: com.MainClass

  1. Fai clic destro sul progetto, seleziona Esporta.
  

seleziona esporta tutte le cartelle di output per il progetto verificato

  1. seleziona usando manifest esistente dallo spazio di lavoro e seleziona il file MANIFEST.MF

Questo ha funzionato per me :)

Ho scoperto quando sto usando un manifest che l'elenco di vasetti per il percorso di classe deve avere uno spazio dopo l'elenco di ogni vaso ad es. " richiesto_lib / sun / pop3.jar richiesto_lib / sole / smtp.jar " ;. Anche se è l'ultimo nell'elenco.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top