Modularitas di Jawa 9

Inovasi utama di Java 9 adalah pengenalan modularitas. Ada banyak pembicaraan tentang fitur ini, tanggal rilis ditunda beberapa kali untuk menyelesaikan semuanya dengan benar. Dalam posting ini, kita akan berbicara tentang apa yang memberi mekanisme modul, dan apa yang dibawa Java 9 secara umum. Dasar untuk jabatan itu adalah laporan rekan saya, Sergei Malkevich .




Untuk mengimplementasikan modul dalam versi Java ini, seluruh proyek dialokasikan - Project Jigsaw - yang mencakup beberapa JEP dan JSR.



Untuk penggemar dokumentasi resmi, Anda dapat membaca lebih lanjut tentang setiap JEP di sini .

Lebih lanjut tentang Project Jigsaw


Project Jigsaw, yang mengimplementasikan modularitas, mulai dikembangkan kembali pada 2005: JSR 277 pertama dirilis, dan sudah pada 2008, pekerjaan langsung pada proyek dimulai. Rilis ini hanya berlangsung pada tahun 2017. Artinya, untuk mengacaukan modul di Jawa, butuh waktu hampir 10 tahun. Yang, pada kenyataannya, menekankan skala penuh pekerjaan dan perubahan yang dibuat selama implementasi modularitas.

Apa tujuan yang ditetapkan oleh pengembang:

  • memfasilitasi pengembangan aplikasi besar dan perpustakaan;
  • Meningkatkan keamanan Java SE secara umum, dan JDK pada khususnya;
  • meningkatkan kinerja aplikasi;
  • buat kemampuan untuk mengurangi ukuran JRE agar dapat berjalan di perangkat kecil agar tidak terlalu banyak menggunakan memori;
  • JAR NERAKA (lebih lanjut tentang itu nanti).

Apa yang dibawa Java 9 bermanfaat


Sebelum versi 9, JDK dan JRE bersifat monolitik. Ukuran mereka bertambah dengan setiap rilis. Java 8 sudah menempati ratusan megabyte, dan semua ini para pengembang harus "membawa bersama mereka" setiap kali untuk dapat menjalankan aplikasi Java. Hanya rt.jar saja yang beratnya sekitar 60 Mb. Nah, di sini kami juga menambahkan awal yang lambat dan konsumsi memori yang tinggi. Java 9 datang untuk menyelamatkan.

Dalam JDK 9pemisahan modul diperkenalkan, yaitu, JDK dibagi menjadi 73 modul. Dan dengan setiap versi baru, jumlah modul ini bertambah. Dalam versi 11, jumlah ini mendekati 100. Pemisahan ini memungkinkan pengembang untuk membuat utilitas JLINK. Menggunakan JLINK, Anda dapat membuat set JRE khusus yang hanya akan menyertakan modul "perlu" yang benar-benar dibutuhkan aplikasi Anda. Dengan demikian, aplikasi sederhana dan beberapa customJRE dengan set modul minimal (atau kecil) akhirnya bisa muat dalam 20 Mb, yang merupakan kabar baik.

Daftar modul dapat ditemukan di sini .

Dengan munculnya Java 9, struktur JDK telah berubah: sekarang identik dengan struktur JRE. Jika sebelumnya JDK menyertakan folder JRE, tempat bin lagi dan file digandakan, sekarang semuanya tampak seperti ini:



Modul


Sebenarnya. Apa itu modul? Modul adalah tingkat agregasi baru dari paket dan sumber daya (sumber. "Kelompok yang unik, dapat digunakan kembali paket terkait, serta sumber daya dan deskriptor modul" ).

Modul dikirimkan dalam file JAR dengan paket dan modul deskriptor
module-info.java . File module-info.java berisi deskripsi modul:
nama, dependensi, paket yang diekspor, layanan yang dikonsumsi dan disediakan, izin untuk akses refleksi.

Contoh deskripsi deskriptor modul:

module java.sql {
    requires transitive java.logging;
    requires transitive java.transaction.xa;
    requires transitive java.xml;

    exports java.sql;
    exports javax.sql;

    uses java.sql.Driver;
}

module jdk.javadoc {
   requires java.xml;
   
   requires transitive java.compiler;
   requires transitive jdk.compiler;
   
   exports jdk.javadoc.doclet;
   
   provides java.util.spi.ToolProvider with
       jdk.javadoc.internal.tool.JavadocToolProvider;
   
   provides javax.tools.DocumentationTool with
       jdk.javadoc.internal.api.JavadocTool;
   
   provides javax.tools.Tool with
      jdk.javadoc.internal.api.JavadocTool;   
}

Setelah modul kata kunci, kami memiliki nama paket jdk.javadoc , yang tergantung pada paket java.xml lain dan secara transitif tergantung pada paket lain.

Mari kita perhatikan lebih dekat setiap kata kunci:

  • membutuhkan menunjukkan modul di mana modul saat ini tergantung;

  • membutuhkan transitif - ketergantungan transitif - berarti yang berikut: jika modul m1 secara transitif bergantung pada modul m2 , dan kami memiliki beberapa modul mX ketiga , yang tergantung pada m1 - modul mX juga akan memiliki akses ke m2 ;

  • membutuhkan statis memungkinkan Anda menentukan dependensi waktu kompilasi;

  • exports , ( β€œβ€);

  • exports...to… : export com.my.package.name to com.specific.package; - () () ;

  • uses , :

    uses java.sql.Driver;

    , ;

  • provides , :

    provides javax.tools.Tool with
        jdk.javadoc.internal.api.JavadocTool;

    β€” javax.tools.Tool, with β€” .

Sedikit tentang layanan.

Misalkan kita memiliki beberapa modul yang terhubung yang mengimplementasikan layanan abstrak - MyService . Saat membangun aplikasi, kami memiliki kesempatan untuk memutuskan implementasi layanan mana yang akan digunakan dengan "menyeret" modul implementasi layanan yang diperlukan ke --module-path :

Iterable<MyService> services = 
        ServiceLoader.load(MyService.class);

Dengan demikian, Iterator yang dikembalikan berisi daftar implementasi antarmuka MyService. Bahkan, itu akan berisi semua implementasi yang ditemukan dalam modul yang ditemukan di --module-path .

Mengapa, pada prinsipnya, layanan diperkenalkan? Mereka diperlukan untuk menunjukkan bagaimana kode kita akan digunakan. Artinya, ada peran semantik. Juga, modularitas adalah tentang enkapsulasi dan keamanan, karena kita dapat membuat implementasi menjadi pribadi dan mengecualikan kemungkinan akses tidak sah melalui refleksi.

Selain itu, salah satu opsi untuk menggunakan layanan adalah implementasi plugin yang cukup sederhana. Kita dapat mengimplementasikan antarmuka plugin untuk aplikasi kita dan menghubungkan modul untuk bekerja dengannya.

Mari kita kembali ke sintaks untuk menjelaskan modul:

Hingga 9ki, melalui refleksi, kami memiliki akses ke hampir semua hal dan dapat melakukan apapun yang kami inginkan dan dengan apa yang kami inginkan. Dan versi ke-9, sebagaimana telah disebutkan, memungkinkan Anda untuk melindungi diri dari akses refleksi "ilegal".

Kami dapat sepenuhnya membuka modul untuk akses refleksi dengan menyatakan terbuka :

open module my.module {
}

Atau, kami dapat menentukan paket apa saja untuk akses refleksi dengan menyatakan open :

module my.module {
    opens com.my.coolpackage;
}

Di sini juga memungkinkan untuk penggunaan membuka com.my.coolpackage untuk ... , sehingga memberikan akses refleksi ke com.my.coolpackage paket dari paket yang kami akan menunjukkan setelah ke .

Jenis Modul


Project Jigsaw mengklasifikasikan modul sebagai berikut:

  • System Modules β€” Java SE JDK . , java --list-modules.

  • Application Modules β€” , , ( ), .

  • Automatic Modules β€” , Java JAR-. , , - . JAR- --module-path Java , JAR-.

  • Unnamed Module β€” , JAR-, --class-path. Java .

Class-path vs module-path


Dengan munculnya modul, konsep baru muncul - modul-path . Intinya, ini adalah jalur kelas yang sama , tetapi untuk modul.

Peluncuran aplikasi modular adalah sebagai berikut:



Dalam mode peluncuran normal, kami menentukan opsi dan jalur lengkap ke kelas utama. Jika kita ingin bekerja dengan modul, kita juga menentukan opsi dan -m atau -module parameter , yang hanya menunjukkan bahwa kita akan menjalankan modul. Artinya, kami menerjemahkan aplikasi kami secara otomatis ke mode modular. Selanjutnya, kami menunjukkan nama modul dan jalur ke kelas utama dari modul.

Juga, jika dalam mode normal kita digunakan untuk bekerja dengan cp dan --class-jalan pilihan, dalam mode modular, kami meresepkan parameter -p dan --module-path baru , yang menunjukkan jalur ke modul yang digunakan dalam aplikasi.

Seringkali saya bertemu dengan fakta bahwa pengembang tidak beralih ke versi 9+, karena mereka percaya bahwa mereka harus bekerja dengan modul. Meskipun pada kenyataannya, kita dapat menjalankan aplikasi kita dalam mode lama, hanya tanpa menulis parameter atau menggunakan modul, tetapi hanya menggunakan chip baru lainnya.

Jar neraka


Saya juga ingin secara diagonal memikirkan masalah Jar Hell.



Singkatnya, apa sih Jar Hell? Sebagai contoh, kami memiliki beberapa jenis aplikasi kita dan itu tergantung pada X perpustakaan dan perpustakaan Y . Pada saat yang sama, kedua pustaka ini bergantung pada pustaka Z , tetapi pada versi yang berbeda: X tergantung pada versi 1 , Y pada versi 2 . Nah, jika versi 2 kompatibel dengan versi 1, maka tidak ada masalah. Dan jika tidak, jelas bahwa kita mendapatkan konflik versi, yaitu, pustaka yang sama tidak dapat dimuat ke memori oleh loader kelas yang sama.

Bagaimana Anda keluar dari situasi ini? Ada metode standar yang telah digunakan pengembang sejak Java pertama, misalnya, mengecualikan , seseorang menggunakan plugin untuk Maven, yang mengubah nama nama paket root dari pustaka. Atau, pengembang mencari versi perpustakaan X yang berbeda untuk menemukan opsi yang kompatibel.

Mengapa saya: prototipe Jigsaw pertama menyiratkan bahwa modul memiliki versi dan memungkinkan pemuatan beberapa versi melalui ClassLoaders yang berbeda, tetapi kemudian ditinggalkan. Akibatnya, "peluru perak", yang ditunggu banyak orang, tidak berhasil.

Tapi, tepat di luar kotak, kami agak aman dari masalah seperti itu. Java 9 Menonaktifkan Paket Split- paket yang dibagi menjadi beberapa modul. Yaitu, jika kita memiliki paket com.my.coolpackage dalam satu modul, kita tidak dapat menggunakannya dalam modul lain dalam aplikasi yang sama. Saat Anda memulai aplikasi dengan modul yang berisi paket yang sama, kami hanya macet. Peningkatan kecil ini menghilangkan kemungkinan perilaku tak terduga sehubungan dengan mengunduh paket Split.

Selain itu, selain modul itu sendiri, ada juga mekanisme lapisan atau Lapisan Jigsaw , yang juga membantu mengatasi masalah Jar Hell.

Lapisan jigsaw dapat didefinisikan sebagai beberapa sistem modular lokal. Dan di sini perlu dicatat bahwa paket Split yang disebutkan di atas hanya dilarang dalam kerangka satu layer Jigsaw. Modul dengan paket yang sama memiliki tempat untuk menjadi, tetapi mereka harus memiliki lapisan yang berbeda.

Kelihatannya seperti ini:



Ketika aplikasi dimulai, lapisan boot dibuat , yang meliputi modul platform yang dimuat oleh Bootstrap, modul platform tambahan yang dimuat oleh platform loader dan modul aplikasi kami dimuat oleh Loader aplikasi.

Kapan saja, kita dapat membuat layer kita sendiri dan "meletakkan" modul dari berbagai versi di sana dan tidak jatuh.

Ada pembicaraan YouTube yang hebat dan terperinci tentang topik ini: Melarikan diri dari Jar Hell dengan Jigsaw Layers

Kesimpulan


Mesin modul dari Java 9 membuka kemungkinan baru bagi kami, sementara dukungan untuk perpustakaan saat ini cukup kecil. Ya, orang menjalankan Spring, Spring Boot dan sebagainya. Tetapi sebagian besar perpustakaan belum beralih ke penggunaan penuh modul. Karena itu, tampaknya, semua perubahan ini dirasakan agak skeptis oleh komunitas teknis. Modul memberi kita peluang baru, tetapi pertanyaan tentang permintaan tetap terbuka.

Dan akhirnya, saya menawarkan pilihan materi tentang topik ini:

Project Jigsaw

Ringkasan Modul JDK

Paul Deitel - Memahami Java 9 Modul

baeldung.com - Pengantar Project Jigsaw

Alex Buckley - Pengembangan Modular dengan JDK 9

Evgeny Kozlov - Modul di Jawa

All Articles