Java Virtual Machine 1-Class Loader

Kerim Fırat
4 min readNov 9, 2020

Class Loader bileşeni her ne kadar az kullanılıyor olsa da,Java Core programcılar için aşina olmaları gereken bir bileşendir.Belki JVM’a katkı yapmaya karar verdiniz.Veya OpenJDK’a katkıcı olamayı düşünüyorsunuz. Ya da core tarafına aşina olmak istiyorsunuz.O halder JVM bileşenlerini ve işleyişlerine iyi aşina olmanız gerekir.

JVM Java’nın kalbidir ve bu ana yapının Class Loader(Sınıf yükleyicisi),Garbage Collector(Çöp toplayıcısı,otomatik bellek yönetimi),Interpreter(Yorumlayıcı),JIT Compiler, ve Thread Management(İş parçacığı yönetimi) gibi birçok önemli bileşeni vardır.Bu bileşenlerin ilki “Class Loader” dır.
Bu yazımda Class Loader’ın nasıl çalıştığını inceleyeceğiz.

NOT: Makalede geçen terimler,dileyenlerin kapsamlı araştırma yapabilmeleri için ingilizce verilmiştir.

Class Loader bileşeni,geliştirdiğimiz uygulamadaki classları ve bu classlar içinde kullanılan API bağlantılı classları çalışma zamanında dinamik olarak yükler.
Ancak yükleme işlemi,sadece çalışan program için ihtiyaç duyulan classları baz alır. Yani X class içinde kullanılan bir api üzerinden ulaştığı bağlantılı classı yükler. Onun dışında kalanlarla ilgilenmez. Dolayısıyla gelişigüzel bir yükleme işleminden kaçınır.
Aşağıda verilen diyagramda basit olarak çalışma mimarisi gösteriliyor.

ClasLoader çalışma mimarisi

NOT: Yükleme işleminin başlatılması ve hafıza alanına kadar geçen süreçte çeşitli işlemler(başlangıç noktası vb.) ve sıra takip edilir.
Bu detayları başka bir yazıda ele almaya çalışacağım.

Yukarıda verilen diyagramda görüldüğü gibi Class Loader bileşeni class dosyalarını JVM hafıza alanına yüklüyor.Ancak yüklenecek Java classları arasında bir hiyerarşi söz konusudur. Dolayısıyla Class Loader bileşeni,JVM’nin çalışma zamanında yüklenecek classlar hakkında hiçbir şey bilmesine gerek kalmayacak şekilde tasarlanmıştır.
Bu nedenle bu bileşenin sorumlu olduğu bir diğer etken ise yüklenecek classların hiyerarşiyle ilgilenmektir. Dolayısıyla gelişigüzel bir yükleme sırası yerine,classlar arasında bir düzen ve tertibi takip eder.
Aşağıdaki diyagram,yükleme sırasında takip edeceği hiyerarşiyi göstermektedir.

Bootstrap ClassLoader:
Bu kısımda,Java’nın çalışma zamanı ortamı(JRE) için gerekli olan core(java.util,java.lang vb.) classların yüklenme süreçleri yürütülür.

Extension ClassLoader:
Bu kısımda,core java standart classlarının uzantıları olan .jar paketlerinin yüklenme süreçleri yürütülür.Buradaki sürece dahil etmek istediğiniz bir paketi “JAVA_HOME/jre/lib/ext” klasörüne ekleyip sürece dahil edebilirsiniz.

System ClassLoader:
Bu kısımda, java classpath yolunda bulunan sistem sınıfları olarak adlandırılan sınıfların yüklenme süreçleri yürütülür.
Ayrıca sistem classlarını belirtmek için kullanılan java komutlar buradaki süreci işaret eder.

Yukarıda belirtilen ana başlıklarda, hiyerarşik bir düzende classların yüklenme süreçlerini gördük.Bunlara bağlı olarak daha bir çok ClassLoader görebiliriz. Ancak tüm bunlar java.lang.ClassLoader’ı temel alarak genişletilmiştir. Aşağıda verilen iki ayrı ClassLoader’lar da bunlara örnektir.

Application ClassLoader:
Uygulama sınıfı yükleyicisi,genellikle uygulama yolundaki sınıfları yüklemek için kullanılır.

Platform ClassLoader:
JDK modülleri tarafından sql vb. gibi alanların güvenlik/izinler süreçlerini yürütmek için seçilir.

Şu ana kadar genel olarak JVM başlangıç esnasından itibaren class loader sürecini inceledik.Ancak bu odak noktasını daraltıp,sadece geliştirdiğimiz bir örnek uygulama üzerine yoğunlaştırırsak,ClassLoader’ın işleyişini daha etkin kavramış olacağız.Bu nedenle aşağıdaki bölüme geçebiliriz.

Bir class ne zaman ve nasıl yüklenir:
Burada temel olarak iki durum var.
1.Derlenmiş bir class’ın byte kodu çalıştırıldığında.
Örnek: MyClass myclass = new MyClass();
Bu durumda MyClass adındaki class yüklenir.

2.Byte kodların bir class’a statik olarak başvurduğunda.
Örnek: System.out.

Classlar yüklenirken şu kurallar takip edilir:
-Class önceden yüklenip yüklenmediği kontrol edilir.
-Eğer yüklenmemişse,ana class yükleyiciden classın yüklenmesi istenir.
-Ana class yükleyici classı yükleyemezse,mevcut class içinden yükleme işlemine girişilir.

Bu kuralların takip edilebilmesi için class’a ait öz referanslar kullanılır.
Class’a ait öz referanslar,java derleyicisi tarafından derlenen dosya içine konulur.Dolayısıyla bir java class derlendiğinde,derleyici java class dosyasına bir alan ekler. Bu “java.lang.Class” türünde bir alandır.
Yani bir diğer deyişle,java.lang.Class’ı işaret eden bir nesne konulur.
Çünkü tüm java classlara “java.lang.Class” olarak erişebilmemiz gerekiyor.

Dinamik olarak class yüklemeyi gösteren bir örnekle JVM serisinin ilkini bitireceğim.Dinamik olarak iki farklı şekilde class yüklemek mümkündür.
Bunlardan ilki “loadClass” ile yapmaktır.
Örnek:

public static void main(String[] args){
ClassLoader classLoader = Main.class.getClassLoader();
try {
Class cls = classLoader.loadClass("java.sql.Connection");
System.out.println("name = " + cls.getName());
System.out.println("package = " + cls.getPackage());
Method[] methods = cls.getDeclaredMethods();
System.out.println("----- Class methods ---------------");
for (Method method : methods) {
System.out.println(method.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
loadClass output

Dinamik olarak class yüklemenin ikincisi ise “Class.forName” ile yapmaktır.
Örnek:

public static void main(String[] args) {
try {
Class<?> c = Class.forName("java.sql.Connection");
System.out.println("name = " + c.getName());
System.out.println("package = " + c.getPackage());
Method[] methods = c.getDeclaredMethods();
System.out.println("----- Class methods ---------------");
for (Method method : methods) {
System.out.println(method.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

İki yöntemle class yüklemek mümkün fakat birbirinden farklı yanları mevcut.
Basit olarak değinirsek,”loadClass” yalnızca classı yükler ancak nesneyi başlatmaz.Oysa “Class.forName” classı yükledikten sonra nesneyi başlatır.Örneğin JDBC driver yüklemek için “loadClass” kullanırsanız bu yöntemle driver kaydedilmez ve JDBC’yi kullanamazsınız.

-end of

--

--

Kerim Fırat
Kerim Fırat

Written by Kerim Fırat

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

No responses yet