JVM Kod Üretme Yaklaşımları
Java ortamı bilindiği üzere, platform bağımsızlığı avantajıyla ve bir kere yaz heryerde çalıştır sloganıyla dillere destan olmuş bir ekosistem. Java platform bağımsızlığı özelliğini JVM adındaki sanal makinaya ve bir ara kod olan ByteCode’ a borçlu. Şimdi sizlerle zaman içerisinde Java kodundan, platforma özgü/bağımlı yerel koda (native code) dönüşümde kullanılan tekniklerden bahsetmek istiyorum. Öncelikle basit bir Java kodundan ByteCode’ a dönüşüm nasıl sağlanıyor bundan bahsetmek istiyorum.
Söz konusu Java kodumuz:
public class Toplama{
public static void main(String[] args){
new Toplama().topla(3,5);
}
public int topla(int a,int b){
return (a+b);
}}
Öncelikle bilindiği üzere .java uzantılı sınıftan ByteCode üretmek için .class uzantılı dosyalar elde etmemiz gerekiyor. Bunun için ise javac (Java Compiler) kullanılıyor.
> javac Toplama.java
Bu işlemden sonra Toplama.java dosyasıyla aynı dizinde bir de Toplama.class dosyası oluşuyor. Toplama.class dosyası içerisinde sınıfımıza ait ByteCode ve ByteCode’a dair JVM’in kullanacağı ek bildirimler (metadata) mevcut. “class” uzantılı dosyamız içerisindeki ByteCode’ u görmek için ise javap aracını kullanabiliriz. (jdk’nın içinde).
> javap -c Toplama > toplama.txt
Bu komut icra edildikten sonra toplama.txt içerisinde ByteCode çıktısı elde edilmiş olacak.
ByteCode çıktısı:
Compiled from "Toplama.java"
public class Toplama {
public Toplama();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class Toplama
3: dup
4: invokespecial #3 // Method "<init>":()V
7: iconst_3
8: iconst_5
9: invokevirtual #4 // Method topla:(II)I
12: pop
13: return
public int topla(int, int);
Code:
0: iload_1
1: iload_2
2: iadd
3: ireturn
}
Bu noktada ByteCode ayrıntılarından pek bahsetmeyeceğim ama sonraki yazılarda buna değinebilirim. Şimdi ByteCode çıktısından platform bağımsız koşturma nasıl gerçekleştiriliyor bunlardan bahsedilmek istiyorum.
Pure bytecode interpretation
Bu yöntemde temel olarak ByteCode’ lar satır satır yorumlayıcı (interpreter) aracılığı ile işlemcide koşturuluyor. Çalışma anında herhangi bir bir metod üzerinde değişiklik gerçekleşirse, ByteCode’ lar satır satır işletildiği için herhangi bir problemle karşılaşılmadan süreç devam ediyor. Sun MicroSystem’ in ilk JVM implementasyonu bu teknik ile platform bağımsızlığını elde etmekte idi.
Static compilation
ByteCode ismi 8 bit=1 Byte eşitliğinden gelmekte. ByteCode komut kümesinde 255 adet komut bulunuyor. 2^8 = 255 olduğu için neden ByteCode dendiği anlaşılabilir. ByteCode’un sağladığı geniş komut kümesi ve JVM sayesinde yazılan programlar platform bağımsız şekilde koşturuluyor demiştik. ByteCode işlemci komut setlerine nazaran daha zengin komut kümesine sahip olduğu için Java > ByteCode dönüşümünde işlemciye ait yerel koda (native code) nazaran kod işletiminde performans kayıpları oluşmaktayd. Örneğin her bir byte kodu bir işlemci cycle’ da işletildiğini düşünürsek, bu method işletimi 4 işlemci çeviriminde tamamlanmış olacak. Peki bu metodla aynı işi gören yerel assembly kodunu kaç çevrimde koşturabiliriz?
topla(..) metodunun assembly dili karşılığı (x86 işlemci ailesine göre)
add eax, edx // eax = edx+eax ret // return eax
Bu iki satırlık assembly kodu 2 çevrimde iki sayının toplama görevini gerçekleştirebilir.
Static compilation’ da bir compiler aracılığı ile yazılan program işlemciden koşturulmadan evvel platforma bağımlı yerel koda dönüştürülmekteydi. Bu sayede performans kayıpları da küçük mertebelere çekilmekteydi. Bu tekniğin dez avantajı ise platform bağımsızlığını devredışı bırakmak oluşturmaktadır. Bu tekniğe ayrıca Ahead-of-time compilation’ da denmektedir.
Total JIT compilation
Sunucu taraflı uygulamalarda performans çok önemli bir etkendir. Salt yorumlama yoluyla kod işletimi performans kayıplarına neden olurken, Static compilation tekniğinde ise platform bağımsızlığı bir tehdit olmaktaydı. Bu sebeple yeni bir yaklaşım olarak JIT (Just-in-Time) compiler/derleyici karşımıza çıkmaktadır. JIT compiler ile byte kodlar çalışma anında ve metodla karşılaşır karşılaşılmaz platforma özgü yerel koda dönüştürülmekte. Bu sayede platform bağımsızlığı da sağlanmış oluyor. Bu yöntemdeki zayıf nokta ise bytecode > native code dönüşümünün çalışma anında uzun vakit alması yani yavaş olması. Fakat derleme işlemi gerçekleştikten sonra salt yorumlama yöntemine göre fazlaca performans kazancı gerçekleşmekte. Derleme işleminin yavaş olmasına çözüm olması için derleme işlemi kademelere ayrılmaktadır. Sık işletilen metodlara ayrı muamele az karşılaşılan metodlara ayrı muamele yapılmaktadır. Sık işletilen metodlara (hot), az karşılaşılan metodlara ise (cold) denmektedir. Sık karşılaşılan (hot) metodları daha performanslı işletmek için daha fazla analiz/optimizasyon imkanı JVM tarafından sağlanmaktadır. Bir metodun hot yada cold olduğuna kanaat getirmek için çeşitli teknikler var fakat burada onlara değinmeyeceğim. Dünya üzerinde JVM şartnamesine uyan birden fazla JVM uygulayıcısı mevcut. JIT compilation tekniğinin en önde uygulayıcısı bir Oracle ürünü olan JRockit. JRockit özellikle sunucu tarafında yüksek performans çözümlerinden dolayı tercih ediliyor ve JRockit içinde interpretation / yorumlama tekniği kesinlikle bulunmuyor. Geliştirme aşamasında JRockit’ in bedava olduğunu, ticari faaliyetler için ücretli olduğunu söyleyebilirim.
Mixed mode interpretation
Mixed mode interpretation yöntemi ise hem JIT compilation hem de Salt interpretation tekniğinin alaşımı denebilir.
Mixed mode interpretation yönteminde başlangıçta tüm metodlar yorumlama / interpretation tekniğiyle satır satır koşturuluyor. Zaman içerisinde adaptif olarak sık karşılaşılan / hot metodlar performans artışı için JIT compilation’ a tabi tutuluyorlar. JIT compilation yönteminde olduğu gibi optimizasyon yine kademe kademe uygulanıyor. Mixed mode interpretation tekniğinin en ünlü uygulayısı HotSpot JVM olarak karşımıza çıkıyor. Oracle firması JRockit ve HotSpot JVM ‘leri birleştirerek türünün en iyi JVM’i 🙂 anlamına gelen “best of breed JVM” yani HotRockit için çalışmalara da devam ediyor.
Tekrardan görüşmek dileğiyle, esen kalın.
2 Comments