Ce face javac
javac citește codul sursă, verifică sintaxa și tipurile și produce câte un fișier .class pentru fiecare clasă (inclusiv cele interne, de forma Exterior$Interioara.class). Fișierele .class conțin bytecode, pe care îl rulează comanda java pe orice sistem de operare.
Opțiuni des folosite: -d dir (unde se scriu clasele, în directoare după pachet), -cp / --class-path (unde se caută clasele deja compilate și bibliotecile .jar), --release N (compilează pentru o versiune mai veche de Java), -encoding UTF-8, -g (informații pentru depanare), --enable-preview (funcții încă în previzualizare).
-Xlint:all activează toate avertismentele utile (tipuri brute, conversii nesigure, serialVersionUID lipsă, cazuri switch fără break), iar -Werror le transformă în erori. Exemplele din această secțiune sunt compilate exact așa. În proiectele mari, javac este apelat de Maven sau Gradle, nu manual.
Exemple
Exemplul 1: Compilare și rulare
javac nu afișează nimic dacă totul e în regulă; rezultatul este Main.class. Din Java 11 poți rula direct și sursa, cu java Main.java, fără un pas separat de compilare.
// Main.java
public class Main {
public static void main(String[] args) {
String nume = args.length > 0 ? args[0] : "lume";
System.out.println("Salut, " + nume + "!");
}
}
Rezultat în terminal
$ javac Main.java
$ ls
Main.class
Main.java
$ java Main Ana
Salut, Ana!
$ javac -version
javac 27
Exemplul 2: Erori și avertismente
Fișierul Raport.java are două probleme: lista este declarată fără tipul elementelor (List în loc de List<String>) și lipsește ; pe linia 8. Prima compilare se oprește la ; lipsă. După corectare, fără opțiuni javac doar menționează operațiile nesigure; cu -Xlint:all arată fiecare avertisment, iar cu -Werror compilarea eșuează (cod de ieșire 1).
import java.util.ArrayList;
import java.util.List;
public class Raport {
public static void main(String[] args) {
List lista = new ArrayList();
lista.add("Iași");
int total = 0
System.out.println(lista);
}
}
Rezultat în terminal
$ javac Raport.java
Raport.java:8: error: ';' expected
int total = 0
^
1 error
# după ce adăugăm ;
$ javac Raport.java
Note: Raport.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
$ javac -Xlint:all -Werror Raport.java
Raport.java:6: warning: [rawtypes] found raw type: List
List lista = new ArrayList();
^
missing type arguments for generic class List<E>
where E is a type-variable:
E extends Object declared in interface List
Raport.java:6: warning: [rawtypes] found raw type: ArrayList
List lista = new ArrayList();
^
missing type arguments for generic class ArrayList<E>
where E is a type-variable:
E extends Object declared in class ArrayList
Raport.java:7: warning: [unchecked] unchecked call to add(E) as a member of the raw type List
lista.add("Iași");
^
where E is a type-variable:
E extends Object declared in interface List
error: warnings found and -Werror specified
1 error
3 warnings
Exemplul 3: Compilatorul apelat din cod (ToolProvider)
Compilatorul este disponibil și ca API: ToolProvider.getSystemJavaCompiler() primește aceleași argumente ca linia de comandă. Programul scrie un fișier sursă în directorul curent, îl compilează și verifică dacă a apărut fișierul .class.
import java.io.ByteArrayOutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
public class Main {
public static void main(String[] args) throws Exception {
Files.writeString(Path.of("Salut.java"), """
public class Salut {
public static void main(String[] args) {
System.out.println("Salut din Salut.class!");
}
}
""");
Files.writeString(Path.of("Gresit.java"), "public class Gresit { int x = }");
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
int cod = javac.run(null, null, null, "-d", ".", "Salut.java");
System.out.println("Salut.java -> cod de ieșire " + cod + ", Salut.class există: " + Files.exists(Path.of("Salut.class")));
ByteArrayOutputStream erori = new ByteArrayOutputStream();
int cod2 = javac.run(null, null, erori, "-d", ".", "Gresit.java");
System.out.println("Gresit.java -> cod de ieșire " + cod2);
System.out.println(erori.toString().lines().findFirst().orElse(""));
}
}
Rezultat
Salut.java -> cod de ieșire 0, Salut.class există: true
Gresit.java -> cod de ieșire 1
Gresit.java:1: error: illegal start of expression
Greșeli frecvente
- Scrii
javac Mainfără extensie:error: Class names, 'Main', are only accepted if annotation processing is explicitly requested. Compilezi fișierul:javac Main.java. - Compilezi cu un JDK mai nou și rulezi cu o versiune mai veche de Java:
UnsupportedClassVersionError. Folosește--releasecu versiunea țintă. - Fișiere sursă cu diacritice salvate în altă codificare decât UTF-8:
unmappable character for encoding. Salvează în UTF-8 sau adaugă-encoding UTF-8. - Uiți
-cppentru o bibliotecă externă:package com.exemplu does not exist.
Comenzi înrudite
java (lansatorul): java pornește mașina virtuală Java și rulează un program: o clasă compilată, un fișier .jar sau direct un fișier sursă .java.jar: jar împachetează clasele compilate (și resursele) într-o singură arhivă .jar, care poate fi distribuită și rulată cu java -jar.main și structura unui program: Orice program Java pornește din metoda main a unei clase: public static void main(String[] args).Pachete și importuri (package, import): package așază clasa într-un pachet (un spațiu de nume, ca un director); import permite folosirea claselor din alte pachete după numele scurt.Module (module-info.java): Un modul (module-info.java) grupează pachete și declară explicit de ce module depinde (requires) și ce pachete oferă altora (exports).