Ricerca…


Osservazioni

Il comando javac viene utilizzato per compilare i file di origine Java in file bytecode. I file Bytecode sono indipendenti dalla piattaforma. Ciò significa che è possibile compilare il codice su un tipo di hardware e sistema operativo e quindi eseguire il codice su qualsiasi altra piattaforma che supporti Java.

Il comando javac è incluso nelle distribuzioni Java Development Kit (JDK).

Il compilatore Java e il resto della toolchain Java standard mettono le seguenti restrizioni sul codice:

  • Il codice sorgente è contenuto in file con il suffisso ".java"
  • I bytecode sono contenuti in file con il suffisso ".class"
  • Per i file sorgente e bytecode nel file system, il percorso dei file deve riflettere la denominazione del pacchetto e della classe.

Nota: il compilatore javac non deve essere confuso con il compilatore JIT (Just in Time) che compila bytecode su codice nativo.

Il comando 'javac': per iniziare

Semplice esempio

Supponendo che "HelloWorld.java" contenga la seguente sorgente Java:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}

(Per una spiegazione del codice precedente, fai riferimento a Come iniziare con Java Language .)

Possiamo compilare il file sopra usando questo comando:

$ javac HelloWorld.java 

Questo produce un file chiamato "HelloWorld.class", che possiamo quindi eseguire come segue:

$ java HelloWorld
Hello world!

I punti chiave da notare da questo esempio sono:

  1. Il nome file di origine "HelloWorld.java" deve corrispondere al nome della classe nel file di origine ... che è HelloWorld . Se non corrispondono, si otterrà un errore di compilazione.
  2. Il nome file bytec "HelloWorld.class" corrisponde al nome della classe. Se si dovesse rinominare "HelloWorld.class", si otterrebbe un errore quando si tenta di eseguirlo.
  3. Quando si esegue un'applicazione Java usando java , si fornisce il nome di classe NOT al nome file bytecode.

Esempio con i pacchetti

Il codice Java più pratico utilizza pacchetti per organizzare lo spazio dei nomi per le classi e ridurre il rischio di collisioni accidentali di nomi di classi.

Se volessimo dichiarare la classe HelloWorld in una chiamata di pacchetto com.example , "HelloWorld.java" conterrà la seguente sorgente Java:

package com.example;

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}

Questo file del codice sorgente deve essere memorizzato in un albero di directory la cui struttura corrisponde alla denominazione del pacchetto.

.    # the current directory (for this example)
|
 ----com
     |
      ----example
          |
           ----HelloWorld.java

Possiamo compilare il file sopra usando questo comando:

$ javac com/example/HelloWorld.java 

Questo produce un file chiamato "com / example / HelloWorld.class"; cioè dopo la compilazione, la struttura del file dovrebbe assomigliare a questa:

.    # the current directory (for this example)
|
 ----com
     |
      ----example
          |
           ----HelloWorld.java
           ----HelloWorld.class

Possiamo quindi eseguire l'applicazione come segue:

$ java com.example.HelloWorld
Hello world!

Ulteriori punti da notare da questo esempio sono:

  1. La struttura della directory deve corrispondere alla struttura del nome del pacchetto.
  2. Quando si esegue la classe, è necessario fornire il nome completo della classe; cioè "com.example.HelloWorld" non "HelloWorld".
  3. Non è necessario compilare ed eseguire il codice Java fuori dalla directory corrente. Lo stiamo facendo solo qui per l'illustrazione.

Compilare più file contemporaneamente con 'javac'.

Se la tua applicazione è composta da più file di codice sorgente (e quasi tutti!) Puoi compilarli uno alla volta. In alternativa, puoi compilare più file contemporaneamente elencando i nomi dei percorsi:

$ javac Foo.java Bar.java

o usando la funzionalità jolly del nome del comando shell shell ....

$ javac *.java
$ javac com/example/*.java
$ javac */**/*.java #Only works on Zsh or with globstar enabled on your shell

In questo modo verranno compilati tutti i file di origine Java nella directory corrente, nella directory "com / example" e, rispettivamente, in modo ricorsivo nelle directory secondarie. Una terza alternativa consiste nel fornire un elenco di nomi di file di origine (e opzioni del compilatore) come un file. Per esempio:

$ javac @sourcefiles

dove il file sourcefiles contiene:

Foo.java
Bar.java
com/example/HelloWorld.java

Nota: il codice di compilazione come questo è appropriato per piccoli progetti di una sola persona e per programmi una tantum. Oltre a questo, è consigliabile selezionare e utilizzare uno strumento di compilazione Java. In alternativa, la maggior parte dei programmatori utilizza un IDE Java (ad esempio NetBeans , eclipse , IntelliJ IDEA ) che offre un compilatore incorporato e la creazione incrementale di "progetti".

Opzioni "javac" comunemente usate

Ecco alcune opzioni per il comando javac che potrebbero esserti utili

  • L'opzione -d imposta una directory di destinazione per scrivere i file ".class".
  • L'opzione -sourcepath imposta un percorso di ricerca del codice sorgente.
  • L'opzione -cp o -classpath imposta il percorso di ricerca per trovare classi esterne e compilate in precedenza. Per ulteriori informazioni sul classpath e su come specificarlo, fare riferimento a The Classpath Topic.
  • L'opzione -version stampa le informazioni sulla versione del compilatore.

Un elenco più completo di opzioni del compilatore verrà descritto in un esempio separato.

Riferimenti

Il riferimento definitivo per il comando javac è la pagina di manuale di Oracle per javac .

Compilare per una versione diversa di Java

Il linguaggio di programmazione Java (e il suo runtime) ha subito numerosi cambiamenti dal suo rilascio dalla sua prima pubblicazione pubblica. Queste modifiche includono:

  • Cambiamenti nella sintassi e nella semantica del linguaggio di programmazione Java
  • Cambiamenti nelle API fornite dalle librerie di classi standard Java.
  • Modifiche nel set di istruzioni Java (bytecode) e nel file di classi.

Con pochissime eccezioni (ad esempio la parola chiave enum , le modifiche ad alcune classi "interne", ecc.), Queste modifiche sono retrocompatibili.

  • Un programma Java compilato utilizzando una versione precedente della toolchain Java verrà eseguito su una piattaforma Java versione più recente senza ricompilazione.
  • Un programma Java che è stato scritto in una versione precedente di Java verrà compilato correttamente con un nuovo compilatore Java.

Compilazione di Java vecchio con un compilatore più recente

Se è necessario (ri) compilare il codice Java precedente su una piattaforma Java più recente per l'esecuzione sulla piattaforma più recente, in genere non è necessario fornire alcun flag di compilazione speciale. In alcuni casi (ad es. Se hai usato enum come identificatore) potresti usare l'opzione -source per disabilitare la nuova sintassi. Ad esempio, data la seguente classe:

public class OldSyntax {
    private static int enum;  // invalid in Java 5 or later
}

quanto segue è necessario per compilare la classe usando un compilatore Java 5 (o successivo):

$ javac -source 1.4 OldSyntax.java

Compilare per una piattaforma di esecuzione precedente

Se è necessario compilare Java per eseguire su piattaforme Java precedenti, l'approccio più semplice è installare un JDK per la versione più vecchia che è necessario supportare e utilizzare il compilatore di JDK nei propri build.

Puoi anche compilare con un compilatore Java più recente, ma ci sono complicati. Prima di tutto, ci sono alcune condizioni preliminari importanti che devono essere soddisfatte:

  • Il codice che stai compilando non deve utilizzare costrutti del linguaggio Java che non erano disponibili nella versione di Java che hai scelto come target.
  • Il codice non deve dipendere da classi, campi, metodi e standard Java standard che non erano disponibili nelle piattaforme precedenti.
  • Le librerie di terze parti che il codice dipende devono essere costruite per la piattaforma precedente e disponibili in fase di compilazione e in fase di esecuzione.

Date le condizioni preliminari soddisfatte, è possibile ricompilare il codice per una piattaforma precedente utilizzando l'opzione -target . Per esempio,

$ javac -target 1.4 SomeClass.java

compilerà la classe precedente per produrre bytecode compatibili con Java 1.4 o successive JVM. (In effetti, l'opzione -source implica un -target compatibile, quindi javac -source 1.4 ... avrebbe lo stesso -source relazione tra -source e -target è descritta nella documentazione di Oracle.)

Detto questo, se si usa semplicemente -target o -source , si procederà comunque alla compilazione delle librerie di classi standard fornite dal JDK del compilatore. Se non si presta attenzione, è possibile ritrovarsi con classi con la versione di bytecode corretta, ma con dipendenze da API non disponibili. La soluzione è usare l'opzione -bootclasspath . Per esempio:

$ javac -target 1.4 --bootclasspath path/to/java1.4/rt.jar SomeClass.java

si compilerà con un insieme alternativo di librerie di runtime. Se la classe che si sta compilando ha dipendenze (accidentali) sulle nuove librerie, questo ti darà errori di compilazione.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow