หากคุณต้องการใช้ตัวโหลดคลาสที่กำหนดเองเพื่อโหลดไฟล์คลาสคุณต้องสืบทอดคลาส java.lang.classloader
มีวิธีการสำคัญหลายประการสำหรับ ClassLoader:
ProtectedClassLoader (classloaderParent): สร้างตัวโหลดคลาสใหม่โดยใช้ตัวโหลดคลาสแม่ที่ระบุสำหรับการดำเนินการมอบหมาย
ProtectedFinalClass <?> defineclass (StringName, byte [] b, intoff, intlen): แปลงอาร์เรย์ของไบต์เป็นอินสแตนซ์ของคลาสคลาส
ProtectedClass <?> findClass (StringName): ค้นหาคลาสที่มีชื่อไบนารีที่ระบุ
PublicClass <?> loadclass (StringName): โหลดคลาสด้วยชื่อไบนารีที่ระบุ
ProtectedFinalClass <?> findLoadEdClass (StringName): หากเครื่องเสมือน Java ได้บันทึกโหลดเดอร์นี้เป็นตัวโหลดเริ่มต้นของคลาสที่มีชื่อไบนารีที่กำหนดคลาสที่มีชื่อไบนารีนั้นจะถูกส่งกลับ มิฉะนั้นให้ส่งคืนโมฆะ
PublicFinalClassLoaderGetParent (): ส่งคืนรถโหลดคลาสแม่ที่ได้รับมอบหมาย
ProtectedFinalVoidResolVeclass (คลาส <?> c): ลิงก์ไปยังคลาสที่ระบุ
หากคุณต้องการทำตามรูปแบบการมอบหมายหลักแล้วให้เขียนวิธี FindClass (StringName) ใหม่ หากคุณไม่ต้องการทำตามรูปแบบการมอบหมายหลักแล้วให้เขียนวิธี loadclass (stringname) ใหม่โดยตรง
ปรับแต่งรถตักคลาสที่เป็นไปตามรูปแบบการมอบหมายหลัก
ParentDelegateclassloader.java
แพ็คเกจ com.zzj.classloader; นำเข้า java.io.ByTeArrayOutputStream; นำเข้า java.io.file; นำเข้า java.io.fileinputstream; นำเข้า java.io.ioException; นำเข้า Java.io.InputStream;/** ** ** ผู้ปกครอง ParenterDelegateclassloader ขยาย classloader {สตริงสุดท้ายคงที่ส่วนตัว ext = ".class"; เส้นทางสตริงส่วนตัว; ผู้ปกครองสาธารณะ delegateclassloader () {path = this.getResource ("") getPath ()} publicDelegateclassloader classnotFoundException {byte [] b = null; ลอง {b = loadclassFile (ชื่อ);} catch (ioexception e) {e.printstacktrace ();} ส่งคืนสิ่งนี้ defineclass (ชื่อ, b, 0, b.length); getClassFile (ชื่อ); system.out.println ("ไฟล์คลาสจะโหลดเร็ว ๆ นี้" + classfile); bytearrayoutputStream out = byteArrayOutputStream (); inputStream อินพุต = new FileInputStream (classFile); int count; {out.write (temp, 0, count);} out.close (); input.close (); return out.tobytearray ();} สตริงส่วนตัว getClassFile (ชื่อสตริง) {สตริง pathname = name.replace ("." ext;} return path + file.Sparator + pathName + ext;}}ตอนนี้มีไฟล์คลาส com/zzj/classloader/user.class ภายใต้ classpath classpath และ f: // classloaderTest // ไดเร็กทอรี bin ชื่อแพ็คเกจคือ com.zzj.classloader ใช้คลาส Loader ParenterDelegateclassloader เพื่อโหลดคลาสภายใต้ F: // classloaderTest // bin
แพ็คเกจ com.zzj.classloader; แอพคลาสสาธารณะ {Private Static Final String Path = "F: // classloaderTest // bin"; สตริงสุดท้ายคงที่ private String classname = "com.zzj.classloader.user"; void main (สตริง [] args) classloader.loadclass (classname); system.out.println (clazz); system.out.println (clazz.getclassloader ());}}เอาท์พุท:
คลาส com.zzj.classloader.user sun.misc.launcher$appclassloader@19821f
ตัวโหลดของคลาสผู้ใช้คือคลาส System Loader AppClassLoader ไม่ใช่ตัวโหลดคลาสที่เรากำหนดเอง ในความเป็นจริงมันไม่ใช่คลาสภายใต้ f: // classloaderTest // bin แต่คลาสภายใต้ classpath นี่คือรูปแบบการมอบหมายหลัก: เมื่อ ParenterDelegateclassLoader Loader ได้รับการร้องขอการโหลดจะได้รับมอบหมายก่อนไปยังตัวโหลดคลาสแม่ หากตัวโหลดคลาสแม่สำเร็จโหลดวัตถุคลาสจะถูกส่งคืน หากโหลดล้มเหลวตัวโหลดคลาสที่ได้รับคำขอโหลดจะถูกโหลด
ลบคลาสผู้ใช้ภายใต้ ClassPath เพื่อทดสอบการทำงาน:
ไฟล์คลาสจะถูกโหลดเร็ว f:/classloaderTest/bin/com/zzj/classloader/user.class คลาส com.zzj.classloader.user com.zzj.classloader.parentsdelegateclassload@61de3333333333333333333333333333333333333333333333
ในเวลานี้คลาสผู้ใช้โหลดเป็น ParentsDelegateclassLoader
สามารถตรวจสอบได้จากซอร์สโค้ดของ classloader:
คลาสสาธารณะ <?> loadclass (ชื่อสตริง) พ่น classnotfoundexception {return loadclass (ชื่อ, false); -วิธีการโอเวอร์โหลดถูกเรียกว่า:
คลาสซิงโครไนซ์ที่ได้รับการป้องกัน <?> loadclass (ชื่อสตริง, การแก้ไขบูลีน) พ่น classnotfoundexception {// ก่อนกำหนดว่าคลาสได้รับการโหลดโดยคลาสโหลดเดอร์คลาสปัจจุบัน c = findloadedClass (ชื่อ); if (c == null) {ลอง {if (parent! = null) {// ถ้าตัวโหลดคลาสพาเรนต์มีอยู่แล้วมอบหมายให้คลาสพาเรนต์เพื่อโหลด c = parent.loadclass (ชื่อเท็จ); } else {// ถ้าคลาสพาเรนต์โหลดว่างเปล่าคลาสพาเรนต์ของมันคือตัวโหลดคลาสบูต c = findBootStrapClass0 (ชื่อ); }} catch (classnotFoundException e) {// ถ้าตัวโหลดคลาสแม่ไม่สามารถโหลดได้มันจะโหลดตัวเองและเรียกวิธี FindClass! c = findclass (ชื่อ); }} ถ้า (แก้ไข) {ResolveClass (c); } return c; -จะเห็นได้ว่าหากคุณต้องการทำลายโมเดลการมอบหมายหลักคุณสามารถเขียนวิธี loadclass (stringname) ได้โดยตรง
ปรับแต่งรถตักคลาสที่ไม่เป็นไปตามรูปแบบการมอบหมายหลัก
notparentsdelegateclassloader.java
แพ็คเกจ com.zzj.classloader; นำเข้า java.io.ByTeArrayOutputStream; นำเข้า java.io.file; นำเข้า java.io.fileinputstream; นำเข้า Java.io.filenotfoundException; นำเข้า Java.io.ioException; @Author Administrator * */คลาสสาธารณะ notparentsDelegAteclassLoader ขยาย classloader {สตริงสุดท้ายคงที่ส่วนตัว ext = ".class"; เส้นทางสตริงส่วนตัว; public notparentsdelegateclassloader () {path = this.getResource ("") คลาส <?> loadclass (ชื่อสตริง) พ่น classnotfoundexception {byte [] b = null; ลอง {b = loadclassfile (ชื่อ);} catch (filenotfoundexception e) {system.err.println ("loader" + this.getClass () ตัวโหลดคลาสแม่กลับ getClass (). getClassLoader (). loadclass (ชื่อ);} catch (ioexception e) {system.err.println ("loader" + this.getClass (). getName () + "คลาสคลาสโหลด" getClass (). getClassLoader (). loadclass (ชื่อ);} // ตรวจสอบว่าคลาสได้รับการโหลดโดยตัวโหลดคลาสปัจจุบัน (ตรวจสอบตัวโหลดคลาสปัจจุบันไม่ใช่คลาส Parent Class Loader) คลาส <?> clazz = findloadedClass (ชื่อ); if (clazz! = null) {system.out.out {system.out.println ("คลาส" + ชื่อ + "ยังไม่โหลด!");} ส่งคืนสิ่งนี้ defineclass (ชื่อ, b, 0, b.length);} ไบต์ส่วนตัว [] loadclassfile classfile); byteArrayOutputStream out = new ByTeArrayOutputStream (); inputStream input = ใหม่ fileInputStream (classFile); int count; byte [] temp = byte ใหม่ [1024]; ในขณะที่ (count = input.read (temp))> -1) {out.write out.tobyteArray ();} สตริงส่วนตัว getClassFile (ชื่อสตริง) {สตริง pathName = name.replace (".", file.Separator); ถ้า (path.endswith ("/") || path.endswith ("//")ตอนนี้มีไฟล์คลาส com/zzj/classloader/user.class ภายใต้ classpath classpath ด้วยชื่อแพ็คเกจ com.zzj.classloader และคลาสผู้ใช้เป็นตัวโหลด notparentsdelegateclassloader
แพ็คเกจ com.zzj.classloader; คลาสสาธารณะ APP2 {สตริงสตริงสุดท้ายคงที่ส่วนตัว = "com.zzj.classloader.user"; โมฆะคงที่สาธารณะหลัก (สตริง [] args) โยนข้อยกเว้น classloader.loadclass (classname); system.out.println (clazz); system.out.println (clazz.getclassloader ());}}เอาท์พุท:
ไฟล์คลาส /e:/myeclipse/zzjtest/webroot/web-inf/classes/com/zzj/classloader/user.class คลาส com.zzj.classloader.user ยังไม่ได้รับการโหลด! ไฟล์คลาสจะถูกโหลดเร็ว/e: /myeclipse/zzjtest/webroot/web-inf/classes/java/lang/object.class คลาส com.zzj.classloader.user com.zzj.classload.notparentsdelegateclasslout ไม่พบ java.lang.Object และจะได้รับมอบหมายให้กับตัวโหลดคลาสแม่!
ในเวลานี้โหลดเดอร์ของคลาสผู้ใช้คือ NotparentsDelegateclassLoader ซึ่งไม่ได้ถูกมอบหมายให้กับคลาสแม่ก่อน มันจะถูกมอบหมายให้กับตัวโหลดคลาสแม่เท่านั้นหากโหลดล้มเหลว สิ่งนี้เกิดขึ้นตรงข้ามกับรูปแบบการมอบหมายผู้ปกครอง
แน่นอนแม้ว่าการโหลดจะล้มเหลว แต่ก็สามารถระบุได้โดยไม่ต้องมอบหมายให้ตัวโหลดคลาสแม่เพื่อให้สามารถสร้างกลไกการโหลดคลาสของโมเดลตาข่ายที่ซับซ้อนมากขึ้นได้
สรุป
ข้างต้นคือทั้งหมดเกี่ยวกับตัวอย่างรหัสของตัวโหลดคลาส Java ที่กำหนดเองฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงหัวข้ออื่น ๆ ที่เกี่ยวข้องในเว็บไซต์นี้ต่อไป หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น ขอบคุณเพื่อนที่ให้การสนับสนุนเว็บไซต์นี้!