Java Virtual Machine Nedir?

JVM’nin basit olarak Java programlarını çalıştıran sanal bir makine olduğunu biliyor olabilirsiniz ancak yine de bu yazıyı okumanızı tavsiye ederim. Çünkü JVM hakkında bilinmesi gereken çok ama çok şey var. Bu yazıda bunların bir kısmına değinmeye çalışacağım.

Bildiğiniz gibi Java derleyicisi doğrudan fiziksel bir makinenin çalıştırabileceği makine kodları değil, sadece Java Sanal Makinesinin anlayıp çalıştırabileceği formatta bir kod üretir. Ara bir dil olarak da tanımlanabilen “bytecode”, class uzantılı dosyalar içinde saklanır. Java derleyicisinin işi burada biter ve bundan sonra ikili (binary) formatta kodlanmış olan class dosyalarının çalıştırılması JVM tarafından yapılır.

Java programlarının çalıştırılması C/C++ gibi dillerde yazılan programların çalıştırılmasından çok daha farklıdır. Bu dillerde yazılan kodlar derlendiğinde direk olarak o makinede çalışacak makine kodları üretilir ve koda bağlanması gereken kütüphaneler bağlanarak (linking) çalıştırılabilir bir dosya üretilir. Java derleyicisi ise fiziksel makinede değil Java Sanal Makinesinde çalışabilecek sabit bir kod üretir. Derleme yapıldıktan sonra bağlama yapılmaz. Bağlama işlemleri JVM tarafından program çalışırken dinamik olarak yapılır ki bu da Java’ya büyük bir esneklik kazandırmaktadır.

JVM, class dosyası içerisindeki her bytecode satırını üzerinde çalıştığı platforma uygun bir biçimde makine koduna dönüştürerek çalışmasını sağlar. Bu dönüştürme işlemi genelde yorumlama (interpretation) olarak bilinse de her zaman öyle olmak zorunda değildir. JVM’ler sadece yorumlama değil “just-in-time compiling” tekniğini kullanarak da bytecode’ları çalıştırabilirler.

JVM’nin fiziksel makinenin kendisiyle uygulama arasında bir köprü görevi yaptığı bu yapı Java diline büyük esneklikler ve avantajlar kazandırmaktadır. JVM, Java’nın en önemli özellikleri olan taşınabilirlik, (bir kere yaz her yerde çalıştır) güvenlik gibi özelliklerin sağlanmasında başrolü oynamaktadır. Bu sebeple de Java platformunun en önemli bileşeni olarak kabul edilmektedir. Bir Java programının çalışabilmesi için o platformda mutlaka bir JVM’nin kurulu olması gerekmektedir ve günümüzde hemen hemen bütün platformlar için yazılmış JVM’ler bulunmaktadır. Sun firmasının iddiasına göre dünyada 4.5 milyardan fazla Java uyumlu cihaz bulunmaktadır.

JVM, her ne kadar sanal da olsa sonuçta kendine ait bir komut seti olan, bu komut setine uygun komutları (bytecode) çalıştırabilen bir makinedir. Bu açıdan bakıldığında JVM, komut seti bytecode olan bir işlemcidir. Peki JVM için çalıştıracağı bytecode’un Java’dan üretilmiş olup olmaması fark eder mi? Tabi ki etmez. Yani teorik olarak JVM üzerinde sadece Java programlarını değil, hangi dilde yazılırsa yazılsın bytecode formatına çevirebileceğiniz her programı çalıştırabilisiniz. Bu konuda yapılan çalışmalar tabii ki var. Bu adreste de yapılan bazı çalışmalarla ilgili bilgiler bulabilirsiniz. Bunların yanında C kodunu bytecode’a çevirip JVM üzerinde çalıştırmak için geliştirilmiş  NestedVMC2J, LLJVM gibi projeler var. Çalışıp çalışmadığını ben de bilmiyorum ancak deneyip öğrenmekte fayda var.

Özellikle şunu da belirtmek gerekir ki JVM sanal bir makinedir ve JVM’nin farklı gerçekleştirimleri olabilir. Sun firması tam anlamıyla çalışır bir Java Sanal Makinesi yazabilmek için gerekli belirtimleri (specification) yayınlamıştır ve isteyen herkes bu dokümanı kaynak olarak kullanıp kendi JVM gerçekleştirimini yapabilir, yani kendi JVM’sini yazabilir. Başka bir deyişle Sun, Java dilinde yazılan programları çalıştırabilecek bir Java Sanal Makinesinin gereksinimlerini ortaya koymuştur. IBM gibi büyük firmalar kendi ihtiyaçları doğrultusunda optimize ettikleri JVM’leri kullanmaktadır.

Sun’ın yayınladığı JVM belirtiminde (Hacettepe Bilgisayar öğrencisi iseniz burada Ersin Töreci’nin ders notlarını okuyormuş gibi hissetmeniz olası :D) JVM’nin taşıması gereken özellikler açıkça belirtilmiştir ancak bu özelliklerin nasıl karşılanacağı tasarımcılara bırakılmıştır. Örneğin bir JVM için bytecode işletimi mutlaka olması gereken bir özelliktir. Ancak JVM’nin bu işi nasıl yaptığı her JVM’de farklılık gösterebilir. Yukarıda değindiğim gibi bazı JVM’ler yorumlama yaparken bazıları hem yorumlama hem de “just-in-time compiling” yapabilirler.  Başka bir örnek verecek olursak, java derleyicisi tarafından üretilen class uzantılı dosyaların kullanılmadan önce bir şekilde JVM’ye yüklenmesi gerekmektedir. Bu, her JVM’nin taşıması gereken bir özelliktir ancak sınıfların yüklemesi yapılırken hangi politikanın izleneceği o JVM’yi tasarlayanların karar vereceği bir konudur.

Bir JVM’nin Ömrü

JVM sanal bir makinedir ancak bizim programlarımızdaki bytecode’ları makine kodlarına çevirip programın çalışmasını sağlayabilmek için kendisi de bellekte yer kaplayarak bir program gibi çalışabilmelidir. Bu bölümde bir JVM’nin ne zaman çalışmaya başlayıp ne zaman sonlanacağını aktarmaya çalışacağım.

javac MerhabaDunya.java

komutu çalıştırılarak MerhabaDunya isimli java programının derlendiğini ve bunun sonucunda da MerhabaDunya.class isimli bir dosyanın üretildiğini düşünelim.

Derlenmiş bir java programının çalıştırılması için

java MerhabaDunya

komutunun verilmesi gerekmektedir. “java” komutu sistem tarafından JVM’nin tetiklenmesini sağlar. Yani JVM’nin ömrü bu noktada başlar. Burada önemli bir nokta her JVM’nin yalnızca bir program çalıştırmasıdır. Yani her java programı, kendi JVM’si içerisinde çalışır.

Bizim uygulamamız çalıştıkça JVM de çalışacaktır çünkü bizim uygulamamızın çalışmasını sağlayan da zaten JVM’dir. JVM’nin ne zaman sonlanacağı da bizim programımızın ne zaman biteceği ile alakalıdır. JVM’nin içerisinde deamon ve non-daemon olmak üzere iki tür thread vardır. Daemon thread JVM’nin kendi içerisinde garbage collection (çöp toplama) gibi amaçlar için kullandığı thread çeşididir. Non-daemon thread ise bizim programımızda çalışan threadlerdir. Bir JVM’nin ömrü, içerisinde çalışan bütün non-daemon threadler sonlandığında biter. Biz ek olarak thread oluşturmadıysak programımızda main bloğunu çalıştıran tek bir non-daemon thread var demektir. Yani main bloğu bittiğinde hem program sonlanır hem de JVM’nin ömrü biter. Program içerisinde birden çok non-daemon thread var ise JVM sonlanmak için bütün non-daemon threadlerin bitmesini bekler.

Umarım faydalı bir yazı olmuştur. Sonraki yazılarda görüşmek üzere..

Share

9 Replies to “Java Virtual Machine Nedir?”

Bir Cevap Yazın