wake-up-neo.com

NoClassDefFoundError beim Versuch, mein jar mit Java.exe -jar auszuführen ... was ist los?

Ich habe eine Anwendung, die ich zur Vereinfachung der Bereitstellung in ein Glas einpacken möchte. Die Anwendung wird kompiliert und ausgeführt (in einem Windows-Cmd-Fenster), wenn sie als Satz von Klassen ausgeführt wird, die vom CLASSPATH aus erreichbar sind. Wenn ich jedoch meine Klassen aufrenne und versuche, sie mit Java 1.6 im selben Cmd-Fenster auszuführen, bekomme ich Ausnahmen:

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

Das Komische ist, die beleidigende LogFactory scheint in commons-logging-1.1.jar zu sein, die sich im angegebenen Klassenpfad befindet. Die JAR-Datei (yep, es ist wirklich da):

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

Der Inhalt der Datei 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 ...)

Ja, Commons-Logging hat die Klasse LogFactory. Und zum Schluss der Inhalt meines Krugmanifests:

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

Das hat mich gestopft, und alle Kollegen, die ich seit mehr als einem Tag nervt. Um nur die Antworten herauszuschlagen, werden Lösungen von Drittanbietern dazu wahrscheinlich aufgrund von Lizenzbeschränkungen und Unternehmensrichtlinien (z. B. Tools zum Erstellen von Exes oder Verpacken von Gläsern) herausgefahren. Das ultimative Ziel ist es, ein Jar zu erstellen, das von meiner Entwicklungs-Windows-Box auf einen Linux-Server (mit abhängigen Jars) kopiert und zum Füllen einer Datenbank verwendet werden kann (Klassenpfade können sich daher in Entwicklungs- und Bereitstellungsumgebungen unterscheiden). Jeder Hinweis auf dieses Geheimnis wäre sehr dankbar!

55
Ogre Psalm33

Die Option -jar schließt -classpath gegenseitig aus. Siehe eine alte Beschreibung hier

-Krug

Führen Sie ein Programm aus, das in einer JAR-Datei enthalten ist. Das erste Argument ist der Name einer JAR-Datei anstelle eines Startklassennamens. Damit diese Option funktioniert, muss das Manifest der JAR-Datei eine Zeile der Form Hauptklasse: Klassenname enthalten. Hier kennzeichnet Klassenname die Klasse mit der öffentlichen statischen Methode void main (String [] args), die als Ausgangspunkt für Ihre Anwendung dient.

Weitere Informationen zum Arbeiten mit Jar-Dateien und Jar-Dateimanifesten finden Sie auf der Jar-Tool-Referenzseite und im Jar-Trail des Lernprogramms Java.

Wenn Sie diese Option verwenden, ist die JAR-Datei die Quelle aller Benutzerklassen, und andere Benutzerklassenpfadeinstellungen werden ignoriert.

Ein schneller und unsauberer Hack besteht darin, Ihren Klassenpfad an den Klassenpfad bootstrap anzuhängen:

-Xbootclasspath/a: path

Geben Sie einen durch Doppelpunkte getrennten Pfad von Direktiven, JAR-Archiven und Zip-Archiven an, der an den Standardklassenpfad bootstrap angehängt werden soll.

Wie @ Dan jedoch zu Recht sagt, besteht die richtige Lösung darin, sicherzustellen, dass das JAR-Manifest den Klassenpfad für alle benötigten JARs enthält.

56
toolkit

Sie können die Option -jar weglassen und die JAR-Datei folgendermaßen starten:

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

28
g_tom

Dies ist das Problem, das auftritt,

wenn die JAR-Datei von "C:\Java\apps\appli.jar" geladen wurde und Ihre Manifestdatei den Klassenpfad: "lib/other.jar" hat, sucht der Klassenlader in "C:\Java"\apps\lib\"für" other.jar ". Der JAR-Dateieintrag "lib/other.jar" wird nicht angezeigt.

Lösung: -

  1. Klicken Sie mit der rechten Maustaste auf das Projekt und wählen Sie Exportieren aus.
  2. Wählen Sie Java-Ordner aus und wählen Sie in diesem Ordner die JAR-Datei anstelle der JAR-Datei.
  3. Wählen Sie die richtigen Optionen aus und wählen Sie im Abschnitt "Bibliotheksverwaltung" die dritte Option aus, d. H. (Erforderliche Bibliotheken in einen Unterordner neben der generierten JAR kopieren).

[EDIT= Die dritte Option erzeugt einen Ordner zusätzlich zum jar. Die zweite Option ("Erforderliche Bibliotheken in generiertes JAR packen") kann ebenso wie das jar verwendet werden. ]

  1. Klicken Sie auf Fertig stellen, und Ihre JAR wird an der angegebenen Position zusammen mit einem Ordner erstellt, der die in der Manifestdatei genannten JARS enthält.
  2. Öffnen Sie das Terminal, geben Sie den richtigen Pfad zu Ihrem jar an und führen Sie es mit dem Befehl Java -jar abc.jar aus 

    Nun wird der Klassenlader im richtigen Ordner nach den referenzierten JARS suchen, da sie sich jetzt in demselben Ordner befinden, in dem sich auch Ihre JAR-App befindet.

Das hat für mich funktioniert ... Hoffe es funktioniert auch für dich !!!

15

wenn Sie in Ihrem Programm externe Bibliotheken verwenden und versuchen, alle zusammen in eine JAR-Datei zu packen, ist dies aufgrund von Klassenpfadproblemen usw. nicht so einfach.

Ich würde es vorziehen, OneJar für diese Ausgabe zu verwenden.

4
flash

ich hatte das gleiche Problem mit meinem Glas, der Lösung 

  1. Erstellen Sie die MANIFEST.MF-Datei:

Manifest-Version: 1.0

Versiegelt: wahr

Klassenpfad:. lib/jarX1.jar lib/jarX2.jar lib/jarX3.jar

Hauptklasse: com.MainClass

  1. Klicken Sie mit der rechten Maustaste auf das Projekt und wählen Sie Exportieren aus.

wählen Sie Export aller Ordner für das geprüfte Projekt aus

  1. wählen Sie ein vorhandenes Manifest aus dem Arbeitsbereich aus und wählen Sie die Datei MANIFEST.MF aus

Das hat für mich funktioniert :) 

2
mouhcine

Wenn ich ein Manifest verwende, habe ich festgestellt, dass die Auflistung von Gläsern für den Klassenpfad nach der Auflistung jedes Glases ein Leerzeichen enthalten muss, z. "required_lib/Sun/pop3.jar required_lib/Sun/smtp.jar". Auch wenn es der letzte in der Liste ist. 

0
Mary C