Java Virtual Machine(JVM) Architecture 4

Kerim Fırat
4 min readMay 31, 2021

--

Java Virtual Machine(JVM) Architecture 1 makalesine buradan erişebilirsiniz.
Java Virtual Machine(JVM) Architecture 2 makalesine buradan erişebilirsiniz.
Java Virtual Machine(JVM) Architecture 3 makalesine buradan erişebilirsiniz.

Java Native Interface (JNI)

Java Native Interface,C/Cpp,ASM gibi başka dillerde yazılmış uygulamalar/kütüphaneler ile iletişim kurmak için arayüz sağlayan bir framework’dur. Dolayısıyla JNI yapısını kullanarak Java ile geliştirdiğimiz projelere C,Cpp,ASM vb. gibi dillerler geliştirilmiş-geliştirdiğimiz kütüphaneler,uygulamalar vb. dahil edebiliriz-kullanabiliriz.
Yani “Java Native Interface”,Java ortamında C/C++ vb. gibi diğer programlama dilleri için bir köprü görevi görür.

Java ile proje geliştirirken,bazı durumlarda farklı dillerde(C,Cpp,ASM,..) yazılmış kodlar-kütüphaneler vb. kullanmamız gerekebilir.Örneğin donanımla iletişime geçmemiz gereken ve/veya Java’daki bellek yönetimi ve performans kısıtlamalarının üstesinden gelmemiz gereken durumlar olabilir.
Veya yalnızca C/C++ ile yazılabilen platforma özgü özellikler geliştirmemiz gerekebilir.Veya java tarafından desteklenmeyen bir kod yazmamız gerekebilir.Bu gibi durumlarda Java Native Interface(JNI) kullanmamız gerekir.Örneğin C++ ile yazdığımız bir kod parçasını,JNI’yi Java ile C++ arasında köprü yaparak Java tarafından C++ tarafını işletebiliriz.
Aşağıda JNI yapısının Java ile birlikte çalışma mimarisini gösteren bir görüntüye yer verilmiştir.

redwerk.com

Native bir kütüphaneyi(library) java’da kullanılabilir bir hale getirmek için öncelikle ilgili kütüphaneyi belleğe yüklememiz gerekir. Bunun için “System.loadLibrary()” kullanacağız. Kütüphaneyi belleğe yükledikten sonra,kütüphane içinde yer alan ve dışarıdan erişime açık olan bir methodu kullanabilmek için ise “native” anahtar kelimesi kullanacağız.
Dolayısıyla Java’da,native bir kütüphane tarafından sağlanan bir methodu belirtmek için “native” anahtar kelimesi kullanılır.

Native Method Libraries(Native Kütüphaneler)

Native kütüphaneler C/C++ ve ASM gibi diğer programlama dilleriyle geliştirilmiş kütüphanelerdir.Bu kütüphaneler genellikle “.so” veya “.dll” uzantılı dosyalar biçimindedir. Bu kütüphaneler JNI aracılığıyla yüklenebilir ve Java projelerinde kullanılabilir.

Java Native Interface(JNI) İş Akışı

JNI tabanlı kütüphaneler geliştirdiğimizde,Java kaynağı “javac” derleyicisi kullanılarak class dosyalarına dönüştürülür. Daha sonra “javah” yardımcı program kullanılarak native headers(.h) dosyaları oluşturulur.
Bu header dosyaları kaynak koduna dahil edilir ve bir CC++ derleyicisi kullanılarak platforma bağlı paylaşılan kütüphaneye derlenir ve linklenir.
Bir java class’ı,paylaşılan JNI kütüphanesini static başlatıcıya yükleyen native methodları içerir.Ve runtime sırasında JNI methodu ile karşılaşıldığında(native anahtar ile işaretlediğimiz method),JVM belleğe yüklenmiş kütüphane içerisindeki methodu çağırır. Bu işleyişi gösteren bir görüntüye aşağıda yer verilmiştir.

oracle.com

Java Native Interface(JNI) Source Code

Yukarıda da detaylandırdığımız gibi,JNI programı içinde native methodları “native” anahtar kelime ile belirtilir. Belirtilen native method,uygulamamızda kullanacağımız kütüphane içinde bulunan bir method olacağını unutmamalıyız.Ve methodları kullanmadan evvel “System.loadLibrary()” fonksiyonu ile ilgili kütüphaneyi JVM’ye dahil etmeliyiz.
Aşağıdaki görünümde bir java programı içinde “hello.so” kütüphanesinin kullanımı veriliyor.

oracle.com

Oluşturulan Java Native Interface(JNI) Başlıkları(Headers)

Program içinde “native” ile belirtilen methodlar “javah” aracı ile native prototipler oluşturulur.
Oluşturulan bu prototipler “jni.h” header dosyasının da dahil olduğu bir bir header dosyasına dönüştürülür. Bu dosyaya aşağıda yer verilmiştir.

oracle.com

Java Native Interface(JNI) Implement(Uygulama)

JNI methodları,öncesinde oluşturulan prototipler kullanılarak uygulanır-implement edilir. Aşağıdaki görünümde de gördüğümüz “JNICALL” VE “JNIEXPORT” maktorları,platform muadili bildirimlerine çevrilir.
JNI uygulamasına ait görünüme aşağıda yer verilmiştir:

oracle.com

Java Native Interface(JNI) kullanırken kafamızda bazı güvenlik endişeleri oluşabilir. Ancak JNI tarafında güvenlik ile ilgili endişe verici bir durum söz konusu değil. JNI’de dahil,bu makele serisinde incelediğimiz tüm süreçlerin güvenliğinden JVM sorumludur. Özellikle JVM güvenliğini konu alarak kapsamlı bir yazı veya yazı serisi planlıyorum.

Yaygın JVM Hataları

Bu başlıkta yaygın olarak karşılaşılan JVM hatalarına yer veriliyor.

  • ClassNotFoundExcecption: Bu hata “Class Loader”’in “Class.forName(),ClassLoader.loadClass(),ClassLoader.findSystemClass()” kullanarak class’ları yüklemeye çalışırken,belirtilen ad/isim’e sahip class bulunamadığında oluşur.
  • NoClassDefFoundError: Bu hata,derleyici class’ı başarıyla derlediğinde,ancak “Class Loader” runtime(çalışma zamanında) esnasında class dosyasını bulamadığında oluşur.
  • OutOfMemoryError: Bu hata,JVM bellek yetersizliği nedeniyle bir nesneyi oluşturamadığında meydana gelir.Bellek ile ilgili detaylar için serinin 3.makalesindeGarbage Collection” konusunu inceleyebilirsiniz.
  • StackOverflowError: Bu hata,bir thread(iş parçacığı) işlerken yeni yığın çerçevesi(stack frame) için JVM’de yer kalmazsa oluşur. Aşağıdaki görünümde bu hatayı oluşturan bir kod parçasına ve hata çıktısına yer verilmiştir.

NOT: Thread(iş parçacığı) yığın boyutunu “-Xss1M” ile ayarlayabilirsiniz.
Bu komut örneğinde yığın boyutu için “1MB” alan belirlenmiştir.

Sonuç

Bu yazı serisinde Java Sanal Makinesi(JVM)’nin mimarisini ve içerdiği bileşenleri inceledik.Java ile geliştirme yaparken genellikle arka planda dönen işleri umursamıyoruz.Ancak bazı durumlarda kaputun altında neler olup bittiğini bilmemiz gerekebilir.
Örneğin eğer Java’da performans konusunu önemsiyorsak bu durumda JVM’yi iyi bilmemiz gerekir.Dolayısıyla daha iyi kod yazmamız,belleği daha etkin kullanabilmemiz ve olağan dışı,beklenmedik bellek problemleriyle ve tuzaklarıyla daha etkin bir şekilde başa çıkmamız için JVM’yi bilmek ve derinlemesine incelemek bir gerekliliktir.

KAYNAKLAR:
https://docs.oracle.com/javase/specs/jvms
https://docs.oracle.com

-end of

--

--

Kerim Fırat

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