Sebagai semacam tindak lanjut dari pertanyaan yang disebut Perbedaan antara MSIL dan bytecode Java? , apa perbedaan (kesamaan) atau kesamaan dalam cara kerja Mesin Virtual Java versus cara.NET Framework Common Language Runtime (CLR) berfungsi?
Juga, adalah Kerangka NET CLR "mesin virtual" atau tidak memiliki atribut mesin virtual?
Jawaban:
Ada banyak kesamaan antara kedua implementasi (dan menurut saya: ya, mereka berdua "mesin virtual").
Untuk satu hal, keduanya VM berbasis stack, tanpa gagasan "register" seperti yang biasa kita lihat di CPU modern seperti x86 atau PowerPC. Evaluasi semua ekspresi ((1 + 1) / 2) dilakukan dengan mendorong operan ke "tumpukan" dan kemudian mengeluarkan operan tersebut dari tumpukan kapan pun instruksi (tambah, bagi, dll) perlu mengonsumsi operan tersebut. Setiap instruksi mendorong hasilnya kembali ke tumpukan.
Ini adalah cara yang mudah untuk mengimplementasikan mesin virtual, karena hampir semua CPU di dunia memiliki setumpuk, tetapi jumlah register sering berbeda (dan beberapa register memiliki tujuan khusus, dan setiap instruksi mengharapkan operandnya dalam register yang berbeda, dll. ).
Jadi, jika Anda akan memodelkan mesin abstrak, model berbasis stack murni adalah cara yang cukup baik untuk dilakukan.
Tentu saja, mesin nyata tidak beroperasi seperti itu. Jadi kompiler JIT bertanggung jawab untuk melakukan "enregistrasi" dari operasi bytecode, pada dasarnya menjadwalkan register CPU aktual untuk berisi operan dan hasil bila memungkinkan.
Jadi, saya pikir itu adalah salah satu kesamaan terbesar antara CLR dan JVM.
Adapun perbedaan ...
Satu perbedaan yang menarik antara kedua implementasi adalah bahwa CLR mencakup instruksi untuk membuat tipe generik, dan kemudian untuk menerapkan spesialisasi parametrik untuk tipe tersebut. Jadi, pada saat runtime, CLR menganggap Daftar <int> sebagai tipe yang sama sekali berbeda dari Daftar <String>.
Di bawah sampul, ia menggunakan MSIL yang sama untuk semua spesialisasi tipe referensi (jadi Daftar <String> menggunakan implementasi yang sama dengan Daftar <Object>, dengan berbagai tipe-gips di batas-batas API), tetapi setiap tipe nilai menggunakan implementasi uniknya sendiri (Daftar <int> menghasilkan kode yang sangat berbeda dari Daftar <double>).
Di Jawa, tipe generik adalah trik kompiler murni. JVM tidak memiliki gagasan tentang kelas mana yang memiliki tipe-argumen, dan itu tidak dapat melakukan spesialisasi parametrik saat runtime.
Dari perspektif praktis, itu berarti Anda tidak bisa membebani metode Java pada tipe generik. Anda tidak dapat memiliki dua metode berbeda, dengan nama yang sama, hanya berbeda pada apakah mereka menerima Daftar <String> atau Daftar <Tanggal>. Tentu saja, karena CLR tahu tentang tipe parametrik, ia tidak memiliki masalah metode penanganan kelebihan beban pada spesialisasi tipe generik.
Pada basis sehari-hari, itulah perbedaan yang paling saya perhatikan antara CLR dan JVM.
Perbedaan penting lainnya termasuk:
CLR memiliki penutupan (diimplementasikan sebagai delegasi C #). JVM tidak mendukung penutupan hanya sejak Java 8.
CLR memiliki coroutine (diimplementasikan dengan kata kunci 'hasil' C #). JVM tidak.
CLR memungkinkan kode pengguna untuk mendefinisikan tipe nilai baru (struct), sedangkan JVM menyediakan koleksi tetap dari tipe nilai (byte, pendek, int, panjang, float, ganda, char, boolean) dan hanya memungkinkan pengguna untuk menentukan referensi baru- jenis (kelas).
CLR memberikan dukungan untuk mendeklarasikan dan memanipulasi pointer. Ini sangat menarik karena JVM dan CLR menggunakan implementasi pengumpul sampah pemadatan generasi yang ketat sebagai strategi manajemen memori mereka. Dalam keadaan biasa, GC pemadatan yang ketat memiliki waktu yang sangat sulit dengan pointer, karena ketika Anda memindahkan nilai dari satu lokasi memori ke yang lain, semua pointer (dan pointer ke pointer) menjadi tidak valid. Tetapi CLR menyediakan mekanisme "pinning" sehingga pengembang dapat mendeklarasikan blok kode di mana CLR tidak diizinkan untuk memindahkan pointer tertentu. Sangat nyaman.
Unit kode terbesar di JVM adalah 'paket' yang dibuktikan dengan kata kunci 'terproteksi' atau bisa dibilang sebagai JAR (yaitu Java ARchive) yang dibuktikan dengan kemampuan menentukan botol di classpath dan memperlakukannya seperti folder kode. Di CLR, kelas digabungkan menjadi 'majelis', dan CLR memberikan logika untuk penalaran dan memanipulasi majelis (yang dimuat ke "AppDomains", menyediakan kotak pasir sub-aplikasi-tingkat untuk alokasi memori dan eksekusi kode).
Format bytecode CLR (terdiri dari instruksi MSIL dan metadata) memiliki tipe instruksi yang lebih sedikit daripada JVM. Dalam JVM, setiap operasi unik (tambahkan dua nilai int, tambahkan dua nilai float, dll) memiliki instruksi uniknya sendiri. Dalam CLR, semua instruksi MSIL bersifat polimorfik (menambahkan dua nilai) dan kompiler JIT bertanggung jawab untuk menentukan jenis operan dan membuat kode mesin yang sesuai. Saya tidak tahu strategi mana yang lebih disukai. Keduanya memiliki trade-off. Kompiler JIT HotSpot, untuk JVM, dapat menggunakan mekanisme pembuatan kode yang lebih sederhana (tidak perlu menentukan tipe operan, karena mereka sudah dikodekan dalam instruksi), tetapi itu berarti membutuhkan format bytecode yang lebih kompleks, dengan lebih banyak jenis instruksi.
Saya telah menggunakan Java (dan mengagumi JVM) selama sekitar sepuluh tahun sekarang.
Tapi, menurut saya, CLR sekarang merupakan implementasi yang unggul, dalam hampir setiap cara.
sumber
Pertanyaan pertama Anda adalah membandingkan JVM dengan .NET Framework - Saya menganggap Anda sebenarnya bermaksud membandingkan dengan CLR. Jika demikian, saya pikir Anda bisa menulis buku kecil tentang ini ( EDIT: sepertinya Benji sudah punya :-)
Satu perbedaan penting adalah bahwa CLR dirancang untuk menjadi arsitektur bahasa-netral, tidak seperti JVM.
Perbedaan penting lainnya adalah bahwa CLR dirancang khusus untuk memungkinkan interoperabilitas tingkat tinggi dengan kode asli. Ini berarti bahwa CLR harus mengelola keandalan dan keamanan ketika memori asli diakses dan dimodifikasi, dan juga mengelola marshalling antara struktur data berbasis CLR dan struktur data asli.
Untuk menjawab pertanyaan kedua Anda, istilah "mesin virtual" adalah istilah yang lebih lama dari dunia perangkat keras (mis. Virtualisasi IBM 360 pada tahun 1960-an) yang dulu berarti emulasi perangkat lunak / perangkat keras dari mesin yang mendasarinya untuk mencapai jenis yang sama. hal-hal yang dilakukan VMWare.
CLR sering disebut sebagai "mesin eksekusi". Dalam konteks ini, itulah implementasi Mesin IL di atas x86. Ini juga yang dilakukan JVM, meskipun Anda bisa berargumen bahwa ada perbedaan penting antara bytecode polimorfik CLR dan bytecode yang diketik oleh JVM.
Jadi jawaban yang bagus untuk pertanyaan kedua Anda adalah "tidak". Tapi itu benar-benar sampai pada bagaimana Anda mendefinisikan kedua istilah ini.
EDIT: Satu lagi perbedaan antara JVM dan CLR adalah bahwa JVM (versi 6) sangat enggan untuk melepaskan memori yang dialokasikan kembali ke sistem operasi, bahkan di mana pun bisa.
Misalnya, katakanlah proses JVM dimulai dan mengalokasikan 25 MB memori dari sistem operasi pada awalnya. Kode aplikasi kemudian mencoba alokasi yang membutuhkan tambahan 50 MB. JVM akan mengalokasikan tambahan 50 MB dari sistem operasi. Setelah kode aplikasi berhenti menggunakan memori itu, itu dikumpulkan sampah dan ukuran tumpukan JVM akan berkurang. Namun, JVM hanya akan membebaskan memori sistem operasi yang dialokasikan dalam keadaan tertentu yang sangat spesifik . Kalau tidak, untuk sisa proses seumur hidup memori itu akan tetap dialokasikan.
CLR, di sisi lain, melepaskan memori yang dialokasikan kembali ke sistem operasi jika tidak lagi diperlukan. Pada contoh di atas, CLR akan merilis memori setelah tumpukan berkurang.
sumber
CLR dan JVM keduanya mesin virtual.
.NET Framework dan Java Runtime Environment adalah bundling dari masing-masing VM dan pustaka mereka. Tanpa perpustakaan, VM sangat tidak berguna.
sumber
Lebih spesifik tentang perbedaan dapat ditemukan di dari berbagai sumber akademik dan swasta. Salah satu contoh yang baik adalah Pilihan Desain CLR .
Beberapa contoh spesifik termasuk:
sumber
Ini bukan mesin virtual, .net framework mengkompilasi rakitan ke dalam binary asli pada saat dijalankan pertama kali:
Dalam komputasi, kompilasi just-in-time (JIT), juga dikenal sebagai terjemahan dinamis, adalah teknik untuk meningkatkan kinerja runtime dari program komputer. JIT dibangun berdasarkan dua ide sebelumnya dalam lingkungan run-time: kompilasi bytecode dan kompilasi dinamis. Ini mengkonversi kode pada saat runtime sebelum menjalankannya secara asli, misalnya bytecode menjadi kode mesin asli. Peningkatan kinerja atas interpreter berasal dari caching hasil menerjemahkan blok kode, dan tidak hanya mengevaluasi kembali setiap baris atau operan setiap kali bertemu (lihat Bahasa yang ditafsirkan). Ia juga memiliki kelebihan dibandingkan dengan mengkompilasi kode secara statis pada waktu pengembangan, karena dapat mengkompilasi ulang kode jika ini dianggap menguntungkan, dan mungkin dapat menegakkan jaminan keamanan.
Beberapa lingkungan runtime modern, seperti Microsoft .NET Framework, sebagian besar implementasi Java, dan yang terbaru Actionscript 3, bergantung pada kompilasi JIT untuk eksekusi kode berkecepatan tinggi.
Sumber: http://en.wikipedia.org/wiki/Just-in-time_compilation
Menambahkan .NET framework berisi mesin virtual, seperti halnya Java.
sumber