web-dev-qa-db-fra.com

Bocaux de référence à l'intérieur d'un bocal

J'ai un pot dont le contenu ressemble à celui indiqué ci-dessous,

enter image description here

Ci-dessous mon fichier manifeste

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.3
Created-By: 1.7.0_06-b24 (Oracle Corporation)
Main-Class: org.sai.com.DerbyDemo
Class-Path: derby.jar derbyclient.jar derbynet.jar derbytools.jar

Lorsque j'essaie de lancer le bocal, il a jeté un ClassNotFoundExcception, ce qui signifie qu'il ne fait pas référence aux bocaux à l'intérieur du bocal externe.

Dans le Class-Path attribut, comment puis-je référencer des bocaux (derby.jar, etc) à l'intérieur du pot?

52
srk

Vous aurez besoin d'un chargeur de classe personnalisé pour cela, jetez un oeil à n Jar .

One-JAR vous permet de conditionner une application Java) avec ses fichiers JAR de dépendance dans un seul fichier Jar exécutable.

Il a une tâche de fourmi qui peut aussi en simplifier la construction.

[~ # ~] référence [~ # ~] (de arrière-plan )

La plupart des développeurs supposent raisonnablement que l'insertion d'un fichier Jar de dépendance dans leur propre fichier Jar et l'ajout d'un attribut Class-Path à META-INF/MANIFEST feront l'affaire:


jarname.jar
| /META-INF
| |  MANIFEST.MF
| |    Main-Class: com.mydomain.mypackage.Main
| |    Class-Path: commons-logging.jar
| /com/mydomain/mypackage
| |  Main.class
| commons-logging.jar

Malheureusement, cela ne fonctionne pas. Le Java Launcher$AppClassLoader ne sait pas comment charger des classes depuis un Jar dans un Jar avec ce genre de Class-Path. Essayer d'utiliser jar:file:jarname.jar!/commons-logging.jar mène également dans une impasse. Cette approche ne fonctionnera que si vous installez (c'est-à-dire scatter) les fichiers Jar correspondants dans le répertoire où le fichier jarname.jar est installé.

34
epoch

Tu ne peux pas. De la tutoriel officiel :

En utilisant l'en-tête Class-Path dans le manifeste, vous pouvez éviter de spécifier un indicateur long -classpath lorsque vous appelez Java pour exécuter votre application.

Remarque: l'en-tête Class-Path pointe vers les classes ou les fichiers JAR du réseau local, et non les fichiers JAR du fichier JAR ou les classes accessibles via les protocoles Internet. Pour charger des classes dans des fichiers JAR d'un fichier JAR dans le chemin de classe, vous devez écrire un code personnalisé pour charger ces classes. Par exemple, si MyJar.jar contient un autre fichier JAR appelé MyUtils.jar, vous ne pouvez pas utiliser l'en-tête Class-Path dans le manifeste de MyJar.jar pour charger des classes dans MyUtils.jar dans le chemin d'accès aux classes.

21
JB Nizet

Dans Eclipse, vous avez la possibilité d’exporter un fichier jar exécutable. enter image description here Vous avez la possibilité de regrouper tous les fichiers jar liés au projet dans le fichier jar généré. Eclipse ajoute ainsi un chargeur de classes personnalisé qui fait référence aux fichiers JAR intégrés au nouveau fichier JAR.

enter image description here

12
vogash

Les implémentations par défaut du chargeur de classe ne peuvent pas être chargées à partir d'un fichier jar-into-a-jar: pour ce faire, le "sous-fichier" entier doit être chargé en mémoire, ce qui annule les avantages du format du fichier jar en matière d'accès aléatoire ( référence en attente - je ferai un montage une fois que je trouverai la documentation le supportant).

Je recommande d'utiliser un programme tel que JarSplice pour tout regrouper pour vous dans un seul fichier jar exécutable.

Edit: Impossible de trouver la référence de la source, mais voici un RFE non résolu du site Web de Sun décrivant ce "problème" exact: http://bugs.Sun.com/bugdatabase/view_bug.do?bug_id=4648386

Vous pouvez également "tester" le fonctionnement de votre programme en plaçant les fichiers jar de la bibliothèque dans un fichier \lib _ sous-répertoire de votre répertoire classes, exécuté à partir de la ligne de commande. En d'autres termes, avec la structure de répertoire suivante:

classes/org/sai/com/DerbyDemo.class
classes/org/sai/com/OtherClassFiles.class
classes/lib/derby.jar
classes/lib/derbyclient.jar

A partir de la ligne de commande, accédez au répertoire "classes" susmentionné et tapez:

Java -cp .:lib/* org.sai.com.DerbyDemo
6
bfishman

Ajoutez les fichiers jar à votre bibliothèque (si vous utilisez netbeans) et modifiez le fichier de votre manifeste classpath comme suit:

Class-Path: lib/derby.jar lib/derbyclient.jar lib/derbynet.jar lib/derbytools.jar

une réponse similaire existe ici

2
BWGathecha

si vous ne voulez pas créer un chargeur de classe personnalisé. Vous lisez le flux de fichiers jar. Et transférez-le dans un objet File. Ensuite, vous pouvez obtenir l'URL du fichier. Envoyez-le à URLClassLoader, vous pouvez charger le fichier jar à votre guise. échantillon:

InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("example"+ ".jar");
final File tempFile = File.createTempFile("temp", ".jar");
tempFile.deleteOnExit();  // you can delete the temp file or not
try (FileOutputStream out = new FileOutputStream(tempFile)) {
    IOUtils.copy(resourceAsStream, out);
}
IOUtils.closeQuietly(resourceAsStream);
URL url = tempFile.toURI().toURL();
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url});
urlClassLoader.loadClass()
...
1
蜡笔小新