logo

ClassLoader i Java

Java ClassLoader

Java ClassLoader er en abstrakt klasse. Det tilhører en java.lang pakke. Den indlæser klasser fra forskellige ressourcer. Java ClassLoader bruges til at indlæse klasserne under kørsel. Med andre ord udfører JVM sammenkædningsprocessen under kørsel. Klasser indlæses i JVM efter behov. Hvis en indlæst klasse afhænger af en anden klasse, indlæses denne klasse også. Når vi anmoder om at indlæse en klasse, uddelegerer den klassen til sin forælder. På denne måde bevares unikhed i runtime-miljøet. Det er vigtigt at køre et Java-program.

gimp gem som jpeg
ClassLoader i Java

Java ClassLoader er baseret på tre principper: Delegation , Sigtbarhed , og Unikhed .

    Delegationsprincip:Den videresender anmodningen om klasseindlæsning til den overordnede klasseindlæser. Den indlæser kun klassen, hvis forælderen ikke finder eller indlæser klassen.Synlighedsprincip:Det giver børneklasseindlæser mulighed for at se alle klasser indlæst af overordnet ClassLoader. Men den overordnede klasseindlæser kan ikke se klasser indlæst af den underordnede klasseindlæser.Unikitetsprincippet:Det giver mulighed for at indlæse en klasse én gang. Det opnås ved delegationsprincippet. Det sikrer, at barnet ClassLoader ikke genindlæser klassen, som allerede er indlæst af forælderen.

Typer af ClassLoader

I Java har hver ClassLoader en foruddefineret placering, hvorfra de indlæser klassefiler. Der er følgende typer ClassLoader i Java:

Bootstrap Class Loader: Den indlæser standard JDK-klassefiler fra rt.jar og andre kerneklasser. Det er en forælder til alle klasselæssere. Den har ingen forælder. Når vi kalder String.class.getClassLoader() returnerer den null, og enhver kode baseret på den kaster NullPointerException. Det kaldes også Primordial ClassLoader. Den indlæser klassefiler fra jre/lib/rt.jar. For eksempel java.lang-pakkeklassen.

Udvidelser Klasse Loader: Den delegerer anmodning om klasseindlæsning til sin forælder. Hvis indlæsningen af ​​en klasse ikke lykkes, indlæser den klasser fra mappen jre/lib/ext eller en hvilken som helst anden mappe som java.ext.dirs. Det er implementeret af sun.misc.Launcher$ExtClassLoader i JVM.

System Class Loader: Den indlæser applikationsspecifikke klasser fra miljøvariablen CLASSPATH. Det kan indstilles, mens du kalder programmet ved hjælp af -cp eller classpath kommandolinjeindstillinger. Det er et barn af Extension ClassLoader. Det er implementeret af sun.misc.Launcher$AppClassLoader-klassen. Alle Java ClassLoader implementerer java.lang.ClassLoader.

ClassLoader i Java

Sådan fungerer ClassLoader i Java

Når JVM anmoder om en klasse, påberåber den en loadClass()-metode af klassen java.lang.ClassLoader ved at videregive det fuldt klassificerede navn på klassen. loadClass()-metoden kalder findLoadedClass()-metoden for at kontrollere, at klassen allerede er blevet indlæst eller ej. Det er påkrævet at undgå at indlæse klassen flere gange.

Hvis klassen allerede er indlæst, uddelegerer den anmodningen til overordnet ClassLoader om at indlæse klassen. Hvis ClassLoader ikke finder klassen, kalder den findClass()-metoden for at lede efter klasserne i filsystemet. Følgende diagram viser, hvordan ClassLoader indlæser klasse i Java ved hjælp af delegering.

ClassLoader i Java

Antag, at vi har en applikationsspecifik klasse Demo.class. Anmodningen om indlæsning af denne klassefiler overføres til Application ClassLoader. Den uddelegerer til sin overordnede Extension ClassLoader. Yderligere uddelegerer den til Bootstrap ClassLoader. Bootstrap søg den klasse i rt.jar og da den klasse ikke er der. Anmod om overførsel til Extension ClassLoader, som søger efter mappen jre/lib/ext og forsøger at finde denne klasse der. Hvis klassen findes der, indlæser Extension ClassLoader denne klasse. Application ClassLoader indlæser aldrig den klasse. Når udvidelsen ClassLoader ikke indlæser den, så indlæser Application ClaasLoader den fra CLASSPATH i Java.

Synlighedsprincippet siger, at den underordnede ClassLoader kan se klassen indlæst af den overordnede ClassLoader, men omvendt er det ikke sandt. Det betyder, at hvis Application ClassLoader indlæser Demo.class, i et sådant tilfælde, at forsøg på at indlæse Demo.class eksplicit ved hjælp af Extension ClassLoader kaster java.lang.ClassNotFoundException.

Ifølge unikhedsprincippet bør en klasse indlæst af forælderen ikke indlæses af Child ClassLoader igen. Så det er muligt at skrive klasseindlæser, som overtræder delegations- og unikkeprincipper og indlæser klasse af sig selv.

Kort sagt følger klasseindlæseren følgende regel:

  • Det tjekker, om klassen allerede er indlæst.
  • Hvis klassen ikke er indlæst, skal du bede den overordnede klasseindlæser om at indlæse klassen.
  • Hvis den overordnede klasseindlæser ikke kan indlæse klassen, så prøv at indlæse den i denne klasseindlæser.

Overvej følgende eksempel:

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

Kompiler og kør ovenstående kode ved at bruge følgende kommando:

 javac Demo.java java -verbose:class Demo 

-verbose:klasse: Det bruges til at vise information om klasser, der indlæses af JVM. Det er nyttigt, når du bruger klasseindlæser til dynamisk indlæsning af klasser. Følgende figur viser output.

ClassLoader i Java

Vi kan observere, at runtime-klasser, der kræves af applikationsklassen (Demo), indlæses først.

Når klasserne er indlæst

Der er kun to tilfælde:

  • Når den nye bytekode udføres.
  • Når bytekoden laver en statisk reference til en klasse. For eksempel, System.ud .

Statisk vs. dynamisk klasseindlæsning

Klasser er statisk indlæst med 'ny' operator. Dynamisk klasseindlæsning påkalder funktionerne i en klasseindlæser under kørsel ved at bruge metoden Class.forName().

Forskellen mellem loadClass() og Class.forName()

Metoden loadClass() indlæser kun klassen, men initialiserer ikke objektet. Mens metoden Class.forName() initialiserer objektet efter indlæsning af det. For eksempel, hvis du bruger ClassLoader.loadClass() til at indlæse JDBC-driveren, tillader klasseindlæser ikke at indlæse JDBC-driveren.

Metoden java.lang.Class.forName() returnerer klasseobjektet koblet med klassen eller grænseflader med det givne strengnavn. Det kaster ClassNotFoundException, hvis klassen ikke findes.

Eksempel

I dette eksempel er java.lang.String-klassen indlæst. Den udskriver klassenavnet, pakkenavnet og navnene på alle tilgængelige metoder i String-klassen. Vi bruger Class.forName() i følgende eksempel.

Klasse: Repræsenterer et klasseobjekt, som kan være af enhver type (? er et jokertegn). Klassetypen indeholder metainformation om en klasse. For eksempel er typen String.class Class. Brug Klasse, hvis klassen, der modelleres, er ukendt.

getDeclaredMethod(): Returnerer et array, der indeholder Method-objekter, der afspejler alle de erklærede metoder for klassen eller grænsefladen, der er repræsenteret af dette klasseobjekt, inklusive offentlige, beskyttede, standard-(pakke)adgang og private metoder, men ekskluderer nedarvede metoder.

getName(): Det returnerer metodenavnet repræsenteret af dette metodeobjekt, som en streng.

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

Produktion

 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