MSIL ve Java bayt kodu arasındaki farklar?


Yanıtlar:


75

Öncelikle, Java bayt kodu ve MSIL arasındaki ince farkların acemi bir .NET geliştiricisini rahatsız etmesi gereken bir şey olduğunu düşünmediğimi söylememe izin verin. Her ikisi de, sonunda kullanılan fiziksel makinenin üzerindeki bir katman olan soyut bir hedef makineyi tanımlamak için aynı amaca hizmet eder.

MSIL ve Java bayt kodu çok benzer, aslında Grasshopper adında MSIL'i Java bayt koduna çeviren bir araç var, Grasshopper geliştirme ekibinin bir parçasıydım, böylece (soluk) bilgilerimi biraz paylaşabilirim. NET framework 2.0 çıktığında bu konu üzerinde çalışmayı bıraktığımı lütfen unutmayın, bu yüzden bunlardan bazıları artık doğru olmayabilir (eğer öyleyse lütfen bir yorum bırakın ve ben düzelteceğim).

  • .NET, normal başvuru semantiğine ( struct) ek olarak değer semantiğine sahip kullanıcı tanımlı türlere izin verir .
  • .NET işaretsiz türleri destekler, bu komut kümesini biraz daha zengin hale getirir.
  • Java, bayt kodunda yöntemlerin istisna belirtimini içerir. İstisna belirtimi genellikle yalnızca derleyici tarafından zorlansa da, varsayılandan farklı bir sınıf yükleyici kullanılırsa JVM tarafından zorlanabilir.
  • .NET jenerikleri IL cinsinden ifade edilirken Java jenerikleri yalnızca tür silmeyi kullanır .
  • .NET özniteliklerinin Java'da eşdeğeri yoktur (bu hala doğru mu?).
  • NET enumsise çok daha tamsayı türlerinden etrafında sarmalayıcıları daha olmayan Javaenums (sayesinde hemen hemen tam teşekkülü sınıfları şunlardır İnternet Arkadaşlar yorumlama için).
  • .NET vardır outve refparametreleri.

Başka dil farklılıkları da vardır, ancak bunların çoğu bayt kodu seviyesinde ifade edilmez, örneğin bellek Java'nın staticiç olmayan sınıflarına (.NET'te bulunmayan) bir bayt kodu özelliği sunmuyorsa, derleyici ek bir argüman oluşturur. iç sınıfın yapıcısı ve dış nesneyi iletir. Aynısı .NET lambda ifadeleri için de geçerlidir.


Özniteliklerle ilgili olarak - Java ek açıklamaları bayt kodunda da görünecek şekilde ayarlanabilir, bu nedenle bir eşdeğeri vardır.
Meşe

@Oak: Java açıklamaları yalnızca veri geçişine izin verirken, .NET öznitelikleri, mantığa sahip olabilecek ve en önemlisi arabirimleri uygulayan tamamen güçlendirilmiş sınıflardır.
Fyodor Soikin

Bytecode ayrıca her tür dönüş türü için ayrı bir dönüş talimatına sahiptir, eğer gerçekten tip güvenliğine yardımcı olursa dunno.
Cecil Dishwasher

1
.NET'teki değer türlerinin bazen yığına tahsis edilebilmesi, değer anlamlarına sahip olmalarına kıyasla önemsiz bir öneme sahiptir ; Her değer-tipi depolama konumu olan bir örneği. Buna karşılık, Java'daki her depolama konumu ya ilkel ya da rastgele bir nesne referansıdır; başka tür yok.
supercat

1
Performansı akıllıca nasıl karşılaştırdıklarını merak ediyor muydunuz? MSIL, örneğin bayt kodunu yorumlamak için daha hızlı mıdır?
Luke T O'Brien

23

CIL (MSIL için doğru isim) ve Java bayt kodu, farklı olduklarından daha fazla aynıdır. Yine de bazı önemli farklılıklar var:

1) CIL, başından beri birden çok dil için bir hedef olarak hizmet etmek üzere tasarlanmıştır. Bu nedenle, imzalı ve işaretsiz türler, değer türleri, işaretçiler, özellikler, temsilciler, olaylar, jenerikler, tek kökü olan bir nesne sistemi ve daha fazlasını içeren çok daha zengin bir tür sistemini destekler. CIL, global işlevler ve kuyruk arama optimizasyonları gibi ilk CLR dilleri (C # ve VB.NET) için gerekli olmayan özellikleri destekler . Karşılaştırıldığında, Java bayt kodu Java dili için bir hedef olarak tasarlanmıştır ve Java'nın kendisinde bulunan kısıtlamaların çoğunu yansıtır. Java bayt kodu kullanarak C veya Şema yazmak çok daha zor olurdu.

2) CIL, yerel kitaplıklara ve yönetilmeyen koda kolayca entegre olacak şekilde tasarlanmıştır

3) Java bayt kodu yorumlanacak veya derlenecek şekilde tasarlanırken, CIL yalnızca JIT derlemesi varsayılarak tasarlandı. Bununla birlikte, Mono'nun ilk uygulaması bir JIT yerine bir yorumlayıcı kullandı.

4) CIL, doğrudan bayt kodu formuyla eşleşen, insan tarafından okunabilir ve yazılabilir bir montaj dili formuna sahip olacak şekilde tasarlanmış ( ve belirtilmiştir ). Java bayt kodunun (adından da anlaşılacağı gibi) yalnızca makine tarafından okunabilir olması gerektiğine inanıyorum. Elbette, Java bayt kodu, orijinal Java'ya nispeten kolay bir şekilde geri derlenebilir ve aşağıda gösterildiği gibi, aynı zamanda "parçalarına ayrılabilir".

JVM'nin (çoğu) CLR'den (herhangi biri) daha yüksek düzeyde optimize edildiğine dikkat etmeliyim. Bu nedenle, ham performans Java bayt kodunu hedeflemeyi tercih etmek için bir neden olabilir. Bu bir uygulama detayıdır.

Bazı insanlar Java bayt kodunun çoklu platform olarak tasarlandığını, CIL ise yalnızca Windows için tasarlandığını söylüyor. Durum bu değil. .NET çerçevesinde bazı "Windows" ismleri vardır ancak CIL'de yoktur.

Yukarıdaki 4) numaralı noktaya örnek olarak, bir süre önce bir Java to CIL derleyicisine bir oyuncak yazdım. Bu derleyiciyi aşağıdaki Java programını beslerseniz:

class Factorial{
    public static void main(String[] a){
    System.out.println(new Fac().ComputeFac(10));
    }
}

class Fac {
    public int ComputeFac(int num){
    int num_aux ;
    if (num < 1)
        num_aux = 1 ;
    else 
        num_aux = num * (this.ComputeFac(num-1)) ;
    return num_aux ;
    }
}

derleyicim aşağıdaki CIL'yi çıkaracak:

.assembly extern mscorlib { }
.assembly 'Factorial' { .ver  0:0:0:0 }
.class private auto ansi beforefieldinit Factorial extends [mscorlib]System.Object
{
   .method public static default void main (string[] a) cil managed
   {
      .entrypoint
      .maxstack 16
      newobj instance void class Fac::'.ctor'()
      ldc.i4 3
      callvirt instance int32 class Fac::ComputeFac (int32)
      call void class [mscorlib]System.Console::WriteLine(int32)
      ret
   }
}

.class private Fac extends [mscorlib]System.Object
{
   .method public instance default void '.ctor' () cil managed
   {
      ldarg.0
      call instance void object::'.ctor'()
      ret
   }

   .method public int32 ComputeFac(int32 num) cil managed
   {
      .locals init ( int32 num_aux )
      ldarg num
      ldc.i4 1
      clt
      brfalse L1
      ldc.i4 1
      stloc num_aux
      br L2
   L1:
      ldarg num
      ldarg.0
      ldarg num
      ldc.i4 1
      sub
      callvirt instance int32 class Fac::ComputeFac (int32)
      mul
      stloc num_aux
   L2:
      ldloc num_aux
      ret
   }
}

Bu, ilasm.exebir yürütülebilir dosya oluşturmak gibi bir CIL derleyicisine beslenebilen geçerli bir CIL programıdır . Gördüğünüz gibi, CIL tamamen okunabilir ve yazılabilir bir dildir. Herhangi bir metin düzenleyicide kolayca geçerli CIL programları oluşturabilirsiniz.

Ayrıca yukarıdaki Java programını javacderleyiciyle derleyebilir ve ardından ortaya çıkan sınıf dosyalarını javap"disassembler" aracılığıyla çalıştırarak aşağıdakileri elde edebilirsiniz:

class Factorial extends java.lang.Object{
Factorial();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   new #3; //class Fac
   6:   dup
   7:   invokespecial   #4; //Method Fac."<init>":()V
   10:  bipush  10
   12:  invokevirtual   #5; //Method Fac.ComputeFac:(I)I
   15:  invokevirtual   #6; //Method java/io/PrintStream.println:(I)V
   18:  return

}

class Fac extends java.lang.Object{
Fac();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public int ComputeFac(int);
  Code:
   0:   iload_1
   1:   iconst_1
   2:   if_icmpge   10
   5:   iconst_1
   6:   istore_2
   7:   goto    20
   10:  iload_1
   11:  aload_0
   12:  iload_1
   13:  iconst_1
   14:  isub
   15:  invokevirtual   #2; //Method ComputeFac:(I)I
   18:  imul
   19:  istore_2
   20:  iload_2
   21:  ireturn
}

javapÇıkışı (bildiğim kadarıyla) derlenebilir değil ama CIL çıkışına karşılaştırmak takdirde iki çok benzer olduğunu görebilirsiniz yukarıda.


2
İnsan tarafından okunabilir / yazılabilir bir Java derleme dili oluşturma girişimlerinin olduğu ortaya çıktı. Bulduğum iki tanesi Jasmin ve Java Bytecode Assembler
Justin

2
Burada çok daha iyi bir tane yazdım. Jasmin'den farklı olarak, herhangi bir geçerli sınıf dosyasını parçalarına ayırıp yeniden birleştirebilmek için tasarlanmıştır. github.com/Storyyeller/Krakatau . Java kodlayıcılarının kendilerininkini yapması gerekirken Microsoft'un standart bir derleyici sağladığını söylemek daha doğru olur diye düşünüyorum.
Antimon

22

Esasen aynı şeyi yapıyorlar, MSIL, Microsoft'un Java bayt kodu sürümüdür.

Dahili olarak temel farklılıklar şunlardır:

  1. Bayt kodu hem derleme hem de yorumlama için geliştirilmiştir, MSIL ise JIT derlemesi için özel olarak geliştirilmiştir.
  2. MSIL, yalnızca Java için yazılan Bytecode'a karşı birden çok dili (C # ve VB.NET, vb.) Desteklemek için geliştirilmiştir, bu da Bytecode'un sözdizimsel olarak Java'ya IL'den herhangi bir belirli .NET diline benzemesine neden olur.
  3. MSIL, değer ve başvuru türleri arasında daha açık bir tanıma sahiptir

Bu makalede çok daha fazla bilgi ve ayrıntılı bir karşılaştırma K John Gough tarafından bulunabilir (postscript belgesi)


"1. Bytecode hem derleme hem de yorumlama için geliştirildi, MSIL ise JIT derlemesi için özel olarak geliştirildi" - Bu, Java kodunun bayt koduna nasıl derlendiğini VE bu bayt kodunun nasıl yorumlandığını anlatıyor. Doğrumuyum? MSIL yürütülecek şekilde yorumlanmıyor mu?
Abdul

2

CIL aka MSIL, insan tarafından okunabilir olması amaçlanmıştır. Java bayt kodu değil.

Java bayt kodunu, var olmayan (ancak JVM'lerin taklit ettiği) donanım için makine kodu olarak düşünün.

CIL daha çok assembly dili gibidir - makine kodundan bir adım ötede, yine de insan tarafından okunabilir.


Onaltılık düzenleyiciniz olduğu sürece bayt kodu aslında çok okunabilir. Sınıfların ve yöntemlerin doğrudan temsili için uzantıları olan oldukça basit, yığın tabanlı bir dildir. MSIL'in daha düşük seviyede olduğunu düşündüm (örneğin, kayıtlar)?
Daniel Spiewak

en.wikibooks.org/wiki/… en.wikibooks.org/wiki/… Biri ham CIL'dir. Diğeri demonte bayt kodudur. Bytecode, hex'e basarsanız makul bir şekilde okunabilir, ancak bu bir tasarım amacı değildir.
ince

"Demonte" gerçekten onun için yanlış bir kelime. "Kod çözülmüş" olabilir. Bytecode, .class dosyalarında yalnızca kompaktlık için okunamaz. Javap'ın man sayfasının tersine, derlenmiş bir sınıftan okunabilir bayt kodu üretmede sökme işlemi yoktur.
Daniel Spiewak

2

O kadar çok fark yok. Her ikisi de yazdığınız kodun ara biçimleridir. Çalıştırıldığında, Sanal makineler yönetilen ara dili çalıştırır, bu da Sanal Makinenin değişkenleri ve çağrıları kontrol ettiği anlamına gelir. Şu anda hatırlamadığım, .Net ve Java'da aynı şekilde çalışabilen bir dil bile var.

Temel olarak, aynı şey için başka bir format

Düzenleme: Dili buldum (Scala dışında): FAN ( http://www.fandev.org/ ), çok ilginç görünüyor, ancak henüz değerlendirmek için zaman yok


Scala, sırasıyla bayt kodu veya MSIL oluşturarak JVM veya CLR'yi hedefleyecek şekilde derlenebilir.
Daniel Spiewak

Bilmem güzel, ama yaklaşık bir ay önce DZone okurken başka bir dil buldum: Buldum!
Gönderimdeki

1

Kabul edildi, farklılıklar yeni başlayanlar için yeterince küçük. Eğer temelden başlayarak .Net öğrenmek istiyorsanız, Ortak Dil Altyapısına ve Ortak Tip Sistemine bakmanızı tavsiye ederim.



1

Bence MSIL, Java bayt kodu ile değil, "Java bayt kodlarını içeren talimat" ile karşılaştırılmalıdır.

Parçalanmış java bayt kodunun adı yoktur. Adını resmi belgede bulamadığım için "Java Bytecode" resmi olmayan bir takma ad olmalıdır. Java Sınıfı Dosya Dağıtıcı diyor ki

Sınıftaki yöntemlerin her biri için demonte edilmiş kodu, yani Java bayt kodlarını içeren talimatları yazdırır. Bunlar, Java Sanal Makine Belirtiminde belgelenmiştir.

Hem "Java VM talimatları" hem de "MSIL", .NET bayt kodu ve Java kodunda bir araya getirilmiştir ve bunlar insan tarafından okunamaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.