Compilazione del codice Java

I plugin JDT comprendono un compilatore Java incrementale e batch per la generazione di file .class Java dal codice di origine. Nessuna API è direttamente fornita dal compilatore. Questa viene installata come generatore su progetti Java. La compilazione viene attivata utilizzando meccanismi di generazione della piattaforma standard.

Il meccanismo di creazione della piattaforma viene dettagliatamente descritto nella sezione relativa ai generatori di progetti incrementali.

Compilazione del codice

È possibile compilare in modo programmatico i file origine Java in un progetto utilizzando l'API di generazione.

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

Per un progetto Java, questa richiama il generatore incrementale di progetto Java (insieme a qualsiasi altro generatore incrementale di progetto aggiunto alla specifica di generazione del progetto). I file .class generati vengono scritti nella cartella di output designata. Nella cartella di output vengono copiati anche altri file di risorse. 

Nel caso di una generazione di batch completa, tutti i file .class della cartella di output vengono 'ripuliti' per garantire che non vengano rilevati file non aggiornati. Questa operazione viene controllata mediante un'opzione del generatore principale JDT (CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER).  L'impostazione predefinita per questa opzione è ripulire le cartelle di output. A meno che questa opzione non venga reimpostata, accertarsi di inserire tutti i file .class per i quali non sono presenti file di origine corrispondenti in cartelle di file di classe separate nel percorso classi e non nella cartella di output.

I generatori incrementali e di batch possono essere configurati con altre opzioni che controllano le risorse copiate nella cartella di output. L'esempio di seguito riportato mostra come impostare un filtro di risorse in modo che i file che terminano con '.ignore' e le cartelle denominate 'META-INF' non vengano copiate nella cartella di output:

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

I nomi file vengono filtrati se corrispondono a uno dei modelli forniti. Intere cartelle vengono filtrate se i relativi nomi corrispondono a uno dei nomi di cartella forniti terminanti con un separatore di percorso.

È anche possibile configurare i generatori di batch e incrementali in modo che generino un unico errore quando il file .classpath presenta errori. Questa opzione è attiva per impostazione predefinita ed elimina numerosi errori. Per un elenco completo delle opzioni correlate al generatore e delle relative impostazioni predefinite, consultare la sezione relativa alle opzioni del generatore principale JDT.

Il compilatore può essere configurato anche mediante le opzioni JavaCore.  Ad esempio, è possibile definire la gravità che deve essere utilizzata per i diversi tipi di problemi rilevati durante la compilazione. Per un elenco completo delle opzioni correlate al compilatore e delle relative impostazioni predefinite, consultare la sezione relativa alle opzioni del compilatore principale JDT.

Quando si configurano programmaticamente le opzioni per il generatore o il compilatore, è necessario determinare l'ambito dell'opzione. Ad esempio, l'impostazione di un filtro di risorse può essere applicata solo ad un determinato progetto.  Nell'esempio di seguito riportato viene impostato lo stesso filtro di risorse illustrato precedentemente, ma solo per un singolo progetto.

   
   Hashtable options = myProject.getOptions(false);  // get only the options set up in this project
   options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, "*.ignore,META-INF/");
   myProject.setOptions(options);

Utilizzo del compilatore batch

Individuazione del compilatore batch

La classe del compilatore batch i trova nelle classi interne del plugin JDT/Core. In questo caso si tratta del file jdtcore.jar nella directory plugins/org.eclipse.jdt.core. Il nome della classe è org.eclipse.jdt.internal.compiler.batch.Main.

Esecuzione del compilatore batch

Opzioni disponibili

Le opzioni suggerite hanno sfondo arancio.

classe Utilizzo
Opzioni del percorso classi
-bootclasspath <dir 1>;<dir 2>;...;<dir P> Elenco di directory o file jar utilizzati per attivare i file di classe utilizzati dal compilatore. Per impostazione predefinita, vengono utilizzate le librerie della VM in esecuzione. Le voci sono separate dal separatore di percorso della piattaforma.
-cp
-classpath <dir 1>;<dir 2>;...;<dir P>
Elenco di directory o file jar utilizzati per compilare i file di origine. Il valore predefinito è quello della proprietà "java.class.path". Le voci sono separate dal separatore di percorso della piattaforma.
-extdirs <dir 1>;<dir 2>;...;<dir P> Elenco di directory o file jar utilizzati per specificare il percorso dei file con estensione zip/jar. Le voci sono separate dal separatore di percorso della piattaforma.
-sourcepath <dir 1>;<dir 2>;...;<dir P> Elenco di directory utilizzato per specificare i file di origine. Le voci sono separate dal separatore di percorso della piattaforma.
-d <dir 1>|none Utilizzato per specificare la directory che conterrà i file .class generati. Se omessa, non verrà creata alcuna struttura di directory per i pacchetti.
Se non si desidera generare file .class, utilizzare -d none.
-encoding <encoding name> Specificare il formato di codifica di origine predefinito (la codifica personalizzata può essere specificata anche in base ai file aggiungendo il suffisso [encoding <encoding name>] a ciascun nome di file o cartella di origine di input).
Opzioni di conformità
-target 1.1|1.2|1.3|1.4|1.5|5|5.0 Specifica le impostazioni di destinazione dei file .class. I valori possibili sono:
  • 1.1 (versione maggiore: 45 minore: 3)
  • 1.2 (versione maggiore: 46 minore: 0)
  • 1.3 (versione maggiore: 47 minore: 0)
  • 1.4 (versione maggiore: 48 minore: 0)
  • 1.5, 5 o 5.0 (versione maggiore: 49 minore: 0)
I valori predefiniti sono:
  • 1.1 in modalità -1.3
  • 1.2 in modalità -1.4
  • 1.5 in modalità -1.5
-1.3 Imposta il livello di conformità su 1.3. Implicito -source 1.3 -target 1.1.
-1.4 Imposta il livello di conformità su 1.4 (predefinito). Implicito -source 1.3 -target 1.2.
-1.5 Imposta il livello di conformità su 1.5. Implicito -source 1.5 -target 1.5.
-source 1.3|1.4|1.5|5|5.0 Utilizzato per abilitare il livello di origine del compilatore.
I valori possibili sono:
  • 1.3
  • 1.4
  • 1.5, 5 or 5.0
I valori predefiniti sono:
  • 1.3 in modalità -1.3
  • 1.4 in modalità -1.4
  • 1.5 in modalità -1.5
In 1.4, assert è considerata una parola chiave. In 1.5, enum e assert sono considerate parole chiave.
Opzioni di avviso
-warn:
allDeprecation
allJavadoc
assertIdentifier
boxing
charConcat
conditionAssign
constructorName
dep-ann
deprecation
emptyBlock
enumSwitch
fieldHiding
finalBound
finally
hiding
incomplete-switch
indirectStatic
intfAnnotation
intfNonInherited
javadoc
localHiding
maskedCatchBlocks
nls
noEffectAssign
null
over-ann
pkgDefaultMethod
semicolon
serial
specialParamHiding
static-access
staticReceiver
suppress
synthetic-access
syntheticAccess
tasks(<task1>|...|<taskN>)
typeHiding
deselezionata
unnecessaryElse
unqualified-field-access
unqualifiedField
uselessTypeCheck
unused
unusedArgument
unusedImport
unusedLocal
unusedPrivate
unusedThrown
varargsCast
warningToken
Impostazione livello di avviso,
ad esempio, -warn:unusedLocals,deprecation

Le impostazioni predefinite sono indicate in rosso.

    -warn:<avvisi separati da ,>    abilita esattamente gli avvisi elencati
    -warn:+<avvisi separati da ,>   abilita gli avvisi aggiuntivi
    -warn:-<avvisi separati da ,>   disabilita specifici avvisi
allDeprecation elementi obsoleti all'interno di codice obsoleto
allJavadoc javadoc non valido o mancante
assertIdentifier ricorrenza di assert utilizzata come identificativo
boxing conversione autoboxing
charConcat quando una matrice di caratteri viene utilizzata in una concatenazione di stringa senza essere convertita esplicitamente in una stringa
conditionAssign possibile assegnazione booleana accidentale
constructorName metodo con nome di costruttore
dep-ann annotazione @Deprecated mancante
deprecation uso di un tipo o membro obsoleto all'esterno del codice obsoleto
emptyBlock blocco vuoto non documentato
enumSwitch,
incomplete-switch
alternanza enum incompleta
fieldHiding campo che nasconde un'altra variabile
finalBound tipo di parametro con limite finale
finally blocco finale non completato normalmente
hiding macro per fieldHiding, localHiding, typeHiding e maskedCatchBlock
indirectStatic riferimento indiretto a un membro statico
intfAnnotation tipo di annotazione utilizzato come superinterfaccia
intfNonInherited compatibilità metodo non ereditato dell'interfaccia
javadoc javadoc non valido
localHiding variabile locale che nasconde un'altra variabile
maskedCatchBlocks blocco catch nascosto
nls letterali di stringhe non tradotti (mancanza di tag //$NON-NLS-<n>)
noEffectAssign per assegnazione senza effetto
null verifica null mancante o ridondante
over-ann annotazione @Override mancante
pkgDefaultMethod tentativo di sostituzione il metodo predefinito del pacchetto
serial serialVersionUID mancante
semicolon punto e virgola non necessario o istruzione vuota
specialParamHiding parametro setter o constructor che nasconde un altro campo
static-access macro per indirectStatic e staticReceiver
staticReceiver se viene utilizzato un ricevitore non statico per ottenere un campo statico o per richiamare un metodo statico
suppress abilita @SuppressWarnings
syntheticAccess,
synthetic-access
quando si esegue l'accesso sintetico alle classi interne
tasks abilita il supporto per i tag di attività nel codice di origine
typeHiding tipo di parametro che nasconde un altro tipo
deselezionata tipo di operazione non selezionata
unnecessaryElse proposizione else non necessaria
unqualified-field-access,
unqualifiedField
riferimento non qualificato a un campo
unused macro per unusedArgument, unusedImport, unusedLocal, unusedPrivate e unusedThrown
unusedArgument argomento metodo non utilizzato
unusedImport riferimento importazione non utilizzato
unusedLocal variabile locale non utilizzata
unusedPrivate dichiarazione membro privato non utilizzata
unusedThrown eccezione attivata dichiarata non utilizzata
uselessTypeCheck operazione cast/instanceof non necessaria
varargsCast argomento varargs necessita un cast esplicito
warningToken token di avviso non gestito in @SuppressWarningsb

-nowarn Nessun avviso (equivalente a -warn:none)
-deprecation Equivalente a -warn:deprecation.
Opzioni di debug
-g[:none|:lines,vars,source] Impostare il livello degli attributi di debug
-g Tutte le informazioni di debug (equivalente a -g:lines,vars,source)
-g:none Nessuna informazione di debug
-g:[lines,vars,source] Informazioni di debug selettive
-preserveAllLocals Richiede esplicitamente al compilatore di conservare tutte le variabili locali (a scopo di debug). Se omesso, il compilatore eliminerà le locali non utilizzate.
Opzioni avanzate
@<file> Legge gli argomenti della riga comandi da un file
-maxProblems <n> Numero massimo di problemi per unità di compilazione (100 per impostazione predefinita)
-log <filename> Specifica un file di log nel quale verrà inserito tutto l'output del compilatore. Opzione molto utile se si desidera eseguire il debug del compilatore batch o se si desidera ottenere un file che contiene tutti gli errori e gli avvisi derivati da una generazione batch. Se l'estensione è .xml, il log generato sarà un file xml.
-proceedOnError Continua la compilazione in caso di errore, eliminando i file di classe con metodi di problema o tipi di problema. Opzione consigliata solo se si desidera eseguire l'applicazione nonostante contenga errori.
-verbose Stampa le unità di compilazione elaborare o attivate nella console o nel file di log, se specificato.
-referenceInfo Elabora le informazioni di riferimento. Utile solo se si è connessi al generatore. Le informazioni di riferimento non sono utili senza connessione al generatore.
-progress Mostra lo stato di avanzamento (solo in modalità -log)
-time Visualizza informazioni sulla velocità
-noExit Non richiama System.exit(n) al termine della compilazione (n=0 se non ci sono errori)
-repeat <n> Ripete il processo di compilazione <n> volte (analisi prestazioni).
-inlineJSR Codice di byte JSR incorporato (implicito se destinazione >= 1.5)
-enableJavadoc Considera i riferimenti interni ai javadoc
Opzioni di aiuto
-? -help Visualizza il messaggio di aiuto
-v -version Visualizza il numero di generazione del compilatore. Utile per riportare un difetto.
-showversion Visualizza il numero di generazione del compilatore e procede. Utile per riportare un difetto.

Esempi

d:\temp -classpath rt.jar -time -g -d d:/tmp Compila tutti i file di origine in in d:\temp e nelle relative sottocartelle. Il percorso classi è semplicemente simply rt.jar. Genera tutti gli attributi di debug e tutti i file .class generati vengono inseriti in d:\tmp. La velocità del compilatore verrà visualizzata dopo aver completato il processo batch.
d:\temp\Test.java -classpath d:\temp;rt.jar -g:none Compila solo Test.java e richiamerà qualsiasi file dipendente da d:\temp. Il percorso classi è rt.jar e d:\temp, il che significa che viene effettuata una ricerca in tutte le classi necessarie prima in d:\temp e poi in rt.jar. Non genera attributi di debug e tutti i file .class generati vengono inseriti in d:\tmp.

Utilizzo dell'adattatore javac ant

Utilizzando l'adattatore javac, è possibile utilizzare il compilatore Eclipse all'interno di uno script Ant. Per utilizzare il compilatore Eclipse, è sufficiente semplicemente definire la proprietà build.compiler nello script. Di seguito viene riportato un breve esempio.
<?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 sintassi utilizzata per l'attività javac ant si trova nella documentazione relativa alle attività javac ant. L'adattatore corrente supporta l'attività Javac Ant 1.4.1 fino alla versione 1.6.5.

Se si utilizza una versione superiore a 1.5.0, è possibile utilizzare l'elemento dell'argomento del compilatore nidificato per indicare le opzioni specifiche del compilatore.

...
		<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>		
...

Per evitare di ottenere script dipendenti dal compilatore, si consiglia di utilizzare l'argomento del compilatore impostato su org.eclipse.jdt.core.JDTCompilerAdapter. In caso contrario, lo script potrà essere utilizzato solo con il,compilatore Eclipse. Se impostato, l'argomento del compilatore nidificato viene ignorato se il nome è diverso dal nome del compilatore specificato dalla proprietà build.compiler.

Determinazione dei problemi

Il JDT di base definisce un indicatore specializzato (tipo di indicatore "org.eclipse.jdt.core.problem") per evidenziare problemi di compilazione. Per scoprire in modo programmatico i problemi rilevati dal compilatore, utilizzare il protocollo degli indicatori di piattaforma standard. Per una panoramica sull'utilizzo degli indicatori, fare riferimento alla sezione relativa agli indicatori di risorse.

Il seguente frammento di codice rileva tutti gli indicatori di problemi Java all'interno di un'unità di compilazione.

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

Gli indicatori di problemi Java vengono conservati dal generatore di progetto Java e vengono automaticamente rimossi nel momento in cui i problemi vengono risolti e il codice di origine Java viene nuovamente compilato.

Il valore id del problema è impostato da una delle costanti in IProblem . L'id del problema è affidabile, tuttavia il messaggio è localizzato, pertanto è possibile modificarlo in base alla locale predefinita. Le costanti definite in IProblem si descrivono autonomamente.

Per raccogliere i problemi rilevati durante un'operazione Java, è necessario definire un'implementazione di IProblemRequestor. È possibile riconciliare le copie di lavoro con la rilevazione dei problemi se è stato fornito un IProblemRequestor per la creazione della copia di lavoro. A questo scopo, è possibile utilizzare il metodo reconcile. Ad esempio:

  ICompilationUnit unit = ..; // get some compilation unit
			
  // create requestor for accumulating discovered problems
  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; } // will detect problems if active
  };
    
  // use working copy to hold source with error
  ICompilationUnit workingCopy = unit.getWorkingCopy(new WorkingCopyOwner() {}, problemRequestor, null);
  ((IOpenable)workingCopy).getBuffer().setContents("public class X extends Zork {}");

  // trigger reconciliation			
  workingCopy.reconcile(NO_AST, true, null, null);
È possibile aggiungere un'azione ai problemi riportati nel metodo acceptProblem(IProblem). In questo esempio, il problema riportato è che Zork non può essere risolto oppure non è una superclasse valida e il relativo id è IProblem.SuperclassNotFound.