Apa yang membuat JVM sangat fleksibel untuk mendukung begitu banyak bahasa JVM?

18

JVM mendukung begitu banyak bahasa selain Java seperti Groovy,Clojure,Scaladll yang bahasa fungsional seperti Java (Saya mengacu pada Java sebelum Versi 8 di mana Lambda'stidak didukung) yang tidak mendukung fungsional capabilities.On tingkat tinggi yang membuat JVM sangat serbaguna yang dapat mendukung baik Bahasa Berorientasi Objek maupun Fungsional?

Kutu buku
sumber
"Groovy, Clojure, Scala dll yang fungsional". Beberapa di antaranya lebih fungsional daripada yang lain. Saya akan menggunakan skala dengan Groovy yang paling tidak berfungsi dan paling Clojure, dengan Scala di tengah.
Vorg van Geir

Jawaban:

37

Dibandingkan dengan VM lain, JVM sebenarnya tidak terlalu serbaguna . Ini secara langsung mendukung OO yang diketik secara statis. Untuk yang lainnya, Anda harus melihat bagian apa yang dapat Anda gunakan, dan bagaimana Anda bisa membangun semua yang dibutuhkan bahasa Anda di atas bagian-bagian itu.

Sebagai contoh, sampai Java 7 memperkenalkan invokedynamicbytecode, sangat sulit untuk mengimplementasikan bahasa OO yang diketik secara dinamis di JVM - Anda harus menggunakan solusi kompleks yang buruk untuk kinerja dan menghasilkan jejak tumpukan yang membengkak.

Namun, banyak bahasa dinamis (Groovy, Jython, JRuby, antara lain) diimplementasikan pada JVM sebelumnya.

Bukan karena JVM sangat fleksibel, tetapi karena sangat luas, dan karena ia memiliki implementasi yang sangat matang, didukung dengan baik, dan berkinerja tinggi.

Dan, mungkin bahkan lebih penting, karena ada sejumlah besar kode Java di luar sana melakukan cukup banyak hal, dan jika bahasa Anda berjalan pada JVM, Anda dapat dengan mudah menawarkan fasilitas untuk berintegrasi dengan kode itu. Pada dasarnya, menjalankan bahasa Anda di JVM adalah versi abad ke-21 yang menawarkan interoperabilitas dengan C.

Michael Borgwardt
sumber
Jawaban bagus (+1). Poin terakhir yang Anda sebutkan adalah IMHO juga bertanggung jawab atas popularitas Java sebagai bahasa: pada akhirnya, memiliki sejumlah besar kode yang dapat Anda gunakan kembali secara gratis dapat menghemat lebih banyak waktu daripada menggunakan bahasa terbaru dan paling modis. fitur.
Giorgio
4

JVM ditulis pada dasarnya bertindak seperti CPU, ada satu set instruksi, semacam perakitan, yang dijalankan oleh VM disebut bytecodes. Jika Anda dapat menulis kompiler yang menghasilkan set bytecode yang valid, maka JVM dapat menjalankannya.

Wikipedia memiliki daftar bytecodes:

http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings

serta penjelasan tentang bagaimana JVM memuat kode byte:

http://en.wikipedia.org/wiki/Java_virtual_machine

Dengan menggunakan bytecodes style invoke, bahasa fungsional dapat mengeksekusi kode, apa pun sumbernya. Juga, dengan penambahan invokevirtual, implementasi bahasa seperti jruby telah memberikan beberapa fleksibilitas dengan bagaimana mereka berjalan.

Sasbury
sumber
1
Hal yang sama berlaku untuk setiap VM lain di luar sana: YARV Ruby VM, Rubinius Ruby VM, CPython VM (yang setelah semua mendahului JVM), Parrot, berbagai Smalltalk dan Lisp VM, dan tentu saja Pascal P- Sistem kode, setelah itu JVM dimodelkan.
Jörg W Mittag
Setuju, JVM jelas bukan VM pertama di luar sana. Saya pikir JVM populer untuk bahasa lain karena Java populer, VM dikembangkan secara aktif dan didokumentasikan dengan baik.
sasbury
2

Saya akan menambahkan bahwa JVM mendukung Memory Model ( JMM ) yang didefinisikan dengan baik dan cukup baik yang berarti dukungan yang baik untuk perilaku threading yang konsisten (meskipun tingkat rendah). Ini juga memiliki kompiler Just In Time yang kuat (tidak lebih berguna untuk bahasa yang dinamis berkat MethodHandles dan invokedynamic).

Terakhir namun tidak kalah pentingnya adalah sub-sistem Pengumpulan Sampah JVM yang (dengan penyetelan yang tepat) mengelola memori untuk Anda terlepas dari bahasa di atasnya.

Martijn Verburg
sumber
JMM adalah salah satu hal yang paling tidak saya sukai tentang Java. Saya penggemar data yang tidak dapat diubah secara efektif (misalnya array yang isinya tidak akan pernah berubah setelah mereka dapat dilihat oleh utas lainnya), tetapi diberi pernyataan seperti someField = new int[]{42};satu-satunya cara untuk memastikan bahwa setiap utas yang melihat array baru akan melihat nilainya 42 adalah untuk membuat lapangan finalatau volatile. Jika bidang dihasilkan dengan malas tetapi sering diakses, membuatnya finaltidak berfungsi, dan membuatnya volatiledapat memberikan hukuman sinkronisasi yang tidak perlu setiap kali diakses. Bahkan model .NET yang paling longgar ...
supercat
... kode dapat meminta agar populasi array terjadi sebelum penyimpanan referensi. Utas lain yang membaca bidang ini mungkin atau mungkin tidak melihat referensi ke array baru, tetapi tidak akan dikenakan biaya untuk diri mereka sendiri bahwa jika mereka melihat array baru, mereka akan melihat isinya.
supercat
1

Elemen kunci dalam hal ini adalah pemisahan kompilasi dari fase eksekusi. Dengan ini dimungkinkan untuk menulis kompiler lain yang mengkompilasi bahasa lain ke bytecode.

Bytecode bertindak serupa dengan kode mesin CPU - Anda memiliki semua operasi kecil yang diperlukan untuk menjalankan program - Anda bisa mendapatkan variabel, melakukan perhitungan matematika, melakukan operasi bersyarat dll.

Java juga tidak spesial. Di Jawa keberadaan beberapa bahasa bahkan bukan tujuan desain, tidak seperti VM lainnya. Untuk Microsoft .Net CIL , kemampuan untuk menjalankan banyak bahasa (C #, VB.Net, ...) adalah elemen desain utama, juga ParrotVM dari proyek Perl6 yang bertujuan untuk menjadi VM generik.

Untuk bersenang-senang, saya pernah membuat bukti bahwa bahkan Zend Engine PHP akan mengizinkannya.

Dan terus terang ini bukan sesuatu yang baru - bahkan pada perangkat keras nyata Anda dapat menjalankan beberapa bahasa - yaitu C atau Fortran.

Perbedaan pemisahan ini dari kompilasi dan eksekusi adalah penerjemah clssic, seperti beberapa bentuk Dasar, skrip shell, dll. Mereka sering bekerja dengan cara yang mengeksekusi kode kurang lebih dalam garis demi garis tanpa membawanya dalam bentuk langsung diantara.

johannes
sumber
1

JVM adalah mesin virtual pertama yang saya ketahui menggabungkan pengumpulan sampah, kinerja, dan model kotak pasir yang bisa diterapkan. Munculnya banyak bahasa untuk mendukung JVM mungkin bukan karena "fleksibilitas" -nya, melainkan fakta bahwa bahasa Jawa tidak memiliki beberapa fitur signifikan yang diinginkan orang dalam bahasa pemrograman. Sebagai contoh, sementara sebagian besar bahasa mesin hanya memiliki sekitar setengah lusin tipe data (mis. Byte, halfword, word, double-word, float presisi tunggal, dan float presisi ganda), sebagian besar bahasa pemrograman memungkinkan kode untuk menggunakan kode jumlah sewenang-wenang dari tipe data yang ditentukan pengguna. JVM mengenali beberapa tipe primitif yang mirip dengan yang ada pada mesin biasa, ditambah satu tipe lagi: Referensi Obyek Promiscuous. Bahasa Jawa juga mengakui primitif itu, dan Referensi Obyek Promiscuous. Sementara variabel mungkin dibatasi untuk tidak memegang referensi ke apa pun yang bukan kelas tertentu, bahasa tidak membuat perbedaan antara salah satu dari jenis bidang bidang berikutList<String>yang mungkin dipegang oleh MyThingkelas instan MyClass:

  • Referensi ke sesuatu kode tahu menjadi implementasi abadi List<String>

  • Referensi ke instance dari tipe daftar yang bisa berubah yang tidak akan pernah terpapar pada apa pun yang mungkin bermutasi.

  • Referensi ke daftar yang dapat berubah yang, kecuali selama pelaksanaan MyThingsmetode, tidak ada referensi lain yang mungkin ada di mana pun di alam semesta.

  • Referensi ke daftar yang dapat diubah yang dimiliki oleh beberapa objek lain , yang ingin MyThingdigunakan oleh objek lain dengan cara tertentu.

  • Referensi ke daftar yang bisa berubah yang MyThingdimiliki, tetapi yang juga terkena beberapa objek lain sehingga mereka dapat melakukan sesuatu dengannya.

Meskipun semua bidang itu bisa memiliki tipe List<String>, mereka memiliki hal-hal yang sangat berbeda. Bahasa ekspresif memungkinkan perbedaan di antara makna-makna itu, tetapi Java tidak. Karena suatu bahasa dapat melampirkan makna pada hal-hal seperti itu (setidaknya di luar konteks generik) dan dijalankan pada JVM, itu menyisakan banyak ruang bagi bahasa-bahasa yang ditargetkan JVM untuk mengekspresikan konsep-konsep yang tidak bisa dilakukan Java.

supercat
sumber