logo

ClassLoader in Java

Java ClassLoader

Java ClassLoader is een abstracte klasse. Het behoort tot een java.lang pakket. Het laadt klassen uit verschillende bronnen. Java ClassLoader wordt gebruikt om de klassen tijdens runtime te laden. Met andere woorden: JVM voert het koppelingsproces tijdens runtime uit. Klassen worden naar behoefte in de JVM geladen. Als een geladen klasse afhankelijk is van een andere klasse, wordt die klasse ook geladen. Wanneer we vragen om een ​​klasse te laden, delegeert deze de klasse aan de ouder. Op deze manier blijft de uniciteit in de runtime-omgeving behouden. Het is essentieel om een ​​Java-programma uit te voeren.

naar string-methode java
ClassLoader in Java

Java ClassLoader is gebaseerd op drie principes: Delegatie , Zichtbaarheid , En Uniciteit .

    Principe van delegatie:Het stuurt het verzoek om klassen te laden door naar de bovenliggende klassenlader. Het laadt de klasse alleen als de ouder de klasse niet vindt of laadt.Zichtbaarheidsprincipe:Hiermee kan de onderliggende klassenlader alle klassen zien die door de bovenliggende ClassLoader zijn geladen. Maar de bovenliggende klassenlader kan de klassen niet zien die zijn geladen door de onderliggende klassenlader.Uniciteitsprincipe:Hiermee kunt u een klasse één keer laden. Dit wordt bereikt door het delegatieprincipe. Het zorgt ervoor dat de onderliggende ClassLoader de klasse, die al door de ouder is geladen, niet opnieuw laadt.

Soorten ClassLoader

In Java heeft elke ClassLoader een vooraf gedefinieerde locatie van waaruit klassebestanden worden geladen. Er zijn de volgende typen ClassLoader in Java:

Bootstrap-klasselader: Het laadt standaard JDK-klassebestanden van rt.jar en andere kernklassen. Het is een ouder van alle klassenladers. Het heeft geen ouder. Wanneer we String.class.getClassLoader() aanroepen, retourneert het null, en elke code die daarop is gebaseerd, genereert NullPointerException. Het wordt ook Primordial ClassLoader genoemd. Het laadt klassebestanden van jre/lib/rt.jar. Bijvoorbeeld de pakketklasse java.lang.

Uitbreidingen Class Loader: Het delegeert het klassenlaadverzoek aan zijn ouder. Als het laden van een klasse niet lukt, worden de klassen uit de map jre/lib/ext of uit een andere map geladen als java.ext.dirs. Het wordt geïmplementeerd door sun.misc.Launcher$ExtClassLoader in JVM.

Systeemklasselader: Het laadt toepassingsspecifieke klassen vanuit de omgevingsvariabele CLASSPATH. Het kan worden ingesteld tijdens het oproepen van het programma met behulp van de opdrachtregelopties -cp of classpath. Het is een onderliggend onderdeel van Extension ClassLoader. Het wordt geïmplementeerd door de klasse sun.misc.Launcher$AppClassLoader. Alle Java ClassLoader implementeert java.lang.ClassLoader.

ClassLoader in Java

Hoe ClassLoader werkt in Java

Wanneer JVM om een ​​klasse verzoekt, roept het een loadClass()-methode van de klasse java.lang.ClassLoader aan door de volledig geclassificeerde naam van de klasse door te geven. De methode loadClass() roept de methode findLoadedClass() op om te controleren of de klasse al is geladen of niet. Het is vereist om te voorkomen dat de klasse meerdere keren wordt geladen.

Als de klasse al is geladen, delegeert deze het verzoek aan de bovenliggende ClassLoader om de klasse te laden. Als de ClassLoader de klasse niet kan vinden, wordt de methode findClass() aangeroepen om naar de klassen in het bestandssysteem te zoeken. Het volgende diagram laat zien hoe ClassLoader klasse in Java laadt met behulp van delegatie.

ClassLoader in Java

Stel dat we een applicatiespecifieke klasse Demo.class hebben. Het verzoek voor het laden van deze klassebestanden wordt overgebracht naar Application ClassLoader. Het delegeert naar de bovenliggende extensie ClassLoader. Verder delegeert het naar Bootstrap ClassLoader. Bootstrap zoekt naar die klasse in rt.jar en aangezien die klasse er niet is. Vraag nu om overdracht naar Extension ClassLoader, die zoekt naar de directory jre/lib/ext en probeert deze klasse daar te lokaliseren. Als de klasse daar wordt gevonden, laadt Extension ClassLoader die klasse. Application ClassLoader laadt die klasse nooit. Wanneer de extensie ClassLoader deze niet laadt, laadt Application ClaasLoader deze vanuit CLASSPATH in Java.

Het zichtbaarheidsprincipe stelt dat de onderliggende ClassLoader de klasse kan zien die door de bovenliggende ClassLoader is geladen, maar omgekeerd is dit niet waar. Dit betekent dat als Application ClassLoader Demo.class laadt, in een dergelijk geval Demo.class expliciet wordt geladen met behulp van Extension ClassLoader, er java.lang.ClassNotFoundException wordt gegenereerd.

Volgens het uniciteitsprincipe mag een klasse die door de ouder is geladen, niet opnieuw door Child ClassLoader worden geladen. Het is dus mogelijk om een ​​klassenlader te schrijven die de principes van delegatie en uniciteit schendt en de klasse zelf laadt.

Kort gezegd volgt de klassenlader de volgende regel:

  • Er wordt gecontroleerd of de klasse al is geladen.
  • Als de klasse niet is geladen, vraagt ​​u de ouderklasselader om de klasse te laden.
  • Als de bovenliggende klassenlader de klasse niet kan laden, probeer deze dan in deze klassenlader te laden.

Beschouw het volgende voorbeeld:

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

Compileer en voer de bovenstaande code uit met behulp van de volgende opdracht:

 javac Demo.java java -verbose:class Demo 

-uitgebreid:klasse: Het wordt gebruikt om informatie weer te geven over klassen die door JVM worden geladen. Het is handig bij het gebruik van de klassenlader om klassen dynamisch te laden. De volgende afbeelding toont de uitvoer.

ClassLoader in Java

We kunnen zien dat de runtimeklassen die vereist zijn voor de applicatieklasse (Demo) eerst worden geladen.

Wanneer klassen zijn geladen

Er zijn slechts twee gevallen:

  • Wanneer de nieuwe bytecode wordt uitgevoerd.
  • Wanneer de bytecode een statische verwijzing naar een klasse maakt. Bijvoorbeeld, Systeemuit .

Statische versus dynamische klassenbelasting

Klassen worden statisch geladen met de 'nieuwe' operator. Dynamisch laden van klassen roept tijdens runtime de functies van een klassenlader aan met behulp van de methode Class.forName().

Verschil tussen loadClass() en Class.forName()

De methode loadClass() laadt alleen de klasse, maar initialiseert het object niet. Terwijl de methode Class.forName() het object initialiseert nadat het is geladen. Als u bijvoorbeeld ClassLoader.loadClass() gebruikt om het JDBC-stuurprogramma te laden, staat de klassenlader niet toe dat het JDBC-stuurprogramma wordt geladen.

De methode java.lang.Class.forName() retourneert het Class-object gekoppeld aan de klasse of interfaces met de opgegeven tekenreeksnaam. Er wordt ClassNotFoundException gegenereerd als de klasse niet wordt gevonden.

Voorbeeld

In dit voorbeeld wordt de klasse java.lang.String geladen. Het drukt de klassenaam, de pakketnaam en de namen van alle beschikbare methoden van de String-klasse af. In het volgende voorbeeld gebruiken we Class.forName().

Klas: Vertegenwoordigt een Class-object dat van elk type kan zijn (? is een jokerteken). Het Class-type bevat meta-informatie over een klasse. Het type String.class is bijvoorbeeld Klasse. Gebruik Class als de klasse die wordt gemodelleerd onbekend is.

getDeclaredMethode(): Retourneert een array met Method-objecten die alle gedeclareerde methoden weerspiegelen van de klasse of interface die door dit Class-object wordt vertegenwoordigd, inclusief openbare, beschermde, standaardtoegang (pakket) en privémethoden, maar exclusief overgenomen methoden.

getName(): Het retourneert de methodenaam die door dit Method-object wordt vertegenwoordigd, als een 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(); } } } 

Uitvoer

 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