Większość witryn internetowych podaje:
„użyj
javac
polecenia, aby skompilować.java
plik. Następnie uruchom go za pomocąjava
polecenia”
Ale dzisiaj próbowałem uruchomić program java bez javac
i otrzymałem dziwny wynik.
Oto zawartość pliku o nazwie hello.java
:
public class Myclass {
public static void main(String[] args){
System.out.println("hello world");
}
}
Potem pobiegłem:
$ javac hello.java
Co daje mi ten błąd:
hello.java:1: error: class Myclass is public, should be declared in a file named Myclass.java
public class Myclass {
^
1 error
Ale kiedy uruchamiam go bez javac
polecenia, wykonywał się bez żadnych błędów.
$ java hello.java
hello world
Czy java
polecenie również kompiluje program? Jeśli tak, po co nam javac
polecenie?
Wersja mojej javy to:
openjdk version "12.0.2" 2019-07-16
OpenJDK Runtime Environment (build 12.0.2+10)
OpenJDK 64-Bit Server VM (build 12.0.2+10, mixed mode)
Myclass.java
a następnie z wiersza poleceń skompiluj go w ten sposób,javac Myclass.java
a następnie uruchom w ten sposóbjava Myclass
.javac
nadal używany do kompilacji, jeśli nie chcą wdrożyć kodu źródłowego, lub masz więcej niż jeden plik ( dokumentacja zjava
: dla opcji źródłowego pliku wyłącznie używany do uruchamiania jednego programu źródłowego pliku.)javac
kompiluje źródło Java do interpretowanego kodu bajtowego specyficznego dla maszyny JVM, ajava
polecenie ładuje je w module ClassLoader maszyny JVM.Odpowiedzi:
Przed wersją Java 11, aby uruchomić kod, musisz go najpierw skompilować, a następnie uruchomić. Oto przykład:
Od wersji Java 11 nadal możesz robić
javac
+java
lub możesz uruchomićjava
samodzielnie, aby skompilować i automatycznie uruchomić swój kod. Zauważ, że żaden.class
plik nie zostanie wygenerowany. Oto przykład:Jeśli uciekniesz
java -help
, zobaczysz różne dozwolone zastosowania. Oto, jak to wygląda na moim komputerze. Ostatnim jest to, na co natrafiłeś:java [options] <sourcefile> [args]
który „uruchomi program z pojedynczym plikiem źródłowym”.AKTUALIZACJA:
Jak wskazał @BillK, OP zapytał również:
Powodem, dla którego potrzebujemy,
javac
jest tworzenie.class
plików, aby kod mógł być tworzony, testowany, dystrybuowany, uruchamiany, współdzielony itp., Tak jak to jest obecnie. Motywacją dla JEP 330 było ułatwienie „wczesnych etapów nauki języka Java i pisania małych programów narzędziowych” bez zmiany jakichkolwiek innych istniejących zastosowań.źródło
1.
w1.8
w nowszych wydaniach)javac
.Jeśli używasz Java 11, dostępna jest nowa funkcja, która umożliwia wykonanie pojedynczego pliku źródłowego. Kompilator z jednym źródłem jest bardziej rozwiązły pod względem nazwy klasy w porównaniu z nazwą pliku, więc w ten sposób można uruchomić, ale nie można pomyślnie skompilować.
Jeśli korzystasz z poprzedniej wersji języka Java, bieżący plik hello.java nie kompiluje się z powodu błędów kompilacji, szczególnie wokół nazwy klasy. Więc nie ma absolutnie żadnego sposobu, aby wywołanie java hello.java skompilowało twój kod, ponieważ nie kompiluje się.
Wydaje się najbardziej prawdopodobne, że podczas wykonywania polecenia java uruchamiałeś jakiś wcześniej skompilowany kod.
źródło
Aby odpowiedzieć na pytanie, dlaczego podano ten błąd, nazwa klasy pliku musi być zgodna z nazwą pliku
basename
.Masz dwie opcje, aby ten kod działał dla tradycyjnego
javac
;java
sekwencja:Zmień nazwę klasy na
public class Hello
lubZmień nazwę
hello.java
namyclass.java
.java
Interpreter Javy 11 nie nakłada tego wymogu. Klasa, która zawiera,main
może mieć dowolną nazwę, o ile jest to pierwsza klasa w pliku. Miało to głównie na celu ułatwienie procesu uczenia się początkującym i umożliwienie „tworzenia skryptów java” z użyciem shebang ( ref. ).źródło
Tak, ale nie w sposób, jaki prawdopodobnie masz na myśli.
Kiedy używasz
javac
polecenia do kompilowania pliku .java do pliku .class, wynik jest nazywany kodem bajtowym. Kod bajtowy to kod maszynowy (instrukcje natywne) teoretycznego procesora opartego na specyfikacji wirtualnej maszyny języka Java.Ta specyfikacja wirtualnego procesora jest swego rodzaju średnią typami procesorów, które były powszechne w momencie pisania specyfikacji. Z tego powodu jest blisko wielu różnych typów procesorów, co ułatwia uruchamianie tych samych plików Java .class na wielu typach procesorów.
Kiedy Java została uruchomiona po raz pierwszy,
java
polecenie odczytywało plik .class i interpretowało instrukcje kodu bajtowego pojedynczo, a następnie odwzorowywało je na równoważną instrukcję natywną dla dowolnego procesora, na którym faktycznie działał. To działało, ale nie było szczególnie szybkie. Aby to ulepszyć, do środowiska wykonawczego Java dodano kompilację Just in Time (JIT).W przypadku JIT
java
polecenie pobiera kod bajtowy i kompiluje go ponownie do natywnych instrukcji procesora, na którym działa. Nowoczesne środowiska wykonawcze Java zwykle rozpoczynają interpretację kodu bajtowego podczas kompilacji JIT w tle i przełączają się na skompilowane natywne instrukcje, gdy są gotowe, a także profilują działającą aplikację, a następnie ponownie kompilują kod bajtowy z inną optymalizacją, aby uzyskać najlepszą możliwą wydajność.EDYTUJ (aby uspokoić słabych wyborców):
Więc w twoim konkretnym przypadku (ponieważ używasz JRE nowszego niż v11) kod jest kompilowany (co najmniej) dwukrotnie
źródło
mixed-mode
wynik wersji