*Markus: Probleme mit Bibliotheken in JAR-Archiv

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

  1. Ich habe nun erfahren, dass dies nicht möglich ist.

    Markus

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

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