39 fitur baru akan tersedia di Java 12

Dari wawancara yang luar biasa tentang Habré: “Simon Ritter adalah orang yang bekerja di Jawa sejak awal dan terus melakukan ini sebagai wakil direktur teknis Azul, sebuah perusahaan yang bekerja pada mesin virtual Zing JVM dan salah satu pengumpul sampah terbaik, C4 (Continuously Concurrent Compacting) Kolektor) »
Di bawah ini adalah terjemahan dari artikelnya tentang fitur JDK 12 baru dan beberapa kesulitan yang mungkin Anda temui ketika bermigrasi ke bangunan baru.

Saya menulis beberapa posting blog yang mencantumkan semua perubahan untuk setiap rilis Java terbaru ( JDK 10 , JDK 11 ). Sekarang saya akan menjelajahi sisi gelap JDK 12, berfokus pada beberapa jebakan yang dapat menyebabkan masalah jika Anda ingin port aplikasi ke versi ini.



JDK 12 memiliki jumlah fitur baru terkecil dari semua rilis Java hingga saat ini (saya menghitung 109 di JDK 10 dan 90 di JDK 11). Ini tidak buruk - karena siklus rilis, beberapa versi akan berisi lebih banyak perubahan, dan beberapa lagi kurang.


Saya akan memecah fungsi baru menjadi area logis yang jelas: Java, libraries, JVM, dan fungsi JDK lainnya.


Perubahan Bahasa


Fungsi yang saya (dan saya berasumsi bahwa banyak orang lain) akan mempertimbangkan yang paling terlihat di JDK 12 adalah pernyataan switch baru ( JEP 325 ). Ini juga merupakan perubahan bahasa pertama yang digunakan sebagai fungsi untuk "melihat dulu". Gagasan "previewing" diperkenalkan pada awal 2018 sebagai bagian dari JEP 12 . Ini pada dasarnya adalah cara untuk mengaktifkan versi beta dari fitur baru menggunakan opsi baris perintah. Menggunakan pratinjau, masih dimungkinkan untuk membuat perubahan berdasarkan umpan balik pengguna, dan dalam kasus terburuk, sepenuhnya menghapus fungsi jika tidak diterima dengan benar. Kunci untuk fungsi pratinjau adalah bahwa mereka tidak termasuk dalam spesifikasi Java SE. Tentang peralihan baru ada terjemahan yang sangat bagus tentang Habré.
Dalam JDK 12, sebuah saklar telah menjadi ekspresi yang mengevaluasi "konten" untuk menghasilkan suatu hasil. Saya akan segera menjelaskan bahwa ini tidak memengaruhi kompatibilitas ke belakang, jadi Anda tidak perlu mengubah kode apa pun yang menggunakan sakelar sebagai operator.


Saya akan menggunakan contoh dari JEP, karena sederhana dan jelas:


Saklar lama
int numLetters; switch (day) { case MONDAY: case FRIDAY: case SUNDAY: numLetters = 6; break; case TUESDAY: numLetters = 7; break; case THURSDAY: case SATURDAY: numLetters = 8; break; case WEDNESDAY: numLetters = 9; break; default: throw new IllegalStateException("Huh? " + day); } 

Seperti yang Anda lihat, kami memetakan hari dalam seminggu dengan nama day variabel, kemudian menetapkan numLetters nilai. Sekarang switch adalah operator, kita dapat melakukan penugasan sekali (secara signifikan mengurangi kemungkinan kode yang salah) menggunakan hasil dari pernyataan switch:


 int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> 9; default -> throw new IllegalStateException("Huh? " + day); }; 

Anda akan segera melihat dua perubahan sintaks. Pengembang OpenJDK menemukan fungsi sintaksis yang tidak dikenal yang disebut daftar yang dipisahkan koma. Juga operator ekspresi lambda -> membuat mengembalikan nilai lebih mudah. Anda masih dapat menggunakan break dengan sebuah nilai jika Anda benar-benar menginginkannya. Ada beberapa detail lain tentang fitur ini, tetapi mungkin lebih mudah untuk membaca JEP.


Perpustakaan


Ada satu perubahan yang menurut saya sangat berguna. Ada juga sejumlah yang sekunder.


kolektor teeing


Streams API, seperti biasa, memiliki Kolektor baru, yang disediakan oleh kelas utilitas Kolektor. Seorang kolektor baru dapat diperoleh dengan menggunakan metode teeing() . Kolektor teeing mengambil tiga argumen: dua kolektor dan bifungsi. Untuk memahami karya kolektor ini, saya merekomendasikan artikel ini tentang Habré .
Untuk memahami bagaimana dia melakukan ini, saya menggambar diagram:


gambar

Semua nilai dari aliran input diteruskan ke setiap kolektor. Hasil dari setiap kolektor dilewatkan sebagai argumen untuk BiFunction untuk dan menghasilkan hasil akhir.


Contoh sederhana menghitung nilai rata-rata (ya, saya tahu bahwa sudah ada kolektor untuk ini, seperti averagingInt() , tetapi ini adalah contoh sederhana untuk membantu memahami konsep).


 /* Assume Collectors is statically imported */ double average = Stream.of(1, 4, 2, 7, 4, 6, 5) .collect(teeing( summingDouble(i -> i), counting(), (sum, n) -> sum / n) ); 

Kolektor pertama menghitung jumlah aliran input, dan yang kedua - jumlah elemen. BiFunction membagi jumlah dengan jumlah elemen untuk mendapatkan nilai rata-rata.


java.io


InputStream skipNBytes(long n) - melompati dan membuang dengan tepat n byte dari aliran input InputStream. Jika n nol atau kurang, byte tidak dilewati.


java.lang


Paket baru telah muncul, java.lang.constant, yang merupakan bagian dari JVM API konstan, JEP 334 .


Setiap file kelas Java memiliki kumpulan persisten yang menyimpan operan untuk instruksi bytecode di kelas. Sulit bagi pengembang untuk memanipulasi file kelas karena masalah memuat kelas. Konstanta JVM API menyediakan tipe referensi simbolis untuk menggambarkan setiap bentuk konstanta (kelas, konstanta yang dapat dimuat, MethodHandle , konstanta MethodType , konstanta MethodType ).


Ini juga memengaruhi beberapa kelas lainnya. Semua kelas berikut sekarang memiliki metode describeConstable() :


  • Kelas
  • Dobel
  • Enum
  • Mengapung
  • Integer
  • Panjang
  • Tali
  • Menangani metode
  • Tipe Metode
  • Varhandle

Sebagai orang Inggris, saya menganggapnya lucu. Istilah Constable, describeConstable digunakan sejak abad ke-11, dan itulah yang sering kita sebut sebagai petugas polisi. Itu juga nama seniman abad ke-18 yang terkenal, John Constable. Ini membuat saya bertanya-tanya apakah metode describeTurner() akan ada di versi yang akan datang. Jelas, dalam hal ini merupakan singkatan dari Constant Table , tidak terkait dengan petugas hukum atau pelukis lanskap.


Kelas-kelas berikut sekarang termasuk metode resolveConstantDesc() :


  • Dobel
  • Enum.EnumDesc
  • Mengapung
  • Integer
  • Panjang
  • Tali

java.lang.Character


Kelas dalam telah diperbarui untuk menyertakan blok Unicode baru. Saya selalu suka melihat apa yang ditemukan orang untuk ditambahkan ke Unicode, berikut adalah beberapa contoh:


  • Simbol catur
  • Angka Maya
  • Sogdian adalah bahasa Iran timur yang tidak lagi digunakan pada abad ke-11.
  • Sogdian Lama adalah versi Sogdian yang lebih lama (dan, saya kira, bahkan lebih terbatas)

java.lang.Class


arrayType() mengembalikan Class untuk jenis array yang tipe komponennya dijelaskan oleh Class ini. Ini dapat diverifikasi menggunakan jshell :


 jshell> (new String[2]).getClass().getName() $11 ==> "[Ljava.lang.String;" jshell> (new String[2]).getClass().arrayType() $12 ==> class [[Ljava.lang.String; jshell> "foo".getClass().arrayType() $15 ==> class [Ljava.lang.String; 

Saya tidak yakin apa arti dari metode ini, karena semua yang dilakukannya hanyalah menambahkan Class ke jenis yang diwakili oleh kelas ini.


componentType() , sama dengan getComponentType() . Pertanyaannya memohon - mengapa menambahkan metode yang berlebihan?


descriptorString() - sekali lagi, mengembalikan hasil yang sama dengan getName() . Namun, itu perlu karena Class sekarang mengimplementasikan antarmuka TypeDescriptor terkait dengan API JVM konstan baru.


lava.lang.String


indent() - Menambahkan serangkaian spasi utama ke string. Jika parameter negatif, maka jumlah spasi utama ini akan dihapus (jika mungkin).


transform() - Menerapkan fungsi yang disediakan ke string. Hasilnya mungkin bukan string.


java.lang.invoke


VarHandle sekarang memiliki toString() untuk mengembalikan deskripsi yang ringkas.


java.net.SecureCacheResponse dan java.net.ssl.HttpsConnection memiliki metode baru, getSSLSession() yang mengembalikan Optional berisi SSLSession digunakan dalam koneksi.


java.nio.files


Kelas Files memiliki metode baru, mismatch() , yang menemukan dan mengembalikan posisi byte ketidakcocokan pertama dalam isi dua file, atau -1L jika tidak ada ketidakcocokan.


java.text


Ada CompactNumberFormat kelas baru. Ini adalah subkelas dari NumberFormat yang memformat angka desimal dalam bentuk ringkas. Contoh bentuk ringkas - 1M bukan 1000000 , karenanya - memerlukan dua bukannya sembilan karakter. NumberFormat dan java.text.spi.NumberFormatProvider telah diperluas untuk menyertakan metode getCompactNumberInstance() yang baru. Ada juga enum baru, NumberFormatStyle yang memiliki dua arti: PANJANG dan SINGKAT.


java.util.concurrent


CompletionStage sekarang mencakup beberapa formulir kelebihan beban dengan tiga metode:


  • sangat async
  • luar biasaCompose
  • luar biasaComposeAsync

Metode-metode ini memperluas kemungkinan membuat CompletionStage baru dari yang sudah ada, CompletionStage jika yang sekarang berakhir dengan pengecualian. Periksa dokumentasi API untuk detailnya.


javax.crypto


Kelas Cipher memiliki metode toString() yang mengembalikan string yang berisi transformasi, mode, dan penyedia Cipher .


javax.naming.ldap.spi


Ini adalah paket baru di JDK 12 dan berisi dua kelas: LdapDnsProvider , yang merupakan kelas penyedia untuk pencarian DNS selama operasi LDAP, dan LdapDnsProviderResults yang merangkum hasil pencarian DNS untuk URL LDAP.


Ayun


Ayunan masih diperbarui! Ya, filechooser.FileSystemView sekarang memiliki metode getChooserShortcutPanelFiles() . Ini mengembalikan array file yang mewakili nilai-nilai untuk ditampilkan secara default di bar pintasan pemilihan file.


Perubahan JVM


JEP 189: Shenandoah : Pengumpul Sampah Rendah Jeda


Shenandoah adalah proyek penelitian yang diumumkan oleh Red Hat pada tahun 2014 yang berfokus pada persyaratan aplikasi latensi rendah untuk manajemen memori di JVM. Sasarannya adalah waktu jeda maksimum 1..10ms untuk tumpukan lebih dari 20 GB ( oleh karena itu tidak dimaksudkan untuk aplikasi kecil - seperti yang dikatakan oleh salah satu pengembang Shenandoah , ini tidak benar dan ia melakukan pekerjaan yang sangat baik dengan aplikasi kecil). Kolektor ini dirancang untuk bekerja secara paralel dengan utas aplikasi, jadi hindari masalah yang kita lihat di sebagian besar pemulung.


JEP 344: Koleksi G1 Campuran


Perubahan ini dimaksudkan untuk meningkatkan perilaku kolektor G1 ketika mencapai tujuan penundaan yang ditetapkan. G1 membagi ruang tumpukan (baik tua dan lama) menjadi daerah. Idenya adalah bahwa di generasi lama Anda tidak perlu mengumpulkan sampah dalam satu operasi. Ketika G1 perlu mengumpulkan sampah, ia memilih daerah yang ditentukannya. Ini disebut koleksi kit. Sebelum JDK 12, ketika pekerjaan dimulai di set, semua pekerjaan harus diselesaikan, pada dasarnya, sebagai operasi atom. Masalahnya adalah bahwa kadang-kadang karena perubahan dalam penggunaan ruang timbunan aplikasi, kumpulan itu ternyata terlalu besar dan terlalu banyak waktu untuk dikumpulkan, yang mengarah pada fakta bahwa waktu jeda tidak tercapai.


Dalam JDK 12, jika G1 mengidentifikasi situasi ini, itu akan mengganggu pengumpulan data di tengah jalan jika ini tidak mempengaruhi kemampuan aplikasi untuk terus mengalokasikan ruang untuk objek baru. Efek bersih G1 akan lebih baik ketika waktu jeda singkat tercapai.


JEP 346: dengan cepat mengembalikan memori yang dialokasikan tidak terpakai dari G1


Ini adalah peningkatan kinerja lain untuk G1, tetapi yang lain terkait dengan bagaimana JVM berinteraksi dengan seluruh sistem. Jelas, memori diperlukan untuk tumpukan JVM, dan saat startup, ia meminta memori dari pengalokasi memori virtual sistem operasi. Ketika aplikasi dimulai, mungkin ada kalanya jumlah memori yang dibutuhkan untuk tumpukan turun, dan bagian dari memori yang dialokasikan dapat dikembalikan ke sistem operasi untuk digunakan oleh aplikasi lain.


G1 sudah melakukan ini, tetapi hanya bisa melakukan ini di salah satu dari dua tempat. Pertama, selama koleksi lengkap, dan kedua, selama salah satu siklus paralel. G1 mencoba untuk tidak melakukan pengumpulan penuh, dan dengan penggunaan memori yang rendah, mungkin ada periode yang signifikan antara siklus pengumpulan. Ini mengarah pada fakta bahwa G1 dapat menyimpan memori tetap untuk waktu yang lama.


Dalam JDK 12, G1 secara berkala akan mencoba untuk melanjutkan atau menjalankan loop paralel sementara aplikasi idle untuk menentukan keseluruhan penggunaan heap Java. Memori yang tidak digunakan dapat dikembalikan ke sistem operasi dengan cara yang lebih tepat waktu dan dapat diprediksi.


Bendera baris perintah baru -XX:G1PeriodicGCInterval dapat digunakan untuk mengatur jumlah milidetik di antara pemeriksaan.


Fitur ini akan mengarah pada penggunaan memori JVM yang lebih konservatif untuk aplikasi yang tidak digunakan dalam waktu yang lama.


Fitur JDK baru lainnya


JEP 230: Perangkat Microbenchmarking


Java Microbenchmarking Harness (JMH) dikembangkan oleh Alexey Shipilev ketika ia bekerja di Oracle dan menyediakan platform yang luas untuk mengembangkan tes kinerja untuk aplikasi Java. Alexey melakukan pekerjaan luar biasa membantu orang-orang untuk menghindari banyak kesalahan sederhana yang mereka buat ketika mencoba menganalisis kinerja aplikasi: pemanasan, hindari pengecualian, dll.


Sekarang JMH dapat dimasukkan dalam OpenJDK. Siapa pun yang tertarik untuk bekerja pada JDK itu sendiri dan mengubah kode dapat menggunakan ini untuk membandingkan kinerja sebelum dan sesudah perubahan mereka, serta untuk membandingkan kinerja dalam rilis yang berbeda. Sejumlah tes disertakan untuk memungkinkan pengujian; Desain JMH sedemikian rupa sehingga mudah untuk menambahkan tes baru ke tempat yang dibutuhkan.


JEP 340: Satu Pelabuhan Aarch64, Bukan Dua


OpenJDK memiliki dua port untuk arsitektur Arm64, satu disediakan oleh Oracle dan lainnya oleh Red Hat. Karena ini tidak diperlukan, dan Oracle berhenti mendukung Arm untuk binari JDK-nya, diputuskan untuk hanya menggunakan port Red Hat, yang masih didukung dan dikembangkan.


JEP 341: arsip CDS default


Kelas Data Sharing (CDS) digunakan untuk fitur komersial di Oracle JDK. Dengan transisi baru-baru ini yang dibuat dalam JDK 11 untuk menghilangkan semua perbedaan fungsional antara Oracle JDK dan OpenJDK, itu dimasukkan dalam OpenJDK.


Untuk menggunakan CDS, Anda memerlukan arsip yang dibuat untuk kelas yang memuat saat aplikasi dimulai. JDK 12 untuk platform 64-bit sekarang memiliki file classes.jsa di lib/server . Ini adalah arsip CDS untuk "kelas default". Saya berasumsi bahwa itu berarti semua kelas publik dalam modul JDK; Saya tidak dapat menemukan cara untuk membongkar untuk memeriksanya. Karena CDS diaktifkan secara default, yang setara dengan opsi -Xshare:auto pada baris perintah, pengguna akan mendapat manfaat dari peningkatan waktu startup aplikasi darinya.


Kesimpulan


JDK 12 menyediakan sejumlah kecil fungsi dan API baru, dengan switch menjadi yang paling menarik bagi pengembang. Pengguna G1 tentu akan menghargai peningkatan kinerja.


Dengan versi baru rilis, saya akan menyarankan semua pengguna untuk menguji aplikasi mereka dalam rilis ini. Melacak perubahan inkremental akan membantu Anda menghindari kejutan jika Anda memutuskan untuk beralih ke rilis dukungan jangka panjang berikutnya.


Kami memiliki JDK 12 build gratis untuk Zulu Community Edition untuk membantu Anda dengan pengujian Anda. Pastikan untuk mencobanya.

Source: https://habr.com/ru/post/id446590/


All Articles