´JAVA CLASS DİAGRAM AND DEPENDENCY{}´
Araştırma Konusu
JVM nedir ve nasıl çalışır? Mimarisi nasıldır? Java 8 ile birlikte JVM mimarisinde ne gibi değişiklikler olmuştur??
What is JVM and how is it made? JVM nedir? Bu:
JVM (Java Sanal Makinesi) bir soyut makinedir. Java Sanal Makinesi (JVM), Java bytecode’nu makine diline çevirir. JVM, Java Çalışma Ortamının (JRE) bir parçasıdır. Başka programlama dillerinde, derleyici, belirli bir sistem için makine kodu üretir. Ancak, Java derleyicisi, Java Sanal Makinesi olarak bilinen bir Sanal Makine için kod üretir.Java platformdan bağımsızdır. Java’ nın “bir kez yaz, her yerde çalıştır” felsefesi de platform bağımsızlığını ifade eder. Platform bağımsızlığını sağlayan bileşen (Java Virtual Machine) Java Sanal Makinasıdır. JVM, tüm platformlarda Java kodlarını çalıştırmak üzere geliştirilmiş ve hemen her platforma uygun sürümü olan bir bileşendir. Linux ve Windows birbirinden çok farklı platformlar olmasına rağmen Java ile geliştirilmiş bir yazılım bu iki platformda da bulunan Java Sanal Makinası sayesinde kullanılabiliyor.
Java Sanal Makineleri pek çok donanım ve yazılım platformu için uygundur.
İlk olarak Java kodunu bytecode’a derler. Bu bayt kodu (bytecode)
farklı makineler üzerinde yorumlanır. Ana makine ve Java kaynağı arasında, Bytecode aracı bir dildir.
Java Sanal Makinesi (JVM), hafıza alanı (memory space) bölüştürmek için sorumludur.
Herhangi bir java sınıfını maksibet çalıştırdığınızda, bir JVM nesnesi oluşturulur.
-JDK, Java Development Kit‘ in ilk harflerinden oluşan kısaltmadır ve JDK programcıya yazılım geliştirme sürecinde gerekli olacak bileşenleri içeren bir pakettir.
-Java Runtime Environment kullanıcıların Java programlarını çalıştırabilmeleri için gerekli yazılımdır. İçerisinde Java Sanal Makinasını ve Java kütüphanelerini barındırır.
O zaman Özetle şu şekilde düşünebiliriz:
-JRE=JVM + Java Kütüphaneleri
-JDK=JRE + Compiler + debugger
Machine Code (Machine Language): Makine kodu ya da makine dili, direkt olarak bir mikroişlemci/mikrodenetleyici üzerinde işletilebilecek komutlardan oluşan en alt seviyedeki programlama dilidir. İşlemci mimarisine/donanımına göre komut seti (instruction set) değişebilmektedir. Donanım diline uzak, insan diline yakın olan yüksek seviyeli diller ile yazılmış kodlar, hangi işlemci üzerinde çalışacak ise öncelikle bu işlemcinin komut setine uygun olarak derlenerek makine kodu oluşturulmak zorundadır.
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:
1-Loading(Yükleme)
2-Linking(Bağlama)
3-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 inceleylim.
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.
-Lambda expressions
-Functional interfaces
-Method references
-Stream API
-Optional class
-Concurrency Enhancements
-JDBC Enhancements etc.
-
(S)ingle Responsibility Principle
-
(O)pen/Closed Principle
-
(L)iskov ‘s Substitution Principle
-
(I)nterface Segregation Principle
-
(D)ependency Inversion Principle
Single Responsibility
Bir sınıf (nesne) yalnızca bir amaç uğruna değiştirilebilir, o da o sınıfa yüklenen sorumluluktur, yani bir sınıfın(fonksiyona da indirgenebilir) yapması gereken yalnızca bir işi olması gerekir.
Open-Closed
Open Sınıf için yeni davranışlar eklenebilmesini sağlar. Gereksinimler değiştiğinde, yeni gereksinimlerin karşılanabilmesi için bir sınıfa yeni veya farklı davranışlar eklenebilir olmasıdır.Gelişme açık değişme kapalı olmalıdır
(L)iskov ‘s Substitution Principle
Kodlarımızı değiştirmeden türettiğimiz sınıfta üst sınfın özelliklerini kullanabilmeliyiz. Türeyen yani alt sınıfımız üst sınıftaki tüm özellikleri kullanabilmeli ve kendine has özellikleri kolaylıkla tanımlayabilmelidir. Burada alt sınıf üst sınıfa şöyle der: Senin metotların benim metotlarım, benim metotlarım gene benim metotlarım. Ve maalesef üst sınıf bu konuda birşey yapamaz
(I)nterface Segregation Principle
“Arayüz Ayırımı” prensibinde; bir interface’e gerekenden fazla metot ve değişken eklemek yerine, daha çok özelleştirilmiş birden fazla interface oluşturulmalıdır. Nesneler, ihtiyacı olmayan özellik veya metotlar içeren interface’leri miras almaya zorlanmamalıdır. Sizinde farkettiğiniz üzere “Single Responsibility” ve “Interface Segregation” prensipleri birbirine oldukça benzemekte ve aynı amaca hizmet etmektedirler. Ancak burada gözden kaçırılmaması gereken en önemli husus şudur ki; ‘Interface Segregation’ prensibi interface’ler ile ilgilenirken, ‘Single Responsibility’ prensibi class’lar ile ilgilenmektedir
(D)ependency Inversion Principle
Bu prensip ise şunu savunur. Üst seviye sınıflar alt seviyedeki sınıflara bağımlı olmamalıdır. Yani yazdığımız projede sınıflar arası bağımlılıklar minimum seviyede olmalıdır.
Mesela türettiğimiz sınıftaki yaptığımız değişiklik ana sınıfımızı etkilememelidir. Bu durumda ana sınıfta da değişiklik yapmamız gerekecek. Ana sınıfta da değişiklik yapınc aana sınıftan türettiğimiz tüm sınıflarda değişiklik yapmak zorunda kalacağız. Proje tarhana çorbası gibi olacaktır.
0ea0a5cf06545c6b34b524c538e9d7fdff8355b2