logo

ClassLoader w Javie

Moduł ładujący klasy Java

Java ClassLoader jest klasą abstrakcyjną. Należy do A Java.lang pakiet. Ładuje klasy z różnych zasobów. Java ClassLoader służy do ładowania klas w czasie wykonywania. Innymi słowy, JVM wykonuje proces łączenia w czasie wykonywania. Klasy są ładowane do JVM w zależności od potrzeb. Jeśli załadowana klasa zależy od innej klasy, ta klasa również zostanie załadowana. Kiedy żądamy załadowania klasy, deleguje ją swojemu rodzicowi. W ten sposób unikalność środowiska wykonawczego zostaje zachowana. Niezbędne jest wykonanie programu Java.

równość ciągów w Javie
ClassLoader w Javie

Java ClassLoader opiera się na trzech zasadach: Delegacja , Widoczność , I Wyjątkowość .

    Zasada delegowania:Przesyła żądanie załadowania klasy do nadrzędnego programu ładującego klasy. Ładuje klasę tylko wtedy, gdy rodzic nie znajdzie lub nie załaduje klasy.Zasada widoczności:Umożliwia potomnemu modułowi ładującemu klasy zobaczenie wszystkich klas załadowanych przez nadrzędny moduł ClassLoader. Jednak nadrzędny moduł ładujący klasy nie widzi klas załadowanych przez moduł ładujący klasy podrzędne.Zasada wyjątkowości:Pozwala na jednokrotne załadowanie klasy. Osiąga się to poprzez zasadę delegowania. Zapewnia to, że podrzędny ClassLoader nie przeładuje klasy, która jest już załadowana przez rodzica.

Rodzaje ClassLoadera

W Javie każdy ClassLoader ma predefiniowaną lokalizację, z której ładuje pliki klas. W Javie istnieją następujące typy ClassLoader:

Moduł ładujący klasy Bootstrap: Ładuje standardowe pliki klas JDK z rt.jar i innych klas podstawowych. Jest rodzicem wszystkich programów ładujących klasy. Nie ma żadnego rodzica. Kiedy wywołujemy metodę String.class.getClassLoader(), zwraca ona wartość null, a każdy oparty na niej kod zgłasza wyjątek NullPointerException. Nazywa się go także pierwotnym modułem ładującym klasy. Ładuje pliki klas z jre/lib/rt.jar. Na przykład klasa pakietu Java.lang.

Moduł ładujący klasy rozszerzeń: Deleguje żądanie załadowania klasy do swojego rodzica. Jeśli ładowanie klasy nie powiedzie się, ładuje klasy z katalogu jre/lib/ext lub dowolnego innego katalogu jako java.ext.dirs. Jest implementowany przez sun.misc.Launcher$ExtClassLoader w JVM.

Moduł ładujący klasy systemowe: Ładuje klasy specyficzne dla aplikacji ze zmiennej środowiskowej CLASSPATH. Można to ustawić podczas wywoływania programu za pomocą opcji wiersza poleceń -cp lub classpath. Jest dzieckiem rozszerzenia ClassLoader. Jest ona implementowana przez klasę sun.misc.Launcher$AppClassLoader. Wszystkie programy Java ClassLoader implementują Java.lang.ClassLoader.

ClassLoader w Javie

Jak ClassLoader działa w Javie

Kiedy JVM żąda klasy, wywołuje metodę loadingClass() klasy java.lang.ClassLoader, przekazując w pełni sklasyfikowaną nazwę klasy. Metoda LoadClass() wywołuje metodę findLoadedClass() w celu sprawdzenia, czy klasa została już załadowana, czy nie. Należy unikać wielokrotnego ładowania klasy.

Jeśli klasa jest już załadowana, deleguje żądanie do nadrzędnego modułu ClassLoader w celu załadowania klasy. Jeśli ClassLoader nie znajduje klasy, wywołuje metodę findClass() w celu wyszukania klas w systemie plików. Poniższy diagram pokazuje, jak ClassLoader ładuje klasę w Javie przy użyciu delegowania.

ClassLoader w Javie

Załóżmy, że mamy klasę Demo.class specyficzną dla aplikacji. Żądanie wczytania plików tej klasy zostanie przesłane do aplikacji ClassLoader. Deleguje do swojego nadrzędnego modułu ClassLoader rozszerzenia. Ponadto deleguje do Bootstrap ClassLoader. Bootstrap przeszuka tę klasę w rt.jar, a ponieważ tej klasy tam nie ma. Teraz poproś o transfer do rozszerzenia ClassLoader, które wyszukuje katalog jre/lib/ext i próbuje zlokalizować tam tę klasę. Jeśli klasa tam zostanie znaleziona, rozszerzenie ClassLoader ładuje tę klasę. Aplikacja ClassLoader nigdy nie ładuje tej klasy. Gdy rozszerzenie ClassLoader nie ładuje go, aplikacja ClaasLoader ładuje je z CLASSPATH w Javie.

Zasada widoczności mówi, że podrzędny ClassLoader może zobaczyć klasę załadowaną przez nadrzędny ClassLoader, ale odwrotnie nie jest to prawdą. Oznacza to, że jeśli aplikacja ClassLoader ładuje Demo.class, wówczas próba jawnego załadowania Demo.class przy użyciu rozszerzenia ClassLoader zgłasza wyjątek java.lang.ClassNotFoundException.

Zgodnie z zasadą unikalności, klasa załadowana przez rodzica nie powinna być ponownie ładowana przez Child ClassLoader. Można więc napisać moduł ładujący klasy, który łamie zasady delegowania i unikalności i sam ładuje klasę.

Krótko mówiąc, moduł ładujący klasy kieruje się następującą zasadą:

  • Sprawdza, czy klasa jest już załadowana.
  • Jeśli klasa nie jest załadowana, poproś moduł ładujący klasy nadrzędnej o załadowanie klasy.
  • Jeśli nadrzędny program ładujący klasy nie może załadować klasy, spróbuj załadować ją w tym programie ładującym klasy.

Rozważ następujący przykład:

 public class Demo { public static void main(String args[]) { System.out.println('How are you?'); } } 

Skompiluj i uruchom powyższy kod za pomocą następującego polecenia:

 javac Demo.java java -verbose:class Demo 

-verbose:class: Służy do wyświetlania informacji o klasach ładowanych przez JVM. Jest to przydatne, gdy używasz modułu ładującego klasy do dynamicznego ładowania klas. Poniższy rysunek przedstawia dane wyjściowe.

ClassLoader w Javie

Możemy zaobserwować, że klasy wykonawcze wymagane przez klasę aplikacji (Demo) są ładowane jako pierwsze.

Kiedy klasy są załadowane

Są tylko dwa przypadki:

  • Kiedy wykonywany jest nowy kod bajtowy.
  • Gdy kod bajtowy tworzy statyczne odniesienie do klasy. Na przykład, System.out .

Ładowanie klas statycznych i dynamicznych

Klasy są ładowane statycznie za pomocą operatora „nowy”. Dynamiczne ładowanie klas wywołuje funkcje modułu ładującego klasy w czasie wykonywania przy użyciu metody Class.forName().

Różnica między LoadClass() i Class.forName()

Metoda LoadClass() ładuje tylko klasę, ale nie inicjuje obiektu. Natomiast metoda Class.forName() inicjuje obiekt po jego załadowaniu. Na przykład, jeśli używasz funkcji ClassLoader.loadClass() do załadowania sterownika JDBC, moduł ładujący klasy nie pozwala na załadowanie sterownika JDBC.

Metoda java.lang.Class.forName() zwraca obiekt klasy połączony z klasą lub interfejsami o podanej nazwie ciągu. Zgłasza wyjątek ClassNotFoundException, jeśli klasa nie zostanie znaleziona.

Przykład

W tym przykładzie ładowana jest klasa java.lang.String. Wypisuje nazwę klasy, nazwę pakietu i nazwy wszystkich dostępnych metod klasy String. W poniższym przykładzie używamy funkcji Class.forName().

Klasa: Reprezentuje obiekt klasy, który może być dowolnego typu (? jest symbolem wieloznacznym). Typ Class zawiera meta-informacje o klasie. Na przykład typ String.class to Class. Użyj Class, jeśli modelowana klasa jest nieznana.

getDeclaredMethod(): Zwraca tablicę zawierającą obiekty Method odzwierciedlające wszystkie zadeklarowane metody klasy lub interfejsu reprezentowanego przez ten obiekt Class, w tym dostęp publiczny, chroniony, dostęp domyślny (pakiet) i metody prywatne, ale z wyłączeniem metod dziedziczonych.

pobierzNazwę(): Zwraca nazwę metody reprezentowaną przez ten obiekt Method w postaci ciągu znaków.

 import java.lang.reflect.Method; public class ClassForNameExample { public static void main(String[] args) { try { Class cls = Class.forName('java.lang.String'); System.out.println('Class Name: ' + cls.getName()); System.out.println('Package Name: ' + cls.getPackage()); Method[] methods = cls.getDeclaredMethods(); System.out.println('-----Methods of String class -------------'); for (Method method : methods) { System.out.println(method.getName()); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } 

Wyjście

 Class Name: java.lang.String Package Name: package java.lang -----Methods of String class ------------- value coder equals length toString hashCode getChars ------ ------ ------ intern isLatin1 checkOffset checkBoundsOffCount checkBoundsBeginEnd access0 access0