Java AOT derleyicileri nasıl çalışır?


18

Java uygulamalarını yerel yürütülebilir dosyalara ( ) dönüştürdüğünü iddia eden birkaç araç ( Excelsior JET , vb.) Var *.exe. Ancak bu benim olduğu anlayış bu araçlar gerçekten sadece çağırmak / çalıştırması yerli sarmalayıcılarını yaratmakta olduğu javabir kabuk veya komut satırından.

Eğer bu anlayış yanlışsa, bunun nasıl olabileceğini anlamıyorum. Çalışan bir JVM ( javaişlem) aslında yüksek performanslı bir yorumlayıcıysa, Java sınıf dosyalarından bayt kodunu anında yüklüyorsa, bir Java uygulamasının (bir JVM'ye girdi görevi gören bayt kodu dosyaları koleksiyonu) hiç nasıl olabileceğini görmüyorum gerçekten çalıştırılabilir bir dosyaya dönüştürülmüş.

JVM süreci olmasıdır zaten girdi olarak baytkod dosyalarının setleri yerli bir yürütülebilir. Bu bayt kodu dosyalarını ve JVM işlemini tek bir yerel yürütülebilir dosyada birleştirmek için, JVM'yi yeniden yazmadan ve JVM belirtiminden korkuluk olmadan birleştirilmiş yerel yürütülebilir dosya mümkün görünmüyor.

Bu yüzden soruyorum: bu araçlar aslında Java sınıfı dosyalarını yerel bir yürütülebilir dosyaya nasıl "dönüştürür"?

Yanıtlar:


26

Tüm programların çalışma zamanı ortamı vardır. Bunu unutmaya eğilimliyiz, ama orada. İşletim sistemine yapılan sistem çağrılarını saran C için standart lib. Objective-C çalışma zamanını ileten tüm mesajını sarar.

Java ile çalışma zamanı JVM'dir. İnsanların aşina olduğu Java uygulamalarının çoğu, bir bayt kodu yorumlayıcısı ve JIT derleyicisi olan HotSpot JVM'ye benzer.

Bunun tek uygulama olması gerekmez. Java için standart bir lib-esque çalışma zamanı oluşturamayacağınızı ve kodu yerel makine koduna derleyemeyeceğinizi ve yeni nesnelerin çağrılarını mallocs'a ve makinedeki sistem çağrılarına dosya erişimini işleyen çalışma zamanı içinde çalıştıramayacağınızı söyleyen kesinlikle hiçbir şey yoktur. Ve bu zamanın öncesinde (JIT yerine AOT) derleyicisinin yaptığı şeydir. Eğer ... Eğer bir JVM uygulaması diyebiliriz ne o çalışma zamanını Çağrı (ve yok JVM şartname izleyin) Java için veya bir yürütme ortamı veya standart lib. Orada ve aslında aynı şeyi yapıyor.

javacYerel makineyi hedeflemek için yeniden uygulayarak yapılabilir ( GCJ'nin yaptığı şey budur). Veya javacbaşka bir makine için üretilen bayt kodunu başka bir makine için makine (veya bayt) koduna çevirerek yapılabilir - Android bunu yapar. Wikipedia'ya dayanarak Excelsior JET de bunu yapar ("Derleyici, taşınabilir Java bayt kodunu istenen donanım ve işletim sistemi (OS) için optimize edilmiş yürütülebilir dosyalara dönüştürür") ve aynı RoboVM için de geçerlidir .

Java ile ek komplikasyonlar vardır, bu da bunun özel bir yaklaşım olarak yapılması çok zor olduğu anlamına gelir . Sınıfların ( class.forName()) veya proxy nesnelerin dinamik yüklenmesi, AOT derleyicilerinin kolayca sağlamadığı dinamikler gerektirir ve bu nedenle ilgili JVM'leri, önceden derlenemeyen sınıfları işlemek için bir JIT derleyicisi (Excelsior JET) veya bir yorumlayıcı (GCJ) içermelidir yerli.

Unutmayın JVM bir özelliğidir , birçok uygulamayla birlikte . C standart kütüphanesi de birçok farklı uygulamaya sahip bir teknik özelliktir .

Java8 ile, AOT derlemesi üzerinde oldukça fazla çalışma yapılmıştır. En iyi ihtimalle, AOT genel olarak sadece metin kutusunun sınırları içinde özetlenebilir. Bununla birlikte, 2015 JVM Dil Zirvesi'nde (Ağustos 2015) bir sunum yapıldı: Java AOT Goes (youtube videosu). Bu video 40 dakika uzunluğunda ve daha derin teknik özelliklerin ve performans kriterlerinin çoğuna giriyor.


Maalesef, bu konuda fazla bir şey bilmiyorum, ama bu java'nın yerli olduğu anlamına mı geliyor? Ya da istersek, java programlarını yerel koda derlememizi sağlayan yeni bir derleyici bayrağı olduğu ve bayt kodunu derleme seçeneğimiz olduğu anlamına mı geliyor?
Pavel

@ paulpaul1076 Bağlantı verdiğim videoyu izlemenizi öneririm. Biraz makul bir yorum içine sığabilecek daha biraz daha var.

4

gcj minimal çalıştırılabilir örnek

Ayrıca gcj(şimdi kullanılmayan) gibi açık kaynaklı bir uygulamayı da gözlemleyebilirsiniz . Örneğin, Java dosyası:

public class Main {
    public static void main(String args[]) {
        System.out.println("hello world");
    }
}

Sonra derleyin ve şununla çalıştırın:

gcj -c Main.java
gcj --main=Main -o Main Main.o
./Main

Şimdi koda dönüştürmekte ve nasıl çalıştığını görmekte özgürsünüz.

file Main.o bir elf dosyası olduğunu söylüyor.

readelf -d Main | grep NEEDED dinamik kütüphanelere bağlı olduğunu söylüyor:

0x0000000000000001 (NEEDED)             Shared library: [libgcj.so.14]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Bu nedenle libgcj.so , Java işlevselliğinin uygulandığı yerde olmalıdır.

Daha sonra aşağıdakilerle kodabilirsiniz:

objdump -Cdr Main.o

ve tam olarak nasıl uygulandığını görün.

C ++, çok sayıda ad yönetimi ve dolaylı polimorfik fonksiyon çağrısı gibi görünüyor.

Çöp koleksiyonunun nasıl devreye girdiğini merak ediyorum. Https://stackoverflow.com/questions/7100776/garbage-collection-implementation-in-compiled-languages ve Go gibi GC ile derlenmiş diğer dillere bakmaya değer .

Ubuntu 14.04, GCC 4.8.4'te test edilmiştir.

Ayrıca Android uygulamalarını optimize etmek için tam AOT yapan Android 5'in omurgası olan https://en.wikipedia.org/wiki/Android_Runtime'a da göz atın .

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.