JVM obsługuje tak wiele języków innych niż Java, jak Groovy,Clojure,Scala
itp., Które są językami funkcjonalnymi w przeciwieństwie do Javy (mam na myśli Javę przed wersją 8, gdzie Lambda's
nie są obsługiwane), która nie obsługuje funkcji funkcjonalnych. Na wysokim poziomie, co sprawia, że JVM jest tak wszechstronny, że może obsługiwać zarówno języki obiektowe, jak i funkcjonalne?
18
Odpowiedzi:
W porównaniu z innymi maszynami wirtualnymi, JVM nie jest szczególnie wszechstronny . Obsługuje bezpośrednio statyczne OO. Jeśli chodzi o wszystko inne, musisz zobaczyć, jakich części możesz użyć i jak zbudować wszystko inne, czego twój język potrzebuje na tych częściach.
Na przykład, dopóki Java 7 nie wprowadziła
invokedynamic
kodu bajtowego, bardzo trudno było wdrożyć dynamicznie typowany język OO w JVM - trzeba było zastosować złożone obejścia, które były złe dla wydajności i skutkowały strasznie rozdętymi śladami stosu.A jednak przed JVM zaimplementowano kilka dynamicznych języków (między innymi Groovy, Jython, JRuby).
Nie dlatego, że JVM jest tak wszechstronny, ale dlatego, że jest tak rozpowszechniony i ponieważ ma bardzo dojrzałe, dobrze obsługiwane i wydajne implementacje.
A może nawet ważniejsze, ponieważ istnieje ogromna ilość kodu Java, który robi prawie wszystko, a jeśli twój język działa na JVM, możesz łatwo zaoferować możliwości integracji z tym kodem. Zasadniczo obsługa języka w JVM jest wersją XXI wieku oferującą współdziałanie z C.
źródło
JVM został napisany tak, aby zachowywał się jak procesor, istnieje zestaw instrukcji, coś w rodzaju zestawu, który uruchamia VM nazywa się bajtecodes. Jeśli możesz napisać kompilator, który generuje prawidłowy zestaw kodów bajtowych, JVM może je uruchomić.
Wikipedia ma listę kodów bajtowych:
http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings
a także wyjaśnienie, w jaki sposób JVM ładuje kody bajtów:
http://en.wikipedia.org/wiki/Java_virtual_machine
Używając kodów bajtowych stylu wywołania, funkcjonalny język może wykonywać kod, niezależnie od tego, jak wygląda źródło. Ponadto, dzięki dodaniu invokevirtual, implementacje języka, takie jak jruby, dają pewną elastyczność w sposobie ich działania.
źródło
Dodam, że JVM obsługuje dobrze zdefiniowany i całkiem przyzwoity model pamięci ( JMM ), co oznacza dobre wsparcie dla spójnego (choć niskiego poziomu) zachowania wątków. Ma także potężny kompilator Just In Time (nieużyteczny dla języków dynamicznych dzięki MethodHandles i invokedynamic).
Ostatni, ale nie mniej ważny, jest podsystem JVM Garbage Collection, który (z odpowiednim strojeniem) zarządza pamięcią dla ciebie niezależnie od języka na górze.
źródło
someField = new int[]{42};
jedyny sposób na zapewnienie, że każdy wątek, który widzi nową tablicę, zobaczy wartość 42 mają albo zrobić pole,final
albovolatile
. Jeśli pole jest generowane leniwie, ale jest często używane, sprawiając, że niefinal
będzie działać, avolatile
nałożenie go może nałożyć niepotrzebną karę synchronizacyjną za każdym razem, gdy jest dostępne. W nawetKluczowym elementem w tym jest oddzielenie kompilacji od fazy wykonania. Dzięki temu możliwe jest pisanie innych kompilatorów kompilujących inne języki do kodu bajtowego.
Bajtek tam działa podobnie jak kod maszynowy procesora - masz wszystkie małe operacje potrzebne do uruchomienia programu - możesz uzyskać zmienną, wykonać matematykę, wykonać operacje warunkowe itp.
Java również nie jest wyjątkowa. W Javie istnienie wielu języków nie było nawet celem projektowym, w przeciwieństwie do innych maszyn wirtualnych. Dla .NET CIL Microsoftu możliwość uruchamiania wielu języków (C #, VB.Net, ...) była kluczowym elementem projektu, również ParrotVM z projektu Perl6, który miał być ogólną maszyną wirtualną.
Dla zabawy stworzyłem kiedyś dowód, że nawet PHP Zend Engine na to pozwoli.
I szczerze mówiąc, nie jest to nic nowego - nawet na prawdziwym sprzęcie możesz obsługiwać wiele języków - np. C lub Fortran.
Różnica w stosunku do tego oddzielenia od kompilacji i wykonywania to interpretatory klasyczne, takie jak niektóre formy Basic, skrypty powłoki itp., Często działają w taki sposób, że wykonują kod mniej więcej wiersz po wierszu, nie wprowadzając go w natychmiastową formę pomiędzy.
źródło
JVM jest pierwszą maszyną wirtualną, o której wiem, która kombinacja wyrzucania elementów bezużytecznych, wydajność i działający model piaskownicy. Pojawienie się wielu języków do obsługi JVM prawdopodobnie nie jest tak bardzo wynikiem „wszechstronności”, ale raczej faktu, że język Java nie ma pewnych istotnych funkcji, które ludzie chcą w języku programowania. Na przykład, podczas gdy większość języków maszynowych ma tylko pół tuzina typów danych (np. Bajt, półsłówko, słowo, podwójne słowo, liczba zmiennoprzecinkowa pojedynczej precyzji i liczba zmiennoprzecinkowa podwójnej precyzji), ogromna większość języków programowania pozwala na użycie kodu dowolna liczba typów danych zdefiniowanych przez użytkownika. JVM rozpoznaje kilka prymitywnych typów podobnych do tych na typowej maszynie, a także jeszcze jeden typ: Promiscuous Object Reference. Język Java również rozpoznaje te prymitywy, i Odwołania do obiektów rozwiązłych. Podczas gdy zmienna może być ograniczona tak, aby nie zawierała odniesień do niczego, co nie jest określoną klasą, język nie rozróżnia żadnego z następujących rodzajów pola typu
List<String>
który może być przechowywany przezMyThing
klasę instancjiMyClass
:Odniesienie do czegoś, co kod wie, jest niezmienną implementacją
List<String>
Odwołanie do instancji typu listy zmiennych, która nigdy nie będzie narażona na nic, co mogłoby ją mutować.
Odwołanie do zmiennej listy, do której, oprócz wykonywania
MyThings
metod, żadne inne odniesienie nie mogłoby istnieć nigdzie we wszechświecie.Odwołanie do listy zmiennych, która jest własnością innego obiektu , którego ten obiekt chciałby
MyThing
użyć w pewien sposób.Odniesienie do listy zmiennych, która
MyThing
jest właścicielem, ale która również wystawiła na działanie innych obiektów, aby mogli coś z tym zrobić.Mimo że wszystkie te pola mogą mieć typ
List<String>
, zawierają bardzo różne rzeczy. Wyrazisty język może pozwolić na rozróżnienie tych znaczeń, ale Java tego nie robi. Ponieważ język może nadawać znaczenie takim rzeczom (przynajmniej poza ogólnymi kontekstami) i działać w JVM, pozostawia to wiele miejsca dla języków docelowych dla JVM do wyrażania pojęć, których Java nie może.źródło