Java Virtual Machine(JVM) Architecture 1

Kerim Fırat
4 min readMay 10, 2021

Java ve Android’de performans konusunu işlerken,buna bağlı olarak bilinmesi gereken en temel konu Java Virtual Machine(JVM) mimarisi’dir.

Soru: JVM’yi Android ile bağdaştırmalı mıyız peki?
Cevap: Elbette. Ancak direkt olarak değil,dolaylı olarak JVM ile Dalvik veya JVM ile ART birbirlerine bağlıdırlar. Bu konuyu,bu makalenin ileriki serilerinde detaylandıracağız. Ancak bu makalade JVM’yi Java temelli ele alacağız.

Virtual Machine(VM)-Sanal Makine Nedir?

JVM(Java Sanal Makine)’ye geçmeden önce,VM(Sanal Makine) kahvramına göz atalım. Bir sanal makine,fiziksel bir bilgisayarın sanal bir temsilcisi denilebilir. Ancak sanal makinenin çalışabilmesi için fiziksel bir bilgisayara ihtiyaç vardır. Yani fiziksel bir bilgisayar ana makine olarak sanal makine veya makineleri desteklemesi gerekir.Dolayısıyla tek bir fiziksel bilgisayar,her biri kendi işletim sistemi ve uygulamalarına sahip birden çok sanal makineyi çalıştırabilir.

Java Sanal Makinesi(JVM) Nedir?

C ve Cpp gibi programlama dillerinde derleme yapılırken,hedef kod ilk olarak platforma özgü makine kodunda derlenir. Bu dillere “derlenmiş diller” denir.

Öte yandan,Python,JavaScript,Php gibi dillerde kodlar derlenmeden çalıştırılabilir. Bu dillere ise “yorumlanmış diller” denir.

Ancak Java,Scala,Kotlin ve Groovy programlama dillerine ise hem “derlenmiş diller” hem de “Yorumlanmış diller” denilebilir. Çünkü bu diller,her iki tekniğin bir kombinasyonunu kullanır. Java’nın çalışma tekniği şu şekilde’dir: Java kodu önce bir .class dosyası oluşturmak için byte kodunda derlenir.Bu .class dosyası daha sonra temel platform olarak JVM tarafından yorumlanarak çalıştırılır. Aynı .class dosyası,herhangi bir platformda ve işletim sisteminde çalışan herhangi bir JVM sürümünde çalıştırılabilir.

Java Sanal Makinesi(JVM) Mimarisi

JVM üç farklı ana bileşenden oluşur.
Bunlar:

1. Class Loader(Sınıf Yükleyici)
2. Runtime Memory-Data Area(Çalışma Zamanı Belleği-Veri Alanı)
3. Execution Engine(Yürütme-Çalıştırma Motoru)

JVM Architecture Diagram

Yukarıda verilen her bir bileşene ayrıntılı bir şekilde bakalım.

-Class Loader:
Bir “.java” kaynak kod dosyası derlendiğinde,bu kaynak kod dosyası byte koduna dönüştürülür ve “.class” olarak yeni bir dosya(.class) oluşturulur. Dönüştürülen bu .class dosyası programda kullanıldığında ve bu dosya çalıştırılırken,class loader bunu belleğe yükler. Bu yükleme işlemi belli bir sıraya göre yapılmaktadır. Bildiğiniz gibi tüm süreçler “main” ana fonksiyonu ve bu fonksiyonun bulunduğu class’dan başlar. Dolayısıyla belleğe yüklenecek ilk class,genellikle “main()” ana fonksiyonu içeren sınıf olacaktır.

Yukarıda verilen görüntüde görüldüğü üzere “Class Loader” kendi içinde üç aşamaya sahiptir. Bunlar:

  • Loading(Yükleme)
  • Linking(Bağlama)
  • Initialization(Başlatma)

-Loading:
Sahip olduğumuz class’lar bu bileşen tarafından yüklenecektir. Bu bileşen bünyesinde bulunan “Bootstrap Class Loader,Extension Class Loader ve Application Class Loader” alt bileşenleri,bunu başarmamıza yardımcı olacak bileşenlerdir. Bu alt bileşenleri inceleyilim.

  • Bootstrap Class Loader: “Loading(Yükleme)” üst bileşeninde en öncelikli yükleyicidir.Öncelikli olmanın sebebi ise,Standart Java Edition’ın tüm sınıflarını içeren “rt.jar” paketini yüklemesidir.
    Bu paket tüm diğer “Loader”’lardan önce yüklenmesi gerekir. Çünkü bu paket içinde “java.lang,java.net,java.util,java.io,…” gibi standart java paketleri bulunur.Dolayısıyla temel java paketleri yüklenmeden diğer aşamaların yüklenmesi tamamen gereksizdir. Çünkü diğer aşamalar bu paketi taban alarak çalışacaktır.
  • Extension Class Loader: İkinci sırada öncelikli olan yükleyicidir. Bu yükleyici “$JAVA_HOME/jre/lib/ext” dizininde bulunan standart java paketlerini(.jar) yükler.
  • Application Class Loader: Bu yükleyici “classpath”’da bulunan class’ları yükler. Default olarak “classpath”,uygulamanın geçerli dizinine ayarlanır. Class yolu ayarlamaları “-classpath” veya “-cp” komutu ile yapılabilir. Dolayısıyla bu yükleyicinin görevi,uygulama seviyesinde olan class’ları yüklemekle sorumludur. Aşağıda uygulama seviyesinde class yüklemeye bir örnek verilmiştir:

-Linking:
Bir class belleğe yüklendikten sonra “bağlama(linking)” sürecinden geçer. Bir class veya arayüzü(interface) bağlamak,programın farklı öğelerini ve bağımlılıklarını bir araya getirmeyi içerir.
Linking(bağlama) işlemi aşağıdaki adımları içerir

  • Verify-Verification: Bu aşama,.class dosyasının yapısal doğruluğunu bir dizi kural veya kısıtlamaya göre kontrol ederek doğrulama işlemi uygular.Yani oluşturulan byte kodunun doğru olup olmadığını,geçerli bir derleyici tarafından oluşturulup oluşturulmadığını doğrulayacaktır. Eğer doğrulama işlemi herhangi bir nedenden dolayı başarısız olursa,”VerifyError,VerifyException” istisnası(Exception) fırlatılacaktır.
    Örneğin,java 16 sürümü kullanılarak uygulama geliştirilmişse ancak java 8 yüklü bir sistemde çalıştırılıyorsa,bu durumda doğrulama aşamasında başarısızlık meydana gelecektir.
  • Prepare-Preparation: Bu aşamada JVM,bir class’ın veya interface’in static alanları için bellek ayırır ve bunları default değerlerle başlatır.
    Örneğin Main.java class’da aşağıdaki değişkeni tanımladığımızı varsayalım:
private static final boolean DEBUG = true;

Bu aşamda JVM DEBUG değişkeni için bellek ayırır ve “true” değerini default olarak ayarlar.

  • Resolve-Resolution: Bu aşamada sembolik referanslar çalışma zamanı sabit havuzunda bulunan doğrudan referanslarla değiştirilir.Örneğin diğer sınıflara veya diğer sınıflarda bulunan sabit değişkenlere referanslarınız varsa,bunlar bu aşamada çözülür ve gerçek referanslarıyla değiştirilir.

-Initialization:
Bu class yüklemenin son aşamasıdır.Bu aşamada class yapıcısını(Constructor) çağırmayı,statik blokları yürütmeyi ve tüm statik değişkenlere değer atamayı içerebilir. Örnek olması açısından şağıdaki kodu inceleyelim.

private static final boolean DEBUG = true;

DEBUG değikeni Preparation(hazırlık) aşamasında “false” değeri default olarak ayarlanır. Ancak Initialization(başlatma) aşamasında bu değişkene gerçek değeri olan “true” atanır.

NOT: JVM çoklu iş parçacığıyla(Multithreaded) çalışır.Birden fazla iş parçacığı aynı anda aynı class’ı başlatmaya çalışıyor olabilir.Bu durum eşzamanlılık sorunlarına yol açacaktır.Programın çoklu iş parçacıklı bir ortamda stabil çalıştığından emin olmamız gerekir.

-end of

--

--

Kerim Fırat

Senior C++,Android Platform(AOSP,AAOS) Developer,Performance Architect,Open Source Contributor | Turkey Java User Group Vice Chairman | Author