Programmation Java/Créer une archive Java
Une archive Java rassemble des classes Java dans un fichier d'archive compressé. Son format est identique à celui des fichiers ZIP.
L'extension de nom de fichier standard est .jar
; elle peut être différente pour certaines utilisations spécifiques (exemple : .war
, ...).
Type d'archives et rôles
modifierIl existe différents types d'archives variant selon le contenu et ayant des rôles différents :
- Une archive de fichiers sources (*.java)
- Elle permet de fournir le code source d'une application ou bibliothèque. Alternativement, il peut s'agir du code source incomplet, n'incluant que la partie publique d'une bibliothèque ; cette archive peut alors être utilisée par les IDE pour exposer le code source de certaines classes.
- Une archive de fichiers compilés (*.class)
- Ce type d'archive inclut également les ressources internes. Une telle archive peut être exécutable si elle contient une classe principale, utilisable dans une ligne de commande simplifiée :
java -jar app.jar
oujavaw -jar app.jar
L'archive peut être signée pour authentifier son contenu.
Contenu
modifierL'archive contient la hiérarchie des répertoires des paquetages de l'application.
Exemple : pour une application dont les classes sont dans un paquetage nommé org.wikibooks.fr.exemple
:
org/wikibooks/fr/exemple/DemarrageApplication.class
org/wikibooks/fr/exemple/ui/FenetrePrincipale.class
org/wikibooks/fr/exemple/ui/icone_application.png
org/wikibooks/fr/exemple/format/LecteurJson.class
org/wikibooks/fr/exemple/format/LecteurJson$1.class
- ...
Elle contient également un répertoire spécial nommé META-INF
contenant des fichiers d'information pour Java dont notamment :
- le fichier manifest décrit dans la section suivante,
- les fichiers de signature des classes (*.RSA, *.DSA, SIG-*, ...).
Fichier manifest
modifierLe fichier manifest META-INF/MANIFEST.MF
est un fichier texte qui définit des propriétés globales à l'archive, dont notamment la classe principale et un chemin de classes (Class-Path
).
Il peut contenir également une section par fichier pour les propriétés de signature.
Exemple :
Manifest-Version: 1.0 Main-Class: org.wikibooks.fr.exemple.ClassePrincipale Class-Path: .
Le fichier est composé de lignes au format nom: valeur
regroupées en sections.
Une section est défini comme un groupe de lignes consécutives sans ligne vide.
Les lignes vides servent à séparer les sections.
Section globale
modifierLa première section concerne l'archive globalement. La première ligne du fichier indique la version du format (1.0).
Manifest-Version: 1.0
Les autres attributs sont optionnels :
Main-Class
- Nom de la classe principale à lancer. L'archive n'est pas exécutable si cet attribut est absent.
Class-Path
- Liste de chemin relatifs vers d'autres archives Java (*.jar) contenant des classes utilisées par cette archive. Contrairement au chemin de classe passé à la ligne de commande de l'interpréteur ou du compilateur Java, les fichiers ne peuvent être que des archives Java. Les chemins sont séparés par un espace.
- Il s'agit en réalité d'une liste d'URL, mais l'utilisation d'URL absolue n'est pas recommandée pour laisser la liberté à l'utilisateur d'installer les archives où il veut. Pour les noms d'archives contenant un espace, cela signifie qu'il peut être encodé en
%20
comme dans les URLs. Created-By
- Créateur de l'archive. Il s'agit en général de l'outil utilisé pour créer l'archive.
Sealed
- Verrouillage des paquetages de l'archive :
true
(oui) oufalse
(non). Un paquetage verrouillé signifie qu'aucune autre archive ne peut ajouter des classes dans les mêmes paquetages que ceux définis dans cette archive.
D'autres attributs existent[1], notamment concernant la signature. Les attributs non reconnus sont ignorés ; il est donc possible d'ajouter ses propres attributs pour ajouter des informations et d'en récupérer la valeur à l'utilisation.
Section par fichier
modifierLes sections suivantes concernent un fichier particulier nommé dans la première ligne du fichier. Un chemin de fichier se terminant pas un slash désigne un répertoire (paquetage).
Exemple :
Name: common/class2.class SHA1-Digest: (...base64 representation of SHA1 digest...) SHA-256-Digest: (...base64 representation of SHA-256 digest...)
Il peut s'agir de modification par rapport aux attributs globaux :
Sealed
- Verrouillage du paquetage :
true
(oui) oufalse
(non). Un paquetage verrouillé signifie qu'aucune autre archive ne peut ajouter des classes dans le même paquetage.
Exemple : Tous les paquetages verrouillés sauf org.wikibooks.fr
:
Manifest-Version: 1.0 Sealed: true Name: org/wikibooks/fr/ Sealed: false
Création
modifierLa création d'une archive peut se faire avec différents outils :
- l'outil
jar
en ligne de commande, fourni avec le JDK (voir la section « jar » du chapitre « JDK »), - depuis l'IDE Eclipse (voir la section « Créer une archive java (JAR) » du chapitre « Eclipse »),
- l'outil Ant,
- d'autres outils qui ne seront pas décrits ici mais qui peuvent être basés sur les outils cités ci-dessus.
En utilisant un fichier jardesc
modifierUn fichier d'extension .jardesc
(JAR description) est un fichier XML décrivant comment construire une archive Java.
Ce type de fichier est généré et utilisé par Eclipse (File > Export... > Java / JAR file
).
Exemple de fichier généré par Eclipse :
<?xml version="1.0" encoding="WINDOWS-1252" standalone="no"?> <jardesc> <jar path="D:/Dev/workspacePerso/Exemple/Export/wikilivres.jar"/> <options buildIfNeeded="true" compress="true" descriptionLocation="/Exemple/wikilivres.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/> <storedRefactorings deprecationInfo="true" structuralOnly="false"/> <selectedProjects/> <manifest generateManifest="false" manifestLocation="/Exemple/wikilivres.mf" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true"> <sealing sealJar="false"> <packagesToSeal/> <packagesToUnSeal/> </sealing> </manifest> <selectedElements exportClassFiles="true" exportJavaFiles="false" exportOutputFolder="false"> <javaElement handleIdentifier="=Exemple/src"/> </selectedElements> </jardesc>
Pour lancer la création du fichier d'archive depuis Eclipse :
- Cliquez avec le bouton droit sur le fichier jardesc,
- Sélectionnez
Create JAR
dans le menu contextuel.
Pour modifier la configuration d'un fichier jardesc existant, vous pouvez relancez le générateur depuis Eclipse :
- Cliquez avec le bouton droit sur le fichier jardesc,
- Sélectionnez
Open With > JAR Export Wizard
dans le menu contextuel.
En utilisant un script Ant
modifierUn script Ant est un fichier XML (extension .xml
) permettant la construction d'une archive Java.
Ce type de fichier est généré et utilisé par Eclipse (File > Export... > Java / Runnable JAR file
).
Exemple : Un fichier généré par Eclipse :
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <project default="create_run_jar" name="Create Runnable Jar for Project Exemple"> <!--this file was created by Eclipse Runnable JAR Export Wizard--> <!--ANT 1.7 is required --> <target name="create_run_jar"> <jar destfile="D:/Dev/workspacePerso/Exemple/export/wikilivres.jar" filesetmanifest="mergewithoutmain"> <manifest> <attribute name="Main-Class" value="org.wikibooks.fr.app.Demarrer"/> <attribute name="Class-Path" value="livres.jar vitrine.jar"/> </manifest> <fileset dir="D:/Dev/workspacePerso/Exemple/bin"/> <fileset dir="D:/Dev/workspacePerso/Images/bin"/> <fileset dir="D:/Dev/workspacePerso/AutreLib/bin"/> <zipfileset excludes="META-INF/*.SF" src="D:/Dev/workspacePerso/Exemple/forms-1.3.0.jar"/> </jar> </target> </project>
<project default="create_run_jar" name="Create Runnable Jar for Project Exemple">
- L'action par défaut est nommée « create_run_jar » définie par la suite.
<target name="create_run_jar">
- Action nommée « create_run_jar »
<jar destfile="D:/Dev/workspacePerso/Exemple/export/wikilivres.jar" filesetmanifest="mergewithoutmain">
- Création d'une archive Java dont le chemin est spécifié par l'attribut
destfile
. Cet élément contient la définition des attributs du manifest et une série d'ensembles de fichiers (fileset en anglais). <manifest>
- Définition des attributs du fichier manifest.
<fileset dir="D:/Dev/workspacePerso/Exemple/bin"/>
- Inclure les fichiers du répertoire désigné par l'attribut
dir
(ici, les classes compilées situées dans le sous-répertoirebin
du projet). <zipfileset excludes="META-INF/*.SF" src="D:/Dev/workspacePerso/Exemple/forms-1.3.0.jar"/>
- Inclure les fichiers de l'archive compressée désignée par l'attribut
src
(pour cet exemple, en excluant les fichiers de signatureMETA-INF/*.SF
).
Pour lancer la création du fichier d'archive depuis Eclipse :
- Cliquez avec le bouton droit sur le fichier ant,
- Sélectionnez
Run As > Ant Build
dans le menu contextuel.
Utilisation
modifierBibliothèque distribuable
modifierUne bibliothèque de classes peut être distribuée sous la forme d'une archive Java.
Dans Eclipse, vous pouvez ajouter une archive Java dans le chemin de compilation :
- Cliquez avec le bouton droit sur un projet ;
- Sélectionnez « Build Path > Configure Build Path... » dans le menu contextuel.
Ajouter l'archive Java des classes compilées. Vous pouvez ensuite lui associer une seconde archive Java pour le code source de la partie publique de la bibliothèque.
Chargement dynamique depuis une application
modifierPour étendre les possibilités d'une application, des extensions peuvent être définies sous forme d'archives Java chargées dynamiquement par l'application plutôt que lié statiquement par un chemin de classe (classpath
ou Class-Path
).
La lecture de fichiers contenus dans une archive Java ainsi que le chargement dynamique de classes sont décrits en détails dans la section « Exemple concret : un gestionnaire d'extensions » du chapitre « Réflexion ».
La récupération d'information depuis le fichier manifest d'une archive Java peut se faire ainsi :
import java.util.jar.*; // ... File f = new File("ext.jar"); // ou passé en argument d'une méthode JarFile jf = new JarFile(f); try { Manifest mf = jf.getManifest(); Attributes attrs = mf.getMainAttributes(); // Attributs de la section principale String info = (String)attrs.get("Wikilivres-Info"); } finally { jf.close(); }