logo

ClassLoader в Java

Java ClassLoader

Java ClassLoader е абстрактен клас. Принадлежи на a java.lang пакет. Зарежда класове от различни ресурси. Java ClassLoader се използва за зареждане на класовете по време на изпълнение. С други думи, JVM изпълнява процеса на свързване по време на изпълнение. Класовете се зареждат в JVM според нуждите. Ако зареден клас зависи от друг клас, този клас също се зарежда. Когато поискаме да заредим клас, той делегира класа на своя родител. По този начин се запазва уникалността в средата за изпълнение. От съществено значение е да се изпълни Java програма.

изпитване и видове изпитване
ClassLoader в Java

Java ClassLoader се основава на три принципа: Делегиране , Видимост , и Уникалност .

    Принцип на делегиране:Той препраща заявката за зареждане на клас към товарач на родителски клас. Той зарежда класа само ако родителят не намери или зареди класа.Принцип на видимост:Позволява на дъщерния зареждащ клас да вижда всички класове, заредени от родителския ClassLoader. Но програмата за зареждане на родителски клас не може да види класове, заредени от програмата за зареждане на дъщерни класове.Принцип на уникалност:Позволява еднократно зареждане на клас. Постига се на принципа на делегиране. Той гарантира, че дъщерният ClassLoader не презарежда класа, който вече е зареден от родителя.

Видове ClassLoader

В Java всеки ClassLoader има предварително дефинирано местоположение, откъдето зарежда клас файлове. В Java има следните типове ClassLoader:

Зареждащ клас на Bootstrap: Той зарежда стандартни JDK клас файлове от rt.jar и други основни класове. Той е родител на всички зареждащи класове. То няма родител. Когато извикаме String.class.getClassLoader(), той връща null и всеки код, базиран на него, хвърля NullPointerException. Нарича се още Primordial ClassLoader. Той зарежда клас файлове от jre/lib/rt.jar. Например клас пакет java.lang.

Разширения за зареждане на класове: Той делегира заявка за зареждане на клас на своя родител. Ако зареждането на клас е неуспешно, той зарежда класове от jre/lib/ext директория или друга директория като java.ext.dirs. Реализира се от sun.misc.Launcher$ExtClassLoader в JVM.

Система за зареждане на класове: Той зарежда специфични за приложението класове от променливата на средата CLASSPATH. Може да се зададе при извикване на програма с помощта на опциите на командния ред -cp или classpath. Това е дете на Extension ClassLoader. Реализира се от клас sun.misc.Launcher$AppClassLoader. Всички Java ClassLoader имплементират java.lang.ClassLoader.

ClassLoader в Java

Как работи ClassLoader в Java

Когато JVM поиска клас, той извиква метод loadClass() на класа java.lang.ClassLoader, като предава напълно класифицираното име на класа. Методът loadClass() извиква метода findLoadedClass(), за да провери дали класът вече е зареден или не. Изисква се да се избягва зареждането на класа многократно.

Ако класът вече е зареден, той делегира заявката към родителския ClassLoader за зареждане на класа. Ако ClassLoader не намира класа, той извиква метода findClass(), за да търси класовете във файловата система. Следващата диаграма показва как ClassLoader зарежда клас в Java чрез делегиране.

ClassLoader в Java

Да предположим, че имаме специфичен за приложението клас Demo.class. Заявката за зареждане на този клас файлове се прехвърля към Application ClassLoader. Той делегира на своя родител Extension ClassLoader. Освен това той делегира на Bootstrap ClassLoader. Bootstrap търси този клас в rt.jar и тъй като този клас го няма. Сега поискайте прехвърляне към Extension ClassLoader, който търси директорията jre/lib/ext и се опитва да намери този клас там. Ако класът е намерен там, Extension ClassLoader зарежда този клас. Application ClassLoader никога не зарежда този клас. Когато разширението ClassLoader не го зарежда, тогава приложението ClaasLoader го зарежда от CLASSPATH в Java.

Принципът на видимост гласи, че дъщерният ClassLoader може да види класа, зареден от родителския ClassLoader, но обратното не е вярно. Това означава, че ако Application ClassLoader зареди Demo.class, в такъв случай опитът да се зареди Demo.class изрично с помощта на Extension ClassLoader хвърля java.lang.ClassNotFoundException.

Според принципа на уникалността клас, зареден от родителя, не трябва да се зарежда отново от Child ClassLoader. Така че е възможно да се напише програма за зареждане на класове, която нарушава принципите на делегиране и уникалност и зарежда класа сама.

Накратко, зареждането на класове следва следното правило:

  • Проверява дали класът вече е зареден.
  • Ако класът не е зареден, помолете родителския зареждащ клас да зареди класа.
  • Ако програмата за зареждане на родителски клас не може да зареди клас, опитайте да го заредите в тази програма за зареждане на класове.

Разгледайте следния пример:

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

Компилирайте и стартирайте горния код, като използвате следната команда:

 javac Demo.java java -verbose:class Demo 

-подробно:клас: Използва се за показване на информация за класове, които се зареждат от JVM. Полезно е, когато използвате програма за зареждане на класове за динамично зареждане на класове. Следващата фигура показва изхода.

ClassLoader в Java

Можем да наблюдаваме, че класовете по време на изпълнение, изисквани от класа на приложението (Demo), се зареждат първи.

Когато се зареждат класове

Има само два случая:

  • Когато новият байт код се изпълни.
  • Когато байтовият код прави статична препратка към клас. Например, System.out .

Статично срещу динамично зареждане на клас

Класовете се зареждат статично с оператор 'нов'. Динамичното зареждане на клас извиква функциите на товарач на клас по време на изпълнение чрез използване на метода Class.forName().

Разлика между loadClass() и Class.forName()

Методът loadClass() зарежда само класа, но не инициализира обекта. Докато методът Class.forName() инициализира обекта след зареждането му. Например, ако използвате ClassLoader.loadClass() за зареждане на JDBC драйвера, програмата за зареждане на класове не позволява зареждането на JDBC драйвера.

Методът java.lang.Class.forName() връща Class Object, свързан с класа или интерфейсите с даденото име на низ. Той хвърля ClassNotFoundException, ако класът не е намерен.

Пример

В този пример се зарежда клас java.lang.String. Той отпечатва името на класа, името на пакета и имената на всички налични методи на клас String. Използваме Class.forName() в следния пример.

клас: Представлява обект на клас, който може да бъде от всякакъв тип (? е заместващ знак). Типът Class съдържа мета-информация за клас. Например типът на String.class е Class. Използвайте Class, ако моделираният клас е неизвестен.

getDeclaredMethod(): Връща масив, съдържащ обекти Method, отразяващи всички декларирани методи на класа или интерфейса, представен от този обект Class, включително публични, защитени, достъп по подразбиране (пакет) и частни методи, но с изключение на наследени методи.

getName(): Той връща името на метода, представено от този обект Method, като String.

 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(); } } } 

Изход

 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