กระบวนการโหลดคลาส
งานหลักของตัวโหลดคลาสคือการโหลดไฟล์คลาสลงใน JVM ดังที่แสดงในรูปด้านล่างกระบวนการแบ่งออกเป็นสามขั้นตอน:
1. การโหลด: ค้นหาไฟล์คลาสที่จะโหลดและโหลดสตรีมไบต์ลงใน JVM;
2. ลิงก์: จัดสรรโครงสร้างหน่วยความจำพื้นฐานที่สุดเพื่อโหลดเพื่อบันทึกข้อมูลเช่นคุณสมบัติวิธีการและคลาสอ้างอิง ในขั้นตอนนี้ชั้นเรียนยังไม่พร้อมใช้งาน
(1) การตรวจสอบ: ตรวจสอบสตรีมไบต์ที่โหลดเช่นรูปแบบและความปลอดภัย
(2) การจัดสรรหน่วยความจำ: เตรียมพื้นที่หน่วยความจำสำหรับคลาสนี้เพื่อแสดงคุณสมบัติวิธีการและคลาสอ้างอิง
(3) การวิเคราะห์: โหลดคลาสอื่น ๆ ที่อ้างอิงโดยคลาสนี้เช่นคลาสแม่, อินเทอร์เฟซที่ใช้งาน ฯลฯ
3. การเริ่มต้น: กำหนดค่าให้กับตัวแปรคลาส
ระดับตัวโหลดคลาส
เส้นประในรูปด้านล่างเป็นรถตักคลาสที่สำคัญหลายประการที่จัดทำโดย JDK และคำอธิบายโดยละเอียดมีดังนี้:
(1) Loader คลาส Bootstrap: เมื่อเริ่มคลาสที่มีฟังก์ชั่นหลักโหลดแพ็คเกจ JAR ในไดเรกทอรี JAVA_HOME/LIB หรือ -XBOOTCLASSPATH DIRECTORY ที่ระบุ;
(2) ตัวโหลดคลาสส่วนขยาย: โหลดแพ็คเกจ JAR ในไดเรกทอรี java_home/lib/ext หรือ -djava.ext.dirs ไดเรกทอรีที่ระบุ
(3) ตัวโหลดคลาสของระบบ: โหลด classpath หรือ -djava.class.path คลาสหรือแพ็คเกจ JAR ในไดเรกทอรีที่ระบุ
สิ่งที่คุณต้องรู้คือ:
1. นอกเหนือจากตัวโหลดคลาส bootstrap แล้วตัวโหลดคลาสอื่น ๆ ยังเป็นคลาสย่อยของ Java.lang.classloader คลาส;
2. ตัวโหลดคลาส Bootstrap ไม่ได้ใช้งานใน Java หากคุณไม่ได้ใช้ตัวโหลดคลาสส่วนบุคคลแล้ว java.lang.string.class.getClassloader () เป็นโมฆะและตัวโหลดหลักของตัวโหลดคลาสส่วนขยายก็เป็นโมฆะ
3. หลายวิธีในการรับรถตักคลาส:
(1) การรับ Loader คลาส Bootstrap: สิ่งที่คุณได้รับจะต้องเป็นโมฆะเมื่อพยายามรับ Loader คลาส Bootstrap คุณสามารถตรวจสอบได้ด้วยวิธีต่อไปนี้: ใช้วิธีการ getClassLoader ของวัตถุคลาสในแพ็คเกจ RT.JAR เช่น java.lang.string.class.getClassLoader () เพื่อรับหรือรับตัวโหลดคลาสส่วนขยายจากนั้นเรียกใช้วิธี getParent เพื่อรับ;
(2) รับ Loader คลาสส่วนขยาย: ใช้วิธี getClassLoader ของวัตถุคลาสในแพ็คเกจ JAR ภายใต้ไดเรกทอรี Java_Home/LIB/EXT หรือได้รับการโหลดคลาสของระบบก่อนแล้วจึงรับผ่านวิธีการ getParent;
(3) รับ Loader คลาส System: เรียกใช้วิธี getClassLoader ของวัตถุคลาสที่มีฟังก์ชั่นหลักหรือ thread.currentthread (). getContextClassLoader () หรือ call classloader.getSystemClassLoader () ภายในฟังก์ชั่นหลัก;
(4) รับตัวโหลดคลาสที่ผู้ใช้กำหนด: เรียกใช้วิธี getClassLoader ของวัตถุคลาสหรือเธรดการโทร.
หลักการปฏิบัติงานของตัวโหลดชั้นเรียน
1. หลักการตัวแทน
2. หลักการทัศนวิสัย
3. หลักการของเอกลักษณ์
4. หลักการพร็อกซีหลักการพร็อกซีหมายถึงตัวโหลดคลาสที่ขอให้พร็อกซีตัวโหลดหลักโหลดเมื่อโหลดคลาสและตัวโหลดพาเรนต์จะขอพร็อกซีตัวโหลดหลักของตัวโหลดดังที่แสดงในรูปด้านล่าง
ทำไมต้องใช้โหมดพร็อกซี? ก่อนอื่นสิ่งนี้สามารถลดการโหลดที่ซ้ำกันของคลาส (มีเหตุผลอื่นอีกไหม?)
จะเข้าใจผิดที่ไหน:
โดยทั่วไปเป็นความคิดว่าคำสั่งซื้อพร็อกซีของตัวโหลดคลาสเป็นพาเรนต์ก่อนนั่นคือ:
1. เมื่อโหลดคลาสรถโหลดคลาสก่อนตรวจสอบว่าได้โหลดคลาสหรือไม่ หากมีการโหลดมันจะกลับมา; มิฉะนั้นให้ขอให้ตัวตักผู้ปกครองพร็อกซี;
2. ตัวโหลดหลักทำซ้ำการทำงานของ 1 จนกว่าจะถึงตัวโหลดคลาส bootstrap;
3. หากตัวโหลดคลาส bootstrap ไม่โหลดคลาสมันจะพยายามโหลดและถ้ามันสำเร็จมันจะกลับมา; ถ้ามันล้มเหลว classnotfoundexception จะถูกโยนมันจะถูกโหลดโดยตัวโหลดเด็ก;
4. ตัวโหลด subclass จับข้อยกเว้นและพยายามโหลด หากประสบความสำเร็จมันจะกลับมา ถ้ามันล้มเหลวมันจะพ่น classnotfoundexception จนกว่าจะเริ่มต้นโหลด subclass loader
ความเข้าใจนี้ถูกต้องสำหรับรถตักเช่นตัวโหลดคลาส bootstrap, ตัวโหลดคลาสส่วนขยายและตัวโหลดคลาสระบบ แต่ตัวโหลดส่วนบุคคลบางตัวไม่เป็นเช่นนั้น ตัวอย่างเช่นตัวโหลดคลาสบางตัวที่ใช้โดย IBM Web Sphere Portal Server เป็นพาเรนต์สุดท้ายซึ่งเป็นตัวโหลดเด็กที่พยายามโหลดก่อน หากโหลดล้มเหลวตัวโหลดพาเรนต์จะถูกถาม เหตุผลนี้คือ: หากคุณคาดหวังว่าแอปพลิเคชันทั้งหมดจะใช้งานในทุกเวอร์ชันของแอปพลิเคชันให้ใส่ไว้ในไลบรารี Was_home และจะโหลดเมื่อเริ่มต้น หากแอปพลิเคชันต้องการใช้ Log4J เวอร์ชันอื่นจะไม่สามารถทำได้หากใช้ Parent ก่อนเพราะคลาสใน log4j ถูกโหลดแล้วในตัวโหลดพาเรนต์แล้ว อย่างไรก็ตามหากผู้ปกครองถูกใช้งานล่าสุดตัวโหลดคลาสที่รับผิดชอบในการโหลดแอปพลิเคชันจะจัดลำดับความสำคัญของการโหลด log4j เวอร์ชันอื่น
หลักการทัศนวิสัย
การมองเห็นของแต่ละคลาสไปยังตัวโหลดคลาสนั้นแตกต่างกันดังแสดงในรูปด้านล่าง
เพื่อขยายความรู้ OSGI ใช้ประโยชน์จากคุณสมบัตินี้ แต่ละชุดจะถูกโหลดโดยตัวโหลดคลาสแยกต่างหากดังนั้นตัวโหลดแต่ละคลาสสามารถโหลดเวอร์ชันของคลาสที่แน่นอนเพื่อให้ทั้งระบบสามารถใช้คลาสได้หลายรุ่น
หลักการของเอกลักษณ์
แต่ละคลาสจะถูกโหลดมากที่สุดครั้งเดียวในตัวโหลด
ความรู้เพิ่มเติม 1: เพื่อความแม่นยำรูปแบบ Singleton หมายถึงวัตถุซิงเกิลที่มีเพียงหนึ่งสำเนาของคลาสในชุดของรถตักคลาส
ความรู้เพิ่มเติม 2: คลาสสามารถโหลดได้โดยรถตักหลายชั้น แต่ละวัตถุคลาสอยู่ในเนมสเปซของตัวเอง เมื่อเปรียบเทียบวัตถุคลาสหรือประเภทการแปลงอินสแตนซ์มันจะเปรียบเทียบเนมสเปซที่เกี่ยวข้องในเวลาเดียวกันเช่น:
คลาส KLASS ถูกโหลดโดย classloadera โดยสมมติว่าวัตถุคลาสคือ Klassa; มันถูกโหลดโดย classloaderb โดยสมมติว่าวัตถุคลาสคือ Klassb จากนั้น Klassa ไม่เท่ากับ KLASSB ในเวลาเดียวกันเมื่ออินสแตนซ์ของ Classa ถูกส่งไปยัง KLASSB ข้อยกเว้น ClassCastException จะถูกโยนลงไป
ทำไมคุณถึงต้องใช้ตัวโหลดคลาสส่วนบุคคล? ตัวโหลดคลาสส่วนบุคคลเพิ่มความยืดหยุ่นให้กับภาษา Java การใช้งานหลักคือ:
1. คลาสสามารถโหลดได้จากหลายสถานที่เช่นบนเครือข่ายในฐานข้อมูลหรือแม้แต่ไฟล์ต้นฉบับที่รวบรวมทันที
2. หลังจากการปรับเปลี่ยนในแบบส่วนตัวตัวโหลดคลาสสามารถโหลดไฟล์คลาสบางรุ่นในหลักการที่รันไทม์;
3. หลังจากการปรับเปลี่ยนในแบบส่วนตัวตัวโหลดคลาสสามารถขนถ่ายคลาสบางคลาสแบบไดนามิกได้
4. หลังจากการปรับแต่งในแบบส่วนตัวตัวโหลดคลาสสามารถถอดรหัสและบีบอัดคลาสก่อนโหลดคลาส
การโหลดโดยนัยและชัดเจนของคลาส
การโหลดโดยนัย: เมื่อคลาสมีการอ้างอิงสืบทอดหรือสร้างอินสแตนซ์มันจะถูกโหลดโดยปริยาย หากโหลดล้มเหลว NOCLASSDeffoundError จะถูกโยนลงไป
การโหลดที่ชัดเจน: ใช้วิธีการต่อไปนี้หากการโหลดล้มเหลวจะมีการโยน classnotFoundException
cl.loadclass (), cl เป็นอินสแตนซ์ของคลาสโหลดเดอร์
class.forName () โหลดโดยใช้คลาสโหลดเดอร์ของคลาสปัจจุบัน
หากการดำเนินการของบล็อกคงที่ของคลาสมีคลาสต่อไปนี้:
แพ็คเกจ cn.fengd; Public Class Dummy {Static {System.out.println ("HI"); - สร้างคลาสทดสอบอื่น:
แพ็คเกจ cn.fengd; คลาสสาธารณะ ClassloaderTest {โมฆะสาธารณะคงที่หลัก (สตริง [] args) พ่น InstantiationException, ข้อยกเว้น {ลอง { / * * วิธีการโหลดที่แตกต่างกัน */ คลาส C = classloaderTest.class.getClassLoader (). loadclass ("cn.fengd.dummy"); } catch (exception e) {// todo บล็อก catch block ที่สร้างอัตโนมัติ e.printstacktrace (); -มันมีประสิทธิภาพแค่ไหนหลังจากทำงาน?
จะเกิดอะไรขึ้นถ้ามันถูกแทนที่ด้วย class.forname ("cn.fengd.dummy"); หรือหุ่นใหม่ ()?
สวัสดีจะเป็นเอาต์พุต
คำถามที่พบบ่อย:
1. ประเภทที่ระบุถูกโหลดโดยรถตักคลาสที่แตกต่างกันยังคงเป็นประเภทเดียวกันหรือไม่?
ใน Java คลาสใช้ชื่อคลาสที่ผ่านการรับรองอย่างสมบูรณ์เป็นตัวระบุ ชื่อคลาสการจับคู่ที่แน่นอนที่อ้างถึงที่นี่มีชื่อแพ็คเกจและชื่อคลาส อย่างไรก็ตามใน JVM คลาสใช้ชื่อเต็มและอินสแตนซ์ของคลาสโหลดคลาสโหลดเป็นตัวระบุที่ไม่ซ้ำกัน คลาสที่โหลดโดยรถตักคลาสที่แตกต่างกันจะถูกวางไว้ในเนมสเปซที่แตกต่างกัน เราสามารถใช้ตัวโหลดคลาสที่กำหนดเองสองแบบเพื่อโหลดประเภทที่กำหนดเอง (โปรดทราบว่าไม่ได้วาง bytecode ของประเภทที่กำหนดเองลงในเส้นทางระบบหรือเส้นทางส่วนขยายมิฉะนั้นจะถูกโหลดก่อนโดยตัวโหลดคลาสระบบหรือตัวโหลดคลาสส่วนขยาย) จากนั้นใช้อินสแตนซ์คลาสสองรายการที่ได้รับ สิ่งนี้สามารถทำได้โดยการเขียนรถตักคลาสที่กำหนดเองสองแบบเพื่อโหลดประเภทที่กำหนดเองเดียวกันแล้วทำการตัดสิน ในเวลาเดียวกันคุณสามารถทดสอบการโหลด Java.* พิมพ์จากนั้นเปรียบเทียบและทดสอบผลการทดสอบ
2. เรียกใช้เมธอดคลาส forName (ชื่อสตริง) โดยตรงในรหัส ตัวโหลดคลาสใดที่จะกระตุ้นพฤติกรรมการโหลดคลาส
class.forName (ชื่อสตริง) จะใช้คลาสโหลดเดอร์ที่เรียกคลาสเพื่อโหลดคลาสตามค่าเริ่มต้น มาวิเคราะห์รหัส JDK ที่เกี่ยวข้องโดยตรง:
//java.lang.class.java คลาส PublicStatic <?> forname (String classname) พ่น classnotfoundexception {return forname0 (classname, true, classloader.getCallerClassloader (); getCallerClassLoader () {// รับประเภทของคลาสการโทร (ผู้โทร) ผู้โทร = reflection.getCallerClass (3); // นี่อาจเป็นโมฆะหาก VM ร้องขอถ้า (caller == null) {returnNull; } // เรียกเมธอดท้องถิ่นใน java.lang.class เพื่อรับ classloader ที่โหลดคลาสการโทร (ผู้โทร) ส่งคืน caller.getClassLoader0 ();} // java.lang.class.java//native การใช้งานเครื่องเสมือน 3. เมื่อเขียนตัวโหลดคลาสที่กำหนดเองหากตัวโหลดพาเรนต์ไม่ได้ตั้งค่าแล้วตัวโหลดพาเรนต์คืออะไร?
เมื่อไม่ได้ระบุตัวโหลดคลาสแม่ตัวโหลดคลาสระบบจะถูกใช้โดยค่าเริ่มต้น บางคนอาจไม่เข้าใจตอนนี้มาดูการใช้งานรหัสที่สอดคล้องกันของ JDK อย่างที่เราทราบกันดีว่าเราเขียนตัวโหลดคลาสที่กำหนดเองโดยตรงหรือโดยอ้อมที่สืบทอดมาจาก Java.lang.cloader คลาสนามธรรม ตัวสร้างเริ่มต้นที่สอดคล้องกันโดยไม่มีพารามิเตอร์ถูกนำไปใช้ดังนี้:
// ข้อความที่ตัดตอนมาจาก java.lang.classloader.javaprotected classloader () {SecurityManager Security = System.getSecurityManager (); if (ความปลอดภัย! = null) {security.checkCreateClassLoader (); } this.parent = getSystemClassLoader (); เริ่มต้น = true;}ลองมาดูการใช้งานที่สอดคล้องกันของวิธีการ getSystemClassLoader ():
PRIVATESTATICSYNCHRONIZEDVOID InitSystemClassLoader () {// ... sun.misc.launcher l = sun.misc.launcher.getlauncher (); scl = l.getclassloader (); -เราสามารถเขียนรหัสทดสอบง่าย ๆ เพื่อทดสอบ:
System.out.println (sun.misc.launcher.getlauncher (). getclassloader ());
ผลลัพธ์ที่สอดคล้องกันของเครื่องนี้มีดังนี้:
sun.misc.launcher$appclassloader@197d257
ดังนั้นตอนนี้เราสามารถเชื่อได้ว่าเมื่อตัวโหลดคลาสที่กำหนดเองไม่ได้ระบุตัวโหลดคลาสพาเรนต์ตัวโหลดคลาสแม่เริ่มต้นคือตัวโหลดคลาสระบบ ในเวลาเดียวกันเราสามารถวาดข้อสรุปต่อไปนี้:
ตัวโหลดคลาสที่ผู้ใช้กำหนดทันทีไม่ได้ระบุตัวโหลดคลาสพาเรนต์จากนั้นคลาสในสามสถานที่ต่อไปนี้สามารถโหลดได้เช่นกัน:
(1) คลาสภายใต้ <java_runtime_home>/lib
(2) คลาสในตำแหน่งที่ระบุโดยตัวแปรระบบ java.ext.dir
(3) คลาสภายใต้เส้นทางคลาสโครงการปัจจุบันหรือในตำแหน่งที่ระบุโดยตัวแปรระบบ java.class.path
4. เมื่อเขียนตัวโหลดคลาสที่กำหนดเองจะเกิดอะไรขึ้นถ้าตัวโหลดคลาสแม่ถูกบังคับให้เป็นโมฆะ? หากตัวโหลดคลาสที่กำหนดเองไม่สามารถโหลดคลาสที่ระบุได้มันจะล้มเหลวอย่างแน่นอนหรือไม่?
ข้อกำหนด JVM กำหนดว่าหากตัวโหลดคลาสที่ผู้ใช้กำหนดบังคับให้ตัวโหลดคลาสแม่เป็น NULL ตัวโหลดคลาสเริ่มต้นจะถูกตั้งค่าโดยอัตโนมัติเป็นตัวโหลดคลาสแม่ของตัวโหลดคลาสที่ผู้ใช้กำหนดปัจจุบัน (ปัญหานี้ได้รับการวิเคราะห์ก่อนหน้านี้) ในเวลาเดียวกันเราสามารถวาดข้อสรุปต่อไปนี้:
หากตัวโหลดคลาสที่ผู้ใช้กำหนดทันทีไม่ได้ระบุตัวโหลดคลาสแม่ก็สามารถโหลดคลาสภายใต้ <java_runtime_home>/lib แต่คลาสภายใต้ไดเรกทอรี <java_runtime_home>/lib/ext ไม่สามารถโหลดไดเรกทอรีในเวลานี้ได้
หมายเหตุ: ข้อสรุปที่อนุมานของคำถามที่ 3 และ 4 ขึ้นอยู่กับตัวโหลดคลาสที่ผู้ใช้กำหนดเองซึ่งยังคงใช้ตรรกะการมอบหมายเริ่มต้นของ java.lang.classloader.loadclass (…) หากผู้ใช้เปลี่ยนตรรกะการมอบหมายเริ่มต้นนี้ข้อสรุปที่อนุมานข้างต้นอาจไม่ถูกต้อง ดูคำถามที่ 5 สำหรับรายละเอียด
5. อะไรคือจุดสนใจทั่วไปเมื่อเขียนรถตักคลาสที่กำหนดเอง?
(1) โดยทั่วไปพยายามอย่าแทนที่ตรรกะการมอบหมายในวิธีการโหลด LoadClass (…) ที่มีอยู่ โดยทั่วไปจะทำในรุ่นก่อน JDK 1.2 และปรากฎว่าการทำเช่นนั้นมีแนวโน้มที่จะทำให้ตัวโหลดคลาสเริ่มต้นของระบบทำงานไม่ถูกต้อง ในข้อกำหนด JVM และเอกสาร JDK (1.2 หรือใหม่กว่า) ไม่แนะนำให้ผู้ใช้เขียนทับวิธีการโหลด (…) ในทางตรงกันข้ามนักพัฒนาได้รับการเตือนอย่างชัดเจนว่าเขียนทับ FindClass (…) ตรรกะเมื่อพัฒนาตัวโหลดคลาสที่กำหนดเอง ยกตัวอย่างเพื่อตรวจสอบปัญหา:
// ผู้ใช้คลาสที่กำหนดเองคลาสโหลดเดอร์ผิดปกติ loader.java (overwrite loadclass logic) publicclasswrongclassloadextends classloader {คลาสสาธารณะ <?> loadclass (ชื่อสตริง) พ่น classnotfoundexception {returnthis.findclass (ชื่อ); } คลาสที่ได้รับการป้องกัน <?> findClass (ชื่อสตริง) พ่น classnotFoundException {// สมมติว่านี่เป็นเพียงไดเรกทอรีเฉพาะอื่น ๆ นอกเหนือจากโครงการ d: /ไลบรารีเพื่อโหลดรหัสการใช้งานเฉพาะคลาสที่ถูกละเว้น}}}จากการวิเคราะห์ก่อนหน้านี้เรารู้อยู่แล้วว่าค่าเริ่มต้นของตัวโหลดคลาสที่ผู้ใช้กำหนด (ผิดพลาด LADSLOADER)
ตัวโหลดคลาสที่ได้รับการยอมรับคือตัวโหลดคลาสระบบ แต่ข้อสรุปของปัญหาทั้งสี่ประเภทนั้นไม่ถูกต้องในขณะนี้ ทุกคนทำได้
เพียงแค่ทดสอบตอนนี้ <java_runtime_home>/lib, <java_runtime_home>/lib/ext และ
ไม่สามารถโหลดคลาสบนพา ธ คลาสของโปรแกรมได้
คำถาม 5 รหัสทดสอบ 1
Publicclass ผิดพลาด loaderTest {PublicStaticVoid Main (String [] args) {ลอง {rougclassloader loader = new ungrassLoader (); คลาส classloaded = loader.loadclass ("beans.account"); System.out.println (classloaded.getName ()); System.out.println (classloaded.getClassLoader ()); } catch (exception e) {e.printstacktrace (); -(หมายเหตุ: D: "คลาส" ถั่ว "บัญชีมีคลาสที่มีอยู่จริง)
ผลลัพธ์ผลลัพธ์:
java.io.filenotfoundexception: d: "คลาส" java "lang" object.class (ระบบไม่สามารถหาเส้นทางที่ระบุ) ที่ java.io.fileinputstream.open (วิธีการดั้งเดิม) ที่ java.io.fileinputstream ungrasslassloader.findclass (ungrasslassloader.java:40) ที่ ungryclassloader.loadclass (ungrasslassloader.java:29) ที่ java.lang.classloader.loadclassinternal (classloader.java:319) ที่ java.lang.lang.lang.lang.lang java.lang.classloader.defineclass (classloader.java:620) ที่ java.lang.classloader.defineclass (classloader.java:400) ที่ผิดปกติ unglasslaDerTest.main (unglassloaderTest.java:27) ข้อยกเว้นในเธรด "Main" java.lang.noclassdeffounderror: java/lang/วัตถุที่ java.lang.classloader.defineclass1 java.lang.classloader.defineclass (classloader.java:400) ที่ ungrongclassloader.findclass (undleclasslader.java:43) ที่ ungryclasslounder.loadclass
ซึ่งหมายความว่าแม้แต่ supertype java.lang.Object ของประเภทที่จะโหลดไม่สามารถโหลดได้ ข้อผิดพลาดเชิงตรรกะที่ระบุไว้ที่นี่เกิดจากการเขียนทับ LoadClass (…) นั้นค่อนข้างง่ายและข้อผิดพลาดเชิงตรรกะที่เกิดขึ้นในความเป็นจริงอาจมีความซับซ้อนมากขึ้น
คำถามที่ 5 ทดสอบ 2
// ผู้ใช้คลาสที่กำหนดเองคลาสโหลดเดอร์ผิดปกติ LOADSLOADER.JAVA (อย่าเขียนทับ LOADCLASS LOGIC) PublassWrongClassLoadExtends classloader {คลาสที่ได้รับการป้องกัน <หลังจากแก้ไขโค้ดตัวโหลดคลาสที่กำหนดเองไม่ถูกต้อง unglassloader.java รันรหัสทดสอบและผลลัพธ์ผลลัพธ์จะเป็นดังนี้:
beans.accountwrongclassloader@1c78e57
สิ่งนี้แสดงให้เห็นว่าการโหลด beans.count นั้นสำเร็จและโหลดโดยตัวโหลดคลาสที่กำหนดเองผิดปกติ
ฉันไม่คิดว่าจะมีความจำเป็นในการอธิบายสาเหตุของเรื่องนี้และคุณควรจะวิเคราะห์ได้
(2) ตั้งค่าตัวโหลดคลาสแม่อย่างถูกต้องผ่านการวิเคราะห์คำถาม 4 และคำถามที่ 5 ด้านบน โดยส่วนตัวแล้วฉันคิดว่านี่เป็นจุดที่สำคัญที่สุดเมื่อปรับแต่งรถตักผู้ใช้ แต่มักจะถูกละเว้นหรือนำมาใช้อย่างง่ายดาย ด้วยการวิเคราะห์รหัส JDK ก่อนหน้านี้เป็นพื้นฐานฉันคิดว่าทุกคนสามารถให้ตัวอย่างใด ๆ ได้ในขณะนี้
(3) ตรวจสอบความถูกต้องเชิงตรรกะของวิธี FindClass (String) พยายามที่จะเข้าใจงานการโหลดที่จะเสร็จสมบูรณ์โดยตัวโหลดคลาสที่จะกำหนดและตรวจสอบให้แน่ใจว่าเนื้อหา bytecode ที่สอดคล้องกันสามารถรับได้ในระดับที่ยิ่งใหญ่ที่สุด
6. วิธีการกำหนดเส้นทางที่ตัวโหลดคลาสระบบสามารถโหลดได้?
ก่อนอื่นคุณสามารถเรียก classloader.getSystemClassLoader () หรือวิธีการอื่น ๆ โดยตรงเพื่อรับตัวโหลดคลาสระบบ (ตัวโหลดคลาสระบบและตัวโหลดคลาสส่วนขยายนั้นมาจาก URLCLASSLOADER) และคุณสามารถรับได้โดยการเรียกใช้วิธี getURLS ()
ประการที่สองคุณสามารถดูข้อมูลรายการเกี่ยวกับ ClassPath ปัจจุบันได้โดยตรงโดยได้รับแอตทริบิวต์ระบบ java.class.path System.getProperty ("java.class.path")
7. วิธีการกำหนดเส้นทางที่ตัวโหลดคลาสส่วนขยายมาตรฐานสามารถโหลดได้อย่างไร?
วิธีที่หนึ่ง:
ลอง {url [] exturls = ((urlclassloader) classloader.getSystemClassLoader (). getParent ()). getUrls (); สำหรับ (int i = 0; i <exturls.length; i ++) {system.out.println (exturls [i]); }} catch (Exception e) {// …}ผลลัพธ์ที่สอดคล้องกันของเครื่องนี้มีดังนี้:
ไฟล์:/d: /demo/jdk1.5.0_09/jre/lib/ext/dnsns.jarfile:/d: /demo/jdk1.5.0_09/jre/lib/ext/localedata.jarfile :/d: /demo/jdk1.5.0_09/jre/lib/ext/sunjce_provider.jarfile:/d: /demo/jdk1.5.0_09/jre/lib/ext/sunpkcs11.jar