W jaki sposób wirtualna maszyna Java wykonuje kod napisany w innych językach?

12

Począwszy od Java 1.6 JVM może uruchamiać niezliczoną liczbę języków programowania zamiast na Javie. Rozumiem koncepcyjnie, w jaki sposób Java jest uruchamiana na maszynie wirtualnej Java, ale nie rozumiem również, w jaki sposób mogą być na niej uruchamiane inne języki. Dla mnie wszystko wygląda jak czarna magia. Czy masz jakieś artykuły, na które chciałbym zwrócić uwagę, abym mógł lepiej zrozumieć, jak to wszystko do siebie pasuje?

Pomario
źródło
2
Taki sam sposób, w jaki procesor Intel / AMD / Solaris (??) może wykonywać „dowolny język” (chociaż tak naprawdę nie uruchamiasz języków, ale tylko płynąc tutaj), który można wkompilować w natywny kod asemblera.
Apoorv Khurasia
13
Chodzi o to, że JVM nie uruchamia Java. Działa w odrębnym (choć pokrewnym i celowo łatwym w kompilatorach Java tworzeniu), bardziej niskim języku.
To prawda. Ale JVM zaczął uruchamiać inne języki od wersji 6; w wersji 1.4.2 nie można (lub nikt nie zrobił) uruchamiać na nim Pythona ani Groovy. Dlaczego to jest takie? Co się zmieniło?
Pomario,
@delnan Lub raczej „bardziej niższy poziom wykonania, że ​​program javac wie, jak zbudować kod Java”.
Apoorv Khurasia
9
@Pomario Jython istnieje już od jakiegoś czasu. A to strona wydaje się sugerować, że skrypty Jython może uruchomić na 1.4.2.
Apoorv Khurasia

Odpowiedzi:

23

Kluczem jest język ojczysty JVM: kod bajtowy Java. Dowolny język można skompilować do kodu bajtowego, który JVM rozumie - wystarczy do tego kompilator emitujący bajtekod. Od tego momentu nie ma różnicy z punktu widzenia JVM. Do tego stopnia, że ​​możesz pobrać skompilowany plik klasy Scala, Clojure, Jython itp. I zdekompilować go (np. JAD ) do normalnie wyglądającego kodu źródłowego Java.

Więcej informacji na ten temat można znaleźć w następujących artykułach / wątkach:

Nie znam żadnych fundamentalnych zmian w JVM Java 5 lub 6, które umożliwiłyby lub ułatwiałyby uruchomienie (kodu skompilowanego z) innych języków na nim. W moim rozumieniu JVM 1.4 był mniej więcej tak samo zdolny jak JVM 6 (mogą się jednak różnić; nie jestem ekspertem od JVM). Po prostu ludzie zaczęli opracowywać inne języki i / lub kompilatory kodu bajtowego w pierwszej połowie dekady, a wyniki zaczęły pojawiać się (i stały się szerzej znane) około 2006 roku, kiedy opublikowano Javę 6.

Jednak wszystkie te wersje JVM mają pewne ograniczenia: JVM jest statycznie typowany z natury, a do wersji 7 nie obsługiwał języków dynamicznych. Zmieniło się to wraz z wprowadzeniem invokedynamicnowej instrukcji kodu bajtowego, która umożliwia wywoływanie metod w oparciu o dynamiczne sprawdzanie typu.

Péter Török
źródło
8
Nie jest do końca prawdą, że JVM nie „obsługiwał” dynamicznych języków. Musieli po prostu zastosować obejścia, które miały poważne wady.
Michael Borgwardt,
3
@MichaelBorgwardt, czy możemy się zgodzić, że JVM w wersjach wcześniejszych niż 7 toleruje dynamiczne języki (do pewnego stopnia)? :-)
Péter Török,
1
To dobry sposób na wyrażenie tego :)
Michael Borgwardt,
3

Maszyna wirtualna, taka jak JVM, to program, który przyjmuje jako dane wejściowe, zwykle pliki, zestaw prostych instrukcji (które zwykle można łatwo przekonwertować na rzeczywiste instrukcje procesora), i faktycznie kompiluje je i uruchamia jako natywne instrukcje procesora (zwykle przy użyciu kompilator na żądanie, taki jak HotSpot lub JIT).

Zasadniczo jest to warstwa abstrakcji. Zwykle znacznie łatwiej jest przenieść implementacje zestawu instrukcji VM do różnych architektur procesorów, z powodu kilku podobieństw (takich jak oparte na stosie). Znacznie łatwiej jest także przenosić różne języki programowania na instrukcje VM, ponieważ jest bardziej zorientowany na współczesne języki programowania niż na prymitywne instrukcje CPU. Wiele maszyn wirtualnych, takich jak JVM i CLR (.NET), zawiera instrukcje wywoływania metod wirtualnych i tworzenia instancji obiektów.

Weźmy na przykład język. Nazwij to MyLanguage. Ponieważ jest to język programowania, ostatecznie kompiluje się do zestawu instrukcji architektury CPU. Oznacza to, że przy zgodnym, elastycznym zestawie instrukcji maszyny wirtualnej możliwe jest również skompilowanie MyLanguage do zestawu instrukcji tej maszyny wirtualnej.

Zawsze pojawia się kwestia wydajności, ponieważ może być konieczne zhakowanie niektórych obejść w zestawach instrukcji VM, których nie musiałbyś robić natywnie, ale nadal jest to możliwe.

Yam Marcovic
źródło
3

JVM jest maszyną obliczeniową Turing-complete (z wyjątkiem ograniczonej pamięci), a każda maszyna Turing-complete (fizyczna lub wirtualna) może wykonywać dowolny język programowania (z wyjątkiem ograniczeń pamięci, wydajności i fizycznych IO).

hotpaw2
źródło
Eee… dlaczego więc potrzebujemy kompilatorów? ;-)
Péter Török,
Sami kompilatorzy i tłumacze mogą działać na maszynach Turinga (może powoli). Być może niektóre kroki przed kompilacją / tłumaczeniem mogą poprawić wydajność uruchamiania danego programu w danym języku?
hotpaw2
1
Chodzi mi o to, że twoje stwierdzenie „dowolna maszyna Turinga (fizyczna lub wirtualna) może wykonywać dowolny język programowania” dosłownie oznacza, że ​​procesor x86 mojego laptopa może bezpośrednio wykonać ten ładny plik źródłowy Java, nad którym teraz pracuję. Lub kod maszynowy dla procesorów PowerPC. Bez kompilatorów - procesory nie zawierają kompilatorów, prawda? :-)
Péter Török,
Twoja „maszyna” to coś więcej niż tylko procesor.
hotpaw2
1
@ PéterTörök Rozumiem twój punkt widzenia. Nie rozwijał się na maszynach wirtualnych tak jak my. Ale myślę, że jego odpowiedź wciąż krótko odpowiada na pytanie PO. JVM może „uruchamiać” inne języki programowania, ponieważ może „uruchamiać” dowolny język programowania, ponieważ Turing jest kompletny. Być może nie jest to skomplikowane, ale wciąż zwięzłe i ważne stwierdzenie. :)
Yam Marcovic
2

Przez chwilę pomyśl o JVM jako procesorze z własnym zestawem instrukcji, jak na przykład x86. Procesor może wykonać kod powiedzmy C, który został wkompilowany w jego język maszynowy. Stosując tę ​​samą analogię do JVM, inne języki mogą być uruchamiane na JVM, podobnie jak na innych procesorach, jeśli języki te zostaną skompilowane zgodnie z instrukcjami maszynowymi JVM. JVM może następnie uruchomić te instrukcje dla języka X.

cobie
źródło
twoja analogia jest dobra
cobi