Halo lagi. Seperti yang sudah kami tulis, minggu depan grup pelatihan baru tentang kursus
"Pengembang Java" akan dimulai, sesuai dengan tradisi yang sudah ada, kami akan membagikan kepada Anda terjemahan materi yang menarik tentang topik tersebut.
Dimulai dengan JDK 9, rangkaian string telah mengalami perubahan signifikan.JEP 280 ("Indify String Concatenation") diimplementasikan sebagai bagian dari
JDK 9 dan, sesuai dengan bagian "Ringkasan": "Mengubah
javac yang dihasilkan rangkaian string bytecode urutan untuk menggunakan panggilan
invokedynamic ke fungsi perpustakaan JDK." Efek ini memiliki pada penggabungan string di Jawa paling mudah diperhatikan dengan melihat output
javap dari kelas yang menggunakan penggabungan string yang dikompilasi dalam JDK sebelum JDK 9 dan setelah JDK 9.

Untuk demonstrasi pertama, kelas Java sederhana yang disebut "HelloWorldStringConcat" akan digunakan.
package dustin.examples; import static java.lang.System.out; public class HelloWorldStringConcat { public static void main(final String[] arguments) { out.println("Hello, " + arguments[0]); } }
Berikut ini adalah perbandingan perbedaan untuk -vote javap output untuk metode
main(String)
dari kelas HelloWorldStringConcat ketika dikompilasi dengan JDK 8
(AdoptOpenJDK) dan JDK 11
(Oracle OpenJDK) . Saya menyoroti beberapa perbedaan utama.
JDK 8 output javap Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringConcat.class Last modified Jan 28, 2019; size 625 bytes MD5 checksum 3e270bafc795b47dbc2d42a41c8956af Compiled from "HelloWorldStringConcat.java" public class dustin.examples.HelloWorldStringConcat minor version: 0 major version: 52 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=1, args_size=1 0: getstatic #2
JDK 11 output javap Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringConcat.class Last modified Jan 28, 2019; size 908 bytes MD5 checksum 0e20fe09f6967ba96124abca10d3e36d Compiled from "HelloWorldStringConcat.java" public class dustin.examples.HelloWorldStringConcat minor version: 0 major version: 55 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=3, locals=1, args_size=1 0: getstatic #2
Bagian "Deskripsi" di
JEP 280 menjelaskan perbedaan ini: "Idenya adalah untuk mengganti seluruh tarian gabungan StringBuilder dengan panggilan
invokedynamic
sederhana ke
java.lang.invoke.StringConcatFactory , yang akan mengambil nilai yang perlu digabungkan." Bagian yang sama menunjukkan perbandingan yang sama dari output yang dikompilasi untuk contoh penggabungan string yang sama.
Output yang dikompilasi dengan JDK 11 untuk penggabungan mudah tidak hanya lebih sedikit dari output dari JDK 8; ia juga memiliki lebih sedikit operasi "mahal". Peningkatan kinerja potensial dapat dicapai karena fakta bahwa tidak perlu membungkus tipe primitif dan Anda tidak perlu membuat banyak objek tambahan. Salah satu motif utama untuk perubahan ini adalah “untuk meletakkan fondasi untuk membuat penangan string yang dioptimalkan yang diimplementasikan tanpa perlu mengubah kompiler Java-to-bytecode” dan “memungkinkan optimasi penggabungan string di masa depan tanpa perubahan tambahan pada bytecode yang dihasilkan oleh javac. "
Ada konsekuensi yang menarik dari ini dalam hal menggunakan
StringBuffer (yang menurut saya
sulit untuk menemukan penggunaan yang baik ) dan
StringBuilder . Di JEP 280, "Non-Goal" menyatakan tidak untuk "memperkenalkan API baru untuk String dan / atau StringBuilder yang dapat membantu menciptakan strategi terjemahan yang lebih efisien." Dalam hal ini, untuk penggabungan string sederhana, seperti pada contoh di awal tulisan ini, penggunaan eksplisit StringBuilder dan StringBuffer secara virtual mengecualikan kompiler dari menggunakan fitur yang diperkenalkan pada
JEP 280 , yang akan kita bahas dalam posting ini.
Dua daftar berikut ini menunjukkan implementasi serupa dari aplikasi sederhana yang ditunjukkan di atas, tetapi alih-alih merangkai string, mereka menggunakan StringBuilder dan StringBuffer secara berurutan. Ketika javap -verbose dieksekusi untuk kelas-kelas ini setelah mereka dikompilasi dengan JDK 8 dan dengan JDK 11, tidak ada perbedaan signifikan dalam metode utama (String []).
Penggunaan eksplisit StringBuilder di JDK 8 dan JDK 11 adalah sama package dustin.examples; import static java.lang.System.out; public class HelloWorldStringBuilder { public static void main(final String[] arguments) { out.println(new StringBuilder().append("Hello, ").append(arguments[0]).toString()); } }
Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringBuilder.class Last modified Jan 28, 2019; size 627 bytes MD5 checksum e7acc3bf0ff5220ba5142aed7a34070f Compiled from "HelloWorldStringBuilder.java" public class dustin.examples.HelloWorldStringBuilder minor version: 0 major version: 52 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=1, args_size=1 0: getstatic #2
Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringBuilder.class Last modified Jan 28, 2019; size 627 bytes MD5 checksum d04ee3735ce98eb6237885fac86620b4 Compiled from "HelloWorldStringBuilder.java" public class dustin.examples.HelloWorldStringBuilder minor version: 0 major version: 55 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=1, args_size=1 0: getstatic #2
Penggunaan eksplisit StringBuffer di JDK 8 dan JDK 11 adalah sama package dustin.examples; import static java.lang.System.out; public class HelloWorldStringBuffer { public static void main(final String[] arguments) { out.println(new StringBuffer().append("Hello, ").append(arguments[0]).toString()); } }
Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringBuffer.class Last modified Jan 28, 2019; size 623 bytes MD5 checksum fdfb90497db6a3494289f2866b9a3a8b Compiled from "HelloWorldStringBuffer.java" public class dustin.examples.HelloWorldStringBuffer minor version: 0 major version: 52 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=1, args_size=1 0: getstatic #2
Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringBuffer.class Last modified Jan 28, 2019; size 623 bytes MD5 checksum e4a83b6bb799fd5478a65bc43e9af437 Compiled from "HelloWorldStringBuffer.java" public class dustin.examples.HelloWorldStringBuffer minor version: 0 major version: 55 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=1, args_size=1 0: getstatic #2
JDK 8 dan JDK 11 Menangani Rangkaian String BertaliUntuk contoh terakhir dari perubahan pada JEP 280 dalam aksi, saya menggunakan kode sampel yang dapat memecah kerentanan beberapa pengembang Java dan merangkai string dalam satu lingkaran. Perlu diingat bahwa ini hanya contoh ilustratif, dan semuanya akan baik-baik saja, tetapi jangan mencoba untuk mengulanginya di rumah.
package dustin.examples; import static java.lang.System.out; public class HelloWorldStringConcatComplex { public static void main(final String[] arguments) { String message = "Hello"; for (int i=0; i<25; i++) { message += i; } out.println(message); } }
Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringConcatComplex.class Last modified Jan 30, 2019; size 766 bytes MD5 checksum 772c4a283c812d49451b5b756aef55f1 Compiled from "HelloWorldStringConcatComplex.java" public class dustin.examples.HelloWorldStringConcatComplex minor version: 0 major version: 52 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=3, args_size=1 0: ldc #2
Classfile /C:/java/examples/helloWorld/classes/dustin/examples/HelloWorldStringConcatComplex.class Last modified Jan 30, 2019; size 1018 bytes MD5 checksum 967fef3e7625965ef060a831edb2a874 Compiled from "HelloWorldStringConcatComplex.java" public class dustin.examples.HelloWorldStringConcatComplex minor version: 0 major version: 55 . . . public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=3, args_size=1 0: ldc #2
Dalam presentasi
“Cukup java.lang. Berusaha Menggantung Diri Sendiri ...” , Dr.
Heinz M. Kabutz dan
Dmitry Vyazelenko membahas perubahan yang dibuat pada rangkaian string Jawa dan merangkumnya secara singkat, “+ lagi tidak dikompilasi ke dalam StringBuilder ”. Pada slide Lessons from Today, mereka menyatakan: "Gunakan + alih-alih StringBuilder jika memungkinkan" dan "Kompilasi ulang kelas untuk Java 9+."
Perubahan yang diterapkan di JDK 9 dengan
JEP 280 , "akan memungkinkan di masa depan untuk mengoptimalkan penggabungan string, tanpa memerlukan perubahan tambahan dalam bytecode yang dihasilkan oleh javac." Menariknya, baru-baru ini diumumkan bahwa JEP 348 ("Java Compiler Intrinsics untuk JDK APIs") sekarang menjadi kandidat untuk JEP, dan tujuannya adalah menggunakan pendekatan yang serupa untuk mengkompilasi metode
String :: format dan
Objects::hash
.
Menurut Anda, apa artikel yang bermanfaat? Kami menunggu komentar Anda dan mengundang semua orang ke
hari terbuka di kursus Java Developer, yang akan diadakan pada tanggal 25 Maret oleh direktur jenderal OTUS -
Vitaly Chibrikov .