Java 9 Yenilikleri-2-Modüler Java-2
Modüler java konumuza kaldığımız yerden devam ediyoruz. Bir önceki makalede konumuza giriş yapmış ve eclipse üzerinde basit bir örnek oluşturmuştuk. Bu örnek ile amacımız modül tanımını görmek, export ve requires anahtar kelimelerini anlamak ve java module sistemi ile gelen güçlü kapsülleme özelliğini görebilmekti.
Bu makalemizde IDE kullanmadan modüler yapımızı oluşturacağız ve sonrasında konsol komutları ile compile edip çalıştıracağız. En son ise jlink aracı ile bir java runtime image dosyası oluşturacağız.
java 9 da standart bir modüler uygulamanın klasör yapısı aşağıdaki gibidir;
Bir source folder altına modüllerimizi ekleriz. Modül isimlendirmesi paket isimlendirmesi gibidir. Eclipse IDE’si şuan java 9 ile gelen modül klasör yapısını tam olarak desteklememekte; Netbeans ve Intelij IDE’leri ise desteklemektedirler. Bu makalemiz boyunca bu yapıya uygun olarak devam edeceğiz.
Önceki makalemizdeki örneğimizi biraz küçültüp kullanacağız. Proje klasör yapımız aşağıdaki gibi olacak.
io.bilisim.queue ve io.bilisim.repository isimli iki modülümüz var.
io.bilisim.queue modülümüzün module-info.java ve CoreProcessor.java içeriği aşağıdaki gibi olacak.
1 2 3 4 5 6 7 |
module io.bilisim.queue { requires io.bilisim.repository; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package io.bilisim.core; import io.bilisim.sender.Sender; public class CoreProcessor { public static void main(String[] args) { Sender sender = new Sender(); sender.sendEntity("Convert to XML"); } } |
io.bilisim.repository modülümüzün içeriği ise aşağıdaki gibi olacak.
1 2 3 4 5 6 7 |
module io.bilisim.repository { exports io.bilisim.sender; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package io.bilisim.processor; public class XmlClient { public void sendEntity(String message) { System.out.println(message); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package io.bilisim.sender; import io.bilisim.processor.XmlClient; public class Sender { public void sendEntity(String message) { XmlClient client = new XmlClient(); client.sendEntity(message); } } |
Yapımızı kurduktan sonra modüllerimizi derleyebiliriz.
jdk-9.0.1/bin/javac -d out –module-source-path src –module io.bilisim.queue,io.bilisim.repository
-d out ile derlenen dosyaların konulacağı klasörü belirttik. Komutu çalıştırdıktan sonra out klasörünün oluştuğunu ve derlenmiş dosylarımızın dosya yapısına uygun şekilde yer aldığını görebiliriz.
–module-source-path ise tahmin edeceğiniz gibi modullerin olduğu kaynak klasörünü işaret eder. Bizim kaynak klasörümüz src idi.
–module ile de derlenecek modülleri belirttik. Şimdi main sınıfımızı çalıştırabilir ve sonucu görebiliriz.
jdk-9.0.1/bin/java –module-path out -m io.bilisim.queue/io.bilisim.core.CoreProcessor
komutu bize “Convert to XML” sonucunu dönderecek.
Artık java komutu ile classpath parametresini değil, module-path parametresini kullanıyoruz. Derlenmiş modüllerimiz out klasörü altında bulunuyor. –module-path ile bu klasörü gösteriyoruz.
-m ile main sınıfımızın olduğu modül bilgisi ve sınıf bilgisini veriyoruz.
Bir önceki makalemizde modül sistemi ile hem güçlü bir kapsüllemenin geldiğinden hem de classpath’in eksik verilmesi ile oluşan hatalardan kurtulduğumuzu belirtmiştik. Kapsüllemeyi örnek üzerinden incelemiştik.
Java 9 öncesinde, java uygulamaları classpathlerinde gereksinim duydukları jar dosyalarını ister ve çalışma zamanında bu dosyaların sınıfları load edilirdi. Bu load edilme işleminde ise, eksik jar var mı gibi bir validasyon işlemi yapılmazdı. Eğer eksik bir sınıf var ise, uygulamada o sınıfın kullanıldığı kod çağrılana kadar hata vermeden işlemlerini yapardı. Ama belki 5 gün sonra belki 10 dakika sonra sınıfı bulamadım diye bağırırdı.
Java 9 ile gelen modüler sistemde ise, artık modüller gereksinim duydukları modülleri açıkça belirtmek zorundadır. Uygulama çalıştırılırken olması gereken herhangi bir modülün eksikliği karşısında uygulama çalışmaz ve hata fırlatır. Bu şekilde java 3 gün sonra gelecek hataların önüne geçmiş oluyor.
Mödüllerimiz üzerinde bağımlılıkları belirttik. Peki JDK bu bağımlılıkları nasıl çözümlüyor? Fazla sayıda modül içeren uygulamamızda hangi modüller hangilerine bağımlı bilgisini nasıl göreceğiz?
Module Çözümleme İşlemi
Module çözümleme süreci, root modulden başlayıp tek yönlü olacak şekilde devam eder. DAG(Directed Acycle Graph) yaklaşımı ile çözümleme yapılır. Bu yöntemin iki zorunluluğu;
- Her zaman bir node’dan(modül) sonrakine doğru, eskiden yeniye doğru gider. İlk hedef akdeniz misali hep ileri.(Directed)
- nodelar arası bağımlılık döngüsü olamaz.(Acycle)
module1 root modülümüz olsun. ilk önce module2 ve module4 bulunur. Ardından module2 nin gösterdiği module3 eklenir. Sonra module3’ün gösterdiği module4 zaten ilk adımda çözüldüğünden işlem sonlandırılır.
Kendi modülümüzün çözümlemesini yaptıralım.
jdk-9.0.1/bin/java –show-module-resolution –module-path out -m io.bilisim.queue/io.bilisim.core.CoreProcessor
Uygulama çalıştırma komutumuza –show-module-resolution parametresini ekledik. Bu da bize bağımlılıkları çözüp listeledi.
1 2 3 4 5 6 |
root io.bilisim.queue file:///home/volkanozdemir/Desktop/modularity/out/io.bilisim.queue/ io.bilisim.queue requires io.bilisim.repository file:///home/volkanozdemir/Desktop/modularity/out/io.bilisim.repository/ |
root modülümüz queue isimli modül ve nu modül repository modülüne gereksinim duyuyor. Çıktı da bu iki satır dışında diğer tüm bağımlılıklarda listelendi. java.base modülü tüm modüllerin bağımlı olduğu root modüldür.
Son olarak jlink komutu ile çalışma zamanı image dosyası oluşturalım. Bu dosya uygulamanın çalışması için gerekli olan herşeyi içerir. Sadece bizim modüllerimizi değil, uygulamanın çalışması için gerekli olan minimum paltform modüllerini de içerir.
1 2 3 4 5 |
jdk-9.0.1/bin/jlink --module-path out --add-modules io.bilisim.queue --output image |
–module-path ile module path bilgisini verdik.
–add-modules bilgisi module çözümünün başlayacağı modül bilgisini ister. Virgül ile ayırarak bir den fazla da verilebilir. Biz root modülümüzü verdik ve son olarak da –output ile çıktı klasör bilgisini verdik.
Komutu çalıştırdığımızda aşağıdaki hatay almış olmalıyız.
Error: Module java.base not found, required by io.bilisim.queue
java.base modülü jdk 9 ‘un core modülüdür. Bu modül, verdiğimiz modül pathinde olmadığında hata aldık. Bunu aşmak için $JAVA_HOME/jmods pathini komutumuza ekleyeceğiz. jmods klasörü core java modüllerinin olduğu klasördür.
1 2 3 4 5 |
jdk-9.0.1/bin/jlink --module-path <strong>jdk-9.0.1/jmods:</strong>out --add-modules io.bilisim.queue --output image |
Artık runtime image dosyamız hazır. Image dosyamız içerisine bakarsak, JDK içeriği ile jmods harici benzer diyebiliriz. Şuan elimizde, java runtime kurulumu olmamış bir makinada dahi çalıştırabileceğimiz bir image var. Uygulamamızı çalıştırmak için artık makinamızdaki jdk’nin java aracını değil, image -> bin altındaki java aracını kullanacağız. image klasörünün içerisine girip aşağıdaki komutu çalıştırırsak kodumuzun sorunsuz çalıştığını görmüş olacağız.
1 2 3 4 5 |
bin/java -m io.bilisim.queue/io.bilisim.core.CoreProcessor |
Bu makalemizide burada sonlandıralım. Vakit buldukça devam etmeye çalışacağım inşallah. Umarım faydalı olmuştur.
Gayret bizden, tevfik Allah’tan.