มีความคล้ายคลึงกันมากระหว่างการติดตั้งใช้งานทั้งสอง (และในความคิดของฉัน: ใช่พวกเขาทั้งคู่เป็น "เครื่องเสมือน")
ประการหนึ่งพวกเขาเป็นทั้ง VM แบบกองซ้อนโดยไม่มีแนวคิดเรื่อง "การลงทะเบียน" เหมือนกับที่เราเคยเห็นในซีพียูสมัยใหม่เช่น x86 หรือ PowerPC การประเมินผลของนิพจน์ทั้งหมด ((1 + 1) / 2) ดำเนินการโดยการกดโอเปอแรนต์ลงใน "สแต็ก" และจากนั้นเปิดโอเปอเรเตอร์เหล่านั้นออกจากสแต็กเมื่อใดก็ตามที่คำสั่ง (เพิ่มหาร ฯลฯ ) แต่ละคำสั่งจะส่งผลลัพธ์กลับไปที่สแต็ก
เป็นวิธีที่สะดวกในการติดตั้งเครื่องเสมือนเพราะ CPU ทุกตัวในโลกมีจำนวนมาก แต่จำนวนของรีจิสเตอร์มักแตกต่างกัน (และรีจิสเตอร์บางตัวมีจุดประสงค์พิเศษและแต่ละคำสั่งคาดว่าจะถูกดำเนินการในรีจิสเตอร์ต่าง ๆ ฯลฯ )
ดังนั้นหากคุณกำลังจะสร้างแบบจำลองเครื่องนามธรรมรูปแบบสแต็กตามล้วนเป็นวิธีที่ดีที่จะไป
แน่นอนว่าเครื่องจักรจริงไม่สามารถใช้งานได้ ดังนั้นคอมไพเลอร์ JIT มีหน้าที่รับผิดชอบในการดำเนินการ "การลงทะเบียน" ของการดำเนินการ bytecode โดยกำหนดตารางเวลาการลงทะเบียน CPU จริงเพื่อให้มีตัวถูกดำเนินการและผลลัพธ์เมื่อใดก็ตามที่เป็นไปได้
ดังนั้นฉันคิดว่าเป็นหนึ่งใน commonalities ที่ใหญ่ที่สุดระหว่าง CLR และ JVM
สำหรับความแตกต่าง ...
ความแตกต่างที่น่าสนใจอย่างหนึ่งระหว่างการนำไปใช้งานสองอย่างคือ CLR มีคำแนะนำสำหรับการสร้างประเภททั่วไป ดังนั้น ณ รันไทม์ CLR จะพิจารณา List <int> เป็นประเภทที่แตกต่างอย่างสิ้นเชิงจาก List <String>
ภายใต้หน้าปกมันใช้ MSIL เดียวกันสำหรับความเชี่ยวชาญเฉพาะประเภทการอ้างอิงทั้งหมด (ดังนั้นรายการ <String> จะใช้การดำเนินการเช่นเดียวกับรายการ <Object> ที่มีการคาสต์ประเภทต่าง ๆ ที่ขอบเขต API) แต่การใช้ค่าแต่ละประเภทนั้น การใช้งานที่ไม่ซ้ำกันของตัวเอง (รายการ <int> สร้างรหัสที่แตกต่างอย่างสิ้นเชิงจากรายการ <double>)
ใน Java ประเภททั่วไปเป็นเคล็ดลับเรียบเรียง JVM ไม่มีความเห็นว่าคลาสใดมีอาร์กิวเมนต์ชนิดและไม่สามารถดำเนินการทางพารามิเตอร์เฉพาะในเวลารันไทม์
จากมุมมองที่ใช้งานได้จริงนั่นหมายความว่าคุณไม่สามารถโอเวอร์โหลดเมธอด Java ในประเภททั่วไปได้ คุณไม่สามารถมีสองวิธีที่แตกต่างกันโดยใช้ชื่อเดียวกันต่างกันเพียงว่าพวกเขายอมรับ List <String> หรือ List <Date> แน่นอนเนื่องจาก CLR รู้เกี่ยวกับประเภทพารามิเตอร์จึงไม่มีวิธีการจัดการกับปัญหาที่เกิดขึ้นกับความเชี่ยวชาญประเภททั่วไป
ในแต่ละวันนั่นคือความแตกต่างที่ฉันสังเกตเห็นมากที่สุดระหว่าง CLR และ JVM
ความแตกต่างที่สำคัญอื่น ๆ ได้แก่ :
CLR มีการปิด (ดำเนินการในฐานะตัวแทน C #) JVM รองรับการปิดเฉพาะตั้งแต่ Java 8
CLR มี coroutines (นำไปใช้กับคำหลัก C # 'yield') JVM ไม่ได้
CLR ช่วยให้รหัสผู้ใช้สามารถกำหนดประเภทของค่าใหม่ (structs) ในขณะที่ JVM มีการจัดเก็บประเภทค่าคงที่ (ไบต์สั้น, int, ยาว, ลอย, สอง, ถ่าน, บูลีน) และอนุญาตให้ผู้ใช้กำหนดการอ้างอิงใหม่เท่านั้น ประเภท (คลาส)
CLR ให้การสนับสนุนในการประกาศและจัดการพอยน์เตอร์ สิ่งนี้น่าสนใจเป็นพิเศษเพราะทั้ง JVM และ CLR ใช้การรวบรวมขยะที่เข้มงวดในการวางระบบเพื่อใช้เป็นกลยุทธ์การจัดการหน่วยความจำ ภายใต้สถานการณ์ปกติ GC ที่มีการบีบอัดอย่างเข้มงวดมีช่วงเวลาที่ยากลำบากกับพอยน์เตอร์เนื่องจากเมื่อคุณย้ายค่าจากตำแหน่งหน่วยความจำหนึ่งไปยังตำแหน่งอื่นพอยน์เตอร์ทั้งหมด (และพอยน์เตอร์ไปยังพอยน์เตอร์) จะไม่ถูกต้อง แต่ CLR จัดให้มีกลไก "การตรึง" เพื่อให้นักพัฒนาสามารถประกาศบล็อกของรหัสที่ CLR ไม่ได้รับอนุญาตให้ย้ายตัวชี้บางอย่าง มันสะดวกมาก
หน่วยที่ใหญ่ที่สุดของรหัสใน JVM นั้นเป็น 'แพ็คเกจ' ที่เห็นได้จากคำสำคัญ 'ที่ได้รับการปกป้อง' หรือ JAR (เช่น Java ARchive) เป็นหลักฐานโดยสามารถระบุขวดใน classpath และให้มันเหมือนโฟลเดอร์ ของรหัส ใน CLR คลาสจะถูกรวมเข้าใน 'แอสเซมบลี' และ CLR จัดเตรียมตรรกะสำหรับเหตุผลเกี่ยวกับและจัดการแอสเซมบลี (ซึ่งถูกโหลดลงใน "AppDomains" ให้แซนด์บ็อกซ์ระดับย่อยสำหรับการจัดสรรหน่วยความจำ
รูปแบบ CLR bytecode (ประกอบด้วยคำสั่ง MSIL และข้อมูลเมตา) มีประเภทคำสั่งน้อยกว่า JVM ใน JVM ทุกการดำเนินการที่ไม่ซ้ำกัน (เพิ่มสองค่า int เพิ่มสองค่าลอย ฯลฯ ) มีคำสั่งที่เป็นเอกลักษณ์ของตัวเอง ใน CLR คำสั่ง MSIL ทั้งหมดคือ polymorphic (เพิ่มสองค่า) และคอมไพเลอร์ JIT มีหน้าที่กำหนดประเภทของตัวถูกดำเนินการและสร้างรหัสเครื่องที่เหมาะสม ฉันไม่ทราบว่าเป็นกลยุทธ์ที่ดีกว่าแม้ว่า ทั้งสองมีการแลกเปลี่ยน คอมไพเลอร์ HotSpot JIT สำหรับ JVM สามารถใช้กลไกการสร้างรหัสที่ง่ายขึ้น (ไม่จำเป็นต้องกำหนดชนิดของตัวถูกดำเนินการเพราะมันถูกเข้ารหัสในคำสั่งแล้ว) แต่นั่นหมายความว่ามันต้องการรูปแบบไบต์ที่ซับซ้อนมากขึ้น ด้วยคำแนะนำเพิ่มเติมประเภท
ฉันใช้ Java (และชื่นชม JVM) มาประมาณสิบปีแล้ว
แต่ในความคิดของฉัน CLR คือตอนนี้การใช้งานที่เหนือกว่าในเกือบทุกทาง