Java ClassLoader คืออะไร


174

ในประโยคง่ายๆไม่กี่ Java ClassLoader คืออะไรเมื่อมันถูกใช้และทำไม?

ตกลงฉันอ่านบทความวิกิ ClassLoader โหลดคลาส ตกลง. ดังนั้นถ้าฉันรวมไฟล์ jar และนำเข้า ClassLoader ก็ทำงานได้

ทำไมฉันถึงต้องกังวลกับ ClassLoader นี้ ฉันไม่เคยใช้มันและไม่รู้ว่ามันมีอยู่จริง

คำถามคือทำไมคลาส ClassLoader อยู่? และคุณจะใช้มันอย่างไรในทางปฏิบัติ? (มีคดีอยู่ฉันรู้)


คุณจะได้ผลลัพธ์ที่ดีขึ้นหากคุณ จำกัด คำถามของคุณให้แคบลงเช่นการชี้เฉพาะส่วนที่คุณไม่เข้าใจความเกี่ยวข้องกับภาษาอื่น ๆ ที่คุณคุ้นเคย ฯลฯ
JRL

75
นี่เป็นคำถามที่สมเหตุสมผลเมื่อมองจากมุมมองของคนที่กำลังค้นหาประโยคง่ายๆเพื่ออธิบายแนวคิด
oxbow_lakes

วิดีโอนี้อาจเป็นที่สนใจ: คุณได้รับคลาสของตัวโหลดจริงหรือไม่
asmaier

คำตอบ:


231

นำมาจากบทช่วยสอนที่ดีจาก Sun:

แรงจูงใจ

แอปพลิเคชันที่เขียนด้วยภาษาการเขียนโปรแกรมแบบคอมไพล์แบบคงที่เช่น C และ C ++ จะถูกรวบรวมเป็นคำสั่งพื้นฐานเฉพาะเครื่องและบันทึกเป็นไฟล์เรียกทำงาน กระบวนการในการรวมรหัสเข้ากับรหัสดั้งเดิมที่เรียกใช้งานได้เรียกว่าการเชื่อมโยง - การรวมรหัสที่คอมไพล์แยกต่างหากกับรหัสไลบรารีที่ใช้ร่วมกันเพื่อสร้างแอปพลิเคชันที่ปฏิบัติการได้ สิ่งนี้แตกต่างกันในภาษาการเขียนโปรแกรมที่คอมไพล์แบบไดนามิกเช่น Java ใน Java ไฟล์. class ที่สร้างโดยคอมไพเลอร์ Java จะยังคงเป็น - จนกว่าจะโหลดลงใน Java Virtual Machine (JVM) - กล่าวอีกนัยหนึ่งกระบวนการเชื่อมโยงจะดำเนินการโดย JVM เมื่อรันไทม์ คลาสถูกโหลดเข้าสู่ JVM บนพื้นฐาน 'ตามต้องการ' และเมื่อคลาสที่โหลดขึ้นอยู่กับคลาสอื่นคลาสนั้นก็จะถูกโหลดเช่นกัน

เมื่อเปิดใช้งานแอปพลิเคชัน Java คลาสแรกที่เรียกใช้ (หรือจุดเข้าสู่แอปพลิเคชัน) เป็นแอปพลิเคชันที่มีช่องว่างแบบสแตติกสาธารณะที่เรียกว่า main () คลาสนี้มักจะมีการอ้างอิงไปยังคลาสอื่น ๆ และความพยายามทั้งหมดในการโหลดคลาสที่อ้างอิงจะดำเนินการโดยโหลดเดอร์ระดับ

ในการรับความรู้สึกของการโหลดคลาสแบบเรียกซ้ำรวมถึงแนวคิดการโหลดคลาสโดยทั่วไปให้พิจารณาคลาสง่าย ๆ ดังต่อไปนี้:

public class HelloApp {
   public static void main(String argv[]) {
      System.out.println("Aloha! Hello and Bye");
   }
}

หากคุณรันคลาสนี้โดยระบุตัวเลือกบรรทัดคำสั่ง -verbose: class เพื่อให้มันพิมพ์คลาสใดที่กำลังโหลดคุณจะได้รับเอาต์พุตที่มีลักษณะดังนี้ โปรดทราบว่านี่เป็นเพียงเอาต์พุตบางส่วนเนื่องจากรายการยาวเกินไปที่จะแสดงที่นี่

prmpt>java -verbose:class HelloApp



[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar]
[Loaded java.lang.Object from shared objects file]
[Loaded java.io.Serializable from shared objects file]
[Loaded java.lang.Comparable from shared objects file]
[Loaded java.lang.CharSequence from shared objects file]
[Loaded java.lang.String from shared objects file]
[Loaded java.lang.reflect.GenericDeclaration from shared objects file]
[Loaded java.lang.reflect.Type from shared objects file]
[Loaded java.lang.reflect.AnnotatedElement from shared objects file]
[Loaded java.lang.Class from shared objects file]
[Loaded java.lang.Cloneable from shared objects file]
[Loaded java.lang.ClassLoader from shared objects file]
[Loaded java.lang.System from shared objects file]
[Loaded java.lang.Throwable from shared objects file]
.
.
.
[Loaded java.security.BasicPermissionCollection from shared objects file]
[Loaded java.security.Principal from shared objects file]
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded HelloApp from file:/C:/classes/]
Aloha! Hello and Bye
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]

อย่างที่คุณเห็นคลาสของรันไทม์ Java ที่แอปพลิเคชันต้องการ (HelloApp) จะถูกโหลดขึ้นมาก่อน

Class Loaders ในแพลตฟอร์ม Java 2

ภาษาการเขียนโปรแกรม Java พัฒนาอย่างต่อเนื่องเพื่อให้ชีวิตของนักพัฒนาแอปพลิเคชันง่ายขึ้นทุกวัน สิ่งนี้ทำได้โดยการให้ API ที่ทำให้ชีวิตของคุณง่ายขึ้นโดยให้คุณจดจ่อกับตรรกะทางธุรกิจมากกว่าใช้รายละเอียดของกลไกพื้นฐาน เรื่องนี้เห็นได้ชัดจากการเปลี่ยนแปลงล่าสุดของ J2SE 1.5 เป็น J2SE 5.0 เพื่อสะท้อนถึงความสมบูรณ์ของแพลตฟอร์ม Java

ตั้งแต่ JDK 1.2 ตัวโหลดคลาส bootstrap ที่สร้างขึ้นใน JVM มีหน้าที่โหลดคลาสของรันไทม์ Java ตัวโหลดคลาสนี้โหลดคลาสที่พบในบูทคลาสพา ธ เท่านั้นและเนื่องจากคลาสเหล่านี้เป็นคลาสที่เชื่อถือได้กระบวนการตรวจสอบจึงไม่ถูกดำเนินการเช่นเดียวกับคลาสที่ไม่น่าเชื่อถือ นอกเหนือจากตัวโหลดคลาส bootstrap แล้ว JVM ยังมีตัวโหลดคลาสส่วนขยายที่รับผิดชอบการโหลดคลาสจาก API ส่วนขยายมาตรฐานและตัวโหลดคลาสระบบที่โหลดคลาสจากพา ธ คลาสทั่วไปเช่นเดียวกับคลาสแอ็พพลิเคชันของคุณ

เนื่องจากมีตัวโหลดคลาสมากกว่าหนึ่งตัวจึงถูกแสดงในทรีที่มีรูทเป็นตัวโหลดคลาส bootstrap ตัวโหลดคลาสแต่ละตัวมีการอ้างอิงถึงตัวโหลดคลาสพาเรนต์ เมื่อคลาสโหลดเดอร์ถูกขอให้โหลดคลาสคลาสนั้นจะพิจารณาพาเรนต์คลาสโหลดเดอร์หลักก่อนพยายามโหลดไอเท็ม ผู้ปกครองในทางกลับกันให้คำปรึกษาผู้ปกครองของมันและอื่น ๆ ดังนั้นหลังจากตัวโหลดคลาสบรรพบุรุษทั้งหมดไม่สามารถค้นหาคลาสที่ตัวโหลดคลาสปัจจุบันเข้าร่วมได้ กล่าวอีกนัยหนึ่งจะใช้แบบจำลองการมอบหมาย

คลาส java.lang.ClassLoader

The java.lang.ClassLoaderเป็นคลาสนามธรรมที่สามารถ subclassed โดยแอ็พพลิเคชันที่ต้องการขยายลักษณะที่ JVM โหลดคลาสแบบไดนามิก ตัวสร้างในjava.lang.ClassLoader(และคลาสย่อย) อนุญาตให้คุณระบุพาเรนต์เมื่อคุณสร้างอินสแตนซ์คลาสโหลดเดอร์ใหม่ หากคุณไม่ได้ระบุพาเรนต์อย่างชัดเจนตัวโหลดคลาสระบบของเครื่องเสมือนจะถูกกำหนดเป็นพาเรนต์เริ่มต้น กล่าวอีกนัยหนึ่งคลาส ClassLoader ใช้โมเดลการมอบหมายเพื่อค้นหาคลาสและทรัพยากร ดังนั้นแต่ละอินสแตนซ์ของ ClassLoader มีตัวโหลดคลาสพาเรนต์ที่เชื่อมโยงดังนั้นเมื่อถูกร้องขอให้ค้นหาคลาสหรือรีซอร์สงานจะถูกมอบหมายให้กับตัวโหลดคลาสพาเรนต์ก่อนที่จะพยายามค้นหาคลาสหรือรีซอร์สเอง loadClass()วิธีการ ClassLoader ดำเนินงานต่อไปนี้ในการสั่งซื้อเมื่อเรียกโหลดชั้นเรียน:

ถ้าคลาสได้ถูกโหลดไปแล้วคลาสนั้นจะส่งคืน มิฉะนั้นจะมอบหมายการค้นหาคลาสใหม่ให้กับคลาสโหลดเดอร์หลัก หากโหลดคลาสพาเรนต์ไม่พบคลาสให้loadClass()เรียกใช้เมธอดfindClass()เพื่อค้นหาและโหลดคลาส finalClass()ค้นหาวิธีการสำหรับการเรียนในคลาสโหลดปัจจุบันถ้าชั้นไม่ได้ถูกค้นพบโดยรถตักดินระดับผู้ปกครอง


ยังมีบทความอื่นอีกมากในบทความต้นฉบับซึ่งจะแสดงวิธีการติดตั้งคลาสเครือข่ายของคุณเองซึ่งตอบคำถามของคุณว่าทำไม (และอย่างไร) ดูเพิ่มเติมเอกสาร API


47

นักพัฒนา Java ส่วนใหญ่ไม่จำเป็นต้องใช้ตัวโหลดคลาสอย่างชัดเจน (ยกเว้นโหลดทรัพยากรเพื่อให้สามารถใช้งานได้เมื่อรวมอยู่ใน JARs) โดยไม่ต้องเขียนเอง

ClassLoaders ใช้ในระบบขนาดใหญ่และแอพพลิเคชันเซิร์ฟเวอร์เพื่อทำสิ่งต่าง ๆ เช่น:

  • ทำให้ระบบและโมดูลโหลดยกเลิกการโหลดและอัปเดตโมดูลที่รันไทม์
  • ใช้ไลบรารี API รุ่นต่าง ๆ (เช่นตัวแยกวิเคราะห์ XML) แบบขนาน
  • แยกแอปพลิเคชั่นต่าง ๆ ที่ทำงานอยู่ภายใน JVM เดียวกัน (ตรวจสอบให้แน่ใจว่ามันจะไม่รบกวนซึ่งกันและกันเช่นผ่านตัวแปรคงที่)

29

คำถามคือ "ทำไมหนึ่งควรรบกวน ClassLoader นี้อยู่"

ส่วนใหญ่คุณสามารถแก้ไขสิ่งต่าง ๆ ได้หากพวกเขาทำผิด :-)

มันเป็นความจริงตราบใดที่คุณเพิ่งเขียนแอปพลิเคชั่นให้รวบรวมไปที่ JAR และอาจรวม JARs ของห้องสมุดอีกสองสามอันคุณไม่จำเป็นต้องรู้เกี่ยวกับตัวโหลดคลาส

ถึงกระนั้นมันก็ยังเป็นประโยชน์ที่จะรู้เล็กน้อยเกี่ยวกับรถตักของชั้นเรียนและการโหลดของชั้นเรียนเพื่อทำความเข้าใจกับสิ่งที่เกิดขึ้นเบื้องหลัง ตัวอย่างเช่น "static initializers" จะทำงานเมื่อโหลดคลาสดังนั้นเพื่อทำความเข้าใจว่าจะรันเมื่อใดคุณจะต้องทราบว่าตัวโหลดคลาสตัดสินใจเมื่อใดเมื่อต้องการโหลด

ยัง .. คุณใช้มันในทางปฏิบัติอย่างไร?

สำหรับกรณีง่าย ๆ คุณไม่ต้องการมัน อย่างไรก็ตามหากคุณต้องการโหลดรหัสแบบไดนามิกในขณะทำงานด้วยการควบคุมอย่างชัดเจนซึ่งมาจาก (เช่นการโหลดผ่านเครือข่ายการโหลดปลั๊กอินไม่สามารถใช้งานได้ในเวลารวบรวม ฯลฯ ) คุณอาจต้องทำมากกว่านี้ จากนั้นคุณสามารถเขียนตัวโหลดคลาสของคุณเอง ดูคำตอบอื่น ๆ สำหรับลิงก์


14

ClassLoaderin Java เป็นคลาสที่ใช้ในการโหลดไฟล์คลาสใน Java โค้ด Java ถูกคอมไพล์ลงในไฟล์คลาสโดยjavacคอมไพเลอร์และ JVM เรียกใช้งานโปรแกรม Java โดยเรียกใช้โค้ดไบต์ที่เขียนในไฟล์คลาส

ClassLoader รับผิดชอบการโหลดไฟล์คลาสจากระบบไฟล์เครือข่ายหรือแหล่งอื่น ๆ มีโหลดเดอร์คลาสเริ่มต้นสามตัวที่ใช้ใน Java, Bootstrap , ExtensionและSystem หรือโหลดคลาสคลาส

ClassLoader


ClassLoader ทำงานอย่างไร

## การโต้ตอบกับ ClassLoader กับ JVM ป้อนคำอธิบายรูปภาพที่นี่

เพิ่มเติม @: how-classloader-works-in-java.html


6

Class Loaders เป็นส่วนประกอบที่ใช้งานได้ของ JVM ซึ่งโหลดข้อมูลคลาสจากไฟล์ '.class' หรือจากทั่วเครือข่ายไปยังพื้นที่เมธอดในฮีป

ดูเหมือนว่าเป็นส่วนหนึ่งของ JVM แต่ในฐานะผู้ใช้จาวาทำไมฉันถึงต้องกังวล? นี่คือเหตุผล:

ตัวโหลดคลาสแต่ละตัวมีพื้นที่ชื่อเป็นของตัวเองและคลาสที่เรียกใช้โดยตัวโหลดคลาสเฉพาะจะเข้าสู่พื้นที่ชื่อ

คลาสที่เรียกใช้โดยตัวโหลดคลาสที่แตกต่างกันสองคลาสจะไม่สามารถมองเห็นซึ่งกันและกันได้ทำให้เกิดความปลอดภัยที่เพิ่มขึ้น

กลไกการมอบหมายผู้ปกครองระดับผู้ปกครองของเดอร์คลาสเดอร์ทำให้มั่นใจได้ว่าคลาส Java api จะไม่ถูกแฮ็กด้วยรหัสที่ไม่ได้รับอนุญาต

ดูรายละเอียดได้ที่นี่


1

รถตักชั้นมีลำดับชั้น คลาสถูกนำไปใช้กับ JVM เนื่องจากถูกอ้างอิงโดยชื่อในคลาสที่รันอยู่แล้วใน JVM

วิธีการที่ชั้นแรกมากโหลด?
ชั้นแรกเต็มไปด้วยความช่วยเหลือของstatic main()วิธีการประกาศในชั้นเรียนของคุณ คลาสที่โหลดในภายหลังทั้งหมดจะถูกโหลดโดยคลาสซึ่งถูกโหลดและรันอยู่แล้ว

ตัวโหลดคลาสสร้างเนมสเปซ JVMทั้งหมดมีตัวโหลดคลาสอย่างน้อยหนึ่งตัวที่ฝังอยู่ภายใน JVM เรียกว่าโหลดเดอร์คลาสดั้งเดิม (หรือ bootstrap) นั่นคือสิ่งหนึ่งและเราจะดูรถตักที่ไม่ใช่แบบดั้งเดิม JVM มีตะขออยู่ในนั้นเพื่ออนุญาตให้ผู้ใช้คลาสโหลดเดอร์สามารถใช้แทนคลาสโหลดเดอร์ดั้งเดิม ต่อไปนี้เป็นรถตักชั้นเรียนที่สร้างขึ้นโดย JVM

Bootstrap (ดั้งเดิม) ตัว โหลดคลาสนี้ไม่สามารถโหลดได้อีกครั้ง โหลดคลาสภายในของ JDK, java. * packages (โดยทั่วไปจะโหลด rt.jar และ i18n.jar) Extesions คลาสโหลดเดอร์นี้ไม่สามารถโหลดได้อีกครั้ง โหลดไฟล์ jar จากไดเรกทอรีส่วนขยาย JDK (โดยทั่วไปคือ lib / ext ของ JRE) ระบบตัวโหลดคลาสนี้ไม่สามารถโหลดได้ โหลดคลาสจากพา ธ คลาสระบบ

http://www.sbalasani.com/2015/01/java-class-loaders.html


1

เมื่อคุณถามว่าทำไมไม่อยู่ระดับ ClassLoader เหตุผลที่สวยเรียบง่าย - เป็นระดับที่รับผิดชอบในการค้นหาและระดับการโหลดไฟล์ในเวลาทำงาน

มาอธิบายอย่างละเอียดกันเถอะ

ใน JVM java.lang.ClassLoaderทุกชั้นมีการโหลดโดยตัวอย่างของบางอย่าง เมื่อใดก็ตามที่ JVM ใหม่เริ่มต้นโดยคุณjava <classname>สั่งเปิดโปรแกรม Java ตามปกติขั้นตอนแรกคือการโหลดคลาสคีย์ทั้งหมดในหน่วยความจำที่จำเป็นสำหรับการทำงานที่เหมาะสมเช่นjava.lang.Objectและคลาสรันไทม์อื่น ๆ ( rt.jar)

ตอนนี้มี ClassLoader 3 ส่วน:

  • BootstrapClassLoaderเป็นผู้รับผิดชอบสำหรับการทำชั้นเรียนเหล่านี้สามารถใช้ได้เช่นการโหลดชั้นเรียนเหล่านี้ในหน่วยความจำ

  • ภารกิจถัดไปคือโหลดไลบรารี / JAR ภายนอกใด ๆ ลงในหน่วยความจำเพื่อการทำงานที่เหมาะสมของแอปพลิเคชัน ผู้ExtClassLoaderรับผิดชอบงานนี้ ตัวโหลดคลาสนี้มีหน้าที่โหลดไฟล์. jar ทั้งหมดที่กล่าวถึงในเส้นทาง java.ext.dirs

  • AppClassLoaderครั้งที่สามและโหลดระดับหลักที่สำคัญคือ ตัวโหลดคลาสแอ็พพลิเคชันมีหน้าที่โหลดไฟล์คลาสที่กล่าวถึงในคุณสมบัติระบบ java.class.path

สิ่งสำคัญคือต้องทราบว่าการใช้งาน ClassLoader ที่เป็นค่าเริ่มต้นนั้นสามารถแทนที่ได้ซึ่งช่วยให้คุณสามารถปรับแต่ง JVM ในรูปแบบที่มีประโยชน์และน่าสนใจซึ่งช่วยให้คุณสามารถกำหนดวิธีนำไฟล์คลาสเข้าสู่ระบบได้อย่างสมบูรณ์

ป้อนคำอธิบายรูปภาพที่นี่

ตรวจสอบออกเพื่อเรียนรู้เพิ่มเติมเกี่ยวกับชั้น Java Loader

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.