Hallo allerseits,
Ich habe folgendes Java-Problem: Ich verwende in einem Projekt Xerces als XML-Parser. Der kommt ja in einer schönen JAR-Datei xercesImpl.jar. Wenn ich nun meinen Code, der Xerces verwende, auch in eine JAR-Datei packe, ein Manifest erzeuge und dann mittels
java -cp xercesImpl.java -jar meinprojekt.jar
versuche, mein Projekt aufzurufen, beschwert er sich, dass er Xerces nicht findet (die erste Xerces-Klasse, die er laden will, findet er nicht, dabei bricht er auch ab).
Ich habe mir daher mal folgenden Testcase gebastelt:
http://www.christian-seiler.de/temp/java-classpath-test.zip
Da drin ist ein Ant-Buildfile, das zwei .jar-Dateien erzeugt. Im folgenden der Code nochmal hier im Forum:
Es gibt zwei Pakete: example.a und example.b. Alle Klassen in example.a werden ins Paket example-a.jar gepackt, alle Klassen in example.b ins Paket example-b.jar.
In src/example/a befindet sich eine Datei Main.java mit folgendem Code:
package example.a;
public class Main {
public static void main (String [] args) throws Exception {
System.out.println ("Class path: " + System.getProperty ("java.class.path"));
if (args.length >= 1) {
System.out.println ("Trying to load: " + args[0]);
Class test1 = Class.forName (args[0]);
}
}
}
Zusätzlich habe ich folgendes Manifest für die example-a.jar-Datei:
Main-Class: example.a.Main
In src/example/b befindet sich eine Datei Test.java mit folgedem Code:
package example.b;
public class Test {
}
Der Testcase ist im Prinzip sehr billig: Die Main-Klasse des example.a-Pakets versucht die Klasse zu laden, deren Namen als erster Parameter übergeben wird.
Sobald man die *.jar mal erzeugt hat, kann man sich davon überzeugen, dass es funktioniert:
java -cp example-a.jar:example-b.jar example.a.Main example.a.Main
Ergibt:
Class path: example-a.jar:example-b.jar
Trying to load: example.a.Main
Ich kann auch problemlos aus example-b.jar eine Klasse laden:
java -cp example-a.jar:example-b.jar example.a.Main example.b.Test
Ergibt:
Class path: example-a.jar:example-b.jar
Trying to load: example.b.Test
Wenn ich nun aber -jar verwende und eine Klasse aus dem example-a.jar laden will (z.B. wieder Main selbst), dann funktioniert das auch noch:
java -cp example-b.jar -jar example-a.jar example.a.Main
Ergibt:
Class path: example-a.jar
Trying to load: example.a.Main
Aber hier sieht man schon: Der Classpath ist hier nur example-a.jar, example-b.jar fehlt! Und deswegen fliegt auch folgender Aufruf auf die Schnauze:
java -cp example-b.jar -jar example-a.jar example.b.Test
Ergibt:
Class path: example-a.jar
Trying to load: example.b.Test
Exception in thread "main" java.lang.ClassNotFoundException: example.b.Test
...
[Die Umgebungsvariable CLASSPATH zu setzen ändert auch nichts.]
Meine Frage nun: Funktioniert das -jar grundsätzlich nicht mit einem zusätzlichen Classpath? Oder funktioniert das doch und man muss nur ein paar Dinge beachten?
Die Doku sagt lediglich lapidar:
| You can only specify one JAR file, which must contain all the application-specific code.
Das könnte man so lesen, als dass das wirklich nicht geht. Interpretiere ich das richtig?
Ja, ich weiß, ich kann selbst java.class.path ändern / mir mit einem java.net.URLClassLoader einen zusätzlichen ClassLoader erzeugen, den ich zum Laden der Klassen aus example-b.jar verwenden kann, aber das fände ich dann doch irgendwie etwas blöd...
Viele Grüße,
Christian