Probleme mit Bibliotheken in JAR-Archiv
*Markus
- java
0 *Markus0 Daniel Thoma0 Slyh
Hallo,
ich habe einige JAR-Archive, die im entgültigen Programm (=ausführbares JAR-Archiv) benötigt werden.
Dazu habe ich das Problem, dass diese Archive nie gefunden werden, sobald ich das JAR-Archiv außerhalb des Verzeichnisses, in dem Eclipse das Projekt ablegt, starte.
Ich weiß gar nicht, was ich nicht schon alles ausprobiert habe, aber zur Zeit sieht es so aus:
TKV.jar ist das Endprodukt.
Es enthält folgende Fremdarchive:
bcmail-jdk15-135.jar checkstyle-all-4.2.jar junit.jar
bcprov-jdk15-135.jar FontBox-0.1.0.jar PDFBox-0.7.3.jar
Das Listing sieht so aus: $ jar tf TKV.jar
META-INF/
META-INF/MANIFEST.MF
DateiSpeicherung.class
Main.class
ProgrammGUI.class
Reader.class
Saver.class
TelefonFileFilter.class
TelefonTableModel.class
YessOneReader.class
libraries/bcmail-jdk15-135.jar
libraries/bcprov-jdk15-135.jar
libraries/checkstyle-all-4.2.jar
libraries/FontBox-0.1.0.jar
libraries/junit.jar
libraries/PDFBox-0.7.3.jar
Inhalt von MANIFEST.MF dieses Verzeichnisses:
jar fx TKV.jar META-INF/MANIFEST.MF && cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Class-Path: libraries/bcmail-jdk15-135.jar libraries/bcprov-jdk15-135.
jar libraries/checkstyle-all-4.2.jar libraries/FontBox-0.1.0.jar libr
aries/junit.jar libraries/PDFBox-0.7.3.jar
Created-By: 1.6.0_02 (Sun Microsystems Inc.)
Main-Class: Main
Sieht für mich eigentlich in Ordnung aus. Starte ich das Ganze nun, geht es so lange gut, bis eine der fremden Archive benötigt wird, denn dann passiert folgendes:
$ java -jar TKV.jar
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: org/pdfbo x/util/PDFTextStripper
at YessOneReader.<init>(YessOneReader.java:20)
at ProgrammGUI.actionPerformed(ProgrammGUI.java:273)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:19 95)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.jav a:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel .java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242 )
at javax.swing.AbstractButton.doClick(AbstractButton.java:357)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:1 216)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMen uItemUI.java:1257)
at java.awt.Component.processMouseEvent(Component.java:6038)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
at java.awt.Component.processEvent(Component.java:5803)
at java.awt.Container.processEvent(Container.java:2058)
at java.awt.Component.dispatchEventImpl(Component.java:4410)
at java.awt.Container.dispatchEventImpl(Container.java:2116)
at java.awt.Component.dispatchEvent(Component.java:4240)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4322 )
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3986)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3916)
at java.awt.Container.dispatchEventImpl(Container.java:2102)
at java.awt.Window.dispatchEventImpl(Window.java:2429)
at java.awt.Component.dispatchEvent(Component.java:4240)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThre ad.java:273)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread. java:183)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThre ad.java:173)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)
Was läuft hier falsch? In Eclipse funktioniert es, aber warum außerhalb von Eclipse nicht?
Markus
Hallo *Markus,
Ich habe nun erfahren, dass dies nicht möglich ist.
Jein, die Classpath-Angabe in der Manifest-Datei bezieht sich nicht auf das jar-Archiv sondern auf das Verzeichnis, in dem es liegt.
Du kannst also eine Verzeichnisstruktur anlegen:
bin/meineanwendung.jar
lib/lib1.jar
lib/lib2.jar
Dann kannst Du ../lib/lib1.jar etc. als Classpath angeben. Das Problem ist natürlich, dass man so eine Anwendung dann nicht mehr als eine einzige jar-Datei ausliefern kann.
Eine andere Möglichkeit ist es, für seine Anwendung ein Startprogramm zu schreiben, dass einen Classloader für das Hauptprogramm und die Bibliotheken enthält und das Hauptprogramm darüber lädt und startet.
Das sollte sich z.B. mittels eines java.net.URLClassLoader und einer jar-URL (hat die Form: jar:file:///path/mein.jar!/blub/datei.txt) relativ einfach machen lassen. Gut möglich, dass es da auch schon irgendwo was fertiges gibt.
Alternativ kannst Du auf Java 7 warten. Dafür ist ein Modulsystem angekündigt inklusive Abhängigkeitsverwaltung etc. Damit wird es dann wahrscheinlich auch möglich sein, mehrere Module in einer jar-Datei auszuliefern.
Grüße
Daniel
Hallo,
Gut möglich, dass es da auch schon irgendwo was fertiges gibt.
Ich habe schon ein paarmal von Fat Jar gelesen, das genau das
können soll. Selbst habe ich es aber nicht probiert.
Gruß
Slyh