Marcin Janic 1. Streszczenie

Podobne dokumenty
Programowanie w języku Java - Wyjątki, obsługa wyjątków, generowanie wyjątków

JAVA. Java jest wszechstronnym językiem programowania, zorientowanym. apletów oraz samodzielnych aplikacji.

Programowanie obiektowe

Java jako język programowania

Programowanie obiektowe. Literatura: Autor: dr inŝ. Zofia Kruczkiewicz

Programowanie obiektowe

Aplikacje RMI

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

Programowanie Strukturalne i Obiektowe Słownik podstawowych pojęć 1 z 5 Opracował Jan T. Biernat

Dokumentacja do API Javy.

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Multimedia JAVA. Historia

Pierwsze kroki. Algorytmy, niektóre zasady programowania, kompilacja, pierwszy program i jego struktura

Obiektowe programowanie rozproszone Java RMI. Krzysztof Banaś Systemy rozproszone 1

Wykład 7: Pakiety i Interfejsy

Programowanie obiektowe zastosowanie języka Java SE

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut.

Katedra Architektury Systemów Komputerowych Wydział Elektroniki, Telekomunikacji i Informatyki Politechniki Gdańskiej

Pakiety i interfejsy. Tomasz Borzyszkowski

Języki i metody programowania Java. Wykład 2 (część 2)

Ćwiczenie 1. Przygotowanie środowiska JAVA

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Język JAVA podstawy. wykład 2, część 1. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Informatyka I. Dziedziczenie. Nadpisanie metod. Klasy abstrakcyjne. Wskaźnik this. Metody i pola statyczne. dr inż. Andrzej Czerepicki

Wyjątki. Streszczenie Celem wykładu jest omówienie tematyki wyjątków w Javie. Czas wykładu 45 minut.

Aplikacje RMI Lab4

KLASY, INTERFEJSY, ITP

Sposoby tworzenia projektu zawierającego aplet w środowisku NetBeans. Metody zabezpieczenia komputera użytkownika przed działaniem apletu.

Dziedziczenie. Tomasz Borzyszkowski

Programowanie obiektowe

Programowanie obiektowe

Enkapsulacja, dziedziczenie, polimorfizm

Programowanie obiektowe

Ćwiczenie 1. Kolejki IBM Message Queue (MQ)

Diagram klas UML jest statycznym diagramem, przedstawiającym strukturę aplikacji bądź systemu w paradygmacie programowania obiektowego.

Programowanie Obiektowe Ćwiczenie 4

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Podstawy i języki programowania

WPROWADZENIE DO JĘZYKA JAVA

Polimorfizm, metody wirtualne i klasy abstrakcyjne

Dzisiejszy wykład. Wzorce projektowe. Visitor Client-Server Factory Singleton

Rozdział 4 KLASY, OBIEKTY, METODY

PHP 5 język obiektowy

Analiza i projektowanie obiektowe 2016/2017. Wykład 11: Zaawansowane wzorce projektowe (1)

D:\DYDAKTYKA\ZAI_BIS\_Ćwiczenia_wzorce\04\04_poprawiony.doc 2009-lis-23, 17:44

Klasy abstrakcyjne i interfejsy

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

1 Atrybuty i metody klasowe

Projektowanie obiektowe. Roman Simiński Wzorce projektowe Wybrane wzorce strukturalne

PARADYGMATY PROGRAMOWANIA Wykład 4

Wyjątki (exceptions)

Programowanie obiektowe

Prototype (prototyp) Cel: Przykład: Określenie rodzaju tworzonych obiektów poprzez wskazanie ich prototypu. Nowe instancje tworzymy kopiując prototyp.

Zaawansowane aplikacje WWW - laboratorium

Wywoływanie metod zdalnych

Zdalne wywołanie metod - koncepcja. Oprogramowanie systemów równoległych i rozproszonych Wykład 7. Rodzaje obiektów. Odniesienie do obiektu

Wykład Ćwiczenia Laboratorium Projekt Seminarium

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

Oprogramowanie systemów równoległych i rozproszonych Wykład 7

Język JAVA podstawy. Wykład 4, część 1. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Wykład 8: Obsługa Wyjątków

Interfejsy. Programowanie obiektowe. Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej

Zaawansowane aplikacje internetowe

Podstawy i języki programowania

Kurs programowania. Wstęp - wykład 0. Wojciech Macyna. 22 lutego 2016

Programowanie obiektowe

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Kurs WWW. Paweł Rajba.

Programowanie obiektowe

Klasy. dr Anna Łazińska, WMiI UŁ Podstawy języka Java 1 / 13

Java Zadanie 1. Aby poprawnie uruchomić aplikację desktopową, należy zaimplementować główną metodę zapewniającą punkt wejścia do programu.

Kurs programowania. Wykład 9. Wojciech Macyna. 28 kwiecień 2016

Remote Method Invocation 17 listopada Dariusz Wawrzyniak (IIPP) 1

Początki Javy. dr Anna Łazińska, WMiI UŁ Podstawy języka Java 1 / 8

Podejście obiektowe do budowy systemów rozproszonych

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

Metody Metody, parametry, zwracanie wartości

Języki i metody programowania Java INF302W Wykład 3 (część 1)

Diagramy klas. dr Jarosław Skaruz

Metody dostępu do danych

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Aplikacje Internetowe. Najprostsza aplikacja. Komponenty Javy. Podstawy języka Java

Obiektowy PHP. Czym jest obiekt? Definicja klasy. Składowe klasy pola i metody

Programowanie w Javie nazwa przedmiotu SYLABUS A. Informacje ogólne

Remote Method Invocation 17 listopada 2010

Bezpieczne uruchamianie apletów wg

Zaawansowane programowanie w języku C++ Programowanie obiektowe

akademia androida Składowanie danych część VI

UML a kod w C++ i Javie. Przypadki użycia. Diagramy klas. Klasy użytkowników i wykorzystywane funkcje. Związki pomiędzy przypadkami.

Aplikacje internetowe i rozproszone - laboratorium

Java - wprowadzenie. Programowanie Obiektowe Mateusz Cicheński

Wprowadzenie. Narzędzia i środowiska programistyczne. Laboratorium 1. Prowadzący: Kierunek: Semestr: Rok: Tomasz Gądek Informatyka Zimowy 2

Java. Programowanie Obiektowe Mateusz Cicheński

Java w 21 dni / Rogers Cadenhead. Gliwice, cop Spis treści. O autorze 11. Wprowadzenie 13 TYDZIEŃ I JĘZYK JAVA

Podejście obiektowe do budowy systemów rozproszonych

Java RMI. Dariusz Wawrzyniak 1. Podejście obiektowe do budowy systemów rozproszonych. obiekt. interfejs. kliencka. sieć

Laboratorium z przedmiotu: Inżynieria Oprogramowania INEK Instrukcja 7

Narzędzia i aplikacje Java EE. Usługi sieciowe Paweł Czarnul pczarnul@eti.pg.gda.pl

Transkrypt:

Rozszerzanie funkcjonalności aplikacji w trakcie działania programu poprzez dynamiczne ładowanie klas na przykładzie pluginów do wczytywania plików w języku Java Marcin Janic 1 1 Wydział Inżynierii Mechanicznej i Informatyki Kierunek informatyka, Rok III poonury@gmail.com Streszczenie Celem niniejszej pracy jest omówienie hierarchii ładowania klas oraz prezentacja sposobu dynamicznego ładowania klas w języku programowania Java. Do realizacji tego zagadnienia należy utworzyć własną procedurę ładująca, która rozszerza klasę "ClassLoader" i zastąpi jej metodę "findclass". Utworzona w ten sposób procedura ładująca pozwoli na ładowanie nieznanych podczas tworzenia aplikacji rozszerzeń plików. 1 Wstęp Podczas tworzenia aplikacji twórca nie zawsze może przewidzieć dokładnego kierunku jej rozwoju. Bardzo często podczas działania zauważa się, że potrzebna jest całkiem nowa funkcjonalność, której analityk bądź programista nie przewidział w fazie projektowania. Tworząc aplikacje należy używać elastycznych rozwiązań co znacznie ułatwia późniejszą rozbudowę jej funkcjonalności. Jedną z metod tworzenia programów jest rozszerzanie ich funkcjonalności w trakcie działania programu poprzez dynamiczne ładowanie klas. Tak zaprojektowana aplikacja może wybrać, które klasy są jej w tym momencie niezbędne i je załadować. 2 Klasa w programowaniu obiektowym Klasa jako byt abstrakcyjny znajduje swoje zastosowanie w programowaniu obiektowym. Jest ona częściową bądź całkowitą definicją obiektu. Tworząc klasę tworzymy nowy typ danych, którego składnikami są inne typy danych nazywane polami klasy. Dodatkowo klasa posiada implementacje funkcji zwanych inaczej metodami, które operują na polach. Klasa[2] może być odwzorowaniem dowolnego rzeczywistego bądź abstrakcyjnego obiektu. Ułatwia to programiście spojrzenie na projekt obiektywnie co wcale nie jest łatwe przy założeniu, że powinien nadawać się do wielokrotnego użytku. Niektóre problemy z jakimi spotykają się programiści powtarzają się, a ich rozwiązanie jest uniwersalne, oraz sprawdzone w praktyce co pozwala na wykorzystanie pewnych wzorców projektowych. Temat wzorców projektowych został opisany przez Erich Gamma [3]. 1

3 Ładowanie klas Maszyna wirtualna, jest to ogólna nazwa środowiska, gdzie uruchamiane są programy. Kontroluje ona wszelkie bezpośrednie odwołania do sprzętu bądź systemu operacyjnego przez program przez co zapewnia ich obsługę. Wirtualna maszyna Javy powszechnie nazywana jest samodzielnym interpreterem. Istniały też komputery, które zdolne były uruchamiać kod bajtowy Javy bezpośrednio stąd można ją postrzegać jako emulator tych maszyn. Kod źródłowy programu napisanego w Javie zostaje przekształcony przez kompilator w kod maszyny wirtualnej. Kod ten umieszczany jest w plikach posiadających rozszerzenie.class, które zawierają kody definicji i implementacji klasy lub interfejsu. Następnie program tłumaczący kod maszyny wirtualnej na kod maszyny na, której wykonuje się program interpretuje pliki klas. Interpreter ładuje jedynie potrzebne pliki bez, których nie będzie w stanie wykonać programu. Standardowymi działaniami maszyny wirtualnej w przypadku uruchomienia klasy są: 1) Maszyna wirtualna posiada mechanizm ładowania plików z klasami, z dysku lub sieci Internet, który wykorzystuje do załadowania żądanej klasy. 2) Jeśli ładowana klasa posiada zmienne typów innych klas lub klasy bazowe to ładowane są także pliki tych klas. 3) Maszyna wirtualna wykonuje metodę main ładowanej klasy. Jest to metoda statyczna, więc nie jest tworzona instancja tejże klasy. 4) Jeśli wywołana metoda main lub jakakolwiek inna wywołana w czasie wykonywania programu wymaga niezaładowanego dotychczas pliku klasy to jest on ładowany. Więcej na temat ładowania klas można przeczytać[4], oraz w dokumentacji języka Java [5]. 4 Procedury ładujące Mechanizm ładowania klas wykorzystuje przynajmniej trzy procedury ładowania klas: początkowa, rozszerzeń, systemowa. Klasy systemowe ładowane są przez procedurę początkową. Zazwyczaj jest zaimplementowana w języku C, oraz stanowi integralną część maszyny wirtualnej. Standardowe rozszerzenia maszyny wirtualnej z katalogu jre/lib/ext ładowane są przez procedurę rozszerzeń. W podanym katalogu możemy, także umieścić swój własny plik.jar co pozwoli na ładowanie zawartych w nim klas bez konieczności podawania ścieżki dostępu. Pliki klas aplikacji ładowane są przez procedurę systemową. Procedura poszukuje plików w katalogach, plikach.jar, oraz.zip wykorzystując ścieżki dostępu do klas zapisane w zmiennej środowiskowej CLASSPATH lub fladze -classpath wpisanej w wierszu poleceń. 2

5 Hierarchia ładowania klas Procedury ładowania posiadają swoje hierarchie, każda z nich posiada swoją procedurę nadrzędną. Procedura początkowa, która jako jedyna nie posiada, jest wyjątkiem. Procedura podrzędna musi najpierw, umożliwić znalezienie i załadowanie pliku klasy swojej procedurze nadrzędnej, gdy ładowanie nie powiedzie się wtedy procedura podrzędna próbuje załadować go sama. Przykładem takiej zależności może być otrzymanie polecenia załadowania klasy systemowej przez procedurę systemową na przykład: import java.util.vector; import java.io.fileinputstream; import java.io.ioexception; Wtedy, najpierw polecenie przekazywane jest do rozszerzonej, a stamtąd z kolei do procedury początkowej. Ponieważ procedura początkowa odnajdzie i załaduje plik to żadna z pozostałych procedur nie będzie, już kontynuować procesu poszukiwania tejże klasy. Poniższy rysunek obrazuje hierarchie procedur ładujących. Rys. 1 - Hierarchia poszczególnych procedur ładujących Zazwyczaj programista zwolniony jest z zajmowania się procedurami ładującymi z powodu iż większość klas ładowana jest automatycznie przez inne klasy, które je używają. W niektórych wypadkach jednak korzystniej jest zaimplementować własną procedurę. 3

6 Procedury ładuj ące a przestrzenie nazw Język Java wykorzystuje pakiety w celu określania przestrzeni nazw, oraz zapobieganiu konfliktów nazw klas. Istnieje wiele klas o tej samej nazwie, lecz znajdują się w różnych pakietach co pozwala jednoznacznie określić ich tożsamość. Program wykonywalny posługuje się tylko i wyłącznie, pełnymi nazwami klas określonymi poprzez umieszczenie ich w pakietach. Nazwa krótka Date używana jest przez programistów dla ich wygody i wymaga polecenia import podanego na początku programu: import java.util.date; import java.sql.date; Zdarzają się również przypadki, gdzie dwie klasy posiadają identyczne nazwy, oraz pakiety. Maszyna wirtualna radzi sobie z takimi przypadkami, ponieważ oprócz pełnej nazwy klasa określana jest też przez procedurę ładującą. Jest to przydatne podczas ładowania kodu z różnych źródeł. Przykładem takiej sytuacji może być przeglądarka internetowa, która dla każdej ze strony internetowej używa osobnej instancji klasy, która ładuje aplet. Bez względu na to jak nazwano klasy, maszyna wirtualna jest w stanie rozróżnić klasy apletów na różnych stronach. Zakładając, że strona zawiera 2 aplety dostarczone przez 2 różnych programistów, a każdy z nich zawiera klasę o nazwie Main. Z powodu iż, każdy aplet ładowany jest przez osobną procedurę ładującą to obie, klasy Main są jednoznacznie rozróżniane i nie występuje jakikolwiek konflikt nazw. Zobrazować może to poniższy schemat. Rys. 2 - Ładowanie dwóch różnych klas o tej samej nazwie 4

7 Implementacja własnej procedury ładuj ącej Tworzenie własnych procedur ładujących nastawione jest na wyspecjalizowane zastosowania, które dotyczą podjęcia pewnych działań przed przekazaniem kodu maszynie wirtualnej. Jednym z przykładowych działań jest odmowa załadowania klasy (np. w przypadku barku wykupionej licencji), bądź załadowanie jakieś klasy alternatywnej o ograniczonych usługach. By stworzyć w pełni funkcjonalną procedurę ładującą musimy rozszerzyć klasę ClassLoader. class PluginLoader extends ClassLoader //... Następnie zastąpić jej metodę findclass(string classname). @Override protected Class<?> findclass(string name) throws ClassNotFoundException Przeciążona metoda findclass, musi załadować kod danej klasy wykorzystując system plików lub inne źródło umożliwiające pobranie kodu. // Utworzenie pustej tablicy bajtów byte [] classbytes = null; try // wywołanie metody ładującej kod klasy i nadpisanie tablicy classbytes = loadclassbytes(name); catch (IOException ex) System.err.println("PluginLoader " + ex); Metodę ładującą, można wykorzystać do odszyfrowywania kodu klasy. W ramach uproszczenia prezentowanego przykładu zignorowano dorobek ludzkości i zastosowano prosty szyfr Cezara[6]. Użyta wersja szyfru używa klucza z zakresu od 1 do 255. Szyfrowanie polega na dodaniu klucza do czytanego bajtu, a następnie wyznaczenia reszty z dzielenia uzyskanej sumy przez 256. private byte[] loadclassbytes(string name) throws IOException // zamiast.class można dać dowolne rozszerzenie pliku String cname = name.replace('/', '.') + ".class"; // stworzenie strumienia wejściowego i otwarcie go dla pliku name.class FileInputStream in = null; in = new FileInputStream( cname ); try ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int ch; // wczytywnie do końca pliku while((ch = in.read() )!= -1 ) 5

finally byte b = (byte) (ch - klucz); // zapisanie danych do bufora buffer.write(b); in.close(); // zwrocenie wczytanego pliku w postaci tablicy bajtów return buffer.tobytearray(); in.close(); // End loadclassbytes(string name) W końcowej fazie wczytywania funkcja, musi wywołać metodę defineclass klasy bazowej ClassLoader by przekazać kod klasy do maszyny wirtualnej. Jako argument podajemy nazwę klasy, która nie musi mieć wcale rozszerzenia.class. Można ustalić swoje własne rozszerzenie, aby nie wprowadzać w błąd zwykłych procedur ładowania. //przekazuje nową klasie maszynie wirtualnej, kod klasy //umieszczony jest w zakresie off=0 i len=classbytes.length Class<?> cl = defineclass(name, classbytes, 0, classbytes.length); if( cl == null ) throw new ClassNotFoundException(name); //zwrocenie klasy return cl; Do uruchomienia dowolnej metody z wczytanej klasy można zastosować przykładową metodę. public static void runplugin(string name) try // Utworznie nowej instancji klasy PluginLoader ClassLoader loader = new PluginLoader(); //Zdefiniowanie nowej klasy Class <?> c = loader.loadclass(name); // Pobranie metody o nazwie "main" i parametrach String[] Method m = c.getmethod("main", String[].class); // Utworzenie parametrow Object args = new String[] ; // Wywołanie metody i przypisanie zwracenej wartości do ret Object ret = m.invoke(c.newinstance(), args); System.out.println( "Funkcja zwrucila "+ ret); catch (Exception ex) System.err.print("RunPlugin " + ex); // End RunPlugin(String name) 6

8 Użycie pluginów do wczytywania plików Prezentowany program przeznaczony jest do wizualizacji obliczeń inżynierskich. Obliczenia wykonane są za pomocą metody elementów skończonych dla siatek dwuwymiarowych. Dane wejściowe, takie jak punkty współrzędnych węzłów siatki, powiązań między tymi węzłami, oraz wartości w węzłach dla poszczególnych kroków czasowych zapisane są w różnych formatach poczynając od.xml przez.obj, a kończąc na zwykłym.txt. Klasa, która jest odpowiedzialna za wczytanie danych wejściowych jest wybierana na podstawie rozszerzenia, a następnie dynamicznie ładowana do pamięci. Pozwala to na elastyczne dodawanie nowych formatów danych wejściowych bez konieczności rekompilowania głównego modułu. Poniższy diagram obrazuje funkcjonalność Wizualizatora dotyczącą wczytywania danych wejściowych. Rys. 3 Diagram funkcjonalności Wizualizatora Za pomocą tej aplikacji, można wygenerować obraz siatki(bez wyników obliczeń) lub rozkład wartości (np. temperatury) w postaci mapy (przejście kolorów), oraz w postaci wykresu konturowego (izolinii). Aplikacja umożliwia także przedstawienie wyników w formie animacji. 9 Podsumowanie Przedstawiony sposób implementowania własnych procedur ładujących jest narzędziem bardzo elastycznym, posiadającym swoje plusy jak i minusy. Bardzo szybko można rozbudować aplikację o nowe możliwości, bez konieczności rekompilowania głównego modułu, którego funkcjonalność była by rozszerzana. Czynności, które możemy podjąć przed wczytaniem klasy dają nam cały wachlarz możliwości od prostego wczytania klasy poprzez weryfikacje kodu bajtowego, aż po wczytywanie zaszyfrowanych klas bądź po prostu odmowy załadowania klasy. Mechanizm może być, wykorzystany do autoryzacji użytkowników i wczytywać jedynie klasy na, które użytkownik posiada licencje. Klasy mogą zostać zaszyfrowane i bez odpowiedniego klucza zawartego w procedurze ładującej wczytanie ich staje się niemożliwe, co czyni je bezużytecznymi. 7

Klasy mogą mieć różne wersje, co pozwala na wprowadzenie dodatkowej funkcjonalności o, które potencjalny klient mógłby się upomnieć. Programista nie jest w stanie przewidzieć kierunku rozwoju aplikacji przez co mechanizm ten staje się bardzo użyteczny w przypadku bardziej rozbudowanych projektów. 10 Bibliografia [1] Cay S. Horstmann, Gary Cornell, Java. Techniki zaawansowane. Wydanie VIII, 2009. [2] Herbert Schildt, Java. Kompendium programisty, 2005 [3] Erich Gamma, Richard Helm, Ralph Johnsin, John Vlissides, Wzorce projektowe. Elementy oprogramowania obiektowego wielokrotnego użytku, 2010 [4] http://edu.pjwstk.edu.pl/wyklady/mpr/scb/w3/w3.htm - Dynamiczna Java i programowanie komponentowe (29 maja 2012) [5] http://docs.oracle.com/javase/6/docs/ - Dokumentacja języka Java (29 maja 2012) [6] http://www.kryptografia.com/algorytmy/cezar.html Opis szyfrowania za pomocą metody Cezara (29 maja 2012) 8