獲得ClassLoader的途徑
1. 獲得當(dāng)前類的ClassLoader
clazz.getClassLoader()
2. 獲得當(dāng)前線程上下文的ClassLoader
Thread.currentThread().getContextClassLoader();
3. 獲得系統(tǒng)的ClassLoader
ClassLoader.getSystemClassLoader()
4. 獲得調(diào)用者的ClassLoader
DriverManager.getCallerClassLoader
ClassLoader源碼解析
(推薦學(xué)習(xí):Java視頻教程)
概述
類加載器是用于加載類的對(duì)象,ClassLoader是一個(gè)抽象類。如果我們給定了一個(gè)類的二進(jìn)制名稱,類加載器應(yīng)嘗試去定位或生成構(gòu)成定義類的數(shù)據(jù)。一種典型的策略是將給定的二進(jìn)制名稱轉(zhuǎn)換為文件名,然后去文件系統(tǒng)中讀取這個(gè)文件名所對(duì)應(yīng)的class文件。
每個(gè)Class對(duì)象都會(huì)包含一個(gè)定義它的ClassLoader的一個(gè)引用。
數(shù)組類的Class對(duì)象,不是由類加載器去創(chuàng)建的,而是在Java運(yùn)行期JVM根據(jù)需要自動(dòng)創(chuàng)建的。對(duì)于數(shù)組類的類加載器來(lái)說(shuō),是通過(guò)Class.getClassLoader()返回的,與數(shù)組當(dāng)中元素類型的類加載器是一樣的;如果數(shù)組當(dāng)中的元素類型是一個(gè)原生類型,數(shù)組類是沒(méi)有類加載器的【代碼一】。
應(yīng)用實(shí)現(xiàn)了ClassLoader的子類是為了擴(kuò)展JVM動(dòng)態(tài)加載類的方式。
類加載器典型情況下時(shí)可以被安全管理器所使用去標(biāo)識(shí)安全域問(wèn)題。
ClassLoader類使用了委托模型來(lái)尋找類和資源,ClassLoader的每一個(gè)實(shí)例都會(huì)有一個(gè)與之關(guān)聯(lián)的父ClassLoader,當(dāng)ClassLoader被要求尋找一個(gè)類或者資源的時(shí)候,ClassLoader實(shí)例在自身嘗試尋找類或者資源之前會(huì)委托它的父類加載器去完成。虛擬機(jī)內(nèi)建的類加載器,稱之為啟動(dòng)類加載器,是沒(méi)有父加載器的,但是可以作為一個(gè)類加載器的父類加載器【雙親委托機(jī)制】。
支持并發(fā)類加載的類加載器叫做并行類加載器,要求在初始化期間通過(guò)ClassLoader.registerAsParallelCapable 方法注冊(cè)自身,ClassLoader類默認(rèn)被注冊(cè)為可以并行,但是如果它的子類也是并行加載的話需要單獨(dú)去注冊(cè)子類。
在委托模型不是嚴(yán)格的層次化的環(huán)境下,類加載器需要并行,否則類加載會(huì)導(dǎo)致死鎖,因?yàn)榧虞d器的鎖在類加載過(guò)程中是一直被持有的。
通常情況下,Java虛擬機(jī)以平臺(tái)相關(guān)的形式從本地的文件系統(tǒng)中加載類,比如在UNIX系統(tǒng),虛擬機(jī)從CLASSPATH環(huán)境所定義的目錄加載類。
然而,有些類并不是來(lái)自于文件;它們是從其它來(lái)源得到的,比如網(wǎng)絡(luò),或者是由應(yīng)用本身構(gòu)建【動(dòng)態(tài)代理】。定義類(defineClass )方法會(huì)將字節(jié)數(shù)組轉(zhuǎn)換為Class的實(shí)例,這個(gè)新定義類的實(shí)例可以由Class.newInstance創(chuàng)建。由類加載器創(chuàng)建的對(duì)象的方法和構(gòu)造方法可能引用其它的類,為了確定被引用的類,Java虛擬機(jī)會(huì)調(diào)用最初創(chuàng)建類的類加載器的loadClass方法。
二進(jìn)制名稱:以字符串參數(shù)的形式向CalssLoader提供的任意一個(gè)類名,必須是一個(gè)二進(jìn)制的名稱,包含以下四種情況
- "java.lang.String" 正常類
- "javax.swing.JSpinner$DefaultEditor" 內(nèi)部類
- "java.security.KeyStore\(Builder\)FileBuilder$1" KeyStore的內(nèi)部類Builder的內(nèi)部類FileBuilder的第一個(gè)匿名內(nèi)部類
- "java.net.URLClassLoader$3$1" URLClassLoader類的第三個(gè)匿名內(nèi)部類的第一個(gè)匿名內(nèi)部類
代碼一:
public class Test12 { public static void main(String[] args) { String[] strings = new String[6]; System.out.println(strings.getClass().getClassLoader()); // 運(yùn)行結(jié)果:null Test12[] test12s = new Test12[1]; System.out.println(test12s.getClass().getClassLoader()); // 運(yùn)行結(jié)果:sun.misc.Launcher$AppClassLoader@18b4aac2 int[] ints = new int[2]; System.out.println(ints.getClass().getClassLoader()); // 運(yùn)行結(jié)果:null } }
loadClass方法
loadClass的源碼如下, loadClass方法加載擁有指定的二進(jìn)制名稱的Class,默認(rèn)按照如下順序?qū)ふ翌悾?/p>
a)調(diào)用findLoadedClass(String)檢查這個(gè)類是否被加載
b)調(diào)用父類加載器的loadClass方法,如果父類加載器為null,就會(huì)調(diào)用啟動(dòng)類加載器
c)調(diào)用findClass(String)方法尋找
使用上述步驟如果類被找到且resolve為true,就會(huì)去調(diào)用resolveClass(Class)方法
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
findClass方法
findClass的源碼如下,findClass尋找擁有指定二進(jìn)制名稱的類,JVM鼓勵(lì)我們重寫(xiě)此方法,需要自定義加載器遵循雙親委托機(jī)制,該方法會(huì)在檢查完父類加載器之后被loadClass方法調(diào)用,默認(rèn)返回ClassNotFoundException異常。
protected Class<?> findClass(String name) throws ClassNotFoundException { throw new ClassNotFoundException(name); }
defineClass方法
defineClass的源碼如下,defineClass方法將一個(gè)字節(jié)數(shù)組轉(zhuǎn)換為Class的實(shí)例。
protected final Class<?> defineClass(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain) throws ClassFormatError { protectionDomain = preDefineClass(name, protectionDomain); String source = defineClassSourceLocation(protectionDomain); Class<?> c = defineClass1(name, b, off, len, protectionDomain, source); postDefineClass(c, protectionDomain); return c; }
自定義類加載器
/** * 繼承了ClassLoader,這是一個(gè)自定義的類加載器 * @author 夜的那種黑丶 */ public class ClassLoaderTest extends ClassLoader { public static void main(String[] args) throws Exception { ClassLoaderTest loader = new ClassLoaderTest("loader"); Class<?> clazz = loader.loadClass("classloader.Test01"); Object object = clazz.newInstance(); System.out.println(object); System.out.println(object.getClass().getClassLoader()); } //------------------------------以上為測(cè)試代碼--------------------------------- /** * 類加載器名稱,標(biāo)識(shí)作用 */ private String classLoaderName; /** * 從磁盤(pán)讀物字節(jié)碼文件的擴(kuò)展名 */ private String fileExtension = ".class"; /** * 創(chuàng)建一個(gè)類加載器對(duì)象,將系統(tǒng)類加載器當(dāng)做該類加載器的父加載器 * @param classLoaderName 類加載器名稱 */ private ClassLoaderTest(String classLoaderName) { // 將系統(tǒng)類加載器當(dāng)做該類加載器的父加載器 super(); this.classLoaderName = classLoaderName; } /** * 創(chuàng)建一個(gè)類加載器對(duì)象,顯示指定該類加載器的父加載器 * 前提是需要有一個(gè)類加載器作為父加載器 * @param parent 父加載器 * @param classLoaderName 類加載器名稱 */ private ClassLoaderTest(ClassLoader parent, String classLoaderName) { // 顯示指定該類加載器的父加載器 super(parent); this.classLoaderName = classLoaderName; } /** * 尋找擁有指定二進(jìn)制名稱的類,重寫(xiě)ClassLoader類的同名方法,需要自定義加載器遵循雙親委托機(jī)制 * 該方法會(huì)在檢查完父類加載器之后被loadClass方法調(diào)用 * 默認(rèn)返回ClassNotFoundException異常 * @param className 類名 * @return Class的實(shí)例 * @throws ClassNotFoundException 如果類不能被找到,拋出此異常 */ @Override protected Class<?> findClass(String className) throws ClassNotFoundException { byte[] data = this.loadClassData(className); /* * 通過(guò)defineClass方法將字節(jié)數(shù)組轉(zhuǎn)換為Class * defineClass:將一個(gè)字節(jié)數(shù)組轉(zhuǎn)換為Class的實(shí)例,在使用這個(gè)Class之前必須要被解析 */ return this.defineClass(className, data, 0 , data.length); } /** * io操作,根據(jù)類名找到對(duì)應(yīng)文件,返回class文件的二進(jìn)制信息 * @param className 類名 * @return class文件的二進(jìn)制信息 * @throws ClassNotFoundException 如果類不能被找到,拋出此異常 */ private byte[] loadClassData(String className) throws ClassNotFoundException { InputStream inputStream = null; byte[] data; ByteArrayOutputStream byteArrayOutputStream = null; try { this.classLoaderName = this.classLoaderName.replace(".", "/"); inputStream = new FileInputStream(new File(className + this.fileExtension)); byteArrayOutputStream = new ByteArrayOutputStream(); int ch; while (-1 != (ch = inputStream.read())) { byteArrayOutputStream.write(ch); } data = byteArrayOutputStream.toByteArray(); } catch (Exception e) { throw new ClassNotFoundException(); } finally { try { if (inputStream != null) { inputStream.close(); } if (byteArrayOutputStream != null) { byteArrayOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } return data; } }
以上是一段自定義類加載器的代碼,我們執(zhí)行這段代碼
classloader.Test01@7f31245a sun.misc.Launcher$AppClassLoader@18b4aac2
可以看見(jiàn),這段代碼中進(jìn)行類加載的類加載器還是系統(tǒng)類加載器(AppClassLoader)。這是因?yàn)閖vm的雙親委托機(jī)制造成的,private ClassLoaderTest(String classLoaderName)
將系統(tǒng)類加載器當(dāng)做我們自定義類加載器的父加載器,jvm的雙親委托機(jī)制使自定義類加載器委托系統(tǒng)類加載器完成加載。
改造以下代碼,添加一個(gè)path屬性用來(lái)指定類加載位置:
public class ClassLoaderTest extends ClassLoader { public static void main(String[] args) throws Exception { ClassLoaderTest loader = new ClassLoaderTest("loader"); loader.setPath("/home/fanxuan/Study/java/jvmStudy/out/production/jvmStudy/"); Class<?> clazz = loader.loadClass("classloader.Test01"); System.out.println("class:" + clazz); Object object = clazz.newInstance(); System.out.println(object); System.out.println(object.getClass().getClassLoader()); } //------------------------------以上為測(cè)試代碼--------------------------------- /** * 從指定路徑加載 */ private String path; ...... /** * io操作,根據(jù)類名找到對(duì)應(yīng)文件,返回class文件的二進(jìn)制信息 * @param className 類名 * @return class文件的二進(jìn)制信息 * @throws ClassNotFoundException 如果類不能被找到,拋出此異常 */ private byte[] loadClassData(String className) throws ClassNotFoundException { InputStream inputStream = null; byte[] data; ByteArrayOutputStream byteArrayOutputStream = null; className = className.replace(".", "/"); try { this.classLoaderName = this.classLoaderName.replace(".", "/"); inputStream = new FileInputStream(new File(this.path + className + this.fileExtension)); byteArrayOutputStream = new ByteArrayOutputStream(); int ch; while (-1 != (ch = inputStream.read())) { byteArrayOutputStream.write(ch); } data = byteArrayOutputStream.toByteArray(); } catch (Exception e) { throw new ClassNotFoundException(); } finally { try { if (inputStream != null) { inputStream.close(); } if (byteArrayOutputStream != null) { byteArrayOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } return data; } public void setPath(String path) { this.path = path; } }
運(yùn)行一下
class:class classloader.Test01 classloader.Test01@7f31245a sun.misc.Launcher$AppClassLoader@18b4aac2
修改一下測(cè)試代碼,并刪除工程下的Test01.class文件
public static void main(String[] args) throws Exception { ClassLoaderTest loader = new ClassLoaderTest("loader"); loader.setPath("/home/fanxuan/桌面/"); Class<?> clazz = loader.loadClass("classloader.Test01"); System.out.println("class:" + clazz); Object object = clazz.newInstance(); System.out.println(object); System.out.println(object.getClass().getClassLoader()); }
運(yùn)行一下
class:class classloader.Test01 classloader.Test01@135fbaa4 classloader.ClassLoaderTest@7f31245a
分析
改造后的兩塊代碼,第一塊代碼中加載類的是系統(tǒng)類加載器AppClassLoader,第二塊代碼中加載類的是自定義類加載器ClassLoaderTest。是因?yàn)镃lassLoaderTest會(huì)委托他的父加載器AppClassLoader加載class,第一塊代碼的path直接是工程下,AppClassLoader可以加載到,而第二塊代碼的path在桌面目錄下,所以AppClassLoader無(wú)法加載到,然后ClassLoaderTest自身嘗試加載并成功加載到。如果第二塊代碼工程目錄下的Test01.class文件沒(méi)有被刪除,那么依然是AppClassLoader加載。
再來(lái)測(cè)試一塊代碼
public static void main(String[] args) throws Exception { ClassLoaderTest loader = new ClassLoaderTest("loader"); loader.setPath("/home/fanxuan/Study/java/jvmStudy/out/production/jvmStudy/"); Class<?> clazz = loader.loadClass("classloader.Test01"); System.out.println("class:" + clazz.hashCode()); Object object = clazz.newInstance(); System.out.println(object.getClass().getClassLoader()); ClassLoaderTest loader2 = new ClassLoaderTest("loader"); loader2.setPath("/home/fanxuan/Study/java/jvmStudy/out/production/jvmStudy/"); Class<?> clazz2 = loader2.loadClass("classloader.Test01"); System.out.println("class:" + clazz2.hashCode()); Object object2 = clazz2.newInstance(); System.out.println(object2.getClass().getClassLoader()); }
結(jié)果顯而易見(jiàn),類由系統(tǒng)類加載器加載,并且clazz和clazz2是相同的。
class:2133927002 sun.misc.Launcher$AppClassLoader@18b4aac2 class:2133927002 sun.misc.Launcher$AppClassLoader@18b4aac2
再改造一下
public static void main(String[] args) throws Exception { ClassLoaderTest loader = new ClassLoaderTest("loader"); loader.setPath("/home/fanxuan/桌面/"); Class<?> clazz = loader.loadClass("classloader.Test01"); System.out.println("class:" + clazz.hashCode()); Object object = clazz.newInstance(); System.out.println(object.getClass().getClassLoader()); ClassLoaderTest loader2 = new ClassLoaderTest("loader2"); loader2.setPath("/home/fanxuan/桌面/"); Class<?> clazz2 = loader2.loadClass("classloader.Test01"); System.out.println("class:" + clazz2.hashCode()); Object object2 = clazz2.newInstance(); System.out.println(object2.getClass().getClassLoader()); }
運(yùn)行結(jié)果
class:325040804 classloader.ClassLoaderTest@7f31245a class:621009875 classloader.ClassLoaderTest@45ee12a7
ClassLoaderTest是顯而易見(jiàn),但是clazz和clazz2是不同的,這是因?yàn)轭惣虞d器的命名空間的原因。
我們可以通過(guò)設(shè)置父類加載器來(lái)讓loader和loader2處于同一命名空間
public static void main(String[] args) throws Exception { ClassLoaderTest loader = new ClassLoaderTest("loader"); loader.setPath("/home/fanxuan/桌面/"); Class<?> clazz = loader.loadClass("classloader.Test01"); System.out.println("class:" + clazz.hashCode()); Object object = clazz.newInstance(); System.out.println(object.getClass().getClassLoader()); ClassLoaderTest loader2 = new ClassLoaderTest(loader, "loader2"); loader2.setPath("/home/fanxuan/桌面/"); Class<?> clazz2 = loader2.loadClass("classloader.Test01"); System.out.println("class:" + clazz2.hashCode()); Object object2 = clazz2.newInstance(); System.out.println(object2.getClass().getClassLoader()); }
運(yùn)行結(jié)果
class:325040804 classloader.ClassLoaderTest@7f31245a class:325040804 classloader.ClassLoaderTest@7f31245a
擴(kuò)展:命名空間
1. 每個(gè)類加載器都有自己的命名空間,命名空間由該加載器及所有的父加載器所加載的類組成
2. 在同一命名空間中,不會(huì)出現(xiàn)類的完整名字(包括類的包名)相同的兩個(gè)類
3. 在不同的命名空間中,有可能會(huì)出現(xiàn)類的完整名字(包括類的包名)相同的兩個(gè)類
php中文網(wǎng),大量的免費(fèi)Java入門(mén)教程,歡迎在線學(xué)習(xí)!??
Atas ialah kandungan terperinci java類加載器ClassLoader詳解. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undress AI Tool
Gambar buka pakaian secara percuma

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Cara menyelesaikan konflik pemuat kelas dalam pembangunan Java Pengenalan: Dalam pembangunan Java, konflik pemuat kelas adalah masalah biasa. Apabila pemuat kelas yang berbeza digunakan untuk memuatkan kelas atau fail sumber yang sama, konflik akan berlaku, menyebabkan program gagal berjalan dengan betul. Artikel ini menerangkan maksud konflik pemuat kelas dan cara menyelesaikannya. 1. Apakah konflik pemuat kelas? Mekanisme pemuatan kelas di Java menggunakan model delegasi induk Setiap pemuat kelas mempunyai pemuat kelas induk, dan pemuat kelas induk terakhir ialah pemuat kelas permulaan. apabila diperlukan

Semasa pembangunan di Java, kami sering menghadapi ralat ClassLoader, yang disebabkan oleh pemuat kelas tidak mencari atau memuatkan kelas yang betul. Ralat seperti ini akan menyebabkan program gagal dilaksanakan seperti biasa dan membawa kesulitan kepada pembangunan. Oleh itu, kita perlu memahami punca ralat ClassLoader dan penyelesaiannya untuk mengoptimumkan program Java kami dengan lebih baik. 1. Punca ralat ClassLoader: Kelas dimuatkan melalui ClassLoader dalam Java, ClassLoad

Latar Belakang Baru-baru ini, kod perniagaan utama telah disulitkan untuk rangka kerja syarikat untuk mengelakkan kod kejuruteraan daripada mudah dipulihkan melalui alat penyahkompilasi seperti jd-gui Konfigurasi dan penggunaan skim pengeliruan yang berkaitan adalah agak rumit dan terdapat banyak masalah untuk projek springboot, jadi fail kelas disulitkan dan kemudiannya Peloder kelas tersuai dinyahsulit dan dimuatkan Penyelesaian ini tidak benar-benar selamat Ia hanya meningkatkan kesukaran penyahkompilasian Ia menghalang lelaki tetapi bukan penjahat dalam rajah di bawah. Pemalam maven menyulitkan kompilasi menggunakan pemalam maven tersuai Fail kelas yang ditentukan disulitkan, dan fail kelas yang disulitkan disalin ke laluan yang ditentukan.

Prinsip dan kaedah pemuatan kelas menggunakan fungsi ClassLoader dalam Java sentiasa menjadi salah satu fokus pembangun Java. Fungsi ClassLoader ialah sebahagian daripada pustaka kelas Java Fungsi utamanya ialah memuatkan fail kelas Java ke dalam Mesin Maya Java (JVM) supaya atur cara boleh berjalan dengan normal. Fungsi ClassLoader ialah teras pemuatan kelas Java Dalam persekitaran masa jalan Java, ia bertanggungjawab untuk mencari dan memuatkan kod bait kelas Java, jadi fahami dan kuasainya.

Gambaran keseluruhan pemuatan automatik PHP Pemuatan automatik PHP bermakna apabila menggunakan kelas, PHP akan memuatkan fail definisi kelas secara automatik. Ini biasanya dicapai melalui pemuat kelas. Pemuat kelas ialah program yang bertanggungjawab untuk memuatkan fail definisi kelas Ia boleh terbina dalam atau disesuaikan. Jenis pemuat kelas Terdapat dua jenis pemuat kelas terbina dalam PHP: Pemuat kelas Zend: Ini ialah pemuat kelas lalai PHP, yang memuatkan fail definisi kelas yang terletak dalam perpustakaan terbina dalam PHP. Pemuat kelas PSR-4: PSR-4 ialah standard pemuatan automatik yang mentakrifkan satu set peraturan untuk memuatkan fail definisi kelas. Pemuat kelas PSR-4 memuatkan fail definisi kelas mengikut piawaian PSR-4. Selain itu, pemuat kelas boleh disesuaikan. Pemuat kelas tersuai boleh disesuaikan mengikut mereka sendiri

Peranan pemuat kelas: Memuatkan: Baca fail kelas daripada sumber yang ditentukan. Pengesahan: Sahkan bahawa fail kelas mematuhi spesifikasi. Penyediaan: memperuntukkan memori dan memulakan pembolehubah statik. Menghuraikan: Menghuraikan rujukan simbol. Permulaan: Kaedah panggilan, laksanakan blok permulaan statik dan peruntukkan objek kelas.

Autoloading ialah teknik yang memuatkan kelas PHP secara automatik tanpa perlu memasukkan setiap fail secara manual. Ia memudahkan pembangunan dan penyelenggaraan aplikasi, meningkatkan prestasi dan kebolehselenggaraan. Artikel ini akan meneroka teknologi pemuatan automatik yang biasa digunakan dalam PHP. SPLAutoloaderSPL (Perpustakaan PHP Standard) mengandungi mekanisme pemuatan auto terbina dalam yang dipanggil fungsi spl_autoload_reGISter(). Fungsi ini membolehkan anda mendaftarkan fungsi pemuat yang akan dipanggil apabila percubaan dibuat untuk memuatkan kelas yang tidak wujud. Contoh berikut menunjukkan cara menggunakan SPLAutoloader: spl_autoload_register(function($class){

Fungsi ClassLoader dalam Java boleh memuatkan kelas secara dinamik pada masa jalan, yang sangat berguna dalam beberapa aplikasi yang memerlukan penggunaan fleksibel dan pengubahsuaian kod. Melalui fungsi ClassLoader, mekanisme pemalam boleh dilaksanakan untuk meningkatkan kebolehskalaan dan fleksibiliti sistem. Artikel ini akan memperkenalkan cara menggunakan fungsi ClassLoader untuk pemuatan kelas dinamik. 1. Peranan ClassLoader Apabila memulakan Java Virtual Machine (JVM), tiga ClassLoader akan dicipta:
