urutan
Artikel ini terutama mempelajari beberapa tindakan pencegahan untuk bermigrasi ke Java9.
Jenis migrasi
1. Kode ini tidak modular, migrasi pertama ke JDK9 untuk memanfaatkan API JDK9
2. Kode ini juga dimigrasi secara modular
Beberapa hal yang perlu diperhatikan
Kelas yang tidak bisa dibaca
Misalnya, sun.security.x509 diklasifikasikan ke dalam modul java.base di java9, tetapi modul tidak mengekspor paket.
Anda dapat memodifikasi pengaturan ekspor dengan menambahkan --add-Exports java.base/sun.security.x509 = all-unnamed saat berjalan
Kelas internal
Misalnya, sun.misc.unsafe awalnya ingin menggunakan tim Oracle JDK, tetapi karena kelas -kelas ini terlalu banyak digunakan, Java9 telah membuat kompromi untuk menjadi kompatibilitas ke belakang, tetapi hanya mengklasifikasikan kelas -kelas ini ke dalam modul JDK.
➜ ~ java -d jdk.unsupportedjdk.unsupported@9Exports com.sun.nio.fileexports sun.miscexports sun.reflectrequires java.base wajib sun.miscopens sun.reflect
Kelas yang dihapus
java9 dihapus sun.misc.base64encoder, dalam hal ini, Anda hanya dapat menggunakan API lain sebagai gantinya, seperti java.util.base64
ClassPath vs Module-Path
Java9 memperkenalkan sistem modul, dan JDK sendiri juga dimodulasi, dan modul-path diperkenalkan untuk memblokir Classpath. Dengan kata lain, jalur modul lebih disukai di java9. Bagaimanapun, JDK sendiri modular. Jika aplikasi itu sendiri tidak modular, Java9 secara implisit dimodulasi melalui modul yang tidak disebutkan namanya dan mekanisme modul otomatis. Tentu saja, ClassPath dapat terus digunakan pada Java9, seperti menggunakan Module-Path.
Jar tanpa modularitas akan diklasifikasikan sebagai modul yang tidak disebutkan namanya di Classpath; Di Module-Path, itu akan secara otomatis dibuat sebagai modul otomatis (modul otomatis akan menyatakan bahwa transitif tergantung pada semua modul yang tidak disebutkan dan tidak disebutkan namanya, dan kemudian mengekspor paketnya sendiri)
Nama paket tidak dapat muncul di beberapa modul (paket split)
Karena ekspor dapat ditentukan ke modul lain dalam modul, jika beberapa modul mengekspor nama paket yang sama, itu akan menyebabkan kebingungan. Terutama jika ada perpustakaan kelas lain yang membutuhkan kedua modul ini secara bersamaan, Anda tidak tahu modul mana yang harus dirujuk.
Ketergantungan transitif
Jika parameter antarmuka atau jenis pengembalian modul, gunakan kelas modul lain, disarankan untuk meminta modul transitif tergantung pada.
Hati -hati dengan dependensi melingkar
Saat merancang modul, pertimbangkan apakah akan ada dependensi melingkar sebanyak mungkin. Jika demikian, Anda perlu mendesain ulang mereka.
Gunakan layanan untuk mengimplementasikan dependensi opsional
Layanan sangat cocok untuk memisahkan dependensi penelepon dan kelas implementasi. Jika antarmuka memiliki beberapa kelas implementasi, penelepon tidak perlu memerlukan semua kelas implementasi, tetapi hanya memerlukan antarmuka yang memerlukan, dan menggunakan jenis layanan untuk memuat instance kelas implementasi. Decoupling dicapai dengan secara dinamis menambahkan modul implementasi dalam jalur modul.
Manajemen Versi Modul
MODULE-INFO.java tidak mendukung menyatakan nomor versi, tetapi saat membuat paket toples, Anda dapat mengaturnya melalui-Versi-Versi. Namun, ketika sistem modul mencari modul, masih menggunakan nama modul untuk mencari (jika ada beberapa modul duplikat dalam jalur modul, sistem modul akan tahu untuk menggunakan yang pertama ditemukan dan secara otomatis mengabaikan modul berikutnya dengan nama yang sama). Masalah ketergantungan versi tidak berada dalam ruang lingkup solusi sistem modul, dan dibiarkan untuk alat manajemen ketergantungan seperti Maven untuk dikelola.
Akses Sumber Daya Modul
Setelah modularisasi, file sumber daya juga dilindungi, dan modul hanya dapat mengakses file sumber daya modul itu sendiri. Jika akses cross-module diperlukan, Anda juga harus menggunakan Modulelayer untuk menemukan modul target, dan kemudian hubungi modul target untuk memuat file sumber daya modul.
Penggunaan refleksi
Ini melibatkan masalah refleksi yang dalam. Refleksi mendalam yang disebut adalah untuk memanggil elemen non-publik kelas melalui refleksi. Ekspor Modul-Info.java menyatakan bahwa paket hanya memungkinkan kelas yang dimiliki paket secara langsung memungkinkan akses ke elemen publiknya, dan tidak mengizinkan panggilan refleksi ke elemen non-publik.
Refleksi membutuhkan deklarasi khusus untuk diizinkan dalam sistem modul (menggunakan deklarasi Opens untuk memungkinkan refleksi yang dalam), yang mengarah ke banyak perpustakaan kelas yang menggunakan refleksi seperti Spring, yang membutuhkan konfigurasi tambahan untuk dimigrasi ke Java9. Ada dua solusi: satu untuk membuka nama paket ke modul yang membutuhkan refleksi, seperti spring.beans, dll.; Yang lainnya adalah secara langsung membuka seluruh modul.
Default --legal-access = izin, dan pengaturan ini hanya berlaku untuk paket sebelum java9 yang tidak diizinkan untuk diakses di java9, dan tidak berlaku untuk paket baru yang tidak diizinkan untuk diakses di java9. (Disarankan untuk disangkal saat bermigrasi ke sistem modular)
Namun, dalam sistem modul, nama paket berbeda, dan tidak ada hubungan warisan. Misalnya, com.service.func1 dan com.service.func2 adalah paket yang berbeda. Anda tidak bisa hanya membuka layanan, tetapi Anda harus menentukannya secara terpisah, yang mengarah ke lebih banyak paket yang membutuhkan pembukaan. Oleh karena itu, membuka seluruh modul mungkin lebih mudah digunakan, tetapi juga merupakan pendekatan yang relatif kasar.Metode di atas adalah membuat perubahan dalam modul asli-info.java. Metode lain adalah memodifikasi hubungan asli melalui perintah yang ditentukan saat menjalankan Java atau Javac. Misalnya
Java ... --Dadd-opens Sumber-Module/Source-Package = Target-Module
Jika Anda perlu mengekspor ke modul yang tidak disebutkan namanya, modul target tidak disebutkan namanya
Tentu saja, jika itu adalah sistem baru, tidak disarankan untuk menggunakan refleksi. Methodhandles dan Varhandles dapat digunakan.
FAQ dan Langkah -langkah
ClassNotFoundException/NoClassDeffoundError
Misalnya, javax.xml.bind.jaxbException, jaxb telah diklasifikasikan ke dalam modul java.xml.bind dan ditambahkan setelah penamaan java.
--Add-modules java.xml.bind
Jika Anda ingin menyimpan masalah, tambahkan $ java_home dan semua perpustakaan pihak ketiga ke modul-path, dan kemudian lakukan
--Add-modules all-module-path
Akses reflektif ilegal oleh XXX ke metode java.lang.classloader.defineClass
Penyebab refleksi, karena sistem lama tidak memiliki modul-info, tambahkan parameter ke penamaan java dan memodifikasinya.
--Add-Opens Java.Base/Java.lang = All-Nonnamed
Tentukan modul ketergantungan
Analisis melalui IDE atau JDEPS
JDEPS - -Class -Path 'Kelas/lib/*' -recursive -summary app.jar
JDEPS hanyalah analisis kode statis. Jika ada kelas yang menggunakan refleksi, Anda tidak dapat menganalisisnya. Anda harus membutuhkannya secara manual. Jika ketergantungan adalah opsional, Anda dapat membutuhkan statis.
Masalah keterbacaan untuk tes unit modul
Jika suatu modul digunakan untuk pengujian unit, modul uji unit dapat diberikan kemampuan keterbacaan dan refleksi dari modul target melalui -Add-exports atau --dadd-opens saat runtime. Selain itu, karena masalah paket split, nama paket kelas uji unit tidak dapat digandakan dengan nama paket modul target. Ternyata tes proyek Maven
ringkasan
Anda dapat pindah ke Java9 dalam dua langkah. Pertama, Anda tidak modular terlebih dahulu, Anda hanya menjalankan JDK9 terlebih dahulu; maka Anda modular.