Java ClassLoader
Java ClassLoader är en abstrakt klass. Den tillhör en java.lang paket. Den laddar klasser från olika resurser. Java ClassLoader används för att ladda klasserna vid körning. Med andra ord utför JVM länkningsprocessen vid körning. Klasser laddas in i JVM efter behov. Om en laddad klass beror på en annan klass, laddas den klassen också. När vi begär att ladda en klass delegerar den klassen till sin förälder. På så sätt bibehålls unikhet i runtime-miljön. Det är viktigt att köra ett Java-program.
rdbms
Java ClassLoader bygger på tre principer: Delegation , Synlighet , och Unikhet .
Typer av ClassLoader
I Java har varje ClassLoader en fördefinierad plats varifrån de laddar klassfiler. Det finns följande typer av ClassLoader i Java:
Bootstrap Class Loader: Den laddar standard JDK-klassfiler från rt.jar och andra kärnklasser. Det är en förälder till alla klasslastare. Den har ingen förälder. När vi anropar String.class.getClassLoader() returnerar den null, och all kod baserad på den kastar NullPointerException. Det kallas också Primordial ClassLoader. Den laddar klassfiler från jre/lib/rt.jar. Till exempel, java.lang paketklass.
Extensions Class Loader: Den delegerar begäran om klassladdning till sin förälder. Om laddningen av en klass misslyckas, laddar den klasser från jre/lib/ext-katalogen eller någon annan katalog som java.ext.dirs. Det implementeras av sun.misc.Launcher$ExtClassLoader i JVM.
Systemklassladdare: Den laddar applikationsspecifika klasser från miljövariabeln CLASSPATH. Det kan ställas in när programmet anropas med -cp eller classpath kommandoradsalternativ. Det är ett barn till Extension ClassLoader. Det implementeras av klassen sun.misc.Launcher$AppClassLoader. Alla Java ClassLoader implementerar java.lang.ClassLoader.
Hur ClassLoader fungerar i Java
När JVM begär en klass, anropar den en loadClass()-metod för klassen java.lang.ClassLoader genom att skicka det fullständigt klassificerade namnet på klassen. Metoden loadClass() kräver metoden findLoadedClass() för att kontrollera att klassen redan har laddats eller inte. Det krävs för att undvika att ladda klassen flera gånger.
Om klassen redan är laddad, delegerar den begäran till överordnad ClassLoader att ladda klassen. Om ClassLoader inte hittar klassen anropar den metoden findClass() för att leta efter klasserna i filsystemet. Följande diagram visar hur ClassLoader laddar klass i Java med hjälp av delegering.
Antag att vi har en applikationsspecifik klass Demo.class. Begäran om att ladda dessa klassfiler överförs till Application ClassLoader. Den delegerar till sin överordnade Extension ClassLoader. Vidare delegeras till Bootstrap ClassLoader. Bootstrap sök den klassen i rt.jar och eftersom den klassen inte finns där. Begär nu överföring till Extension ClassLoader som söker efter katalogen jre/lib/ext och försöker hitta denna klass där. Om klassen hittas där, laddar Extension ClassLoader den klassen. Application ClassLoader laddar aldrig den klassen. När tillägget ClassLoader inte laddar det, så laddar Application ClaasLoader det från CLASSPATH i Java.
Synlighetsprincipen säger att den underordnade ClassLoader kan se klassen laddad av den överordnade ClassLoader, men vice versa är inte sant. Det betyder att om Application ClassLoader laddar Demo.class, i ett sådant fall, försök att ladda Demo.class explicit med Extension ClassLoader kastar java.lang.ClassNotFoundException.
Enligt unikhetsprincipen ska en klass som laddas av föräldern inte laddas av Child ClassLoader igen. Så det är möjligt att skriva klassladdare som bryter mot principerna om delegering och unikhet och laddar klass av sig själv.
Kort sagt, klasslastaren följer följande regel:
- Den kontrollerar om klassen redan är laddad.
- Om klassen inte är inläst, be den överordnade klassladdaren att ladda klassen.
- Om den överordnade klassläsaren inte kan ladda klass, försök att ladda den i den här klassladdaren.
Tänk på följande exempel:
public class Demo { public static void main(String args[]) { System.out.println('How are you?'); } }
Kompilera och kör ovanstående kod genom att använda följande kommando:
javac Demo.java java -verbose:class Demo
-verbose:klass: Den används för att visa information om klasser som laddas av JVM. Det är användbart när du använder class loader för att ladda klasser dynamiskt. Följande bild visar utgången.
Vi kan observera att körtidsklasser som krävs av applikationsklassen (Demo) laddas först.
När klasserna är laddade
Det finns bara två fall:
- När den nya bytekoden exekveras.
- När bytekoden gör en statisk referens till en klass. Till exempel, System.ut .
Statisk kontra dynamisk klassladdning
Klasser laddas statiskt med 'ny' operator. Dynamisk klassladdning anropar funktionerna hos en klassladdare vid körning genom att använda metoden Class.forName().
Skillnaden mellan loadClass() och Class.forName()
Metoden loadClass() laddar bara klassen men initierar inte objektet. Medan Class.forName()-metoden initierar objektet efter att det har laddats in. Om du till exempel använder ClassLoader.loadClass() för att ladda JDBC-drivrutinen, tillåter inte class loader att ladda JDBC-drivrutinen.
Metoden java.lang.Class.forName() returnerar klassobjektet kopplat med klassen eller gränssnitt med det givna strängnamnet. Den kastar ClassNotFoundException om klassen inte hittas.
Exempel
I det här exemplet laddas java.lang.String-klassen. Den skriver ut klassnamnet, paketnamnet och namnen på alla tillgängliga metoder för String-klassen. Vi använder Class.forName() i följande exempel.
Klass: Representerar ett klassobjekt som kan vara av vilken typ som helst (? är ett jokertecken). Klasstypen innehåller metainformation om en klass. Till exempel är typen av String.class Class. Använd Klass om klassen som modelleras är okänd.
getDeclaredMethod(): Returnerar en array som innehåller metodobjekt som återspeglar alla deklarerade metoder för klassen eller gränssnittet som representeras av detta klassobjekt, inklusive offentliga, skyddade, standard (paket)åtkomst och privata metoder, men exklusive ärvda metoder.
hämta namn(): Den returnerar metodnamnet som representeras av detta metodobjekt, som en sträng.
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