Czy Java jest skompilowanym czy zinterpretowanym językiem programowania?

169

W przeszłości używałem C ++ jako języka programowania. Wiem, że kod napisany w C ++ przechodzi przez proces kompilacji, aż stanie się „kodem maszynowym” kodu wynikowego.

Chciałbym wiedzieć, jak działa Java w tym zakresie. W jaki sposób kod Java napisany przez użytkownika jest uruchamiany przez komputer?

wyświetlana nazwa
źródło
14
C ++ można zinterpretować. Jest tam kilku interpreterów języka C.
Tom Hawtin - tackline

Odpowiedzi:

220

Implementacje języka Java zazwyczaj wykorzystują dwustopniowy proces kompilacji. Kod źródłowy Java jest kompilowany do kodu bajtowego przez kompilator Java. Kod bajtowy jest wykonywany przez wirtualną maszynę języka Java (JVM). Nowoczesne maszyny JVM wykorzystują technikę zwaną kompilacją Just-in-Time (JIT) do kompilowania kodu bajtowego do natywnych instrukcji rozumianych przez sprzętowy procesor CPU w locie w czasie wykonywania.

Niektóre implementacje JVM mogą zdecydować się na interpretację kodu bajtowego zamiast kompilacji JIT do kodu maszynowego i bezpośredniego uruchamiania. Chociaż jest to nadal uważane za „interpreter”, różni się znacznie od interpreterów, które odczytują i wykonują kod źródłowy wysokiego poziomu (tj. W tym przypadku kod źródłowy Javy nie jest interpretowany bezpośrednio, kod bajtowy danych wyjściowych kompilatora Javy jest).

Jest technicznie możliwe skompilowanie Java do kodu natywnego z wyprzedzeniem i uruchomienie wynikowego pliku binarnego. Istnieje również możliwość bezpośredniej interpretacji kodu Java.

Podsumowując, w zależności od środowiska wykonawczego, kodem bajtowym może być:

  • kompilowany z wyprzedzeniem i wykonywany jako kod natywny (podobnie jak większość kompilatorów C ++)
  • skompilowane just-in-time i wykonane
  • interpretowane
  • wykonywane bezpośrednio przez obsługiwany procesor (kod bajtowy to natywny zestaw instrukcji niektórych procesorów)
Mehrdad Afshari
źródło
20
W rzeczywistości niektóre maszyny JVM HotSpot rozpoczynają od interpretacji kodów bajtowych i kompilują je do kodu natywnego dopiero po zorientowaniu się, co warto skompilować, i zebraniu statystyk dotyczących sposobu wykonywania kodu; np. aby znaleźć najpopularniejszą ścieżkę wybraną w każdej gałęzi warunkowej.
Stephen C
1
Stąd określenie „Hotspot” :) Robi to z tym, co często się uruchamia, aby uzyskać optymalizację.
Noon Silk
4
Możesz wyłączyć interpreter w HotSpot za pomocą -Xcomp. Warto wypróbować aplikację, aby zobaczyć, jaki to zły pomysł.
Tom Hawtin - tackline
1
Jest tam stwierdzenie: „Bieżąca wersja Sun HotSpot JVM wykorzystuje technikę zwaną kompilacją Just-in-Time (JIT) do kompilowania kodu bajtowego do natywnych instrukcji rozumianych przez procesor w locie w czasie wykonywania”. Miałem wrażenie, że JVM jest interpreterem, ale sugeruje, że dalej kompiluje kod bajtowy. Jestem zdezorientowany. Napisano również, że robi to w locie w czasie wykonywania. Czy ktoś może to również wyjaśnić?
Anand
ponieważ java jest językiem interpretowanym, w jaki sposób wpłynie to na wydajność lub wykonanie dowolnej aplikacji java
NAND
92

wprowadź opis obrazu tutaj

Kod napisany w Javie to:

  • Najpierw skompilowany do kodu bajtowego przez program o nazwie javac, jak pokazano w lewej części powyższego obrazu;
  • Następnie, jak pokazano w prawej części powyższego obrazu, inny program o nazwie java uruchamia środowisko wykonawcze Java i może kompilować i / lub interpretować kod bajtowy za pomocą interpretera języka Java / kompilatora JIT.

Kiedy java interpretuje kod bajtowy, a kiedy go kompiluje? Kod aplikacji jest początkowo interpretowany, ale JVM monitoruje, które sekwencje kodu bajtowego są często wykonywane i tłumaczy je na kod maszynowy w celu bezpośredniego wykonania na sprzęcie. W przypadku kodu bajtowego, który jest wykonywany tylko kilka razy, oszczędza to czas kompilacji i zmniejsza początkowe opóźnienie; w przypadku często wykonywanych kodów bajtowych kompilacja JIT jest używana do uruchamiania z dużą prędkością, po początkowej fazie powolnej interpretacji. Ponadto, ponieważ program spędza większość czasu na wykonywaniu mniejszości swojego kodu, skrócony czas kompilacji jest znaczący. Wreszcie, podczas wstępnej interpretacji kodu, statystyki wykonania można zebrać przed kompilacją, co pomaga w lepszej optymalizacji.

wyświetlana nazwa
źródło
Czy to ze względu na buforowany kod bajtowy Java zużywa dużo pamięci?
Pedro Gordo
3
@sedulam: „Dużo pamięci” to niejasne stwierdzenie. Zarządzanie pamięcią w Javie jest dość proste - maszyna JVM wykorzystuje trzy generacje do tworzenia i obsługi swoich obiektów. Ta kolejna odpowiedź SO może być dla Ciebie przydatna.
displayName
Mając powyższe wyjaśnienie, teoretycznie skompilowany kod C ++ zawsze będzie szybszy niż logicznie podobny kod java, ponieważ zawsze będzie jakaś część pliku .class, której JIT postanowi nie przekształcić na kod maszynowy. Innymi słowy, java nigdy nie jest w stanie złapać szybkości wykonywania od podstaw, jaką wykazał C ++. Czy to prawidłowe założenie?
DevdattaK
@DevdattaK: Nie znam C ++ aż za dużo, ale przypuszczam, że w przypadku mniejszych i wyspecjalizowanych programów Java może dać wynik szybciej, ponieważ nie marnowałaby czasu na kompilowanie tych fragmentów kodu, w których nie ma możliwości przyspieszenia.
displayName
1
@DevdattaK Twoje założenie jest omówione na tej stronie wiki en.m.wikipedia.org/wiki/Java_performance?wprov=sfla1 Krótko mówiąc, nie zawsze jest to prawdą.
Sundar Rajan
57

Terminy „język interpretowany” lub „język kompilowany” nie mają sensu, ponieważ każdy język programowania może być interpretowany i / lub kompilowany.

Jeśli chodzi o istniejące implementacje języka Java, większość z nich obejmuje etap kompilacji do kodu bajtowego , więc obejmują one kompilację. Środowisko wykonawcze może również dynamicznie ładować kod bajtowy, więc zawsze potrzebna jest pewna forma interpretera kodu bajtowego. Ten interpreter może z kolei wewnętrznie używać kompilacji do kodu natywnego lub nie.

Obecnie częściowa kompilacja just-in-time jest używana w wielu językach, które kiedyś były uważane za „interpretowane”, na przykład w JavaScript.

starblue
źródło
5
Ponadto silnik wykonawczy JavaScript V8 firmy Google nie wykonuje tylko częściowej kompilacji just-in-time. To zawsze kompiluje się do kodu natywnego, w rzeczywistości, V8 nawet nie mieć tłumacza. Ma tylko kompilator (podobny do Maxine, ale w przeciwieństwie do Maxine V8 ma tylko jeden kompilator). Wszystkie trzy przykłady (GCJ, Maxine i V8) jeszcze mocniej potwierdzają twój punkt widzenia: nie ma czegoś takiego jak język interpretowany lub język kompilowany. Język nie jest interpretowany ani kompilowany. Język po prostu jest (to właściwie cytat Shrirama Krishnamurthi).
Jörg W Mittag,
3
Dlaczego mówisz o javascript w pytaniu java?
Koray Tugay
1
@KorayTugay Tylko jako przykład. Z pewnością nie chcę sugerować, że Java i Javascript mają coś wspólnego poza pierwszymi czterema literami ich nazwy.
starblue
Czy przynajmniej różnica w interpretowanym i skompilowanym języku nie oznaczałaby, że skompilowany plik binarny języka nie może zmienić swojego przepływu wykonywania w dowolnym momencie, podczas gdy język interpretowany jest bardzo posłuszny niektórym obecnym działaniom funkcji? Biblioteki w C są opcją, podczas gdy w innych językach nie można mieć obiektu tablicy bez rozszerzenia binarnego C, które można zaktualizować lub być zupełnie innym kodem na innej platformie. Język skryptowy będzie mógł działać na obu, podczas gdy język skompilowany wymagałby innego pliku binarnego do uruchomienia
Eaton Emmerich
53

Java jest kompilowana do kodu bajtowego, który następnie trafia do maszyny wirtualnej Java, która ją interpretuje.

Noon Silk
źródło
33
... ale nie do końca dokładne.
Stephen C
2
JVM może nie „interpretować” kodu bajtowego. Może JIT skompilować go i wykonać bezpośrednio.
Mehrdad Afshari
1
JIT technicznie nie wykonuje tego bezpośrednio. Po prostu przypomina sobie, jak został wykonany.
cletus
Mehrdad: Zgadzam się, nie opisałem tutaj ewentualnych operacji JIT, ponieważ uważam, że aż do JVM, a moja odpowiedź i tak była prosta :)
Noon Silk
7
cletus: Po JIT zostanie to bezpośrednio wykonane. JIT odczytuje fragment kodu bajtowego (np. Kompletną metodę) i kompiluje go do kodu maszynowego i przeskakuje do niego.
Mehrdad Afshari
12

Java jest skompilowanym językiem programowania, ale zamiast bezpośrednio kompilować do wykonywalnego kodu maszynowego, kompiluje się do pośredniej postaci binarnej zwanej kodem bajtowym JVM. Kod bajtowy jest następnie kompilowany i / lub interpretowany w celu uruchomienia programu.

Sam Harwell
źródło
11

W pewnym sensie z obu. Najpierw skompilowano java (niektórzy woleliby powiedzieć „przetłumaczone”) do kodu bajtowego, który następnie albo skompilowano, albo zinterpretowano w zależności od nastroju JIT.

maykeye
źródło
32
To zaawansowane oprogramowanie, które stworzyło nastroje :)
Thorarin,
5
JIT jest rzeczywiście bardzo wyrafinowanym oprogramowaniem, które może przeprowadzać optymalizacje w oparciu o informacje w czasie wykonywania (jak profiler), czego nie może wykonać kompilator z wyprzedzeniem (ponieważ nie ma informacji o zachowaniu w czasie wykonywania program z wyprzedzeniem). Ale chyba nie ma nastrojów ... :-)
Jesper
5

Java zajmuje się zarówno kompilacją, jak i interpretacją,

W Javie programy nie są kompilowane do plików wykonywalnych ; są one kompilowane do kodu bajtowego (jak omówiono wcześniej), który JVM (wirtualna maszyna języka Java) interpretuje / wykonuje w czasie wykonywania. Kod źródłowy Java jest kompilowany do kodu bajtowego, gdy używamy kompilatora javac. Kod bajtowy zostanie zapisany na dysku z rozszerzeniem pliku .class .

Gdy program ma zostać uruchomiony, kod bajtowy jest konwertowany, a kod bajtowy może być konwertowany za pomocą kompilatora just-in-time (JIT). Rezultatem jest kod maszynowy, który jest następnie wprowadzany do pamięci i wykonywany.

Javac to kompilator języka Java, który kompiluje kod Java do kodu bajtowego. JVM to wirtualna maszyna Java, która uruchamia / interpretuje / tłumaczy kod bajtowy na natywny kod maszynowy. W Javie, chociaż jest uważany za język interpretowany, może używać kompilacji JIT (Just-in-Time), gdy kod bajtowy jest w JVM. Kompilator JIT odczytuje kody bajtowe w wielu sekcjach (lub w całości, rzadko) i kompiluje je dynamicznie do kodu maszynowego, dzięki czemu program może działać szybciej, a następnie buforowany i ponownie używany później bez konieczności ponownej kompilacji. Kompilacja JIT łączy więc szybkość kompilowanego kodu z elastycznością interpretacji.

Interpretowany język jest rodzajem języka programowania, dla którego większość implementacji bezpośredniego i swobodnego wykonywania instrukcji, bez uprzedniego kompilacji programu na instrukcje maszynowe językowych. Interpreter wykonuje program bezpośrednio, tłumacząc każdą instrukcję na sekwencję jednego lub więcej podprogramów już skompilowanych na kod maszynowy.

Skompilowany język jest językiem programowania, którego implementacje są zwykle kompilatory (tłumacze, które generują kod maszynowy z kodem źródłowym), a nie tłumaczy (krok po kroku wykonawcami kodu źródłowego, gdzie nie tłumaczenie pre-runtime odbywa)

We współczesnych implementacjach języków programowania, takich jak Java, coraz popularniejsze jest, aby platforma zapewniała obie opcje.

główny
źródło
Powinno być „kod bajtowy można konwertować” zamiast „ jest konwertowany”. Specyfikacje Java definiują kod bajtowy. To, czy ten kod bajtowy jest uruchamiany (a) bezpośrednio na sprzęcie , (b) przez interpreter, (c) skompilowany wcześniej, czy (d) częściowo skompilowany w locie w czasie wykonywania, pozostaje jako szczegóły implementacji. Zauważ, że wszystkie cztery z tych opcji były rzeczywiście używane przez różne implementacje języka Java w świecie rzeczywistym.
Basil Bourque
Dzięki za zwrócenie uwagi. Więc co się stanie, jeśli kod bajtowy nie zostanie przekonwertowany na kod maszynowy? Przychodzi mi do głowy scenariusz, w którym kod bajtowy jest rodzimym zestawem instrukcji dla niektórych procesorów i wtedy nie ma potrzeby konwersji. Albo coś mi brakuje.
prime
Kliknij łącze, które podałem dla technologii Jazelle DBX (Direct Bytecode eXecution) , w której podzbiór kodu bajtowego JVM to natywne instrukcje maszynowe procesora (kinda-sorta). Bez tego otrzymujesz kod maszynowy generowany z kodu bajtowego (a) z interpretera (w locie), (b) z kompilatora z wyprzedzeniem lub (c) w locie z kompilatorem just-in-time ( najpierw interpretowane, a czasami kompilowane i buforowane podczas wykonywania).
Basil Bourque,
-2

Java to język kompilowany bajtowo, przeznaczony dla platformy zwanej Java Virtual Machine, która jest oparta na stosie i ma kilka bardzo szybkich implementacji na wielu platformach.

Hobbs
źródło
1
Co oznacza „kompilacja bajtowa”?
Jesper
2
@Jesper: „Skompilowany bajtowo” zwykle oznacza „skompilowany do kodu bajtowego”. „Kod bajtowy” to termin ogólny obejmujący wszelkiego rodzaju nietekstowe kody pośrednie (zazwyczaj niewykonywalne maszynowo).
Greg Hewgill
-3

Cytat z: https://blogs.oracle.com/ask-arun/entry/run_your_java_applications_faster

Programiści aplikacji mogą opracowywać kod aplikacji w dowolnym z różnych systemów operacyjnych dostępnych obecnie na rynku. Na tym etapie język Java jest agnostyczny w stosunku do systemu operacyjnego. Genialny kod źródłowy napisany przez programistę aplikacji Java jest teraz kompilowany do kodu Java Byte, który w terminologii Java jest określany jako kompilacja po stronie klienta. Ta kompilacja do kodu Java Byte umożliwia programistom Javy „napisanie raz”. Kod Java Byte może działać na dowolnym kompatybilnym systemie operacyjnym i serwerze, dzięki czemu kod źródłowy jest niezależny od systemu operacyjnego / serwera. Po utworzeniu kodu Java Byte interakcja między aplikacją Java a bazowym systemem operacyjnym / serwerem jest bardziej intymna. Podróż trwa - struktura aplikacji korporacyjnych wykonuje te kody Java Byte w środowisku wykonawczym znanym jako Java Virtual Machine (JVM) lub Java Runtime Environment (JRE). JVM ma bliskie powiązania z podstawowym systemem operacyjnym i sprzętem, ponieważ wykorzystuje zasoby oferowane przez system operacyjny i serwer. Kod Java Byte jest teraz kompilowany do kodu wykonywalnego języka maszynowego, który jest specyficzny dla platformy. Nazywa się to kompilacją po stronie serwera.

Więc powiedziałbym, że Java jest zdecydowanie językiem kompilowanym.

Teo
źródło