1. หนึ่งคำสั่งสอดคล้องกับหนึ่งกระบวนการ
เมื่อเราเริ่มโปรแกรม Java นั่นคือเมื่อเราเริ่มวิธีการหลัก กระบวนการเครื่องเสมือน Java จะเริ่มต้นขึ้น ไม่ว่ากระบวนการจะซับซ้อนแค่ไหนก็ตาม กระบวนการ JVM ที่แตกต่างกันจะไม่ส่งผลกระทบซึ่งกันและกัน นี่คือเหตุผลที่ว่ากันว่าโปรแกรม Java มีทางเข้าเดียวเท่านั้น - วิธีการหลักซึ่งถูกเรียกโดยเครื่องเสมือน วิธีการหลักสองวิธีสอดคล้องกับกระบวนการ JVM สองกระบวนการ โดยสตาร์ทตัวโหลดคลาสที่แตกต่างกันสองตัว และใช้งานคลาสที่แตกต่างกันจริง ๆ จึงไม่กระทบกระเทือนซึ่งกันและกัน
2. การโหลดชั้นเรียน
เมื่อเราใช้คลาส ถ้าคลาสไม่ได้ถูกโหลดลงในหน่วยความจำ ระบบจะเริ่มต้นคลาสผ่านการโหลด การเชื่อมต่อ และการเริ่มต้น
1. การโหลดคลาส: หมายถึงการอ่านไฟล์คลาสของคลาสลงใน JVM และสร้างคลาสอ็อบเจ็กต์สำหรับมัน
2. การเชื่อมต่อคลาส: หมายถึงการรวมข้อมูลไบนารีของคลาสเข้ากับ JRE ซึ่งแบ่งออกเป็นสามขั้นตอน:
ก) การตรวจสอบ: ตรวจสอบความถูกต้องของข้อมูลไฟล์คลาสที่โหลด
b) การเตรียมการ: จัดสรรพื้นที่จัดเก็บข้อมูลให้กับตัวแปรคงที่ของคลาสและดำเนินการกำหนดค่าเริ่มต้น
c) การแยกวิเคราะห์: แทนที่การอ้างอิงสัญลักษณ์ในข้อมูลไบนารีของคลาสด้วยการอ้างอิงโดยตรง
3. การเริ่มต้น: เริ่มต้นตัวแปรแบบคงที่และบล็อกการเริ่มต้นแบบคงที่ของคลาส
(หมายเหตุ: สำหรับคุณสมบัติคงที่ของประเภทสุดท้าย หากได้รับค่าคุณสมบัติในขณะรวบรวม การเรียกคุณสมบัติจะไม่ทำให้คลาสเริ่มต้นได้ เนื่องจากเทียบเท่ากับการใช้ค่าคงที่
การใช้เมธอด ClassLoader() จะโหลดคลาสเท่านั้นและไม่ได้เริ่มต้นคลาส -
3. ตัวโหลดคลาส
ตัวโหลดคลาสมีหน้าที่โหลดไฟล์ .class ลงในหน่วยความจำและสร้างอ็อบเจ็กต์ java.lang.Class ที่เกี่ยวข้อง
ใน Java คลาสจะถูกระบุด้วยชื่อคลาสแบบเต็ม (นั่นคือ ชื่อแพ็กเกจ + ชื่อคลาส)
ใน JVM คลาสจะถูกระบุโดยชื่อคลาสแบบเต็มและตัวโหลดคลาส
เมื่อ JVM รันอยู่ ClassLoader สามตัวจะถูกสร้างขึ้น ได้แก่: BootstrapClassLoader (ตัวโหลดคลาสรูท), ExtClassLoader (ตัวโหลดคลาสแบบขยาย) และ AppClassLoader (ตัวโหลดคลาสระบบ) โครงสร้าง UML เป็นดังนี้:
ในหมู่พวกเขา BootstrapClassLoader มีหน้าที่โหลดไลบรารีคลาสหลักของ JRE ไม่ใช่คลาสย่อยของ ClassLoader และเขียนด้วยภาษา C ++ ดังนั้นเราจึงไม่สามารถมองเห็นได้ใน Java เมื่อได้รับผ่านเมธอด getParent() ของคลาสย่อย จะถูกส่งกลับ BootstrapClassLoader รับผิดชอบในการโหลดไลบรารีคลาสหลักของ Java เช่น rt.jar และ charsets.jar ภายใต้เป้าหมาย JRE
ดังที่เห็นได้จากรูป ExtClassLoader และ AppClassLoader เป็นคลาสย่อยของ ClassLoader คุณไม่เห็นสิ่งเหล่านี้ใน API แต่อยู่ในไฟล์ rt.jar ชื่อคลาสที่มีคุณสมบัติครบถ้วนคือ:
sun.misc.Launcher$ExtClassLoader และ sun.misc.Launcher$AppClassLoader
ในหมู่พวกเขา ExtClassLoader รับผิดชอบในการโหลดแพ็คเกจ JAR ในไดเรกทอรีส่วนขยาย JRE ext และ AppClassLoader รับผิดชอบในการโหลดแพ็คเกจคลาสภายใต้เส้นทาง Classpath
การทดสอบมีดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
แพ็คเกจ com.stopTalking.crazy;
TestClassLoader คลาสสาธารณะ {
โมฆะคงที่สาธารณะ main (String [] args) {
//รับคลาสโหลดเดอร์ของเธรดปัจจุบัน
ตัวโหลด ClassLoader = Thread.currentThread().getContextClassLoader();
//รับคลาสโหลดเดอร์ของคลาส System
ClassLoader loader1 = System.class.getClassLoader();
//รับคลาสโหลดเดอร์ loader2 ของคลาส TestClassLoader นี้
ClassLoader loader2 = TestClassLoader.class.getClassLoader();
//รับคลาสพาเรนต์ของ loader2
ClassLoader loader3 = loader2.getParent();
//รับคลาสพาเรนต์ของคลาสพาเรนต์ของ loader2
ClassLoader loader4 = loader3.getParent();
System.out.println (ตัวโหลด);
System.out.println(ตัวโหลด 1);
System.out.println(loader2);
System.out.println(ตัวโหลด 3);
System.out.println(loader4);
-
-
เอาต์พุตคอนโซล:
คัดลอกรหัสรหัสดังต่อไปนี้:
//ตัวโหลดคลาสที่ได้รับจากคลาสเธรดปัจจุบันคือ AppClassLoader
sun.misc.Launcher$AppClassLoader@6b97fd
//คลาส System ถูกโหลดโดยตัวโหลดรูทและไม่สามารถเข้าถึงได้ใน java ดังนั้นจึงเป็นโมฆะ
โมฆะ
//ตัวโหลดคลาสของคลาสนี้ก็เป็น AppClassLoader เช่นกัน
sun.misc.Launcher$AppClassLoader@6b97fd
sun.misc.Launcher$ExtClassLoader@1c78e57
โมฆะ