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

modifier

Il 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 ou javaw -jar app.jar

L'archive peut être signée pour authentifier son contenu.

Contenu

modifier

L'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

modifier

Le 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

modifier

La 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) ou false (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

modifier

Les 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) ou false (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

modifier

La création d'une archive peut se faire avec différents outils :

En utilisant un fichier jardesc

modifier

Un 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 :

  1. Cliquez avec le bouton droit sur le fichier jardesc,
  2. 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 :

  1. Cliquez avec le bouton droit sur le fichier jardesc,
  2. Sélectionnez Open With > JAR Export Wizard dans le menu contextuel.

En utilisant un script Ant

modifier

Un 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épertoire bin 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 signature META-INF/*.SF).

Pour lancer la création du fichier d'archive depuis Eclipse :

  1. Cliquez avec le bouton droit sur le fichier ant,
  2. Sélectionnez Run As > Ant Build dans le menu contextuel.


Utilisation

modifier

Bibliothèque distribuable

modifier

Une 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 :

  1. Cliquez avec le bouton droit sur un projet ;
  2. 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

modifier

Pour é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();
}

Pour en savoir plus

modifier

Références

modifier
  1. https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Main_Attributes