# JAR Dateien in JAR Datei einbetten



## nogi (31. Dez 2004)

Servus,

ich habe mir mit Eclipse zum Anlegen von Tabellen ein kleines Programm geschrieben. Dazu verwende ich je nach Datenbank unterschiedliche JDBC Treiber und JDOM.
Das ganze läuft auch wunderbar. Wenn ich allerdings eine ausführbare Datei erstelle müssen die angesprochenen JAR Dateien im gleichen Verzeichnis sein wie das exportierte Projekt. Die JAR Dateien habe ich selbstverständlich zum Export hinzugefügt und kontrolliert ob sich diese wirklich im neuen JAR Archiv befinden. Zusätzlich habe ich noch eine MANIFEST Datei angelegt:

Manifest-Version: 1.0
Main-Class: XYZ
Class-Path: db2.zip mysql.jar jdom.jar

Aber leider werden die entsprechenden Klasse bzw. der JDBC Treiber nicht gefunden.

1. Ist es überhaupt möglich JAR Dateien in eine andere JAR Datei einzubetten?
2. Liegt es am Classpath in der MANIFEST Datei?

Vielen Dank im voraus


Gruß

NoGi


----------



## bygones (31. Dez 2004)

es hält sich das gerücht, dass man jars in jars machen kann... ich entpacke immer die fremd jars und füge die Klassen in mein jar ein - oder ich lasse die fremd jars einfach ganz raus aus meinem jar und regel das über den Classpath


----------



## Bleiglanz (31. Dez 2004)

in der j2ee Welt ist das durchaus üblich (ear - module), bei Standalone Anwendungen, die mit 

java -jar Foo.jar

gestartet werden, ist es wohl eher so, dass sich der Class-Path Eintrag im Manifest auf Pfade AUSSERHALB des Archivs bezieht, jars innerhalb von jars sind definitiv (??) nicht möglich

Der einzige Nutzen des ManifestEintrags ist daher, dass man beim Start mit java -jar Foo.jar keinen Classpath mehr setzen muss


----------



## Beni (31. Dez 2004)

Hm, Roar (?) hat mal geschrieben dass man auf Jars in Jars (in Jars in Jars...) zugreiffen kann, indem man Pfade so schreibt: "c:/dateien/jarEins.jar!data/jarZwei.jar!/blabla.txt"
Ich hab das noch nie ausprobiert, ist nur mein Beitrag an die Gerüchteküche :bae:

[Edit: http://www.tutorials.de/tutorials173991.html  ???:L ]


----------



## Bleiglanz (31. Dez 2004)

versteh ich nicht, ich glaube das geht nicht

Frage an alle: Hat es schon mal jemand geschafft, ein jar innerhalb eines jars zu haben und dieses zu Laufzeit in den Classpath hineinzubekommen - wenn ja, welche Rolle spielt der Class-Path Eintrag im Manifest?

P.S.: ich meine jetzt nicht die Lösung mit 

a) das jar extrahieren und ins dateisystem schreiben

b) dann mit einem selbstgeschriebenen Classloader zu arbeiten


----------



## SebiB90 (31. Dez 2004)

das DashBoard ist dochvon roar?
wenn ja, fragt ihn.
er hat in einem plugin(Calendar) die jar datei fürs tablelyout in einer andere jar gepackt.


----------



## bygones (31. Dez 2004)

die frage ist inwieweit es sinnvoll ist jedes mal beim programmstart die jars zu laden...

außerdem hat Roar die jars nicht in seinem jar, sondern die liegen außerhalb in einem dir.

ich halte die von mir geposteten beiden Lösungen für die sinnvollsten


----------



## SebiB90 (31. Dez 2004)

deathbyaclown hat gesagt.:
			
		

> außerdem hat Roar die jars nicht in seinem jar, sondern die liegen außerhalb in einem dir.


entpack die datei calendar.jar
dann siehst du das da eine jar datei drin ist


----------



## bygones (31. Dez 2004)

wie die jars an sich aufgebaut sind ist eine andere Sache...

ich meinte das Hauptprogramm lädt sich alle jars die im Plugins Ordner sind


----------



## 0xdeadbeef (31. Dez 2004)

Nur mal so am Rande. Es gibt da einen gepatchten Classloader namens "One-Jar" (http://www-106.ibm.com/developerworks/java/library/j-onejar/), der auch im Eclipse-Plugin FatJar verwendet wird. Damit ist es möglich, Jars innerhalb eines Jars zu benutzen.
Allerdings ist mein erster und letzter Versuch in dieser Richtung fehgeschlagen. Das lag allerdings an der kruden Implementierung des Suchpfads in der Comm-API. Derlei Probleme sind allerdings auch bei anderen Library-Jars zu erwarten, egal ob man die Jars entpackt oder per gepatchtem Classloader ausliest.


----------



## nogi (31. Dez 2004)

Da sag ich doch erst einmal vielen Dank für die vielen, schnellen und ausführlichen Antworten.

Ich werde wohl die drei JAR Dateien entpacken und in die neue JAR mit einfügen.

Gruß NoGi


----------



## stev.glasow (31. Dez 2004)

Was spricht denn dagegen die zusätzlichen jars mit den  Programordner zu legen und in der Manifest anzugeben?


----------



## 0xdeadbeef (31. Dez 2004)

stevg hat gesagt.:
			
		

> Was spricht denn dagegen die zusätzlichen jars mit den  Programordner zu legen und in der Manifest anzugeben?



Genau das geht eben nicht. Die property "java.class.path" enthält bei aus Jars gestarteten Klassen nur den Name dieses JARs, egals welcher Classpath im Manifest übergeben wurde. Das macht es dem normalen Classloader anscheinend umöglich, Klassen aus Jars nachzuladen. Dazu muß man wie gesagt den Klassenlader durch eine Version ersetzen, die das kann.


----------



## Roar (31. Dez 2004)

1. jo warum sollte man jars nich in jars packen können?
2. das mit jar in jar und dann automatisch in classpath funktioniert aber nicht. die tablelayout.jar is nur dummy...
3. also mit der klasse URL kann man auf jars so zugreifen bla.jar!/eintrag.class
ob bla.jar!/blupp.jar!/eintrag.class funktinoiert weiß ich auch nicht


----------



## stev.glasow (1. Jan 2005)

0xdeadbeef hat gesagt.:
			
		

> stevg hat gesagt.:
> 
> 
> 
> ...


Verstehen wir uns jetzt miss?
Ich lege mir einfach eine Programmordner an in dem ich dann meine rechner.jar lege und einen unter Ordner lib anlegen, in diesen kommt dann die swt.jar und jdom.jar und hinein (Z.B.) - und in der manifest der rechner.jar brauche ich dann nur noch den classpath-eintrag für  beiden jars aus dem lib ordner machen. Und das geht auch.


----------



## 0xdeadbeef (2. Jan 2005)

Nach meinen eigenen Experimenten und Recherchen geht das nicht. Siehe auch der One-Jar-Link, den ich oben bereits anegegeben hatte.
Zitat daraus:


> The biggest hurdle I tackled in the process of developing One-JAR was how to load JAR files that are contained inside another JAR file. The Java classloader sun.misc.Launcher$AppClassLoader, which takes over at the start of java -jar, only knows how to do two things:
> 
> * Load classes/resources that appear at the root of a JAR file.
> 
> ...



Hab's noch nicht mit der 1.5er probiert, aber es würde mich sehr überraschen, wenn man da plötzlich Klassen aus Jars innerhalb Jars laden könnte.


----------



## stev.glasow (3. Jan 2005)

Von jars in jars rede ich ja nicht  :? es liegt hier eindeutig ein mißverständnis vor.  :autsch:


----------



## 0xdeadbeef (3. Jan 2005)

Aber genau darum geht es doch in diesem Thread  :autsch:


----------



## stev.glasow (3. Jan 2005)

Ja schon, aber ich wollte wissen was ihr gegen die "normale" Variante habt die ist doch gut. Find das besser als wenn alles in einer jar wäre.


----------



## dotlens (3. Jan 2005)

de vorteil wenn alles in einer jar liegt, liegt doch auf der hand (Wortspiel ;-))
du willst deinem Kumpel ein Programm geben, dann kannst du ihm das Jar schicken und alles ist ok.  ansonsten muss er noch einen ordner lib habern mit den bibliotheken.

nebenbei wäre es super wenn jemand einen FAQ Beitrag über Jars machen würde. ich selbst kenne mich da noch zu wenig aus.


----------



## stev.glasow (3. Jan 2005)

Ne, sorry das ist kein Argument.  Denn ich kann dem Kumpel auch ein zipfile schicken, die er dann zu entpacken hat. 
Aber das muss eh jeder selber wissen, aber besser überhaupt eine jar als keine.


----------



## Karl (3. Jan 2005)

Hallo,

da ich jar in jar schon mal ausprobiert habe, hier meine Erfahrungen:

1. Der Standard-ClassLoader und auch der URL-ClassLoader unterstützen das nicht
2. Die Klasse URL ist nicht darauf ausgerichtet: Eine URL kann zwar wie Benji geschrieben
hat auf eine Ressource in einem Jar innerhalb eines anderen Jars verweisen (Trennung durch Ausrufezeichen).
Eine solche URL kann aber nicht aufgelöst werden (openStream() ist nicht entsprechend implementiert).
3. Jar in Jar ist in Java nicht angebracht, man tut es einfach nicht. Der Grund ist vermutlich die Performance und aus Komprimierungssicht die Sinnlosigkeit.
4. Muss man das unbedingt doch tun, ist die Lösung recht einfach. Man implementiert einen ClassLoader, der
einen Jar-Eintrag richtig wieder als zip oder jar interpretiert, lässt sich den Stream des Eintrags geben, stülpt einen Zip-/Jar-InputStream drüber und schon läufts. Das geht auch n-fach rekursiv.
5. Hinweis: Immer wenn's ums Signieren geht, ist das ganze sehr fehlerträchtig. Die VM ist nämlich zu schlau, die merkt sofort, wenn eine Klasse "wild geladen" wurde. Aufrufe aus Methoden einer solchen Klasse unterliegen großen Einschränkungen, was zur Laufzeit zu Permission-Problemen führt. Innere Jars müsste man folglich auch signieren.

Fazit: Jar's nach der Installation nebeneinander, nicht geschachtelt, ggf. kann man die verpackten Jars auch bei Programmstart in ein temporäres Verzeichnis packen (~ Verbergen der Installation der Anwendung).

Gruß,

Karl


----------



## thE_29 (3. Jan 2005)

Hrhr 

schickst ihm halt 1000 class Files und er solls dann per Hand mit java  dein.package.mainclass starten 


Was willsten über JARs großartig für ein FAQ machen? Ich habs noch nie mit dem java -jar erstellt (immer mit IDEs) und das ich jar Files komplett einbinde mache ich auch net (hat ja keinen sinn...)

ob ich es komplett einbinde oder so wie dbac mache, das ich es extrahiere und dann 1 jar File drauß mache ist ja egal, da brauch ich mich wenigstens um nichts mehr zu kümmern, da es ja immer entpackt in 1em jar File liegt..


----------



## dotlens (3. Jan 2005)

FAQ Beitrag ist meiner Ansicht nach nötig, denn wenn du mal nach Jar suchst, findest du jenes viele Threads.

ich hatte riesen mühe mein erstes jar file hinzukriegen und ich denke da bin ich nicht der einzige.

sinvolle themen:
- wie erstellt man ein jar file
- was ist ein classpath?
- manifest datei
- jar in jar
- vor- und nachteile von jars

bestimt gibts noch einiges mehr dazu zu schreiben


----------



## Bleiglanz (3. Jan 2005)

@Karl

endlich mal ein klares Wort!

kann man also vermutlich so festhalten:

1. jars in jars funktionieren (out of the box) NICHT

2. der Class-Path Eintrag im Manifest erlaubt es nur, den Classpath beim Aufruf java -jar Meine.jar wegzulassen (und bezieht sich auf Dinge "ausserhalb" von Meine.jar)

3. in J2EE konformen .ear Archiven kann der Class-Path Eintrag trotzdem funktionieren (d.h. jars innerhalb des ears werden gefunden) , je nach Applicationserver


----------

