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?
12
Odpowiedzi:
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
invokedynamic
nowej instrukcji kodu bajtowego, która umożliwia wywoływanie metod w oparciu o dynamiczne sprawdzanie typu.źródło
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.
źródło
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).
źródło
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.
źródło