Her iki uygulama arasında birçok benzerlik var (ve bence: evet, her ikisi de "sanal makineler").
Birincisi, ikisi de yığın tabanlı VM'ler, x86 veya PowerPC gibi modern bir CPU'da görmeye alışık olduğumuz gibi "kayıt" kavramı yok. Tüm ifadelerin ((1 + 1) / 2) değerlendirilmesi, işlenenlerin "yığın" üzerine itilmesi ve daha sonra bir talimatın (ekleme, bölme, vb.) Bu işlenenleri tüketmesi gerektiğinde bu işlenenleri yığından atmak suretiyle gerçekleştirilir. Her talimat sonuçlarını yığına geri iter.
Sanal bir makine uygulamak için uygun bir yoldur, çünkü dünyadaki hemen hemen her CPU'nun bir yığını vardır, ancak kayıt sayısı genellikle farklıdır (ve bazı kayıtlar özel amaçlıdır ve her talimat, işlenenlerini farklı kayıtlarda vb. ).
Yani, soyut bir makineyi modelleyecekseniz, tamamen yığın tabanlı bir model gitmek için oldukça iyi bir yoldur.
Tabii ki, gerçek makineler bu şekilde çalışmaz. Bu nedenle JIT derleyicisi, bayt kodu işlemlerinin "kayıt" işleminden, esasen gerçek CPU kayıtlarını mümkün olduğunda işlenenleri ve sonuçları içerecek şekilde programlamaktan sorumludur.
Bence bu CLR ve JVM arasındaki en büyük ortak noktalardan biri.
Farklılıklara gelince ...
İki uygulama arasındaki ilginç bir fark, CLR'nin genel türler oluşturmak ve daha sonra bu türlere parametrik uzmanlıklar uygulamak için talimatlar içermesidir. Bu nedenle, çalışma zamanında, CLR bir List <int> öğesini bir List <String> öğesinden tamamen farklı bir tür olarak kabul eder.
Kapakların altında, tüm başvuru türü uzmanlıkları için aynı MSIL'i kullanır (bu nedenle bir Liste <String>, API sınırlarında farklı tür yayınları olan bir Liste <Object> ile aynı uygulamayı kullanır), ancak her değer türü kullanır kendi benzersiz uygulaması (Liste <int> Liste <double> 'den tamamen farklı bir kod üretir).
Java'da genel türler tamamen derleyici bir numaradır. JVM'nin hangi sınıfların tür bağımsız değişkenleri olduğu hakkında hiçbir fikri yoktur ve çalışma zamanında parametrik uzmanlıklar gerçekleştiremez.
Pratik açıdan bakıldığında, genel türlerde Java yöntemlerini aşırı yükleyemeyeceğiniz anlamına gelir. Aynı ada sahip iki farklı yönteme sahip olamazsınız, yalnızca bir Liste <Dizleme> veya bir Liste <Tarih> kabul edip etmediklerine göre farklılık gösterir. Tabii ki, CLR parametrik türleri bildiğinden, genel tip uzmanlıklarına aşırı yüklenmiş sorun giderme yöntemleri yoktur.
Günlük bazda, CLR ve JVM arasında en çok fark ettiğim fark bu.
Diğer önemli farklılıklar şunları içerir:
CLR'nin kapanışları vardır (C # delegeleri olarak uygulanır). JVM, yalnızca Java 8'den beri kapanmaları destekler.
CLR'de (C # 'verim' anahtar kelimesiyle uygulanan) couteinler bulunur. JVM bunu yapmaz.
CLR, kullanıcı kodunun yeni değer türleri (yapılar) tanımlamasına izin verirken, JVM sabit bir değer türleri koleksiyonu (bayt, kısa, int, uzun, kayan nokta, çift, karakter, boole) sağlar ve yalnızca kullanıcıların yeni referans tanımlamasına izin verir. türleri (sınıfları).
CLR, işaretçilerin bildirilmesi ve işlenmesi için destek sağlar. Bu özellikle ilginçtir çünkü hem JVM hem de CLR, bellek yönetimi stratejisi olarak katı nesil sıkıştırma çöp toplayıcı uygulamaları kullanmaktadır. Sıradan koşullar altında, sıkı bir sıkıştırma GC'sinin işaretçilerle gerçekten zor bir zamanı vardır, çünkü bir değeri bir bellek konumundan diğerine taşıdığınızda, tüm işaretçiler (ve işaretçilerden işaretleyicilere) geçersiz olur. Ancak CLR, geliştiricilerin CLR'nin belirli işaretçileri hareket ettirmesine izin verilmediği bir kod bloğu bildirebilmeleri için bir "sabitleme" mekanizması sağlar. Çok uygun.
JVM'deki en büyük kod birimi ya 'korumalı' anahtar kelime ile kanıtlandığı gibi bir 'paket' ya da sınıf yolunda bir kavanoz belirleyip bir klasör gibi davranarak kanıtlanabilir bir JAR'dır (yani Java ARchive). kod. CLR'de, sınıflar 'derlemeler' halinde toplanır ve CLR, derlemeler hakkında mantık yürütmek ve işlemek için mantık sağlar (bunlar "AppDomains" e yüklenir, bellek ayırma ve kod yürütme için alt uygulama düzeyinde sanal alanlar sağlar).
CLR bayt kodu biçimi (MSIL talimatları ve meta verilerden oluşur) JVM'den daha az komut türüne sahiptir. JVM'de her benzersiz işlemin (iki int değeri ekleyin, iki float değeri ekleyin, vb.) Kendi benzersiz talimatı vardır. CLR'de, tüm MSIL talimatları polimorfiktir (iki değer ekleyin) ve JIT derleyicisi, işlenen türlerini belirlemek ve uygun makine kodu oluşturmaktan sorumludur. Yine de tercih edilen stratejinin hangisi olduğunu bilmiyorum. Her ikisinin de ödünleri var. JVM için HotSpot JIT derleyicisi daha basit bir kod oluşturma mekanizması kullanabilir (talimatlarda zaten kodlandıkları için işlenen türlerini belirlemesine gerek yoktur), ancak bu daha karmaşık bir bayt kodu formatına ihtiyaç duyduğu anlamına gelir, daha fazla talimat türü ile.
Yaklaşık on yıldır Java kullanıyorum (ve JVM'ye hayranım).
Fakat bence CLR şimdi neredeyse her şekilde üstün bir uygulama.