Compilation de code Java

Les plug-ins de JDT comprennent un compilateur Java incrémentiel et par lots qui permet de compiler des fichiers .class Java à partir d'un code source. Le compilateur ne fournit pas d'API directe. Il est installé comme compilateur dans les projets Java. La compilation est déclenchée au moyen des mécanismes de génération standard de la plateforme.

Le mécanisme de compilation de la plateforme est détaillé à la rubrique Compilateurs de projet incrémentaux .

Compilation du code

Grâce à l'API de compilation, vous pouvez compiler les fichiers source Java d'un projet par programme.

   IProject myProject;
   IProgressMonitor myProgressMonitor;
   myProject.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, myProgressMonitor);

Pour un projet Java, cette instruction appelle le compilateur de projet incrémentiel Java (avec les autres compilateurs de projet incrémentaux qui ont été ajoutés à la spécification de compilation du projet). Les fichiers .class générés sont enregistrés dans le dossier de sortie indiqué. Les fichiers de ressources supplémentaires sont également copiés dans le dossier de sortie. 

Dans le cas d'une compilation par lots complète, tous les fichiers .class du dossier de sortie peuvent être vérifiés pour s'assurer qu'aucun fichier périmé ne sera trouvé. Cette opération est contrôlée par une option du compilateur de l'API principale de JDT(CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER).  Par défaut, cette option vide les dossiers de sortie.Sauf si l'option est réinitialisée, vous devez veiller à placer tous les fichiers .class pour lesquels vous ne disposez pas des fichiers source correspondants dans un dossier de fichiers classe distinct sur le chemin de classe et non dans le dossier de sortie.

Les compilateurs incrémentaux et par lots peuvent être configurés avec d'autres options qui contrôlent les ressources copiées dans le dossier de sortie.L'exemple suivant montre comment configurer un filtre de ressources de sorte que les fichiers se terminant par '.ignore' et les dossiers nommés 'META-INF' ne soient pas copiés dans le dossier de sortie :

   Hashtable options = JavaCore.getOptions();
   options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, "*.ignore,META-INF/");
   JavaCore.setOptions(options);

Les noms de fichier sont éliminés s'ils correspondent à l'un des critères fournis. Des dossiers entiers sont éliminés si leur nom correspond à l'un des noms de dossier fourni se terminant par un séparateur de chemins.

Vous pouvez également configurer les compilateurs incrémentaux et de lots pour ne générer qu'une seule erreur lorsque le fichier .classpath contient des erreurs. Cette option est définie par défaut et élimine de nombreuses erreurs. Pour obtenir la liste complète des options relatives au compilateur et leurs valeurs par défaut, reportez-vous à la rubrique Options du compilateur de l'API principale de JDT.

La compilateur peut également être configuré à l'aide des options JavaCore.  Vous pouvez par exemple définir la gravité devant être utilisée pour les différents types de problèmes rencontrés au cours de la compilation.  Pour obtenir la liste complète des options relatives au compilateur et leurs valeurs par défaut, reportez-vous à la rubrique Options du compilateur de l'API principale de JDT.

Lors de la configuration par programme des options du compilateur, vous devez indiquer la portée de l'option. Par exemple, la configuration d'un filtre de ressources peut être applicable à un seul projet particulier :

   
   Hashtable options = myProject.getOptions(false);  // obtention des options configurées dans ce projet uniquement
   options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, "*.ignore,META-INF/");
   myProject.setOptions(options);

Utilisation du compilateur par lots

Recherche du compilateur par lots

La classe du compilateur par lots se situe dans les classes internes du plug-in de l'API principale JDT. Le nom de la classe est le suivant : org.eclipse.jdt.internal.compiler.batch.Main. Elle est contenue dans le fichier plugins/org.eclipse.jdt.core_3.2.0.jar. Depuis la version 3.2, elle est également téléchargeable séparément. Le nom du fichier est ecj.jar. Sa source correspondante est également disponible. Pour les obtenir, accédez à la page de téléchargement et rechercher la section JDT Core Batch Compiler. Ce fichier jar contient le compilateur par lots et l'adaptateur javac ant.

Ainsi vous pouvez l'utiliser comme une application autonome et à l'intérieur d'une génération Ant hors d'Eclipse.

Exécution du compilateur par lots

Quelles sont les options disponibles ?

Les options suggérées sont représentées avec un arrière-plan de couleur orange.

Nom Syntaxe
Options de chemin de classe
-bootclasspath <dir 1>;<dir 2>;...;<dir P> Liste des répertoires ou des fichiers JAR utilisés pour amorcer les fichiers de classe utilisés par le compilateur. Par défaut, les bibliothèques de la machine virtuelle en cours d'exécution sont utilisées. Les entrées sont séparées par le séparateur de chemin de plateforme.
Chaque répertoire ou fichier peut définir des règles d'accès pour les types, ces derniers devant être alors placés entre crochets ("[" et "]").
-cp
-classpath <dir 1>;<dir 2>;...;<dir P>
Liste des répertoires ou des fichiers JAR utilisés pour compiler les fichiers source. La valeur par défaut est la valeur de la propriété "java.class.path". Les entrées sont séparées par le séparateur de chemin de plateforme.
Chaque répertoire ou fichier peut définir des règles d'accès pour les types, ces derniers devant être alors placés entre crochets ("[" et "]") ; par exemple [-X] pour interdire l'accès au type X, [~X] pour déconseiller l'accès au type X, et [+p/X:-p/*] pour interdire l'accès à tous les types inclus dans le package p mais autoriser l'accès à p/X.
-extdirs <dir 1>;<dir 2>;...;<dir P> Liste des répertoires utilisés pour définir l'emplacement des fichiers d'extension zip/jar. Les entrées sont séparées par le séparateur de chemin de plateforme.
-endorseddirs <dir 1>;<dir 2>;...;<dir P> Liste des répertoires utilisés pour définir l'emplacement des fichiers zip/jar validés. Les entrées sont séparées par le séparateur de chemin de plateforme.
-sourcepath <dir 1>;<dir 2>;...;<dir P> Liste des répertoires utilisés pour définir les fichiers source. Les entrées sont séparées par le séparateur de chemin de plateforme.
Chaque répertoire peut définir des règles d'accès pour les types, ces derniers devant être alors placés entre crochets ("[" et "]").
-d <dir 1>|none Permet de définir dans quel répertoire les fichiers .class générés doivent être vidés. En cas d'oubli, aucune structure de répertoire de package n'est créée.
Si vous ne souhaitez pas générer de fichier .class, utilisez -d none.
-encoding <nom du codage> Définit le format de codage de la source par défaut (il est également possible de définir un codage personnalisé fichier par fichier en ajoutant à chaque nom de dossier/fichier source un suffixe avec [<nom de codage>], par exemple X.java[utf8]).
Options de conformité
-target 1.1|1.2|1.3|1.4|1.5|5|5.0|1.6|6|6.0 Définit le paramètre cible du fichier .class. Les valeurs possibles sont les suivantes :
  • 1.1 (version majeure : 45 mineure : 3)
  • 1.2 (version majeure : 46 mineure : 0)
  • 1.3 (version majeure : 47 mineure : 0)
  • 1.4 (version majeure : 48 mineure : 0)
  • 1.5, 5 ou 5.0 (version majeure : 49 mineure : 0)
  • 1.6, 6 ou 6.0 (version majeure : 50 mineure : 0)
La valeurs par défaut sont :
  • 1.1 en mode -1.3
  • 1.2 en mode -1.4
  • 1.5 en mode -1.5
  • 1.6 en mode -1.6
-1.3 Définit le niveau de conformité sur 1.3. Implicitement -source 1.3 -cible 1.1.
-1.4 Définit le niveau de conformité sur 1.4 (par défaut). Implicitement -source 1.3 -cible 1.2.
-1.5 Définit le niveau de conformité sur 1.5. Implicitement -source 1.5 -cible 1.5.
-1.6 Définit le niveau de conformité sur 1.6. Implicitement -source 1.6 -target 1.6.
-source 1.3|1.4|1.5|5|5.0|1.6|6|6.0 Utilisé pour indiquer le niveau source attendu par le compilateur.
Les valeurs possibles sont les suivantes :
  • 1.3
  • 1.4
  • 1.5, 5 ou 5.0
  • 1.6, 6 ou 6.0
La valeurs par défaut sont :
  • 1.3 en mode -1.3
  • 1.3 en mode -1.4
  • 1.5 en mode -1.5
  • 1.6 en mode -1.6
Dans 1.4, assert est considéré comme un mot clé. Dans 1.5 et 1.6 , enum et assert sont considérés comme des mots clé.
Options d'avertissement
-warn:
allDeprecation
allJavadoc
assertIdentifier
boxing
charConcat
conditionAssign
constructorName
dep-ann
deprecation
discouraged
emptyBlock
enumSwitch
fallthrough
fieldHiding
finalBound
finally
forbidden
hiding
incomplete-switch
indirectStatic
intfAnnotation
intfNonInherited
javadoc
localHiding
maskedCatchBlocks
nls
noEffectAssign
null
over-ann
paramAssign
pkgDefaultMethod
raw
semicolon
serial
specialParamHiding
static-access
staticReceiver
suppress
synthetic-access
syntheticAccess
tasks(<task1>|...|<taskN>)
typeHiding
unchecked
unnecessaryElse
unqualified-field-access
unqualifiedField
unused
unusedArgument
unusedImport
unusedLabel
unusedLocal
unusedPrivate
unusedThrown
uselessTypeCheck
varargsCast
warningToken
Définit le niveau d'avertissement.
e.g. -warn:unusedLocal,deprecation

Les paramètres par défaut sont indiqués en rouge.

    -warn:none                               désactive tous les avertissements
    -warn:<avertissements séparés par ,>    active exactement les avertissements répertoriés
    -warn:+<avertissements séparés par ,>   active des avertissements supplémentaires
    -warn:-<avertissements séparés par ,>   désactive certains avertissements en particulier
allDeprecation obsolescence même au sein du code obsolète
allJavadoc Javadoc invalide ou manquant
assertIdentifier occurrence de assert utilisé comme un identifiant
boxing conversion autoboxing
charConcat lorsqu'un tableau de caractères est utilisé dans une concaténation de chaînes sans être explicitement converti en une chaîne
conditionAssign affectation booléenne accidentelle possible
constructorName méthode et nom du constructeur
dep-ann annotation @Deprecated manquante
deprecation utilisation de type obsolète ou de membre hors du code obsolète
discouraged utilisation de types correspondant à une règle d'accès de type "déconseillé"
emptyBlock bloc vide non renseigné
enumSwitch,
incomplete-switch
Commutateur d'énumération incomplet
fallthrough cas de fall-through possible
fieldHiding zone masquant une autre variable
finalBound paramètre de type et association finale
finally bloc ne se terminant pas normalement
forbidden utilisation de types correspondant à une règle d'accès de type "interdit"
hiding macro pour fieldHiding, localHiding, typeHiding et maskedCatchBlock
indirectStatic référence indirecte à un membre statique
intfAnnotation type d'annotation utilisé comme super interface
intfNonInherited compatibilité de méthode non héritée d'interface
javadoc javadoc invalide
localHiding variable locale masquant une autre variable
maskedCatchBlocks bloc catch masqué
nls libellés de chaîne non-nls (manque de balises //$NON-NLS-<n>)
noEffectAssign affectation sans effet
null contrôle null manquant ou redondant
over-ann annotation @Override manquante
paramAssign affectation à un paramètre
pkgDefaultMethod tentative de substitution de la méthode de package par défaut
raw utilisation d'un type brut (raw) (au lieu d'un type paramétré)
semicolon point-virgule inutile ou instruction vide
serial serialVersionUID manquante
specialParamHiding paramètre constructeur ou setter masquant une autre zone
static-access macro pour indirectStatic et staticReceiver
staticReceiver si un récepteur non statique est utilisé pour obtenir un champ statique ou appeler une méthode statique
suppress active @SuppressWarnings
syntheticAccess,
synthetic-access
lorsqu'un accès synthétique est réalisé pour innerclass
tasks active le support des balises de tâches du code source
typeHiding paramètre de type masquant un autre type
unchecked opération de type 'unchecked'
unnecessaryElse clause else inutile
unqualified-field-access,
unqualifiedField
accès non qualifié à une zone
unused macro pour unusedArgument, unusedImport,unusedLabel, unusedLocal, unusedPrivate et unusedThrown
unusedArgument argument de méthode inutilisé
unusedImport référence d'importation inutilisée
unusedLabel Label inutilisé
unusedLocal variable locale inutilisée
unusedPrivate déclaration de membre privé non-utilisé
unusedThrown exception émise déclarée et non-utilisée
uselessTypeCheck transtypage/instance de l'opération non requis
varargsCast l'argument varargs requiert un transtypage explicite
warningToken jeton d'avertissement non géré dans @SuppressWarnings

-nowarn Pas d'avertissement (équivalent de -warn:none)
-deprecation Equivalent de -warn:deprecation.
Options de débogage
-g[:none|:lines,vars,source] Définit le niveau des attributs de débogage
-g Toutes les infos de débogage (équivalent de -g:lines,vars,source)
-g:none Aucune information de débogage
-g:[lines,vars,source] Informations de débogage sélectives
-preserveAllLocals Demande explicitement au compilateur de préserver toutes les variables locales (à des fins de débogage). En cas d'oubli, le compilateur supprime les variables locales inutilisées.
Options ignorées (pour des raisons de compatibilité avec les options javac)
-J<option> transmet l'option à la machine virtuelle
-X<option> indique une option non standard. -Xemacs n'est pas ignoré.
-X imprime les options non standard et quitte
-O optimisation de la durée d'exécution
Options avancées
@<fichier> Arguments de ligne de commande de type lecture provenant du fichier
-maxProblems <n> Nombre maximal de problèmes par unité de compilation (100, par défaut)
-log <filename> Définit un fichier journal dans lequel sont vidées toutes les sorties du compilateur. Ceci s'avère particulièrement utile si vous souhaitez déboguer le compilateur par lots ou récupérer un fichier contenant toutes les erreurs et tous les avertissements ayant pour origine une compilation par lots. Si l'extension est du type .xml, le journal généré sera un fichier xml.
-Xemacs Utilisez le type emacs pour présenter les emplacements des erreurs et des avertissements dans la console et les journaux de texte classique. Les journaux XML ne sont pas affectés par cette option. Si cette option est activée, le message :
2. WARNING in /workspace/X.java
(at line 8)...

est présenté sous la forme :
/workspace/X.java:8: warning: The method...
-proceedOnError Poursuit la compilation malgré les erreurs, en vidant les fichiers de classe comportant des méthodes ou des types à problèmes. Cette procédure est recommandée uniquement si vous souhaitez pouvoir exécuter votre application même si des erreurs persistent.
-verbose Imprime les unités de compilation accédées/traitées dans la console ou le fichier journal si défini.
-referenceInfo Traite les informations de référence. Utile uniquement en cas de connexion au compilateur. Dans le cas contraire, les informations de référence ne sont d'aucune utilité.
-progress Affiche la progression (uniquement en mode -log).
-time Affiche les informations relatives à la vitesse.
-noExit N'appelle pas System.exit(n) au terme de la compilation (n=0 en l'absence d'erreur).
-repeat <n> Répète le processus de compilation <n> fois (analyse des performances).
-inlineJSR Intègre le bytecode JSR (implicite si cible >= 1.5).
-enableJavadoc Prend en compte les références contenues dans javadoc.
Options d'aide
-? -help Affiche le message d'aide.
-v -version Affiche le numéro de version du compilateur. Cette information est particulièrement utile pour signaler un bogue.
-showversion Affiche le numéro de version du compilateur et poursuit. Cette information est particulièrement utile pour signaler un bogue.

Exemples

d:\temp -classpath rt.jar -time -g -d d:/tmp Compile tous les fichiers sources dans d:\temp et ses sous-dossiers. Le chemin de classe est tout simplement rt.jar. Il génère tous les attributs de débogage et tous les fichiers .class générés sont vidés dans d:\tmp. La vitesse du compilateur est affichée une fois le processus par lots achevé.
d:\temp\Test.java -classpath d:\temp;rt.jar -g:none Compile uniquement Test.java et ses fichiers dépendants (le cas échéant), en extrayant les fichiers dépendants du répertoire d:\temp. Le chemin de classes est d:\temp suivi de rt.jar, ce qui signifie que toute les classes nécessaires sont recherchées initialement dans d:\temp puis dans rt.jar. Ne génère aucun attribut de débogage. Tous les fichiers .class sont vidés dans d:\temp.

Utilisation de l'adaptateur Ant javac

Vous pouvez utiliser le compilateur Eclipse dans un script Ant utilisant l'adaptateur javac. Pour ce faire, il suffit de définir la propriété build.compiler dans votre script. En voici un petit exemple.
<?xml version="1.0" encoding="UTF-8" ?>
<project name="compile" default="main" basedir="../.">

	<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>

	<property name="root" value="${basedir}/src"/>

	<property name="destdir" value="d:/temp/bin" />

	<target name="main">
		<javac srcdir="${root}" destdir="${destdir}" debug="on" nowarn="on" extdirs="d:/extdirs" source="1.4">
		    <classpath>
		      <pathelement location="${basedir}/../org.eclipse.jdt.core/bin"/>
		    </classpath>
		</javac>		
	</target>
</project>
La syntaxe utilisée pour la tâche Ant javac se trouve dans la documentation sur les tâches Ant javac. L'adaptateur actuel prend en charge la tâche Ant Javac, des versions 1.4.1 à 1.6.5.

Si vous utilisez une version supérieure à la version 1.5.0, vous pouvez utiliser l'élément d'argument de compilateur intégré pour définir des options propres au compilateur.

...
		<javac srcdir="${root}" destdir="${destdir}" debug="on" nowarn="on" extdirs="d:/extdirs" source="1.4">
    		    <classpath>
      		      <pathelement location="${basedir}/../org.eclipse.jdt.core/bin"/>
    		    </classpath>
    <compilerarg compiler="org.eclipse.jdt.core.JDTCompilerAdapter" line="-1.5 -warn:+boxing"/>
</javac>		
...

Pour éviter d'obtenir des scripts dépendant du compilateur, il est recommandé d'utiliser l'argument du compilateur défini par org.eclipse.jdt.core.JDTCompilerAdapter. Si cet argument n'est pas défini, le script ne peut être utilisé qu'avec le compilateur Eclipse. S'il est défini, l'argument de compilateur imbriqué est ignoré si le nom est différent du nom de compilateur indiqué dans la propriété build.compiler.

Identification des incidents

L'API principale (core) du JDT définit un marqueur spécialisé (type "org.eclipse.jdt.core.problem") pour indiquer les incidents de compilation. Pour découvrir par programme les incidents détectés par le compilateur, vous devez utiliser le protocole de marqueurs standard de la plateforme. Pour plus d'informations sur l'utilisation des marqueurs, reportez-vous à la rubrique Marqueurs de ressources.

Le fragment de code suivant identifie tous les marqueurs Java problématiques dans une unité de compilation.

   public IMarker[] findJavaProblemMarkers(ICompilationUnit cu) 
      throws CoreException {
      IResource javaSourceFile = cu.getUnderlyingResource();
      IMarker[] markers = 
         javaSourceFile.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER,
            true, IResource.DEPTH_INFINITE);
   }

Les marqueurs d'incidents Java sont gérés par le compilateur de projet Java. Ils sont supprimés automatiquement à mesure que les incidents sont résolus et que la source Java est recompilée.

La valeur de l'ID de l'incident a la valeur d'une des constantes définies dans IProblem . L'ID de l'incident est fiable mais le message est traduit et peut par conséquent changer selon l'environnement local par défaut. La description des constantes définies dans IProblem est explicite.

Une implémentation d' IProblemRequestor doit être définie pour regrouper les incidents détectés lors d'une opération Java. Les copies de travail peuvent être adaptées à la détection des incidents si un élément IProblemRequestor a été fourni pour leur création. Pour ce faire, vous pouvez utiliser la méthode reconcile. Exemple :

  ICompilationUnit unit = ..; // obtention d'une unité de compilation
			
  // création d'un demandeur pour le regroupement des incidents détectés
  IProblemRequestor problemRequestor = new IProblemRequestor() {
    public void acceptProblem(IProblem problem) {
      System.out.println(problem.getID() + ": " + problem.getMessage());
    }
    public void beginReporting() {}
    public void endReporting() {}
    public boolean isActive() {	return true; } // détecte les incidents si actif
  };
    
  // utilisation de la copie de travail pour conserver la source contenant l'erreur
  ICompilationUnit workingCopy = unit.getWorkingCopy(new WorkingCopyOwner() {}, problemRequestor, null);
  ((IOpenable)workingCopy).getBuffer().setContents("public class X extends Zork {}");

  // déclenchement de la réconciliation
  workingCopy.reconcile(NO_AST, true, null, null);
Vous pouvez ajouter une opération sur les incidents détectés dans la méthode acceptProblem(IProblem). Dans cet exemple, l'incident détecté est le suivant : Zork ne peut pas être résolu ou n'est pas une superclasse valide et son ID est IProblem.SuperclassNotFound.

Exclusion d'avertissements à l'aide de SuppressWarnings

Java 5.0 offre à l'utilisateur la possibilité de désactiver les avertissements de compilation relatifs à un sous-ensemble d'unité de compilation, à l'aide de l'annotation java.lang.SuppressWarning.

	@SuppressWarning("unused") public void foo() {
		String s;
	}

Sans cette annotation, le compilateur signalerait le fait que la variable locale s n'est jamais utilisée. Avec cette annotation, il ignore cet avertissement localement par rapport à la méthode foo. Il est ainsi possible de conserver les avertissements dans d'autres emplacements de la même unité de compilation ou du même projet.

La liste ci-dessous répertorie les jetons pouvant être utilisés dans une annotation SuppressWarning :