Pengenalan Projek Jigsaw

1. Pengenalan

Project Jigsaw adalah projek payung dengan ciri baru yang bertujuan untuk dua aspek:

  • pengenalan sistem modul dalam bahasa Jawa
  • dan pelaksanaannya dalam sumber JDK dan waktu proses Java

Dalam artikel ini, kami akan memperkenalkan anda kepada projek Jigsaw dan ciri-cirinya dan akhirnya membungkusnya dengan aplikasi modular sederhana.

2. Modulariti

Ringkasnya, modulariti adalah prinsip reka bentuk yang membantu kita mencapai:

  • gandingan longgar antara komponen
  • kontrak dan pergantungan yang jelas antara komponen
  • pelaksanaan tersembunyi menggunakan enkapsulasi yang kuat

2.1. Unit Modulariti

Sekarang timbul persoalan mengenai apakah unit modulariti? Di dunia Java, terutama dengan OSGi, JAR dianggap sebagai unit modulariti.

JAR membantu dalam mengumpulkan komponen yang berkaitan, tetapi mereka mempunyai beberapa batasan:

  • kontrak eksplisit dan kebergantungan antara JAR
  • enkapsulasi elemen yang lemah di dalam JAR

2.2. JAR Neraka

Terdapat masalah lain dengan JAR - neraka JAR. Pelbagai versi JAR yang terletak di classpath, menyebabkan ClassLoader memuat kelas yang dijumpai pertama dari JAR, dengan hasil yang sangat tidak dijangka.

Masalah lain dengan JVM menggunakan classpath adalah bahawa penyusunan aplikasi akan berjaya, tetapi aplikasi akan gagal pada waktu berjalan dengan ClassNotFoundException , kerana JAR yang hilang pada classpath pada waktu runtime.

2.3. Unit Modulariti Baru

Dengan semua batasan ini, ketika menggunakan JAR sebagai unit modularitas, pencipta bahasa Java membuat konstruk baru dalam bahasa yang disebut modul. Dengan ini, terdapat sistem modular baru yang dirancang untuk Java.

3. Jigsaw Projek

Motivasi utama untuk projek ini adalah:

  • buat sistem modul untuk bahasa - dilaksanakan di bawah JEP 261
  • gunakannya pada sumber JDK - dilaksanakan di bawah JEP 201
  • memodulasi perpustakaan JDK - dilaksanakan di bawah JEP 200
  • kemas kini jangka masa untuk menyokong modulariti - dilaksanakan di bawah JEP 220
  • dapat membuat jangka masa lebih kecil dengan subset modul dari JDK - dilaksanakan di bawah JEP 282

Inisiatif penting lain adalah merangkumi API dalaman di JDK, mereka yang berada di bawah sinar matahari. * Paket dan API bukan standard lain. API ini tidak pernah dimaksudkan untuk digunakan oleh orang ramai dan tidak pernah dirancang untuk dikekalkan. Tetapi kekuatan API ini membuat pengembang Java memanfaatkannya dalam pengembangan berbagai perpustakaan, kerangka kerja, dan alat. Terdapat penggantian yang disediakan untuk beberapa API dalaman dan yang lain telah dipindahkan ke modul dalaman.

4. Alat Baru untuk Modulariti

  • jdeps - membantu dalam menganalisis asas kod untuk mengenal pasti pergantungan pada API JDK dan JAR pihak ketiga. Ia juga menyebutkan nama modul di mana JDK API dapat dijumpai. Ini menjadikannya lebih mudah dalam memodulasi asas kod
  • jdeprscan - membantu dalam menganalisis asas kod untuk penggunaan API yang tidak digunakan lagi
  • jlink - membantu dalam mewujudkan masa berjalan yang lebih kecil dengan menggabungkan modul aplikasi dan JDK
  • jmod - membantu dalam bekerja dengan fail jmod. jmod adalah format baru untuk mengemas modul. Format ini memungkinkan termasuk kod asli, fail konfigurasi, dan data lain yang tidak sesuai dengan fail JAR

5. Senibina Sistem Modul

Sistem modul, dilaksanakan dalam bahasa, menyokongnya sebagai konstruk peringkat teratas, sama seperti pakej. Pembangun boleh menyusun kod mereka ke dalam modul dan menyatakan kebergantungan di antara mereka dalam fail definisi modul masing-masing.

Fail definisi modul, dinamakan sebagai modul-info.java , mengandungi:

  • namanya
  • pakej yang disediakannya secara terbuka
  • modul yang bergantung kepadanya
  • sebarang perkhidmatan yang digunakannya
  • apa-apa pelaksanaan untuk perkhidmatan yang diberikannya

Dua item terakhir dalam senarai di atas tidak biasa digunakan. Mereka digunakan hanya apabila perkhidmatan diberikan dan dimakan melalui antara muka java.util.ServiceLoader .

Struktur umum modul kelihatan seperti:

src |----com.baeldung.reader | |----module-info.java | |----com | |----baeldung | |----reader | |----Test.java |----com.baeldung.writer |----module-info.java |----com |----baeldung |----writer |----AnotherTest.java

Ilustrasi di atas mentakrifkan dua modul: com.baeldung.reader dan com.baeldung.writer . Masing-masing mempunyai definisi yang ditentukan dalam modul-info.java dan fail kod masing-masing diletakkan di bawah com / baeldung / reader dan com / baeldung / writer .

5.1. Terminologi Definisi Modul

Marilah kita melihat beberapa istilah; kita akan menggunakan semasa menentukan modul (iaitu, dalam modul-info.java) :

  • modul : fail definisi modul bermula dengan kata kunci ini diikuti dengan nama dan definisi
  • memerlukan : digunakan untuk menunjukkan modul yang bergantung kepadanya; nama modul mesti dinyatakan selepas kata kunci ini
  • transitif : ditentukan selepaskata kunci yang diperlukan ; ini bermaksud bahawa setiap modul yang bergantung pada penentuan modul memerlukan transitif mendapat pergantungan tersirat pada < modulename>
  • eksport : digunakan untuk menunjukkan paket dalam modul yang tersedia untuk umum; nama pakej mesti dinyatakan selepas kata kunci ini
  • opens: is used to indicate the packages that are accessible only at runtime and also available for introspection via Reflection APIs; this is quite significant to libraries like Spring and Hibernate, highly rely on Reflection APIs; opens can also be used at the module level in which case the entire module is accessible at runtime
  • uses: is used to indicate the service interface that this module is using; a type name, i.e., complete class/interface name, has to specified after this keyword
  • provides … with ...: they are used to indicate that it provides implementations, identified after the with keyword, for the service interface identified after the provides keyword

6. Simple Modular Application

Let us create a simple modular application with modules and their dependencies as indicated in the diagram below:

The com.baeldung.student.model is the root module. It defines model class com.baeldung.student.model.Student, which contains the following properties:

public class Student { private String registrationId; //other relevant fields, getters and setters }

It provides other modules with types defined in the com.baeldung.student.model package. This is achieved by defining it in the file module-info.java:

module com.baeldung.student.model { exports com.baeldung.student.model; }

The com.baeldung.student.service module provides an interface com.baeldung.student.service.StudentService with abstract CRUD operations:

public interface StudentService { public String create(Student student); public Student read(String registrationId); public Student update(Student student); public String delete(String registrationId); }

It depends on the com.baeldung.student.model module and makes the types defined in the package com.baeldung.student.service available for other modules:

module com.baeldung.student.service { requires transitive com.baeldung.student.model; exports com.baeldung.student.service; }

We provide another module com.baeldung.student.service.dbimpl, which provides the implementation com.baeldung.student.service.dbimpl.StudentDbService for the above module:

public class StudentDbService implements StudentService { public String create(Student student) { // Creating student in DB return student.getRegistrationId(); } public Student read(String registrationId) { // Reading student from DB return new Student(); } public Student update(Student student) { // Updating student in DB return student; } public String delete(String registrationId) { // Deleting student in DB return registrationId; } }

It depends directly on com.baeldung.student.service and transitively on com.baeldung.student.model and its definition will be:

module com.baeldung.student.service.dbimpl { requires transitive com.baeldung.student.service; requires java.logging; exports com.baeldung.student.service.dbimpl; }

The final module is a client module – which leverages the service implementation module com.baeldung.student.service.dbimpl to perform its operations:

public class StudentClient { public static void main(String[] args) { StudentService service = new StudentDbService(); service.create(new Student()); service.read("17SS0001"); service.update(new Student()); service.delete("17SS0001"); } }

And its definition is:

module com.baeldung.student.client { requires com.baeldung.student.service.dbimpl; }

7. Compiling and Running the Sample

We have provided scripts for compiling and running the above modules for the Windows and the Unix platforms. These can be found under the core-java-9 project here. The order of execution for Windows platform is:

  1. compile-student-model
  2. compile-student-service
  3. compile-student-service-dbimpl
  4. compile-student-client
  5. run-student-client

The order of execution for Linux platform is quite simple:

  1. compile-modules
  2. run-student-client

In the scripts above, you will be introduced to the following two command line arguments:

  • –module-source-path
  • –module-path

Java 9 is doing away with the concept of classpath and instead introduces module path. This path is the location where the modules can be discovered.

We can set this by using the command line argument: –module-path.

To compile multiple modules at once, we make use of the –module-source-path. This argument is used to provide the location for the module source code.

8. Module System Applied to JDK Source

Every JDK installation is supplied with a src.zip. This archive contains the code base for the JDK Java APIs. If you extract the archive, you will find multiple folders, few starting with java, few with javafx and the rest with jdk. Each folder represents a module.

The modules starting with java are the JDK modules, those starting with javafx are the JavaFX modules and others starting with jdk are the JDK tools modules.

All JDK modules and all the user defined modules implicitly depend on the java.base module. The java.base module contains commonly used JDK APIs like Utils, Collections, IO, Concurrency among others. The dependency graph of the JDK modules is:

You can also look at the definitions of the JDK modules to get an idea of the syntax for defining them in the module-info.java.

9. Conclusion

In this article, we looked at creating, compiling and running a simple modular application. We also saw how the JDK source code had been modularized.

There are few more exciting features, like creating smaller runtime using the linker tool – jlink and creating modular jars among other features. We will introduce you to those features in details in future articles.

Project Jigsaw adalah perubahan besar, dan kita harus menunggu dan melihat bagaimana ia diterima oleh ekosistem pemaju, khususnya dengan alat dan pencipta perpustakaan.

Kod yang digunakan dalam artikel ini boleh didapati di GitHub.