Ci, którzy dopiero zaczynają zapoznawać się z Javą, często mylą się z pojęciami kodu
maszynowego i
kodu bajtowego . Czym oni są? Jakie są różnice? W krótkiej notatce postaramy się opisać ich cechy tak prosto i przejrzyście, jak to możliwe, aby raz na zawsze zamknąć tę kwestię.
Kod maszynowy
Procesor jest w istocie bardzo złożonym i zaawansowanym kalkulatorem. Posiada wiele lokalizacji pamięci (zwanych rejestrami), na których i pomiędzy którymi wykonywane są różne operacje matematyczne i bajtowe. Kod maszynowy to dokładny opis sekwencji operacji i zestawu danych. W rzeczywistości jest to jedyny język, jaki rozumie procesor Twojego komputera.
Wrodzona niezgodność
Jednocześnie nie wszystkie procesory „mówią” tym samym językiem. Istnieją różnice nie tylko pomiędzy architekturami
CISC i
RISC , ale także w obrębie tych „obozów”.
CISC (Complex Order Set Computing) to koncepcja projektowania procesora charakteryzująca się następującym zestawem właściwości:
- wiele poleceń o różnej długości;
- wiele trybów adresowania;
- złożone kodowanie instrukcji.
RISC (Reduced Order Set Computing) – procesor ze zredukowanym zestawem instrukcji. Polecenia mają ten sam format, są krótkie i mają proste kodowanie. |
Nowe generacje procesorów wprowadzają dodatkowe zestawy instrukcji, które są po prostu nieznane modelom starszej generacji. Z tego powodu programy skompilowane dla jednej architektury (lub jednej generacji procesorów) nie mogą działać na innym sprzęcie. Wszystko to zmusza nas do ponownej kompilacji programów, aby mieć pewność, że działają na innych komputerach. Jednak rekompilację trzeba przeprowadzić nie tylko ze względu na procesory, ale także ze względu na różnice w interakcji programów i systemu operacyjnego. To właśnie z ich powodu nie da się uruchomić programu „Windows” pod Linuksem, a programu „Linux” pod Windowsem.
Kod bajtowy
Kod bajtowy pod wieloma względami przypomina kod maszynowy, tyle że wykorzystuje zestaw instrukcji nie z prawdziwego procesora, ale z wirtualnego. Ponadto może zawierać sekcje skupiające się na wykorzystaniu
kompilatora JIT , który optymalizuje wykonywanie poleceń dla rzeczywistego procesora, na którym uruchomiony jest program.
Kompilacja JIT (kompilacja just-in-time, kompilacja w locie) lub kompilacja dynamiczna (tłumaczenie dynamiczne) to technologia zwiększająca wydajność systemów oprogramowania korzystających z kodu bajtowego poprzez kompilację kodu bajtowego do kodu maszynowego lub do innego formatu bezpośrednio podczas program jest uruchomiony. „Oficjalnie” w Javie do wersji 9 istniał tylko kompilator JIT. W Javie 9 pojawił się inny kompilator, który kompiluje się z wyprzedzeniem (AoT). Ta funkcja umożliwia kompilację klas Java do kodu natywnego przed uruchomieniem na maszynie wirtualnej. Ta funkcja ma na celu skrócenie czasu uruchamiania zarówno małych, jak i dużych aplikacji, przy ograniczonym wpływie na maksymalną wydajność. |
W przypadku procesorów
CISC niektóre instrukcje można łączyć w bardziej złożone struktury obsługiwane przez procesor, a w przypadku
RISC wręcz przeciwnie, można je rozbić na prostsze ciągi instrukcji.
Również wirtualny system operacyjny
Jednak kod bajtowy zawiera nie tylko instrukcje procesora. Zawiera także logikę interakcji z wirtualnym systemem operacyjnym, dzięki czemu zachowanie aplikacji jest niezależne od systemu operacyjnego używanego na komputerze. Widać to wyraźnie w
JVM , gdzie praca z wywołaniami systemowymi i
GUI często jest niezależna od systemu operacyjnego, na którym uruchomiony jest program. Ogólnie rzecz biorąc,
JVM emuluje uruchomienie procesu programu, w przeciwieństwie do rozwiązań takich jak
Virtual Box , które tworzą jedynie wirtualny system/sprzęt.
Czy JVM jest jedyny taki?
Absolutnie nie. Ten sam
DotNet CLI jest jednocześnie maszyną wirtualną, z której najczęściej korzysta się na komputerach z systemem Windows i procesorami kompatybilnymi
z x86 . Istnieje jednak implementacja dla innych systemów: aplikacje dla niego muszą działać w
systemie Windows RT działającym na procesorach zgodnych z
ARM (RISC) lub można je uruchamiać w
systemie Linux/OSX w środowisku
Mono , które jest oprogramowaniem innej firmy (a zatem nie w pełni kompatybilny) implementacja
DotNet dla tych platform. Zatem ta platforma, podobnie jak
JVM , działa na różnych procesorach i różnych systemach operacyjnych. Podobnych rozwiązań (starych i nowych) jest znacznie więcej:
LLVM ,
Flash SWF i inne. Niektóre języki programowania mają własne maszyny wirtualne. Na przykład
CPython kompiluje źródła
PY do plików
PYC - skompilowanego kodu bajtowego, który jest przygotowany do uruchomienia w
PVM . Lub istnieje znacznie starszy przykład -
Lisp można skompilować do plików
FASL (Fast Load). W rzeczywistości zawierają
drzewo AST zbudowane przez generator z kodu źródłowego. Pliki te mogą być odczytywane i wykonywane przez interpreter
Lisp na różnych platformach lub wykorzystywane do generowania kodu maszynowego dla aktualnie używanej architektury sprzętowej.
GO TO FULL VERSION