| Fiche technique | |
|---|---|
| Nom : | classpath |
| Type d'élément : | Variable système |
Introduction
Le classpath désigne l'ensemble des chemins (répertoires et fichiers JAR) que la machine virtuelle Java (JVM) parcourt pour localiser les classes et les ressources nécessaires à l'exécution d'un programme. Lorsqu'une application Java est lancée, la JVM consulte le classpath pour trouver les fichiers .class, les bibliothèques externes et parfois des ressources comme des fichiers de configuration. Le classpath peut être défini de différentes manières : via une variable d'environnement (CLASSPATH), en ligne de commande avec l'option -classpath ou -cp, ou encore automatiquement par des outils comme Maven ou Gradle. Une mauvaise configuration du classpath est une cause fréquente d'erreurs telles que ClassNotFoundException ou NoClassDefFoundError.
Qu'est-ce que le classpath, conceptuellement ?
Le classpath est le mécanisme de localisation des classes et des ressources utilisé par la JVM (Java Virtual Machine) et par les outils Java (compilateur javac, lanceur java, outils de test, serveurs applicatifs,...).
Contrairement à d'autres langages où les fichiers sont référencés explicitement par chemin, Java ne charge jamais une classe par son chemin de fichier direct.
Il charge une classe par son nom pleinement qualifié (Fully Qualified Class Name), par exemple :
- java.util.ArrayList
La JVM doit donc répondre à la question suivante :
« Où se trouve le fichier ArrayList.class correspondant à java.util.ArrayList ? »
La réponse dépend entièrement du classpath.
De nom de classe à fichier .class
Nom logique vs emplacement physique
Une classe Java possède :
- un nom logique : com.example.app.Main
- un emplacement physique :
| com/example/app/Main.class |
Le classpath fournit une liste de racines de recherche.
Pour chaque racine, la JVM :
- Remplace les points . du nom de classe par des /
- Ajoute .class
- Vérifie si le fichier existe dans cette racine
Exemple de classpath :
|
/app/classes /app/lib/utils.jar |
Recherche de com.example.app.Main :
| /app/classes/com/example/app/Main.class /app/lib/utils.jar!/com/example/app/Main.class |
Important : La première occurrence trouvée est utilisée.
Ce que peut contenir un classpath
Un classpath est une liste ordonnée de :
Répertoires
- Racine d'un arbre de paquets
- Très courant pour le code compilé
|
/bin /classes /target/classes |
Fichiers JAR
Archives ZIP contenant des .class
Peuvent inclure un META-INF/MANIFEST.MF
|
commons-lang3-3.14.0.jar spring-core.jar |
Caractères génériques (depuis Java 6)
| lib/* |
Important : inclut tous les JARs du dossier.
Pas récursif : lib/* ≠ lib/**/*.jar
Comment définir le classpath
En ligne de commande
Compilation :
| javac -classpath lib/utils.jar src/Main.java |
Exécution :
| java -cp classes:lib/utils.jar com.example.Main |
Sous Windows :
| java -cp classes;lib\utils.jar com.example.Main |
Le séparateur dépend du système d'exploitation :
Variable d'environnement CLASSPATH
| export CLASSPATH=classes:lib/utils.jar |
Fortement déconseillée aujourd'hui :
- Globale
- Difficile à diagnostiquer
- Source de conflits invisibles
Via le manifeste d'un JAR
Dans META-INF/MANIFEST.MF :
|
Main-Class: com.example.Main Class-Path: lib/utils.jar lib/logging.jar |
Utilisé avec :
| java -jar app.jar |
Important : Les chemins sont relatifs au JAR, pas au dossier courant.
Via des outils de build
Maven
- Le classpath est calculé automatiquement
- Dépend des dépendances déclarées dans pom.xml
Gradle
- Résolution dynamique
- Séparation compile / runtime
Important : En pratique, les développeurs ne gèrent presque jamais le classpath à la main.
Classpath et chargement des classes
ClassLoader : le vrai moteur
Le classpath n'est pas lu directement par la JVM.
Il est utilisé par les ClassLoaders.
Principaux chargeurs :
- Bootstrap ClassLoader
- Classes coeur (java.lang, java.util)
- JDK
- Plateforme ClassLoader
- Modules standard
- Application ClassLoader
- Classes du classpath
Délégation parent-first
Lorsqu'une classe est demandée :
- Le chargeur demande à son parent
- Si le parent ne trouve pas → recherche locale
Important : Empêche de remplacer java.lang.String
Classpath vs Modules (Java 9+)
Depuis Java 9, Java introduit le système de modules (JPMS).
Différence clef
| Classpath | Module path |
|---|---|
| Non structuré | Structuré |
| Tout est visible | Accès contrôlé |
| Conflits possibles | Dépendances explicites |
| Legacy | Moderne |
Le classpath existe toujours et reste :
- obligatoire pour les anciennes bibliothèques
- très utilisé en pratique
Un projet peut mixer :
|
--class-path lib/* --module-path mods |
Classpath et ressources (fichiers non-Java)
Le classpath ne sert pas seulement aux classes.
On peut y entreposer :
- fichiers .properties
- XML
- JSON
- images
- gabarits
Chargement via :
- InputStream is =
- getClass().getClassLoader()
- .getResourceAsStream("config/app.properties");
Attention : Le chemin est relatif à la racine du classpath, pas au système de fichiers.
Problèmes classiques liés au classpath
ClassNotFoundException
- La classe n'est pas dans le classpath.
NoClassDefFoundError
- Classe présente à la compilation
- Absente à l'exécution
Conflits de versions
- Deux JARs contiennent la même classe
- La première trouvée gagne
Bug subtil et dangereux
Ordre du classpath : détail critique
Le classpath est ordonné.
Exemple :
| lib/v1.jar:lib/v2.jar |
v1.jar masque v2.jar
Certains cadres d'applications (Tomcat, OSGi) modifient cet ordre.