40
1 POLITECHNIKA ŚLĄSKA WYDZIAŁ INŻYNIERII MATERIAŁOWEJ I METALURGII Edukacja Techniczno Informatyczna Studia dzienne Praca dyplomowa inżynierska Tomasz Babiarz PORÓWNANIE KOMPILATORÓW DLA ŚRODOWISKA JAVA COMPARISON OF JAVA COMPILERS Kierujący pracą: dr inż. Marcin Blachnik Katowice, marzec 2010r.

Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

  • Upload
    others

  • View
    9

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

1

POLITECHNIKA ŚLĄSKA

WYDZIAŁ INŻYNIERII MATERIAŁOWEJ I METALURGII

Edukacja Techniczno Informatyczna

Studia dzienne

Praca dyplomowa inżynierska

Tomasz Babiarz

PORÓWNANIE KOMPILATORÓW DLA ŚRODOWISKA JAVA

COMPARISON OF JAVA COMPILERS

Kierujący pracą:

dr inż. Marcin Blachnik

Katowice, marzec 2010r.

Page 2: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

2

Spis treści

1. Wstęp .................................................................................................. 3

1.1 Cel pracy .......................................................................................... 4

1.2 Wersje Javy ..................................................................................... 5

1.3 Tworzenie programu w Javie ............................................................ 6

2. Wirtualna maszyny Javy ....................................................................... 7

3. Kompilatory ........................................................................................... 9

3.1 Kompilacja w Javie ......................................................................... 14

3.2 Javac ............................................................................................. 19

3.3 Jikes .............................................................................................. 22

3.4 GCJ ............................................................................................... 22

4. Część praktyczna ................................................................................ 24

4.1 Wyniki testów ................................................................................. 31

4.2 Wykresy ......................................................................................... 32

4.3 Wnioski .......................................................................................... 35

5. Podsumowanie .................................................................................... 36

6. Literatura............................................................................................. 37

7. Spis rysunków ..................................................................................... 38

8. Spis tabel ............................................................................................ 39

9. Spis wykresów .................................................................................... 40

Page 3: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

3

1. Wstęp

Początki JAVY sięgają 1991, kiedy to James Gosling wraz z grupką

inżynierów rozpoczął prace nad niewielkim językiem komputerowym, który

znalazłby zastosowanie w niewielkich urządzeniach elektronicznych. Z powodu , iż

urządzenia te nie posiadały za wiele pamięci, język musiał być mały a przy tym

generować prosty kod maszynowy. Ponieważ producenci sprzętu elektronicznego

montowali w swoich produktach rożne procesory, ważne było aby język nie był

zależny od żadnej konkretnej architektury, a tym samym był przenośny. Projekt

ten początkowo został nazwany Green [1].

Projektanci oparli swój język na C++ czerpiąc z niego to, co najlepsze

wprowadzając jednocześnie dużo prostszą składnie. Gotowy język ochrzczono

nazwą Oak (ang. dąb). Ta nazwa nie zakorzeniła się na długo gdyż, jak się

okazało była już zajęta przez inny język programowania, więc została zmieniona

na Java. Swój debiut na scenie internetowej Java miała pod koniec 1995 roku od

razu podbijając serca użytkowników. Za zadanie postawiono jej aby stała się

uniwersalnym łącznikiem miedzy użytkownikami a informacjami, bez zależności,

czy informacja pochodzi z serwerów stron internetowych, baz danych czy innego

miejsca. Jak się okazało Java doskonale spełnia pokładane w niej nadzieje, co

sprawiło że uzyskała akceptacje wszystkich największych firm oprócz

Microsoftu [2]. Java posiada wbudowany system ochrony i bezpieczeństwa, który

zapewnia komfort użytkownikom i programistom, jak i również wbudowane

biblioteki uproszczające łączność między bazami danych, programowanie

sieciowe. Jedną z najważniejszy zmian jaka została wprowadzona w porównaniu

do poprzedników, jest to, że kod źródłowy programu jest kompilowany do kodu

pośredniego. Sprawia to, że skompilowany kod nie jest programem, który można

od razu uruchomić lecz powstaje tzw. Beta-kod interpretowany przez

zainstalowaną na dowolnej stacji roboczej maszynie wirtualnej. Takie rozwiązanie

sprawia, że powstały kod jest niezależny od konfiguracji sprzętowych

i systemowych [2].

Page 4: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

4

Rysunek 1. Wieloplatformowość Javy

1.1 Cel pracy

Nie od dziś wiadomo, że Java jest jednym z najpopularniejszych języków

programowania. Popularność Javy sprawiła, że jest dla niej dostępny obok

oficjalnego kompilatora producenta Javy, firmy Sun, szereg innych rozwiązań.

Spośród dostępnych kompilatorów dla języka Java, dwa z nich produkowane są

przez jedne z największych firm udostępniających oprogramowanie: Sun

Microsystems i IBM. Są to Javac i Jikes, które konkurują z tworzonym przez

projekt GNU kompilatorem GCJ. Wszystkie wyżej wymienione programy są do

pobrania bezpłatnie ze stron ich producentów. Celem pracy będzie przedstawienie

i porównanie tych kompilatorów na podstawie pomiaru czasu wykonywania się

Page 5: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

5

kodu maszynowego powstałego podczas kompilacji. Kod uruchamiany będzie na

najpopularniejszej obecnie wśród maszyn wirtualnych, wirtualnej maszynie Javy.

Dla porównania wyników, testy zostaną przeprowadzone pod dwoma systemami

operacyjnymi zainstalowanymi na programie wirtualizującym stacje roboczą –

VirtualBox firmy Sun Microsystems. Wyżej wymienionymi systemami będą

Microsoft Windows XP z Service Pack’iem 2 oraz Ubuntu 10.4. Programy, którymi

zostaną przetestowane kompilatory, będą korzystać z najpopularniejszych funkcji

wykorzystywanych przez programistów. W celu wyeliminowania ewentualnych

błędów pomiarowych całość testów zostanie powtórzona dziesięciokrotnie,

a wszystkie wyniki uśrednione.

1.2 Wersje Javy

Do tej pory firma Sun Microsystems wydała już kilka wersji Javy, którymi są :

1.0x – pierwsza uboga i niedopracowana wersja Javy

1.1x – wprowadzenie: nowego modelu zdarzeń, Swing, JavaBeans

1.2x – zmiana nazwy interfejsu programistycznego z JDK (Java Development Kit)

na Java 2 SDK (Software Development Kit), integracja obecnych rozwiązań

platforma Java 2 – posiadająca trzy niezależne edycje:

standardowa J2SE (Java 2 Standard Edition)

biznesowa J2EE (Java 2 Enterprise Edition)

mikro J2ME (Java 2 Micro Edition)

Java 6 – obecna wersja platformy Javy dostępna w trzech wersjach:

Obecnie dostępne wersje to:

JSE 6.0 (Java Standard Edition) - środowisko podstawowe do

standardowych zastosowań komputerów osobistych i serverów

Page 6: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

6

JEE 6.0 (Java 2 Enterprise Edition) – środowisko do tworzenia

zaawansowanych i rozbudowanych aplikacji biznesowych, stworzone na

bazie JSE

JME 3.0 (Java 2 Mobility Edition) – środowisko do tworzenie aplikacji do

urządzeń przenośnych o ograniczonych zasobach np. telefony komórkowe,

palmtopy[3][4]

1.3 Tworzenie programu w Javie

Do stworzenia najprostszego programu w Javie nie jest potrzebny żaden

specjalnie dedykowany program. Wystarczy dowolny edytor tekstu np. notatnik.

Dla wszystkich programów postępujemy według schematu:

Stworzenie pliku źródłowego zawierającego klasę o takiej samej nazwie jak

nazwa pliku

Zapisanie kodu w pliku z rozszerzeniu *.java

Kompilacja pliku z kodem źródłowym o rozszerzeniu *.java do pliku o

rozszerzeniu *.class

Uruchomienie w środowisku interpretatora Beta-kodu

Pisanie programów w notatniku nie jest jednak komfortowe, gdyż istnieje duże

prawdopodobieństwo popełnienia błędu, co uniemożliwi kompilacje i późniejsze

uruchomienie programu. Dlatego najlepiej korzystać z jakiegoś środow iska

programistycznego, które sprawdzi czy nie popełniliśmy blędów np. „literówek”,

oraz w znaczący sposób ułatwi programowanie. Najpopularniejszymi

środowiskami wśród programistów są Eclipse i NetBeans. Oba programy są

darmowe i można je ściągnąć ze stron ich producentów:

http://www.eclipse.org/

http://netbeans.org/

Page 7: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

7

2. Wirtualna maszyny Javy

Wirtualna maszyna jest to system uruchomieniowy dla programów, którego

charakterystyczną cechą jest niezależność od platformy, na której jest

zainstalowany. Obecnie najpopularniejszą maszyną wirtualna jest JVM firmy Sun

Microsystems. Istnieje także kilka innych wirtualnych maszyn, produkowanych

przez tak znane i uznane firmy jak IBM czy Oracle. Maszyny wirtualne wyżej

wymienionych firm nie znalazły jednak zbyt dużej popularności wśród zwykłych

użytkowników.

Firma SUN Microsystems dostarcza bezpłatnie oprogramowanie Java

w dwóch wersjach Java SE Development Kit 6u18 oraz Java SE Runtime

Environment 6u18. Środowisko RE zawierający podstawowy pakiet programów

pozwalających na ich uruchomienie. Wirtualna maszyna Javy posiada wsparcie

dla wszystkich wersji Windows’a oraz dla różnych dystrybucji Linuxa i Solarisa.

Java Software Development Kit jest zestawem narzędzi przeznaczonym dla

programistów w jego skład wchodzą:

narzędzia do budowania, kompilacji i uruchamiania programu,

narzędzia do dokumentowania i archiwizacji programów,

pakiety klas standardowych

przykładowe aplety i aplikacje.

Zainstalowany pakiet SDK zawiera min. katalogi:

bin zawierający programy usługowe:

javac – kompilator,

java - interpreter,

appletviewer – przeglądarka apletów,

javadoc - generator dokumentacji,

jdb – debuger,

jar – narzędzie do tworzenia archiwów,

Page 8: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

8

jre zawierający środowisko uruchomieniowe, maszynę wirtualną - Javy,

bibliotekę klas,

lib zawierający dodatkowe biblioteki klas,

demo zawierający aplety i aplikacje demonstracyjne,

src.zip kody źródłowe klas standardowych,

docs zawierający znormalizowana dokumentacja pakietu w postaci stron

HTML. [2]

Page 9: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

9

3. Kompilatory

Kompilator najprościej możemy opisać jako program, który czyta kod

napisany w jednym języku (języku źródłowym) i tłumaczy go na program

równoważny (język wynikowy). Bardzo ważnym elementem procesu translacji jest

zgłaszanie i wyświetlanie użytkownikowi komunikatów o ewentualnych błędach

w programie źródłowym.

Rysunek 2. Ogólny schemat kompilatora

Analizując ilość dostępnych kompilatorów początkowo możemy zostać

przytłoczeni. Obecnie istnieją tysiące języków źródłowych, licząc od tradycyjnych

języków programowania Java, Pascal, rodzina języków C, aż po

wyspecjalizowane języki, stosowane do bardzo różnych zastosowań komputera.

W takim samym stopniu zróżnicowane są języki wynikowe, którymi mogą być: inny

język programowania albo kod maszynowy dowolnego urządzenia

elektronicznego (od procesor mikrofalówki po procesor komputera). Zazwyczaj

kompilatory są sklasyfikowane w oparciu o cel ich przeznaczenia jak

i w zależności od ich konstrukcji. Kompilatory dzielą się na:

jednoprzebiegowe

wieloprzebiegowe

uruchomieniowe (ang. debugging)

typu załaduj i uruchom (ang. load-and-go)

Page 10: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

10

Pomimo zróżnicowanych zadań kompilatorów, podstawowe ich funkcje

pozostają takie same.

Kompilatory działają w fazach, które następując kolejno po sobie

przekształcają program z jednej postaci na inną. Poniżej znajduje się schemat

pozwalający zobrazować to zagadnienie

Rysunek 3. Schemat blokowy kompilatora

Page 11: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

11

Pierwsze trzy części składają się na część analizującą kompilatora. W jej

skład wchodzi :

analizator leksykalny

analizator składnikowy

analizator semantyczny

Pozostałe części kompilatora to:

generator kodu pośredniego

optymalizator kodu

generator kodu

Zarządzanie tablicą symboli i obłoga błędów współdziałają ze wszystkimi

elementami i zazwyczaj również nazywane fazami.

W celu ułatwienia rozrumienia zasady działania kompilatorów Javy, trzeba

przynajmniej znać sposób działania niektórych z wyżej wymienionych elementów

składowych uogólnionego kompilatora.

Jak już wiemy praca kompilatora przebiega w fazach, a sam kompilator

zbudowany jest z kilku części. Pierwsze fazy kompilatora wchodzą w skład analizy

źródłowej programu. W wcześniej przedstawionym modelu kompilatora program

źródłowy w pierwszej kolejności trafia do analizatora leksykalnego. Jego głównym

zadaniem jest czytanie znaków z wejścia oraz produkcja symboli leksykalnych do

analizy składniowej.

Page 12: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

12

Rysunek 4. Wymiana danych miedzy analizatorem leksykalnym i składniowym

Powyższy schemat obrazuje oddziaływanie między analizatorem

leksykalnym a analizatorem składniowym. Współpraca między nimi polega na tym,

że po otrzymaniu polecenia „daj następny symbol” od analizatora składniowego,

analizator leksykalny czyta wszystkie znaki z wejścia, aż zidentyfikuje kolejny

symbol leksykalny. Analizator leksykalny będąc częścią kompilatora czytającą

tekst źródłowy również może wykonywać pewne zadania związane z interfejsem

użytkownika. Jednym z nich może być omijanie z pliku wejściowego komentarzy

i białych znaków czyli spacji, tabulacji i nowych wierszy. Kolejnym zadaniem jest

dopasowywanie wyświetlanych komunikatów do określonego miejsca w kodzie

źródłowym programu. Polega to na śledzeniu przez analizator leksykalny

wczytanych wierszy z wejścia aby kompilator podczas wystąpienia ewentualnego

błędu mógł razem z komunikatem o danym błędzie wyświetlić numer wiersza,

w którym on występuje. Zdarza się, że analizatory leksykalne podzielone są na

dwie fazy, pierwszą z nich jest skanowanie, a drugą analiza leksykalna. Skaner

odpowiedzialny jest za wykonywanie prostych zadań, a analizator leksykalny

zajmuje się tymi bardziej skompilowanymi.

Kolejną istotnym elementem kompilatora, jest analizator składniowy, który

otrzymuje ciąg znaków leksykalnych od analizatora leksykalnego, a następnie

Page 13: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

13

sprawdza czy dany ciąg może zostać wygenerowany przez gramatykę dla języka

źródłowego. Analizator składniowy ma również jeszcze jedno bardzo istotne

zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

bezpośrednio związane z tym, że nie realne jest aby kompilator przetwarzał tylko

poprawne programy, gdyż programiści to też ludzie i zdarzają się im błędy. Gdyby

jednak dało się ich całkowicie unikać, wtedy projekt i stworzenie kompilatora

bardzo by się uprościły. Niestety tak nie jest i często zdarza się, że programiści

piszą niepoprawne programy, więc dobry kompilator powinien pomóc

programiście w zlokalizowaniu błędu i jego usunięciu. To spowodowało, że

obsługa błędów w analizatorze składniowym ma postawione proste cele:

zgłaszać obecność błędu, w jasny sposób

w razie wykrycia błędu, szybo wracać do analizy składniowej w celu

wykrycia kolejnych błędów

nie spowalniać w sposób znaczący przetwarzania poprawnych programów.

Jedną z ważniejszych funkcji kompilatora jest zapamiętywanie

identyfikatorów, które są używane w programie źródłowym oraz zbieranie

informacji o ich różnych atrybutach. Atrybuty mogą dostarczać informacji na temat

ilości zajętej pamięci przez identyfikator, o jego typie, zasięgu (jego dostępność

i widoczność w programie). Także w przypadku nazw atrybuty podają liczbę i typy

argumentów, metody przekazywania każdego argumentu oraz typ wyniku o ile ta

metoda zwraca wynik. Tablica symboli jest zbudowana ze zbioru rekordów

z atrybutami dla wszystkich identyfikatorów. Struktura to za zadanie ma

umożliwiać szybkie znalezienie rekordu dla każdego identyfikatora oraz szybkie

zapisywanie i odczytywanie danych z rekordu. Identyfikator napotkany przez

analizę leksykalną dodawany jest do tablicy symboli. Reszta faz wstawia do

tablicy informacje o identyfikatorach, aby w kolejnych etapach kompilacji

wykorzystać je do różnych celów takich jak; sprawdzenie podczas analizy

semantycznej i generacji kodu czy identyfikatory używane są poprawnie oraz

wygenerowania poprawnych operacji na nich działających. Dokładne informacje

na temat przydzielonej pamięci identyfikatorom są niezbędne do działania

generatora kodu [5].

Page 14: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

14

Ostatnim etapem pracy kompilatora Javy jest generowanie kodu

pośredniego (inne kompilatory np. języka C posiadają jeszcze dodatkowo

generatory kodu wynikowego). Efektem jego pracy jest stworzenie tzw. Beta –

kodu, które zostanie opisane w dalszej części pracy

3.1 Kompilacja w Javie

Znając ogólne zasady działania kompilatorów możemy przyjrzeć się jak

wygląda kompilacja programu napisanego w konkretnym języku, którym w naszym

przypadku jest Java. Jak wiemy proces kompilacji jest niezbędny do uruchomienia

programu napisanego w Javie. Polega on na zamianie kodu źródłowego programu

na kod bajtowy, a następnie bezpośrednio przed jego wykonaniem na kod

maszynowy, co dobrze obrazuje poniższy schemat

Rysunek 5. Ogólny schemat kompilacji programu napisanego w Javie

Page 15: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

15

Podczas kompilacji plików z kodem Javy (pliki *.java) tworzone są instrukcje

kodu bajtowego (pliki *.class) które zostają wykonane przez interpreter kodu

bajtowego. Jednak dobrze by było przyjrzeć się bliżej temu procesowi gdyż, co

prawda cała kompilacja od strony praktycznej sprowadza się do wpisania

polecenia w linii komend i jest przeprowadzana automatycznie przez kompilator,

jednak obserwacja efektów jego działania należy już do użytkownika. Programista

tworzący programy w Javie powinien wiedzieć jaka metodą powstaje kod

maszynowy dla danej platformy, czyli innymi słowy jaka jest droga pomiędzy

kodem źródłowym a kodem wykonywalnym. Musimy sobie jednak uświadomić, że

użytkownik nie zawsze ma dostęp do kodu wykonywalnego na daną platformę,

ponieważ taki kod może być generowany dopiero w trakcie uruchamiania

programu. Aby wyjaśnić cały mechanizm generowania kodu maszynowego

programu stworzonego w Javie dla danej platformy trzeba przedstawić kilka

podstawowych zagadnień z nim związanych.

Kod maszynowy jest ciągiem liczb interpretowanych przez komputer,

a konkretnie jego procesor w celu wywołania pożądanego efektu. Używanie serii

liczb w celu wykonania określonego zadania nie jest jednak zbyt efektywne, a dla

samego użytkownika niekomfortowe. Dlatego też stworzony został prosty język,

który posiada proste instrukcje wywoływane z odpowiednimi parametrami lub

wartościami. Tak przygotowany kod tłumaczony jest przez komputer na kod

maszynowy. Opisywany wyżej język nosi nazwę assembler, a w przypadku Javy

kod źródłowy kompilowany jest do pseudo-assamblera nazwanego b-kodem.

Instrukcje napisane w B-kodzie, tłumaczone są na odpowiadające im ciągi liczb

(kod maszynowy) w trakcie uruchomienia programu (klasy). W praktyce oznacza

to, że jedna linia kodu napisanego w assamblerze zwykle generuje jedną linie

kodu maszynowego. Dla porównania assemblera i pseudo-assamblera, poniżej

przedstawiony jest fragment kodu w assemblerze, który wygląda następująco:

add eax, edx

mov ecx, eax

Page 16: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

16

Natomiast te same instrukcje, w pseudo-assamblerze wyglądają zupełnie

inaczej [6]:

0 iload_1

1 iload_2

2 iadd

3 istore_3

W celu ułatwienia życia programistom stworzone zostały języki tzw.

wysokiego rzędu jak np. C, C++, Pascal w których pojedyncza linia komend może

być zamieniona na kilka linii kodu maszynowego dla danej platformy. Cały proces

konwertowania kodu źródłowego języka wysokiego rzędu do kodu wykonywalnego

nazwano kompilacją statyczną i w przypadku technologii Java sprowadza się do

kompilacji kodu źródłowego do B-kodu. Proces kompilacji składa się z siedmiu

podstawowych procesów wymienionych w poprzednim rozdziale. tłumaczenie

kodu źródłowego

generacja kodu maszynowego/B-kodu

optymalizacja kodu maszynowego/B-kodu

Pierwszym etapem jest tłumaczenie kodu źródłowego, które polega na

wydobyciu z tekstu poszczególnych elementów języka np. „if”, „)”, „class”;

a w kolejnym etapie połączenie w wyrażenia języka. W momencie gdy zostaną

napotkane elementy niezrozumiałe dla danego języka, które nie są zgodne z jego

wzorcami, to kompilator przerywa pracę i zwraca użytkownikowi błąd, co

zazwyczaj niesie za sobą konieczność skorygowania elementów powodujących

konflikty. Jeżeli tłumaczenie całego kodu przebiegnie pomyślnie to następuje

konwersja do B-kodu, który w kolejnym kroku zostaje zoptymalizowany. Celem

procesu optymalizacji jest zmniejszenie rozmiarów kodu oraz poprawa szybkości

jego działania. Wyrażenia języka są bardzo często kompilowane i tworzą biblioteki

czyli gotowe zbiory kodów, które możemy wykorzystać podczas konstrukcji

własnego programu. Podczas kompilacji programu korzystamy więc z gotowych

wcześniej skompilowanych kodów. Zbiór bibliotek stanowi niezbędną część

zasobów danego języka programowania, jednak mogą być też wytwarzane przez

użytkowników środowiska tworzenia programów. Krótko podsumowując

Page 17: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

17

kompilacja statyczna jest procesem konwertowania kodu źródłowego na kod

pośredni.

Kod pośredni (B-kod) podczas uruchomienia aplikacji jest konwertowany na

kod maszynowy. Do tego celu służą różne techniki. Jedną z nich jest

interpretowanie, które polega na cyklicznym pobieraniu instrukcji języka,

tłumaczeniu ich na kod maszynowy, generacji i wykonywaniu. Przykładowymi

interpreterami są powłoki (ang. shell) systemów operacyjnych przykładem, których

są DOS, bash, csh. Największą wada interpretowanie jest jednak to, że nie można

wykonać optymalizacji kodu maszynowego, gdyż nie jest on dostępny.

Jeżeli chodzi o Javę interpretowanie kodu wygląda jednak trochę inaczej.

Związane jest to z jedną z głównych cech, która była jednym z powodów jej

stworzenia. Mowa oczywiście o przenośności kodu. Założenie, że kod może być

uruchamiany na każdej platformie sprzętowej spowodowało konieczność

stworzenia takich interpretatorów, które umożliwiałyby efektywną konwersję tego

samego kodu źródłowego na kod wykonywujący się tak samo na rożnych

platformach sprzętowych. Proces interpretacji zajmuje stosunkowo bardzo dużo

czasu, dlatego konieczne były pewne modyfikacje przyśpieszające go, aby

uruchamiany program był odpowiednio efektywny. Zabiegi te znacznie poprawi ły

wydajność programów napisanych w Javie. Proces ten przebiega dwuetapowo.

Pierwszym etapem opisanym wyżej jest kompilacja kodu źródłowego na kod

pośredniego, który nosi również nazwę kodu maszyny wirtualnej. Kod pośredni

jest efektem translacji kodu źródłowego zgodnie z architekturą języka Java. W

wyniku translacji powstaje zestaw bajtów, który przed uruchomieniem musi być

przekonwertowany na kod maszynowy zgodny z architekturą platformy

sprzętowej, na której jest uruchamiany. W języku używanym przez programistów

zestaw bajtów jest również nazywany Beta-kodem lub B-kodem. Kod wynikowy

konkretnej platformy powstaje w wyniku interpretowania Beta-kodu przez

interpreter maszyny wirtualnej.

Potrzeba jeszcze większego przyśpieszenia procesu kompilacji

spowodowała, że zamiast interpretatora B-kodu opracowano różne kompilatory

dynamiczne. Ich działanie oparte jest na kompilacji w locie B-kodu do kodu

wykonywalnego dla danej maszyny. Otrzymany w ten sposób kod wykonywalny

Page 18: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

18

umieszczany jest w pamięci komputera, tym samym oznacza to, że nie jest

zapisywany w postaci pliku na dysku. Z tego wynika, że kod po skończeniu

działania programu jest po prostu niedostępny. [2] Ta metoda kompilacji została

nazwana kompilacją JIT – Just-In-Time (kompilacja w locie). Poprawa wydajności

w stosunku do interpreterów kodu polega na buforowaniu bloków kodu, a nie

interpretowaniu każdej linii po kolei za każdym razem gdy program jest otwierany.

Kod źródłowy skompilowany do Beta-kodu nie jest przypisany do konkretnego

komputera co sprawia, że może on być przenoszony miedzy rożnymi

architekturami. Taki kod może być interpretowany lub uruchamiany na maszynie

wirtualnej. Mimo, iż kompilacja JIT ma za zadanie przyśpieszenie wykonywania

programów zwykle powoduje nieznacznie opóźnienie w początkowym etapie

realizacji kodu. Wpływa na to czas potrzebny do załadowania i skompilowania

Beta-kodu. Kod wykonuje się tym lepiej im więcej razy zostanie wykonany.[7]

Receptą na potrzebę rozgrzewania się wyeliminowano przez stworzenie

kompilatora AOT (ang. Ahead-of-time), który przed uruchomieniem kodu jeszcze

raz go przekompilowuje wprowadzając przy tym zmiany, które poprawiają

wydajność kodu.

W Javie oprócz błędów występują również wyjątki. Wyjątki są to określone

sytuacje konfliktowe spowodowane przez niewłaściwe funkcjonowanie klas

i metod. Przykładem wyjątków mogą być: dzielenie przez zero, brak pliku

o podanej ścieżce, brak hosta o podanym adresie, czy też brak klasy. Wystąpienie

wyjątku nie powoduje zazwyczaj przerwania pracy programu. Każdy wyjątek

związany jest bezpośrednio z określoną klasą i jej metodami. Przykładowe wyjątki

i ich klasy to:

w pakiecie java.lang.*:

ClassNotFoundExeption – brak klasy,

ArrayIndexOutOFBoundsExeption – przekroczenie zakresu tablicy,

ArithmeticExeption – wyjątek operacji arytmetycznych np. dzielenie

przez zero,

w pakiecie java.io.*;

Page 19: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

19

EOFExeption –koniec pliku,

FileNotFoundExeption – brak pliku,

InterruptedIOExeption – przerwanie operacji we/wy.

Przykładowe błedy:

OutOfMemoryError – bład braku pamięci,

NonSuchMethodError – bład braku danej metody w klasie,

NonSuchFieldError – bład braku danego pola w klasie [2].

3.2 Javac

Javac jest podstawowym narzędziem wchodzącym w skład JVM (Java

Virtual Machine) służącym do kompilacji programów. Jego najnowsza wersja ma

oznaczenie 1.6.0_17.

Pierwszym krokiem do rozpoczęcia kompilacji programów jest instalacja

pakietu Java SE Development Kit 6u18 – dostępny do pobrania

z http://java.sun.com/javase/downloads/widget/jdk6.jsp. Aby rozpocząć prace

z kompilatorem Javac należy rozpocząć od dodania zmiennej środowiskowej

PATH do katalogu bin zawierającego kompilator Javac i interpreter Java.

Page 20: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

20

Rysunek 6. Dodawanie zmiennej środowiskowej

Po tej czynności można bez problemu korzystać z kompilatora. Jego

uruchomienie odbywa się z linii komend. Wprowadzona zmienna środowiskowa

pozwala nam na nie podawanie całej ścieżki dostępu do kompilatora.

Wystarczające jest przejście do katalogu z plikiem programu i wprowadzenie

jedynie polecenia javac nazwa_pliku.java. Jeżeli program został prawidłowo

skompilowany konsola powinna nie wyświetlić żadnego błędu a jedynie nową linie

komend. Gotowy program uruchamiamy poleceniem java nazwa_pliku. Ważne

aby nie dodawać rozszeżenia class, ponieważ wtedy program nie uruchomi się.

Page 21: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

21

Rysunek 7. Poprawnie skompilowany program

Javac zawiera duża ilość opcji i ustawień kompilacji są to min.:

-g generuje wszystkie informacje debugowania

-g:none generuje informacje bez błędów

-g:{lines,vars,source} generuje tylko niektóre informacje

-nowarn nie wyświetla ostrzeżeń

-verbose wyświetla informacje na temat pracy kompilatora

-classpath <path> określa ścieżkę dodatkowych klas użytkownika

-cp <path> j.w.

-sourcepath <path> lokalizacja źródła plików wejściowych

-extdirs <dirs> zmienia lokalizację zainstalowanych rozszerzeń

-d <directory> określ, gdzie umieścić wygenerowane pliki class

-s <directory> określ, gdzie umieścić wygenerowane pliki

źródłowe

-target <release> generowanie plików class dla konkretnych wersji

VM

-version informacje o wersji

-help wyświetla standardowe opcje

-X wyświetla niestandardowe opcje [8]

Page 22: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

22

3.3 Jikes

Jikes jest produktem IBM’a jednak projekt ten nie jest od kilku lat rozwijany.

Jego ewaluacja stanęła na wersji 1.22. Jikes jest tylko kompilatorem, nie wchodzi

w skład żadnej maszyny wirtualnej przez to jego rozmiary są niewielkie. Program

można z łatwością pobrać z http://sourceforge.net/projects/jikes/files/ wybierając

wersje odpowiadającą naszemu systemowi operacyjnemu. Kompilator jest

dostępny w wersjach dla takich platform jak: MS Windows, platformy Linux’ owe

oraz MAC OS.

Aby rozpocząć prace z kompilatorem Jikes nie potrzebna jest nam jego

instalacja, jednak kompilacja kodu źródłowego wymaga zainstalowanej JVM. Jest

to konieczne aby wskazać kompilatorowi położenie podstawowych klas. Dlatego

kompilator do uruchomienia procesu kompilacji potrzebuje wskazania lokalizacji

pliku rt.jar znajdującego się katalogu lib pakietu JRE. Gotowe polecenie wpisane

w konsole wygląda następująco: jikes –bootclasspath sciazka_do_rt.jar

plik_kompilowany.java. Podobnie jak w przypadku kompilatora Javac jeżeli plik

zostal poprawnie skompilowany konsola nie wyświetla żadnych komunikatów

i zapisuje plik z rozszerzeniem *.class, który bez problemu można uruchomić

poleceniem java plik_kompilowany [9].

3.4 GCJ

Ostatni z przedstawionych kompilatorów jest najczęściej stosowany przez

użytkowników platform UNIX’owych. GCJ czyli kompilator projektu GNU dla

języka Java jest (GNU Compiler for Java) jest częścią GCC (GNU Compiler

Collection) w skład którego wchodzi kompilator jak, środowisko uruchomieniowe

podstawowe biblioteki i narzędzia dla języka Java. Jedną z głównych cech tego

kompilatora jest to, że ułatwia integrację z innymi językami obsługiwanymi przez

pakiet GCC.

Page 23: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

23

Instalacja GCJ polega na wpisaniu w konsolę systemową Ubuntu polecenia

sudo apt-get install gcj. Gdy oprogramowanie zostanie pobrane i zainstalowane

w naszym systemie, możemy rozpocząć kompilacje programów. Skompilowanie

programu polega na przejściu do katalogu zawierającego przygotowany wcześniej

program i wpisaniu polecenia gcj –C nazwa_pliku.java. Podobnie jak

w poprzednich przypadkach, jeżeli program został prawidłowo skompilowany to

konsola nie wyświetla żadnych błędów. Trzeba jednak pamiętać że GCJ jest

bardziej wrażliwy na błędy występujące w kodzie. Przykładem może być sytuacja

w której wykonywane są pewne obliczenia ale nie jest zwracana żadna wartość.

Wtedy co prawda kompilator skompiluje program jednak, wyświetlany błąd

zasygnalizuje nam, o zaistniałym problemie [10].

Page 24: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

24

4. Część praktyczna

Zgodnie z zdefiniowanym celem pracy, część praktyczna będzie polegać

na porównaniu szybkości wykonywania skompilowanego wyżej opisanymi

kompilatorami kodu. Proces ten zostanie zrealizowany przez trzy kompilatory:

Javac, Jikes i GCJ. Wszystkie skompilowane pliki zostaną uruchomione na

maszynie wirtualnej Javy (JVM).

W skład zestawu testującego wchodzi laptop HP Pavilon dv5 o parametrach:

Procesor: Intel Core 2 Duo P7350 2GHz

Pamięć: 3GB

Karta graficzna NVIDIA GeForce 9600M GT (512 MB)

Dysk twardy: 300GB

System operacyjny: Windows Vista Ultimate

Wszystkie testy zostały przeprowadzone na wirtualnie zainstalowanych

systemach, którymi były:

Windows XP z SP@

Ubuntu 10.4

Do uruchomienia wirtualnych systemów został użyty darmowy program

VirtualBox w wersji 3.1.2 [11]. Dla lepszego porównania wyników systemy

zainstalowane są na maszynach wirtualnych o takich samych ustawieniach, które

przedstawiają się następująco:

Pamięć podstawowa: 1GB

Partycja systemowa: 8GB

Pamięć video: 16MB

Do testów zostało użytych 8 programów. Programy w istocie są bardzo

proste i sprawdzają wydajność podstawowych klas. Każdy z kodów jest

zbudowany według tego samego schematu, czyli pętli wykonywanej określoną

ilość razy oraz metody, która mierzy czas wykonywania programu. Każdy program

Page 25: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

25

został uruchomiony 10 razy, a wszystkie wyniki uśrednione. Poszczególne

programy mierzyły:

Program 1 – wydajność typowych operacji liczbowych takich jak

dodawanie, odejmowanie, mnożenie i dzielenie, kod programu poniżej:

[12][13]

public static double RunTest(int Wielkoscpetli) {

long x = 10;

double y = 0;

double z = 0;

for (int i = 0; i < Wielkoscpetli; i++) {

x = x + 3;

y = (double) x / 7;

z = y * 5;

x -= 3;

}

return z;

}

Program 2 – wydajność operacji na stringach używając metody do

porównania ciągu znaków, kod programu poniżej: [12][13]

public static boolean RunTest(int Wielkoscpetli) {

String val0_2 = "hm";

String val1_2 = "hm";

String val2_2 = "Hm";

String val3_2 = "kg";

String val4_2 = "hm1";

String val0_4 = "Hara";

String val1_4 = "Hara";

String val2_4 = "HaRa";

String val3_4 = "xFdW";

String val4_4 = "Harai";

String val0_8 = "Haralamb";

String val1_8 = "Haralamb";

String val2_8 = "haRaLAmb";

String val3_8 = "AmbzJ3pQ";

String val4_8 = "Haralambxq";

String val0_16 = "Haralambos Marma";

String val1_16 = "Haralambos Marma";

String val2_16 = "hAraLamBos maRmA";

Page 26: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

26

String val3_16 = "gtswq*skdn-2iosc";

String val4_16 = "Haralambos Marmanis";

boolean test = false;

for (int i = 0; i < Wielkoscpetli; i++) {

if (val0_2.equals(val1_2)

| val0_2.equals(val2_2)

| val0_2.equals(val3_2)

| val0_2.equals(val4_2)) {

test = !test;

}

if (val0_4.equals(val1_4)

| val0_4.equals(val2_4)

| val0_4.equals(val3_4)

| val0_4.equals(val4_4)) {

test = !test;

}

if (val0_8.equals(val1_8)

| val0_8.equals(val2_8)

| val0_8.equals(val3_8)

| val0_8.equals(val4_8)) {

test = !test;

}

if (val0_16.equals(val1_16)

| val0_16.equals(val2_16)

| val0_16.equals(val3_16)

| val0_16.equals(val4_16)) {

test = !test;

}

}

return test;

}

Program 3 - konfiguracja programu jest taka sama jak programu 2, ale

program używa metody equalsIgnoreCase, która przy porównaniu ignoruje

wielkość znaków. Poniżej fragment kodu, którym rożni się od poprzedniego

programu: [12][13]

if (val0_2.equalsIgnoreCase(val1_2)

| val0_2.equalsIgnoreCase(val2_2)

| val0_2.equalsIgnoreCase(val3_2)

| val0_2.equalsIgnoreCase(val4_2))

Page 27: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

27

Program 4 - konfiguracja programu jest taka sama jak programu 2, ale

program używa metody compareTo. Poniżej fragment kodu, którym rożni

się od poprzedniego programu: [12][13]

if (val0_2.compareTo(val1_2) == 0 | val0_2.compareTo(val2_2) == 0

| val0_2.compareTo(val3_2) == 0

| val0_2.compareTo(val4_2) == 0)

Program 5 – wydajność niektórych, najczęściej używanych funkcji

matematycznych klasy Java.lang.Math (podnoszenie do potęgi,

pierwiastkowanie, cosinus kąta, tworzenie zbioru liczb losowych), kod

programu poniżej: [12][13]

public static double RunTest(int Wielkoscpetli) {

double pi = java.lang.Math.PI;

double e = java.lang.Math.E;

double x = 0;

double y = 0;

long n1 = 0;

long n2 = 0;

double sign = 0;

double random = 0;

long randomL = 0;

for (int i = 0; i < Wielkoscpetli; i++) {

random = Math.random();

sign = Math.cos(100 * random);

random = (sign * random) * pi * e;

randomL = Math.round((double) random);

x = Math.abs(random);

n1 = Math.abs(randomL);

y = Math.exp(x);

y = Math.log(x);

n2 = Math.max(n1, n2);

y = Math.max(x, y);

x = Math.sqrt(y);

y = Math.pow(y, x);

}

return y;

}

Page 28: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

28

Program 6 – wydajność optymalizacji if, kod programu poniżej: [12][14][15]

public static boolean RunTest(int size) {

boolean a = true, b = false, c = true, d = false;

int i, j;

for (i = 0; i <= size; i++) {

if (a | b) {

a = !c;

b = !d;

if (a | b) {

a = !c;

b = !d;

} else {

a = c;

b = d;

}

} else {

a = c;

b = d;

if (a | b) {

a = !c;

b = !d;

} else {

a = c;

b = d;

}

}

}

return b;

}

Program 7 – wydajność optymalizacji „martwego kodu”, kod programu

poniżej: [12][14][15]

public static boolean RunTest(int size) {

boolean a = true, b = false;

int i, j;

double x = 0.12, y = 0.13, z = 0.14;

for (i = 0; i <= size; i++) {

x += 0.0001;

z += 0.00012;

y += Math.log(Math.atan(Math.sqrt(x / z)));

}

b = Math.random() > 0.5;

for (i = 0; i <= size; i++) {

if (b) {

a = b;

} else {

a = !b;

}

}

return a;

}

Page 29: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

29

Program 8 – wydajność upraszczania wyrażeń, kod programu poniżej:

[12][14][15]

public static int RunTest(int size) {

int[] a = new int[4];

int i, j;

for (i = 0; i <= size; i++) {

a[0] += i + 0 + i + 0;

a[1] += i * 0;

a[2] += i - i + 2 - 5 + 3;

a[3] += 1 + i + 1;

}

return a.hashCode();

}

Page 30: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

30

Konsola po uruchomieniu programu wyświetla czas wykonywania się programu

Rysunek 8. Konsola, wyświetlenie czasów poszczególnych przebiegów

Jest to realizowane za pomocą wpisania w main kodu znajdującego się poniżej:

long startOfTest

long endOfTest;

int test;

startOfTest = System.currentTimeMillis();

test = Test1.RunTest(Wielkoscpetli);

endOfTest = System.currentTimeMillis();

// Raport

output.append("Test[1] (ms): " + (endOfTest - startOfTest));

output.append(" Wolna Pamiec : " + Runtime.getRuntime().freeMemory());

output.append(" Wynik obliczen˝: " + test + "\n");

//Nowy test

startOfTest = System.currentTimeMillis();

test = Test1.RunTest(Wielkoscpetli);

endOfTest = System.currentTimeMillis()

Program przy każdym uruchomieniu wykonywał 3 przebiegi, w celu

zaobserwowania ewentualnej poprawy jego działania (optymalizacji)

Page 31: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

31

4.1 Wyniki testów

Tabela 1. Wyniki testów dla kompilatora Javac (czas w tabeli podany w ms)

Przebieg 1 Przebieg 2 Przebieg 3

WinXP Ubuntu WinXP Ubuntu WinXP Ubuntu

Program 1 3479 3728 3422 3644 3449 3586

Program 2 2546 2790 2551 2705 2413 2574

Program 3 12852 13874 12848 13706 12850 13420

Program 4 5768 6214 5744 6060 5670 5957

Program 5 1101 1248 1075 1142 1157 1124

Program 6 8641 9561 8681 9357 2008 2138

Program 7 3157 2378 3176 2271 2122 2239

Program 8 8842 10724 8903 9398 5311 5561

Tabela 2. Wyniki testów dla kompilatora Jikes (czas w tabeli podany w ms)

Przebieg 1 Przebieg 2 Przebieg 3

WinXP Ubuntu WinXP Ubuntu WinXP Ubuntu

Program 1 3478 3750 3475 3685 3413 3584

Program 2 2588 2851 2591 2740 2457 2593

Program 3 12624 13527 12604 13340 12602 13368

Program 4 5712 6175 5712 6019 5624 5919

Program 5 1108 1277 1082 1142 1159 1122

Program 6 5982 6484 5991 6344 2001 2171

Program 7 2172 2474 2166 2372 2113 2247

Program 8 8908 11227 10123 9821 5279 6467

Tabela 3. Wyniki testów dla kompilatora GCJ (czas w tabeli podany w ms)

Przebieg 1 Przebieg 2 Przebieg 3

WinXP Ubuntu WinXP Ubuntu WinXP Ubuntu

Program 1 3486 3827 3485 3795 3416 3679

Program 2 2250 2501 2230 2400 2108 2235

Program 3 12605 13638 12628 13370 12598 13553

Program 4 5712 6201 5712 6060 5624 5941

Program 5 1111 1277 1089 1156 1156 1131

Program 6 8663 9238 8678 9131 2023 2139

Program 7 2180 2495 2190 2399 2128 2243

Program 8 8917 10916 8935 9393 5873 5604

Page 32: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

32

4.2 Wykresy

Wykres 1. Porównanie wydajności kompilatora Javac w systemach Windows XP i Ubuntu (na osi pionowej czas w ms)

Wykres 2. Porównanie wydajności kompilatora Jikes w systemach Windows XP i Ubuntu (na osi pionowej czas w ms)

0

10000

20000

30000

40000

50000

60000

Przebieg 1 Przebieg 1 Przebieg 2 Przebieg 2 Przebieg 3 Przebieg 3

WinXP Ubuntu WinXP Ubuntu WinXP Ubuntu

Program 8

Program 7

Program 6

Program 5

Program 4

Program 3

Program 2

Program 1

0

10000

20000

30000

40000

50000

60000

Przebieg 1 Przebieg 1 Przebieg 2 Przebieg 2 Przebieg 3 Przebieg 3

WinXP Ubuntu WinXP Ubuntu WinXP Ubuntu

Program 8

Program 7

Program 6

Program 5

Program 4

Program 3

Program 2

Program 1

Page 33: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

33

Wykres 3. Porównanie wydajności kompilatora GCJ w systemach Windows XP i Ubuntu (na osi pionowej czas w ms)

Wykres 4. Porównanie wydajności kompilatorów dla przebiegu 1 w systemach Windows XP i Ubuntu (na osi pionowej czas w ms)

0

10000

20000

30000

40000

50000

60000

Przebieg 1 Przebieg 1 Przebieg 2 Przebieg 2 Przebieg 3 Przebieg 3

WinXP Ubuntu WinXP Ubuntu WinXP Ubuntu

Program 8

Program 7

Program 6

Program 5

Program 4

Program 3

Program 2

Program 1

0

10000

20000

30000

40000

50000

60000

WinXP Ubuntu WinXP Ubuntu WinXP Ubuntu

Javac Javac Jikes Jikes GCJ GCJ

Program 8

Program 7

Program 6

Program 5

Program 4

Program 3

Program 2

Program 1

Page 34: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

34

Wykres 5. Porównanie wydajności kompilatorów dla przebiegu 2 w systemach Windows XP i Ubuntu (na osi pionowej czas w ms)

Wykres 6. Porównanie wydajności kompilatorów dla przebiegu 3 w systemach Windows XP i Ubuntu (na osi pionowej czas w ms)

0

10000

20000

30000

40000

50000

60000

WinXP Ubuntu WinXP Ubuntu WinXP Ubuntu

Javac Javac Jikes Jikes GCJ GCJ

Program 8

Program 7

Program 6

Program 5

Program 4

Program 3

Program 2

Program 1

0

5000

10000

15000

20000

25000

30000

35000

40000

WinXP Ubuntu WinXP Ubuntu WinXP Ubuntu

Javac Javac Jikes Jikes GCJ GCJ

program 8

program 7

program 6

program 5

program 4

program 3

program 2

program 1

Page 35: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

35

4.3 Wnioski

Testy jednoznacznie pokazały, że każdy kod potrzebuje kilku przebiegów

do pełnego zoptymalizowania. W przypadku każdego testowanego kompilatora ta

reguła się sprawdza. Można to zaobserwować na wykresie 1, 2 i 3. Z wykresów

wynika również, że dystrybucja wirtualnej maszyny Javy działa o wiele szybciej

w systemie Windows XP niż w systemie opartym na Linuxie – Ubuntu.

Początkowo może to być zastanawiające (Linux jest z reguły wydajniejszym

systemem), ale po zastanowieniu można dojść do wniosku, że łatwo jest taka

sytuacje uargumentować. Pierwszym czynnikiem, który miał na to wpływ jest to,

że przeprowadzane testy odbywały się na systemach operacyjnych

zainstalowanych na maszynach wirtualnych. Systemem hostującym był system

Windows, a co za tym idzie komunikacja pomiędzy systemem gościem –

Windows, a systemem macierzystym, mogła przebiegać dużo efektywniej.

W przypadku gdy systemem goszczącym w systemie Windows był system

Ubuntu, komunikacja między nimi wymagała pewnych konwersji, więc wpłynęło to

znacząco na czas wykonywania się testowanych programów. Do interesujących

wniosków można również dojść analizując wykresy 3, 4, 6 bowiem okazuje się,

że najlepszym kompilatorem pod względem wydajności w systemie Windows jest

Jikes. Jego wynikowy kod działa szybciej od jego konkurentów przy każdym

przebiegu, bez względu na to czy kod jest już w pełni zoptymalizowany czy nie.

Drugie miejsce pod tym względem przypada kompilatorowi GCJ, na szarym końcu

jest Javac. Sytuacja zmienia się, jeżeli przeanalizujemy wydajność kompilatorów

w systemie Ubuntu. W pierwszych dwóch przebiegach najlepszym kompilatorem

okazuje się być Jikes. Zaskakujące jest, że kod skompilowany przez kompilator

Jikes w trzecim przebiegu jest znacznie wolniejszy od kodu najszybszego w tym

systemie kompilatora - Javac. Kolejnym nasuwającym się wnioskiem jest to, że

kod jest w pełni zoptymalizowany, gdy zostanie uruchomiony minimum 3 razy.

Doskonale można to zaobserwować po czasach pracy programu 6, które

w przypadku wszystkich kompilatorów przy trzecim przebiegu są kilkakrotnie

krótsze niż podczas pierwszego i drugiego przebiegu. Związane jest to z tym, że

kompilatory nie wykonują niepotrzebnie kilkakrotnie tego samego kodu, jeżeli

wcześniej został on już wykonany.

Page 36: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

36

5. Podsumowanie

W pracy zostały przedstawione podstawowe założenia dynamicznie

rozwijającego się języka programowania, jakim jest niewątpliwie Java. Celem

pracy było zapoznanie się z zasadą działania i rodzajami dostępnych na rynku

oprogramowania komputerowego kompilatorów, a w części praktycznej

porównania ich pod względem wydajności, cel został zrealizowany. W porównaniu

wzięły udział 3 najbardziej popularne kompilatory: Javac, Jikes i GCJ. Okazało

się, że w systemie Windows bezkonkurencyjny okazał się Jikes, wyprodukowany

przez firmę IBM. Wygrał on pod każdym względem, jego kod wykonywał się

najszybciej podczas pierwszego, drugiego i trzeciego przebiegu. Drugie miejsce

zajął GCJ, a najgorszy okazał się kompilator Javac. Jednak w systemie Ubuntu

najlepszym kompilatorem okazał Javac. Szczególnie wyniki testów dla systemu

Windows, są bardzo ciekawe, gdyż okazuje się, nie zawsze narzędzia

wyprodukowane przez wiodące firmy na rynku są najlepsze. Istnieje wiele

programów, które nie są bliżej znane większej rzeszy użytkowników, dlatego też

przed rozwiązaniem danego problemu należy prześledzić rynek i wybrać

najbardziej odpowiadający nam program. Niestety jeżeli chodzi o kompilatory to

najlepszy obecnie dostępny kompilator Jikes nie jest już aktualizowany, co za tym

idzie nie posiada obecnie żadnego wsparcia technicznego, a szkoda bo

konkurencja z kompilatorem Javac na pewno wyszłaby na dobre obydwóm

narzędziom. Dlatego mam nadzieję, że programiści IBM’a reaktywują Jikes

i doczekamy się kolejnych jeszcze szybszych i wydajniejszych wersji.

Page 37: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

37

6. Literatura

1. Java 2 podstawy, Prentice Hall, Wydawnictwo HELION, 2003

2. Język Java podstawy programowania, Jacek Rumuński, 1999

3. Oficjalna strona Javy http://www.java.com/en/javahistory/timeline.jsp

4. Historia wersji Javy, Wikipedia

http://en.wikipedia.org/wiki/Java_version_history

5. Kompilatory. Reguły metody i narzędzia, Alfred V. Aho, Ravi Sethi, Jeffley

D Ullman, Wydawnictwo Naukowo-Techniczne, Warszawa 2002

6. Opis B-kodu Javy, Wikipedia http://en.wikipedia.org/wiki/Java_bytecode

7. Opis Kompilacji JIT, Wikipedia http://en.wikipedia.org/wiki/Just-in-

time_compilation

8. Oficjalna strona Javy tutorial,

http://java.sun.com/j2se/1.4.2/docs/tooldocs/solaris/javac.html

9. Oficjalna strona Jikes, http://jikes.sourceforge.net/index.shtml

10. Oficjalna strona GNU Project http://gcc.gnu.org/onlinedocs/gcj/Input-

Options.html#Input-Options

11. Oficjalna strona Virtual Boxa http://www.virtualbox.org/wiki/Downloads.

12. Thinking In Java Wydanie 3, Eckel Bruce, Wydawnictwo HELION, 2003

13. Artykuł J. Kowalski, Java performance of java compilers, PWN,

http://java.sys-con.com/node/37555/

14. Strona z przykładowymi programami sprawdzającymi wydajność

kompilatorów, http://www.nullstone.com/htmls/results/java.htm

15. Strona doktora Blachnika

http://kzi.polsl.pl/~mblachnik/doku.php?id=notatki:informatyka:java

Page 38: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

38

7. Spis rysunków

Rysunek 1. Wieloplatformowość Javy .................................................................. 4

Rysunek 2. Ogólny schemat kompilatora ............................................................. 9

Rysunek 3. Schemat blokowy kompilatora ......................................................... 10

Rysunek 4. Wymiana danych miedzy analizatorem leksykalnym i składniowym.. 12

Rysunek 5. Ogólny schemat kompilacji programu napisanego w Javie ............... 14

Rysunek 6. Dodawanie zmiennej środowiskowej ............................................... 20

Rysunek 7. Poprawnie skompilowany program .................................................. 21

Rysunek 8. Konsola, wyświetlenie czasów poszczególnych przebiegów ............ 30

Page 39: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

39

8. Spis tabel

Tabela 1. Wyniki testów dla kompilatora Javac (czas w tabeli podany w ms) ...... 31

Tabela 2. Wyniki testów dla kompilatora Jikes (czas w tabeli podany w ms) ....... 31

Tabela 3. Wyniki testów dla kompilatora GCJ (czas w tabeli podany w ms) ........ 31

Page 40: Edukacja Techniczno Informatyczna Studia dziennemblachnik.pl/lib/exe/fetch.php/dydaktyka/mgr... · zadanie, mianowicie ma zgłaszać występowanie błędów składniowych. Jest to

40

9. Spis wykresów

Wykres 1. Porównanie wydajności kompilatora Javac w systemach Windows XP i

Ubuntu (na osi pionowej czas w ms) .................................................................. 32

Wykres 2. Porównanie wydajności kompilatora Jikes w systemach Windows XP i

Ubuntu (na osi pionowej czas w ms) .................................................................. 32

Wykres 3. Porównanie wydajności kompilatora GCJ w systemach Windows XP i

Ubuntu (na osi pionowej czas w ms) .................................................................. 33

Wykres 4. Porównanie wydajności kompilatorów dla przebiegu 1 w systemach

Windows XP i Ubuntu (na osi pionowej czas w ms) ........................................... 33

Wykres 5. Porównanie wydajności kompilatorów dla przebiegu 2 w systemach

Windows XP i Ubuntu (na osi pionowej czas w ms) ........................................... 34

Wykres 6. Porównanie wydajności kompilatorów dla przebiegu 3 w systemach

Windows XP i Ubuntu (na osi pionowej czas w ms) ........................................... 34