Saya terus mendengar tentang semua fitur keren baru yang ditambahkan ke JVM dan salah satu fitur keren itu adalah invokedynamic. Saya ingin tahu apa itu dan bagaimana membuat pemrograman reflektif di Jawa lebih mudah atau lebih baik?
sumber
Saya terus mendengar tentang semua fitur keren baru yang ditambahkan ke JVM dan salah satu fitur keren itu adalah invokedynamic. Saya ingin tahu apa itu dan bagaimana membuat pemrograman reflektif di Jawa lebih mudah atau lebih baik?
Ini adalah instruksi JVM baru yang memungkinkan kompiler untuk menghasilkan kode yang memanggil metode dengan spesifikasi yang lebih longgar daripada sebelumnya - jika Anda tahu apa itu " mengetik bebek ", invokedynamic pada dasarnya memungkinkan untuk mengetik bebek. Tidak terlalu banyak yang bisa Anda lakukan sebagai programmer Java; jika Anda seorang pembuat alat, Anda dapat menggunakannya untuk membangun bahasa berbasis JVM yang lebih fleksibel dan lebih efisien. Berikut ini adalah posting blog yang sangat manis yang memberikan banyak detail.
meth.invoke(args)
. Jadi bagaimanainvokedynamic
cocoknyameth.invoke
?MethodHandle
, yang benar-benar hal yang sama tetapi dengan lebih banyak fleksibilitas. Tetapi kekuatan sebenarnya dalam semua ini bukan berasal dari bahasa Jawa, tetapi pada kemampuan JVM sendiri dalam mendukung bahasa lain yang secara intrinsik lebih dinamis.invokedynamic
yang menjadikannya performant (dibandingkan dengan membungkusnya dalam kelas-anonim yang hampir menjadi satu-satunya pilihan sebelum memperkenalkaninvokedynamic
). Kemungkinan besar banyak bahasa pemrograman fungsional di atas JVM akan memilih untuk mengkompilasi ini daripada kelas-dalam-dalam.Beberapa waktu lalu, C # menambahkan fitur keren, sintaks dinamis dalam C #
Anggap saja sebagai sintaks gula untuk panggilan metode reflektif. Ini dapat memiliki aplikasi yang sangat menarik. lihat http://www.infoq.com/presentations/Statically-Dynamic-Typing-Neal-Gafter
Neal Gafter, yang bertanggung jawab untuk tipe dinamis C #, baru saja membelot dari SUN ke MS. Jadi tidak masuk akal untuk berpikir bahwa hal yang sama telah dibahas di dalam SUN.
Saya ingat segera setelah itu, beberapa pria Jawa mengumumkan sesuatu yang serupa
Sayangnya, fitur ini tidak dapat ditemukan di Java 7. Sangat kecewa. Untuk programmer Java, mereka tidak memiliki cara mudah untuk memanfaatkan
invokedynamic
program mereka.sumber
invokedynamic
tidak pernah dimaksudkan untuk digunakan untuk programmer Java. IMO itu tidak sesuai dengan filosofi Java sama sekali. Itu ditambahkan sebagai fitur JVM untuk bahasa non-Jawa.Ada dua konsep untuk dipahami sebelum melanjutkan ke invokedynamic.
1. Pengetikan Statis vs. Dynamin
Static - pengecekan tipe preforms pada waktu kompilasi (misal Java)
Dynamic - pemeriksaan tipe preforms saat runtime (mis. JavaScript)
Pengecekan tipe adalah proses memverifikasi bahwa suatu program adalah tipe aman, ini adalah, memeriksa informasi yang diketik untuk variabel kelas dan instance, parameter metode, nilai kembali, dan variabel lainnya. Misalnya Java tahu tentang int, String, .. pada waktu kompilasi, sedangkan jenis objek dalam JavaScript hanya dapat ditentukan saat runtime
2. Mengetik Kuat vs Lemah
Strong - menetapkan batasan pada jenis nilai yang disediakan untuk operasinya (mis. Java)
Lemah - mengkonversi (melemparkan) argumen operasi jika argumen tersebut memiliki tipe yang tidak kompatibel (mis. Visual Basic)
Mengetahui bahwa Java adalah jenis yang Statically and Weakly typed, bagaimana Anda mengimplementasikan bahasa yang diketik secara Dinamis dan Kuat pada JVM?
Invokedynamic mengimplementasikan sistem runtime yang dapat memilih implementasi metode atau fungsi yang paling tepat - setelah program dikompilasi.
Contoh: Memiliki (a + b) dan tidak tahu apa-apa tentang variabel a, b pada waktu kompilasi, invokedynamic memetakan operasi ini ke metode yang paling tepat di Java saat runtime. Misalnya, jika ternyata a, b adalah Strings, maka panggil metode (String a, String b). Jika ternyata a, b adalah ints, maka panggil metode (int a, int b).
invokedynamic diperkenalkan dengan Java 7.
sumber
Sebagai bagian dari artikel Java Records saya, saya mengartikulasikan tentang motivasi di balik Inoke Dynamic. Mari kita mulai dengan definisi kasar dari Indy.
Memperkenalkan Indy
Invoke Dynamic (Juga dikenal sebagai Indy ) adalah bagian dari JSR 292 yang bermaksud untuk meningkatkan dukungan JVM untuk Dynamic Type Languages. Setelah rilis pertama di Java 7,
invokedynamic
opcode besertajava.lang.invoke
kopernya digunakan cukup luas oleh bahasa berbasis JVM dinamis seperti JRuby.Meskipun indy dirancang khusus untuk meningkatkan dukungan bahasa dinamis, indy menawarkan lebih dari itu. Sebenarnya, ini cocok untuk digunakan di mana pun perancang bahasa membutuhkan segala bentuk dinamika, dari akrobat tipe dinamis hingga strategi dinamis!
Misalnya, Java 8 Lambda Expressions sebenarnya diimplementasikan menggunakan
invokedynamic
, meskipun Java adalah bahasa yang diketik secara statis!Bytecode yang Dapat Ditentukan Pengguna
Untuk beberapa waktu JVM mendukung empat tipe pemanggilan metode:
invokestatic
memanggil metode statis,invokeinterface
memanggil metode antarmuka,invokespecial
memanggil konstruktor,super()
atau metode pribadi daninvokevirtual
memanggil metode instan.Terlepas dari perbedaan mereka, tipe doa ini memiliki satu sifat yang sama: kita tidak dapat memperkaya mereka dengan logika kita sendiri . Sebaliknya,
invokedynamic
memungkinkan kita untuk Bootstrap proses doa dengan cara apa pun yang kita inginkan. Kemudian JVM menangani memanggil Metode Bootstrapped secara langsung.Bagaimana Indy Bekerja?
Pertama kali JVM melihat
invokedynamic
instruksi, ia memanggil metode statis khusus yang disebut Metode Bootstrap . Metode bootstrap adalah bagian dari kode Java yang telah kami tulis untuk menyiapkan logika yang akan dipanggil:Kemudian metode bootstrap mengembalikan instance dari
java.lang.invoke.CallSite
. IniCallSite
memegang referensi ke metode aktual, yaituMethodHandle
.Mulai sekarang, setiap kali JVM melihat
invokedynamic
instruksi ini lagi, ia melompati Slow Path dan secara langsung memanggil executable yang mendasarinya. JVM terus melewati jalur lambat kecuali ada perubahan.Contoh: Java 14 Records
Java 14
Records
menyediakan sintaksis kompak yang bagus untuk mendeklarasikan kelas yang seharusnya menjadi pemegang data bodoh.Mempertimbangkan catatan sederhana ini:
Bytecode untuk contoh ini akan menjadi sesuatu seperti:
Dalam Tabel Metode Bootstrapnya :
Jadi metode bootstrap untuk Records disebut
bootstrap
yang berada dijava.lang.runtime.ObjectMethods
kelas. Seperti yang Anda lihat, metode bootstrap ini mengharapkan parameter berikut:MethodHandles.Lookup
mewakili konteks pencarian (BagianLjava/lang/invoke/MethodHandles$Lookup
).toString
,equals
,hashCode
, dll) bootstrap yang akan untuk nge-link. Misalnya, ketika nilainya adalahtoString
, bootstrap akan mengembalikan aConstantCallSite
(CallSite
yang tidak pernah berubah) yang menunjuk ketoString
implementasi aktual untuk Catatan khusus ini.TypeDescriptor
metode (Ljava/lang/invoke/TypeDescriptor
bagian).Class<?>
, mewakili tipe kelas Rekam. DalamClass<Range>
kasus ini.min;max
.MethodHandle
per komponen. Dengan cara ini metode bootstrap dapat membuatMethodHandle
berbasis pada komponen untuk implementasi metode khusus ini.The
invokedynamic
instruksi melewati semua argumen mereka dengan metode bootstrap. Metode bootstrap, pada gilirannya, mengembalikan sebuah instance dariConstantCallSite
. IniConstantCallSite
memegang referensi untuk implementasi metode yang diminta, misalnyatoString
.Mengapa indy
Berbeda dengan Reflection APIs,
java.lang.invoke
API ini cukup efisien karena JVM dapat sepenuhnya melihat semua permintaan. Karena itu, JVM dapat menerapkan segala macam optimasi selama kita menghindari jalan lambat sebanyak mungkin!Selain argumen efisiensi,
invokedynamic
pendekatan ini lebih dapat diandalkan dan kurang rapuh karena kesederhanaannya .Selain itu, bytecode yang dihasilkan untuk Java Records tidak tergantung pada jumlah properti. Jadi, bytecode lebih sedikit dan waktu startup lebih cepat.
Akhirnya, anggaplah versi baru Java menyertakan implementasi metode bootstrap baru dan lebih efisien. Dengan
invokedynamic
, aplikasi kami dapat memanfaatkan peningkatan ini tanpa kompilasi ulang. Dengan cara ini kita memiliki semacam Kompatibilitas Biner Teruskan . Juga, Itulah strategi dinamis yang sedang kita bicarakan!Contoh lain
Selain Java Records, dinamis yang dipanggil telah digunakan untuk mengimplementasikan fitur-fitur seperti:
LambdaMetafactory
StringConcatFactory
sumber