Part 14: Java Module System

1. Apa Itu Java Module System?

Java Module System adalah framework untuk mengemas kode Java (packages) menjadi unit-unit mandiri yang disebut modul. Setiap modul memiliki:

  • Nama unik (mis: com.example.myapp)
  • Deklarasi ketergantungan (modul lain yang dibutuhkan)
  • Daftar paket yang diekspor (akses publik ke modul lain)
  • Daftar layanan yang disediakan atau dikonsumsi

File konfigurasi module-info.java menjadi jantung sistem ini. Contoh sederhana:

module com.example.greeting {  
    requires java.base;  
    exports com.example.greeting.api;  
}  

Kode di atas mendefinisikan modul com.example.greeting yang:

  • Membutuhkan modul dasar Java (java.base)
  • Mengekspor paket com.example.greeting.api untuk diakses modul lain

2. Mengapa Modul Diperlukan?

Sebelum Java 9, pengembang menghadapi tiga masalah utama:

a. JAR Hell

Konflik versi library (misalnya dua versi berbeda Library X dalam satu aplikasi) sering menyebabkan error misterius. Modul menyelesaikan ini dengan versioning eksplisit.

b. Enkapsulasi Lemah

Paket internal di suatu JAR tetap bisa diakses oleh kode luar. Modul memungkinkan Anda “menyembunyikan” paket tertentu menggunakan keyword exports selektif.

c. JDK Monolitik

JDK versi lama berukuran besar (±320MB) karena menyertakan semua API sekaligus. Dengan modul, Anda bisa membuat runtime image khusus menggunakan jlink yang hanya berisi modul diperlukan (±40MB).


3. Anatomi Modul: Memahami module-info.java

File module-info.java adalah blueprint modul Anda. Berikut elemen utamanya:

KeywordFungsiContoh
requiresMendeklarasikan ketergantungan ke modul lainrequires java.sql;
exportsMengekspos paket ke modul tertentuexports com.example.util to moduleA, moduleB;
opensMembolehkan akses refleksi ke paketopens com.example.internal;
providesMendeklarasikan implementasi layananprovides Service with MyServiceImpl;
usesMenyatakan konsumsi layananuses com.example.Service;

Contoh Lengkap:

module com.example.ecommerce {  
    requires java.base;  
    requires java.sql;  
    requires com.example.payment;  

    exports com.example.ecommerce.catalog;  
    exports com.example.ecommerce.user;  

    opens com.example.ecommerce.internal;  
}  

4. Membuat Modul Pertama: Tutorial Langkah Demi Langkah

Mari bangun modul sederhana untuk sistem begreeting.

Langkah 1: Struktur Direktori

src/  
└── com.greeting/  
    ├── module-info.java  
    └── com/  
        └── greeting/  
            ├── Greeter.java  
            └── internal/  
                └── GreetingHelper.java  

Langkah 2: Definisikan Modul

module-info.java:

module com.greeting {  
    exports com.greeting;  
    // Paket internal tidak diekspor, jadi aman!  
}  

Langkah 3: Tulis Kode

Greeter.java:

package com.greeting;  

public class Greeter {  
    public static void sayHello() {  
        System.out.println("Hello from Module!");  
    }  
}  

Langkah 4: Kompilasi dan Jalankan

javac -d out --module-source-path src --module com.greeting  
java --module-path out -m com.greeting/com.greeting.Greeter  

Output:

Hello from Module!  

5. Alat Penting untuk Bekerja dengan Modul

a. javac

Tambahkan opsi --module-path untuk menentukan lokasi modul:

javac --module-path libs -d out src/module-info.java src/com/greeting/*.java  

b. java

Gunakan --module atau -m untuk menjalankan modul utama:

java --module-path out -m com.greeting/com.greeting.Greeter  

c. jlink

Buat runtime image khusus:

jlink --module-path $JAVA_HOME/jmods:out --add-modules com.greeting --output customjre  

6. Migrasi ke Java Module System

Jika Anda punya proyek Java lama, ikuti strategi bertahap ini:

  1. Automatic Modules
    Konversi JAR lama ke modul otomatis dengan menambahkan nama di module-info.java:
requires libX; // Nama JAR: libX-1.0.jar → modul libX  
  1. Unnamed Module
    Kode tanpa module-info.java tetap bisa dijalankan, tapi tanpa isolasi modul.
  2. Layered Migration
    Mulai dengan modul inti, lalu perluas ke bagian lain secara bertahap.

7. Tips dan Praktik Terbaik

  • Gunakan Nama Modul Deskriptif
    Contoh buruk: module1utils. Contoh baik: com.company.inventoryorg.logger.core.
  • Minimalkan Ekspos Paket
    Hanya ekspor paket yang benar-benar perlu diakses eksternal.
  • Hindari Circular Dependencies
    Modul A membutuhkan B, dan B membutuhkan A? Desain ulang struktur!
  • Manfaatkan jdeps
    Analisis dependensi dengan perintah:
jdeps --list-deps yourmodule.jar  

Kesimpulan: Langkah ke Era Baru Java

Java Module System bukan sekadar fitur tambahan—ini evolusi fundamental dalam cara kita membangun aplikasi Java. Dengan mempelajari sistem ini, Anda bisa:

  • Mengurangi konflik dependensi
  • Meningkatkan keamanan melalui enkapsulasi ketat
  • Membuat aplikasi lebih ringkas dengan custom runtime

Mulai Bereksperimen! Cobalah konversi proyek kecil ke modul, analisis dependensi dengan jdeps, atau buat runtime image menggunakan jlink. Semakin awal Anda mengadopsi modul, semakin mudah transisi ke masa depan Java yang lebih modular.