Java "Virtual Machine" vs. Python "Interpreter" bahasa?

207

Tampaknya jarang membaca tentang "mesin virtual" Python sementara di Jawa "mesin virtual" digunakan sepanjang waktu.

Keduanya menginterpretasikan kode byte; mengapa menyebut satu mesin virtual dan yang lainnya seorang juru bahasa?

twils
sumber

Jawaban:

137

Mesin virtual adalah lingkungan komputasi virtual dengan seperangkat instruksi atom yang didefinisikan dengan baik yang didukung secara independen dari bahasa tertentu dan umumnya dianggap sebagai kotak pasir bagi dirinya sendiri. VM analog dengan seperangkat instruksi dari CPU tertentu dan cenderung bekerja pada tingkat yang lebih mendasar dengan blok bangunan yang sangat mendasar dari instruksi tersebut (atau kode byte) yang tidak tergantung pada yang berikutnya. Instruksi dijalankan secara deterministik hanya berdasarkan pada kondisi saat ini dari mesin virtual dan tidak bergantung pada informasi di tempat lain dalam aliran instruksi pada saat itu.

Sebaliknya, seorang juru bahasa lebih canggih karena ia dirancang untuk mengurai aliran sintaksis yang dari bahasa tertentu dan grammer tertentu yang harus diterjemahkan dalam konteks token sekitarnya. Anda tidak dapat melihat setiap byte atau bahkan setiap baris secara terpisah dan tahu persis apa yang harus dilakukan selanjutnya. Token dalam bahasa tidak dapat diambil secara terpisah seperti mereka dapat relatif terhadap instruksi (kode byte) dari VM.

Kompiler Java mengubah bahasa Java menjadi aliran kode byte yang tidak berbeda dengan kompiler C yang mengubah program Bahasa C menjadi kode assembly. Seorang penerjemah di sisi lain tidak benar-benar mengubah program menjadi bentuk peralihan yang didefinisikan dengan baik, hanya mengambil tindakan program sebagai masalah proses menafsirkan sumber.

Tes lain dari perbedaan antara VM dan penerjemah adalah apakah Anda menganggapnya sebagai bahasa yang independen. Apa yang kita ketahui sebagai Java VM bukanlah Java yang spesifik. Anda bisa membuat kompiler dari bahasa lain yang menghasilkan kode byte yang dapat dijalankan di JVM. Di sisi lain, saya tidak berpikir kita akan benar-benar berpikir untuk "menyusun" beberapa bahasa lain selain Python ke Python untuk interpretasi oleh juru bahasa Python.

Karena kecanggihan proses penafsiran, ini bisa menjadi proses yang relatif lambat .... secara khusus menguraikan dan mengidentifikasi token bahasa, dll. Dan memahami konteks sumber untuk dapat melakukan proses eksekusi dalam juru bahasa. Untuk membantu mempercepat bahasa yang ditafsirkan seperti ini, di sinilah kita dapat mendefinisikan bentuk-bentuk menengah dari kode sumber pra-parsing, pra-tokenized yang lebih mudah langsung ditafsirkan. Bentuk biner semacam ini masih ditafsirkan pada waktu pelaksanaan, itu hanya mulai dari bentuk yang jauh lebih mudah dibaca manusia untuk meningkatkan kinerja. Namun, logika yang mengeksekusi bentuk itu bukan mesin virtual, karena kode-kode itu masih tidak dapat diambil secara terpisah - konteks token di sekitarnya masih penting, mereka sekarang dalam bentuk yang lebih efisien komputer.

Jeff tinggi
sumber
7
Saya mendapat kesan bahwa python memang menghasilkan kode byte, pyc, atau apa yang Anda maksudkan dengan "membantu mempercepat bahasa yang ditafsirkan seperti ini, di sinilah kita dapat mendefinisikan bentuk perantara kode sumber pra-parsing, pra-tokenized yang lebih siap ditafsirkan secara langsung. "
James McMahon
32
@InSciTek Jeff: Dari jawaban Anda, tidak jelas apakah Anda tahu bahwa Python juga menggunakan mesin virtual.
tzot
3
@ TX - Implementasi Python yang populer adalah kompiler Python dengan VM sisi belakang. Dalam mode interaktif, itu sedikit hibrida dengan kedua ujung depan juru bahasa, dan ujung belakang kompiler. Namun itu adalah pilihan implementasi. Saya mencoba menggambarkan perbedaan antara konsep VM dan Interpreter
Tall Jeff
8
On the other hand, I don't think we would really think of "compiling" some other language other than Python into Python for interpretation by the Python interpreter.Dimungkinkan untuk menulis bahasa yang dapat dikompilasi menjadi bytecode Python, sama seperti Scala dikompilasi ke dalam bytecode Java. Dalam mode interaktif, shell interaktif Python mengkompilasi perintah yang Anda ketik menjadi bytecode dan mengeksekusi bytecode itu. Anda dapat menulis shell Anda sendiri menggunakan eval dan exec, dan Anda dapat menggunakan fungsi kompilasi () bawaan untuk mengubah string menjadi bytecode.
Lie Ryan
4
@ Lie Ryan ya tapi itu tidak didukung secara resmi seperti halnya dengan JVM. Dalam Python, bytecode adalah detail implementasi tanpa dokumen.
Antimony
159

Dalam posting ini, "mesin virtual" mengacu pada proses mesin virtual, bukan ke sistem mesin virtual seperti Qemu atau Virtualbox. Mesin virtual proses hanyalah sebuah program yang menyediakan lingkungan pemrograman umum - program yang dapat diprogram.

Java memiliki juru bahasa serta mesin virtual, dan Python memiliki mesin virtual serta juru bahasa. Alasan "mesin virtual" adalah istilah yang lebih umum di Jawa dan "interpreter" adalah istilah yang lebih umum di Python memiliki banyak kaitan dengan perbedaan utama antara dua bahasa: pengetikan statis (Java) vs pengetikan dinamis (Python). Dalam konteks ini, "tipe" mengacu pada tipe data primitif - tipe yang menunjukkan ukuran penyimpanan data dalam memori. Mesin virtual Java memudahkannya. Ini membutuhkan programmer untuk menentukan tipe data primitif dari setiap variabel. Ini memberikan informasi yang cukup untuk bytecode Java tidak hanya untuk ditafsirkan dan dieksekusi oleh mesin virtual Java, tetapi bahkan untuk dikompilasi ke dalam instruksi mesin. Mesin virtual Python lebih kompleks dalam arti bahwa ia mengambil tugas tambahan berhenti sebelum eksekusi setiap operasi untuk menentukan tipe data primitif untuk setiap variabel atau struktur data yang terlibat dalam operasi. Python membebaskan programmer dari pemikiran dalam hal tipe data primitif, dan memungkinkan operasi untuk diekspresikan pada tingkat yang lebih tinggi. Harga kebebasan ini adalah kinerja. "Interpreter" adalah istilah yang lebih disukai untuk Python karena harus berhenti sejenak untuk memeriksa tipe data, dan juga karena sintaksis ringkas dari bahasa yang diketik secara dinamis sangat cocok untuk antarmuka interaktif. Tidak ada hambatan teknis untuk membangun antarmuka Java interaktif, tetapi mencoba untuk menulis kode yang diketik secara statis akan membosankan, jadi itu tidak dilakukan dengan cara itu.

Di dunia Java, mesin virtual mencuri perhatian karena menjalankan program yang ditulis dalam bahasa yang sebenarnya dapat dikompilasi menjadi instruksi mesin, dan hasilnya adalah kecepatan dan efisiensi sumber daya. Bytecode Java dapat dijalankan oleh mesin virtual Java dengan kinerja yang mendekati program yang dikompilasi, relatif berbicara. Hal ini disebabkan oleh adanya informasi tipe data primitif dalam bytecode. Mesin virtual Java menempatkan Java dalam kategori sendiri:

portabel ditafsirkan bahasa yang diketik secara statis

Hal terdekat berikutnya adalah LLVM, tetapi LLVM beroperasi pada tingkat yang berbeda:

bahasa majelis ditafsirkan portabel

Istilah "bytecode" digunakan dalam Java dan Python, tetapi tidak semua bytecode dibuat sama. bytecode hanyalah istilah umum untuk bahasa perantara yang digunakan oleh kompiler / juru bahasa. Bahkan kompiler C seperti gcc menggunakan bahasa perantara (atau beberapa) untuk menyelesaikan pekerjaan. Bytecode Java berisi informasi tentang tipe data primitif, sedangkan bytecode Python tidak. Dalam hal ini, mesin virtual Python (dan Bash, Perl, Ruby, dll.) Benar-benar secara fundamental lebih lambat daripada mesin virtual Java, atau lebih tepatnya, ia hanya memiliki lebih banyak pekerjaan yang harus dilakukan. Penting untuk mempertimbangkan informasi apa yang terkandung dalam berbagai format bytecode:

  • llvm: register cpu
  • Java: tipe data primitif
  • Python: tipe yang ditentukan pengguna

Untuk menggambar analogi dunia nyata: LLVM bekerja dengan atom, mesin virtual Java bekerja dengan molekul, dan mesin virtual The Python bekerja dengan bahan. Karena semuanya akhirnya harus terurai menjadi partikel subatomik (operasi mesin nyata), mesin virtual Python memiliki tugas yang paling kompleks.

Intepreters / kompiler dari bahasa yang diketik secara statis tidak memiliki bagasi yang sama dengan yang dimiliki oleh penerjemah / kompiler dari bahasa yang diketik secara dinamis. Programmer dari bahasa yang diketik secara statis harus mengambil kendur, yang hasilnya adalah kinerja. Namun, sama seperti semua fungsi nondeterministic diam-diam deterministik, demikian pula semua bahasa yang diketik secara dinamis diam-diam diketik secara statis. Oleh karena itu, perbedaan kinerja antara dua rumpun bahasa seharusnya meningkat pada saat Python mengubah namanya menjadi HAL 9000.

Mesin virtual bahasa dinamis seperti Python mengimplementasikan beberapa mesin logis ideal, dan tidak harus berhubungan erat dengan perangkat keras fisik nyata. Mesin virtual Java, sebaliknya, lebih mirip fungsinya dengan kompiler C klasik, kecuali bahwa alih-alih memancarkan instruksi mesin, ia menjalankan rutinitas bawaan. Dalam Python, integer adalah objek Python dengan banyak atribut dan metode yang melekat padanya. Di Jawa, int adalah jumlah bit yang ditentukan, biasanya 32. Ini sebenarnya bukan perbandingan yang adil. Bilangan bulat Python harus benar-benar dibandingkan dengan kelas Java Integer. Tipe data primitif "int" Java tidak dapat dibandingkan dengan apa pun dalam bahasa Python, karena bahasa Python tidak memiliki lapisan primitif ini, dan begitu juga bytecode Python.

Karena variabel Java diketik secara eksplisit, orang bisa berharap sesuatu seperti kinerja Jython berada di ballpark yang sama dengan cPython . Di sisi lain, mesin virtual Java yang diimplementasikan dengan Python hampir dijamin lebih lambat daripada lumpur. Dan jangan berharap Ruby, Perl, dll, untuk ongkos lebih baik. Mereka tidak dirancang untuk melakukan itu. Mereka dirancang untuk "scripting", yang disebut pemrograman dalam bahasa yang dinamis.

Setiap operasi yang terjadi di mesin virtual pada akhirnya harus mencapai perangkat keras yang nyata. Mesin virtual berisi rutinitas yang telah dikompilasi sebelumnya yang cukup umum untuk menjalankan kombinasi operasi logis apa pun. Mesin virtual mungkin tidak memancarkan instruksi mesin baru, tetapi tentu saja menjalankan rutinitas sendiri berulang-ulang dalam urutan rumit yang kompleks. Mesin virtual Java, mesin virtual Python, dan semua mesin virtual serba guna lainnya di luar sana sama dalam arti bahwa mereka dapat dibujuk untuk melakukan logika apa pun yang dapat Anda impikan, tetapi mereka berbeda dalam hal tugas apa yang mereka mengambil, dan tugas apa yang mereka berikan kepada programmer.

Psyco untuk Python bukan mesin virtual Python penuh, tetapi kompilator just-in-time yang membajak mesin virtual Python biasa pada titik-titik yang menurutnya dapat mengkompilasi beberapa baris kode - terutama loop di mana ia berpikir jenis primitif dari beberapa variabel akan tetap konstan bahkan jika nilainya berubah dengan setiap iterasi. Dalam hal ini, ia dapat melepaskan beberapa penentuan jenis mesin virtual reguler. Anda harus sedikit berhati-hati, jangan sampai Anda menarik tipe keluar dari bawah kaki Psyco. Pysco, bagaimanapun, biasanya tahu untuk kembali ke mesin virtual biasa jika tidak sepenuhnya yakin tipe tidak akan berubah.

Moral dari cerita ini adalah bahwa informasi tipe data primitif sangat membantu untuk mesin kompiler / virtual.

Akhirnya, untuk menempatkan semuanya dalam perspektif pertimbangkan ini: program Python dieksekusi oleh juru bahasa Python / mesin virtual diimplementasikan di Jawa berjalan pada mesin penerjemah / virtual Java diimplementasikan dalam LLVM berjalan di mesin virtual qemu yang berjalan pada iPhone.

permalink

pooryorick
sumber
1
trying to write any statically-typed code interactively would be tedious. Jika Anda tahu OCaml dan Haskell Anda akan melihat bahwa itu tidak benar karena mereka adalah bahasa yang diketik dengan sangat statis.
Matthias Braun
@MatthiasBraun Saya bisa setuju bahwa bahasa-bahasa fungsional menghasilkan kode ringkas tetapi itu tidak berarti bahwa mereka cocok untuk mode interaktif. Jika OCaml dan Haskell diketik secara dinamis seperti lisp, mereka akan bekerja lebih baik untuk mode interaktif.
bom
58

Mungkin salah satu alasan untuk terminologi yang berbeda adalah bahwa orang biasanya berpikir untuk memberi makan python interpreter mentah kode sumber yang dapat dibaca manusia dan tidak khawatir tentang bytecode dan semua itu.

Di Jawa, Anda harus secara eksplisit mengkompilasi ke bytecode dan kemudian menjalankan bytecode, bukan kode sumber pada VM.

Meskipun Python menggunakan mesin virtual di bawah selimut, dari sudut pandang pengguna, sebagian besar orang dapat mengabaikan detail ini.

Tuan Fooz
sumber
1
Saya setuju. Perbedaan dalam terminologi ini benar-benar bermuara pada pengalaman pengguna akhir (pengembang, yaitu). Ini tidak ada hubungannya dengan perbedaan teknis yang nyata, karena garis teknis sangat kabur sampai hampir tidak ada.
Cody Brocious
1
+1: Dan - yang lebih penting - apa gunanya? Program apa yang tidak bisa Anda tulis karena perbedaan ini? Apa tumpukan traceback membingungkan Anda? Pustaka apa yang tampaknya tidak berfungsi dengan benar?
S.Lott
@ S.Lott Karena selalu baik untuk memenangkan pertengkaran dengan rekan kerja. ;)
Qix - MONICA DISALAHKAN
16

Penerjemah , menerjemahkan kode sumber menjadi beberapa perwakilan perantara (kode) yang efisien dan segera menjalankannya.

Virtual Machine , secara eksplisit menjalankan kode pra-kompilasi yang disimpan yang dibangun oleh kompiler yang merupakan bagian dari sistem interpreter.

Karakteristik yang sangat penting dari mesin virtual adalah bahwa perangkat lunak yang berjalan di dalam, terbatas pada sumber daya yang disediakan oleh mesin virtual. Tepatnya, ia tidak bisa keluar dari dunia virtualnya. Pikirkan eksekusi aman kode jarak jauh, Java Applets.

Dalam kasus python, jika kita menjaga pyc file , seperti yang disebutkan dalam komentar posting ini, maka mekanismenya akan menjadi lebih seperti VM, dan bytecode ini dieksekusi lebih cepat - itu masih akan ditafsirkan tetapi dari bentuk komputer yang lebih ramah . Jika kita melihat ini secara keseluruhan, PVM adalah langkah terakhir dari Python Interpreter.

Intinya adalah, ketika merujuk Python Interpreter, itu berarti kita merujuknya secara keseluruhan, dan ketika kita mengatakan PVM, itu berarti kita hanya berbicara tentang bagian dari Python Interpreter, sebuah lingkungan runtime. Mirip dengan Java, kami merujuk berbagai bagian yang berbeda, JRE, JVM, JDK, dll.

Untuk lebih lanjut, Masukan Wikipedia: Juru Bahasa , dan Mesin Virtual . Satu lagi di sini . Di sini Anda dapat menemukan Perbandingan aplikasi mesin virtual . Ini membantu dalam memahami perbedaan antara, Compiler, Interpreter, dan VM.

Adeel Ansari
sumber
12

Istilah juru bahasa adalah istilah lama yang berasal dari bahasa skrip shell sebelumnya. Karena "bahasa scripting" telah berevolusi menjadi bahasa fitur penuh dan platform yang sesuai telah menjadi lebih canggih dan berpasir, perbedaan antara mesin virtual dan penerjemah (dalam arti Python), sangat kecil atau tidak ada.

Interpreter Python masih berfungsi dengan cara yang sama seperti skrip shell, dalam arti bahwa itu dapat dieksekusi tanpa langkah kompilasi yang terpisah. Di luar itu, perbedaan antara interpreter Python (atau Perl atau Ruby) dan mesin virtual Java sebagian besar detail implementasi. (Orang bisa berpendapat bahwa Java lebih sepenuhnya berpasir daripada Python, tetapi keduanya akhirnya memberikan akses ke arsitektur yang mendasarinya melalui antarmuka C asli.)

Daniel Naab
sumber
1
ada cangkang java yang dapat menjalankan kode java tanpa langkah kompilasi terpisah (terlihat pengguna).
Lie Ryan
1
beri nama: D
Maciej Nowicki
11

Untuk memberikan jawaban yang mendalam untuk pertanyaan " Mengapa Java Virtual Machine, tetapi Python interpreter? " Mari kita coba kembali ke bidang teori kompilasi sebagai titik awal diskusi.

Proses khas penyusunan program mencakup langkah-langkah berikut:

  1. Analisis leksikal . Pisahkan teks program menjadi "kata" bermakna yang disebut token (sebagai bagian dari proses, semua komentar, spasi, baris baru, dll. Dihapus, karena tidak memengaruhi perilaku program). Hasilnya adalah aliran token yang dipesan.
  2. Analisis sintaksis . Membangun apa yang disebut Pohon Sintaksis Abstrak (AST) dari aliran token. AST membangun hubungan antara token dan, sebagai konsekuensinya, menentukan urutan evaluasi program.
  3. Analisis semantik . Memverifikasi kebenaran semantik AST menggunakan informasi tentang jenis dan seperangkat aturan semantik bahasa pemrograman. (Misalnya, a = b + cpernyataan yang benar dari sudut pandang sintaksis, tetapi sepenuhnya salah dari sudut pandang semantik jika adinyatakan sebagai objek konstan)
  4. Pembuatan kode menengah . Serializes AST ke dalam aliran yang dipesan secara linier dari operasi "primitif" alat berat yang independen. Bahkan, pembuat kode melintasi AST dan mencatat urutan langkah-langkah evaluasi. Sebagai hasilnya, dari representasi program yang mirip pohon, kami mencapai representasi daftar yang lebih sederhana di mana urutan evaluasi program dipertahankan.
  5. Pembuatan kode mesin . Program dalam bentuk bytecode "primitif" independen mesin diterjemahkan ke dalam kode mesin arsitektur prosesor tertentu.

Baik. Sekarang mari kita mendefinisikan persyaratan.

Penerjemah , dalam arti klasik dari kata itu, mengasumsikan eksekusi berdasarkan evaluasi program berdasarkan AST yang dihasilkan langsung dari teks program . Dalam hal ini, sebuah program didistribusikan dalam bentuk kode sumber dan penerjemah diumpankan oleh teks program, sering kali dengan cara yang dinamis (pernyataan demi pernyataan atau baris demi baris). Untuk setiap pernyataan input, juru bahasa membangun AST-nya dan segera mengevaluasinya mengubah "keadaan" program. Ini adalah perilaku khas yang ditunjukkan oleh bahasa scripting. Pertimbangkan misalnya Bash, Windows CMD dll. Secara konseptual, Python mengambil cara ini juga.

Jika kita mengganti langkah eksekusi berbasis AST pada pembuatan langkah bytecode biner independen mesin menengah dalam interpreter, kami akan membagi seluruh proses eksekusi program menjadi dua fase terpisah: kompilasi dan eksekusi. Dalam hal ini apa yang sebelumnya adalah juru bahasa akan menjadi kompiler bytecode, yang akan mengubah program dari bentuk teks menjadi beberapa bentuk biner . Kemudian program didistribusikan dalam bentuk biner itu, tetapi tidak dalam bentuk kode sumber. Pada mesin pengguna, bytecode dimasukkan ke entitas baru - mesin virtual , yang sebenarnya mengartikan bytecode itu. Karena ini, mesin virtual juga disebut interpreter bytecode . Tetapi berikan perhatian Anda di sini! Seorang juru bahasa klasik adalah apenerjemah teks penerjemah , tetapi mesin virtual adalahpenerjemah biner ! Ini adalah pendekatan yang diambil oleh Java dan C #.

Akhirnya, jika kita menambahkan pembuatan kode mesin ke kompiler bytecode, kita mencapai apa yang kita sebut kompiler klasik . Compiler klasik mengubah kode sumber program menjadi kode mesin prosesor tertentu. Kode mesin itu kemudian dapat dieksekusi langsung pada prosesor target tanpa mediasi tambahan (tanpa interpreter apa pun, tidak ada penerjemah teks atau penerjemah biner).

Ayo sekarang kembali ke pertanyaan awal dan pertimbangkan Java vs Python.

Java pada awalnya dirancang untuk memiliki dependensi implementasi sesedikit mungkin. Desainnya didasarkan pada prinsip "tulis sekali, jalankan di mana saja" (WORA). Untuk mengimplementasikannya, Java pada awalnya dirancang sebagai bahasa pemrograman yang mengkompilasi ke dalam bytecode biner bebas-mesin , yang kemudian dapat dieksekusi pada semua platform yang mendukung Java tanpa perlu melakukan kompilasi ulang. Anda dapat berpikir tentang Java seperti tentang C ++ berbasis WORA . Sebenarnya, Java lebih dekat ke C ++ daripada ke bahasa scripting seperti Python . Tetapi berbeda dengan C ++ , Javadirancang untuk dikompilasi menjadibytecode biner yang kemudian dieksekusi di lingkungan mesin virtual , sementara C ++ dirancang untuk dikompilasi dalam kode mesin dan kemudian langsung dieksekusi oleh prosesor target.

Python pada awalnya dirancang sebagai semacam bahasa pemrograman scripting yang menafsirkan skrip (program dalam bentuk teks yang ditulis sesuai dengan aturan bahasa pemrograman). Karena ini, Python awalnya mendukung interpretasi dinamis dari perintah atau pernyataan satu baris, seperti yang dilakukan Bash atau Windows CMD. Untuk alasan yang sama, implementasi awal Python tidak memiliki jenis bytecode compiler dan mesin virtual untuk eksekusi bytecode di dalamnya, tetapi sejak awal Python membutuhkan penerjemah yang mampu memahami dan mengevaluasi teks program Python .

Karena ini, secara historis, pengembang Java cenderung berbicara tentang Java Virtual Machine (karena pada awalnya, Java telah datang sebagai paket kompiler bytecode Java dan interteter bytecode - JVM ), dan pengembang Python cenderung berbicara tentang interpreter Python (karena pada awalnya Python memiliki bukan mesin virtual dan sejenis penerjemah teks klasik yang mengeksekusi teks program secara langsung tanpa kompilasi atau transformasi apa pun ke dalam bentuk kode biner apa pun).

Saat ini, Python juga memiliki mesin virtual di bawah kap dan dapat mengkompilasi dan menafsirkan bytecode Python. Dan fakta itu membuat investasi tambahan ke dalam kebingungan " Kenapa Java Virtual Machine, tetapi Python interpreter?dan bahwa program akan menunjukkan perilaku yang sama persis dan menghasilkan output yang sama dari input yang sama. Satu-satunya perbedaan yang dapat diamati adalah kecepatan eksekusi program dan jumlah memori yang dikonsumsi oleh penerjemah. Dengan demikian, mesin virtual dalam Python bukan bagian yang tidak dapat dihindari dari desain bahasa, tetapi hanya perpanjangan opsional dari juru bahasa Python utama.

Java dapat dianggap dengan cara yang sama. Java di bawah kap memiliki kompiler JIT dan secara selektif dapat mengkompilasi metode kelas Java ke dalam kode mesin platform target dan kemudian langsung menjalankannya. Tapi! Java masih menggunakan interpretasi bytecode sebagai cara utama pelaksanaan program Java. Seperti implementasi Python yang mengeksploitasi mesin virtual di bawah tenda secara eksklusif sebagai teknik optimisasi, mesin virtual Java menggunakan kompiler Just-In-Time secara eksklusif untuk tujuan optimasi. Demikian pula, hanya karena fakta bahwa eksekusi langsung dari kode mesin setidaknya sepuluh kali lebih cepat daripada interpretasi bytecode Java. Dan seperti dalam kasus Python, keberadaan JIT compiler di bawah kap JVM benar-benar transparan untuk desainer bahasa Jawa dan pengembang program Java. Bahasa pemrograman Java yang sama dapat diimplementasikan oleh JVM dengan dan tanpa kompiler JIT. Dan dengan cara yang sama, program yang sama dapat dijalankan dalam JVM dengan dan tanpa JIT di dalam, dan program yang sama akan menunjukkan perilaku yang sama persis dan menghasilkan output yang sama dari input yang sama pada kedua JVM (dengan dan tanpa JIT). Dan seperti dalam kasus Python, satu-satunya perbedaan yang dapat diamati di antara mereka, adalah kecepatan eksekusi dan jumlah memori yang dikonsumsi oleh JVM. Dan akhirnya, seperti dalam kasus Python, JIT di Jawa juga bukan merupakan bagian dari desain bahasa, tetapi hanya perpanjangan opsional dari implementasi JVM utama. dan program yang sama akan menunjukkan perilaku yang sama persis dan menghasilkan output yang sama dari input yang sama pada kedua JVM (dengan dan tanpa JIT). Dan seperti dalam kasus Python, satu-satunya perbedaan yang dapat diamati di antara mereka, adalah kecepatan eksekusi dan jumlah memori yang dikonsumsi oleh JVM. Dan akhirnya, seperti dalam kasus Python, JIT di Jawa juga bukan merupakan bagian dari desain bahasa, tetapi hanya perpanjangan opsional dari implementasi JVM utama. dan program yang sama akan menunjukkan perilaku yang sama persis dan menghasilkan output yang sama dari input yang sama pada kedua JVM (dengan dan tanpa JIT). Dan seperti dalam kasus Python, satu-satunya perbedaan yang dapat diamati di antara mereka, adalah kecepatan eksekusi dan jumlah memori yang dikonsumsi oleh JVM. Dan akhirnya, seperti dalam kasus Python, JIT di Jawa juga bukan merupakan bagian dari desain bahasa, tetapi hanya perpanjangan opsional dari implementasi JVM utama.

Dari sudut pandang desain dan implementasi mesin virtual Java dan Python, mereka berbeda secara signifikan, sementara (perhatian!) Keduanya masih tetap mesin virtual. JVM adalah contoh dari mesin virtual level rendah dengan operasi dasar sederhana dan biaya pengiriman instruksi tinggi. Python pada gilirannya adalah mesin virtual tingkat tinggi, yang instruksi menunjukkan perilaku yang kompleks, dan biaya pengiriman instruksi tidak begitu signifikan. Java beroperasi dengan tingkat abstraksi yang sangat rendah. JVM beroperasi pada set kecil tipe primitif yang terdefinisi dengan baik dan memiliki korespondensi yang sangat ketat (biasanya satu banding satu) antara instruksi bytecode dan instruksi kode mesin asli. Sebaliknya, mesin virtual Python beroperasi pada tingkat abstraksi tinggi, ia beroperasi dengan tipe data (objek) yang kompleks dan mendukung polimorfisme ad-hoc, sementara instruksi bytecode mengekspos perilaku kompleks, yang dapat diwakili oleh serangkaian instruksi kode mesin asli. Misalnya, Python mendukung matematika rentang tak terbatas. Dengan demikian Python VM terpaksa mengeksploitasi aritmatika lama untuk bilangan bulat yang berpotensi besar yang hasil operasi dapat meluap kata mesin. Oleh karena itu, satu instruksi bytecode untuk aritmatika dalam Python dapat mengekspos ke pemanggilan fungsi di dalam Python VM, sedangkan dalam operasi aritmatika JVM akan mengekspos ke operasi sederhana yang diungkapkan oleh satu atau beberapa instruksi mesin asli. Dengan demikian Python VM terpaksa mengeksploitasi aritmatika lama untuk bilangan bulat yang berpotensi besar yang hasil operasi dapat meluap kata mesin. Oleh karena itu, satu instruksi bytecode untuk aritmatika dalam Python dapat mengekspos ke pemanggilan fungsi di dalam Python VM, sedangkan dalam operasi aritmatika JVM akan mengekspos ke operasi sederhana yang diungkapkan oleh satu atau beberapa instruksi mesin asli. Dengan demikian Python VM terpaksa mengeksploitasi aritmatika lama untuk bilangan bulat yang berpotensi besar yang hasil operasi dapat meluap kata mesin. Oleh karena itu, satu instruksi bytecode untuk aritmatika dalam Python dapat mengekspos ke pemanggilan fungsi di dalam Python VM, sedangkan dalam operasi aritmatika JVM akan mengekspos ke operasi sederhana yang diungkapkan oleh satu atau beberapa instruksi mesin asli.

Hasilnya, kita bisa menarik kesimpulan selanjutnya. Java Virtual Machine tetapi juru bahasa Python adalah karena:

  1. Istilah mesin virtual mengasumsikan interpretasi bytecode biner, sedangkan istilah interpreter mengasumsikan interpretasi teks program.
  2. Secara historis, Java dirancang dan diimplementasikan untuk interpretasi bytecode biner dan Python awalnya dirancang dan diimplementasikan untuk interpretasi teks program. Dengan demikian, istilah "Java Virtual Machine" adalah historis dan mapan di komunitas Java. Dan demikian pula, istilah "Penerjemah Python" adalah historis dan mapan di komunitas Python. Masyarakat cenderung memperpanjang tradisi dan menggunakan istilah yang sama yang digunakan sebelumnya.
  3. Akhirnya, saat ini, untuk Java, interpretasi bytecode biner adalah cara utama pelaksanaan program, sementara kompilasi JIT hanyalah optimasi opsional dan transparan. Dan untuk Python, saat ini, interpretasi teks program adalah cara utama pelaksanaan program Python, sementara kompilasi ke bytecode Python VM hanyalah optimasi opsional dan transparan.

Oleh karena itu, baik Java dan Python memiliki mesin virtual adalah penerjemah bytecode biner, yang dapat menyebabkan kebingungan seperti " Mengapa Java Virtual Machine, tetapi interpreter Python?". Poin utama di sini adalah bahwa untuk Python, mesin virtual bukanlah sarana utama atau yang diperlukan untuk eksekusi program; itu hanyalah perpanjangan opsional dari penerjemah teks klasik. Di sisi lain, mesin virtual adalah inti dan tidak dapat dihindari bagian dari ekosistem eksekusi program Java. Pilihan pengetikan statis atau dinamis untuk desain bahasa pemrograman hanya memengaruhi tingkat abstraksi mesin virtual saja, tetapi tidak menentukan apakah mesin virtual diperlukan atau tidak. Bahasa yang menggunakan kedua sistem pengetikan dapat dirancang untuk dikompilasi , ditafsirkan, atau dieksekusi dalam lingkungan mesin virtual, tergantung pada model eksekusi yang diinginkan.

ZarathustrA
sumber
2
Ini harus dipilih sebagai jawaban resmi IMHO.
Ravikanth Andhavarapu
Jawaban resmi harus oleh YA karena "Java dan Python memiliki mesin virtual adalah penerjemah bytecode biner." Titik.
stuartw
10

Tidak ada perbedaan nyata di antara mereka, orang hanya mengikuti konvensi yang telah dipilih pencipta.

Cody Brocious
sumber
3
Saya akan melempar Anda tulang ke sini karena saya pikir ini mungkin jawaban yang sebenarnya dan Anda turun karena kurangnya bit.
vikingben
3

Jangan lupa bahwa Python memiliki kompiler JIT yang tersedia untuk x86, lebih lanjut membingungkan masalah ini. (Lihat psyco).

Penafsiran yang lebih ketat dari 'bahasa yang ditafsirkan' hanya menjadi berguna ketika membahas masalah kinerja VM, misalnya, dibandingkan dengan Python, Ruby dianggap lebih lambat karena merupakan bahasa yang ditafsirkan, tidak seperti Python - di lain kata-kata, konteks adalah segalanya.

Arafangion
sumber
1
Itu salah. Pertama, tidak ada yang namanya "bahasa yang ditafsirkan". Apakah implementasi menggunakan kompiler atau juru bahasa bukan sifat bahasa tetapi implementasi. Kedua, dari 13 atau lebih implementasi Ruby, tepatnya 1 adalah interpreter, yang lainnya memiliki kompiler.
Jörg W Mittag
2
Ketiga, Ruby tidak lambat. Tidak ada bahasa yang lambat, karena kecepatan bukanlah sifat bahasa, tetapi implementasi bahasa. Dari 13 atau lebih implementasi Ruby, ada yang lebih lambat dari 7 implementasi Python, ada yang lebih cepat.
Jörg W Mittag
Saya pikir dia sedang membandingkan implementasi standar di sini Jorg. CPython dan Ruby (saya pikir implementasi resmi bernama Ruby).
James McMahon
Sementara Arafangion mungkin merujuk pada implementasi "standar", ia seharusnya mengatakan demikian. Saya seorang Pythonista tapi saya benci pernyataan apa pun dari bentuk "Bahasa X lambat", karena saya setuju dengan Jorg tentang masalah implementasi.
tzot
1
Inilah tepatnya mengapa saya berkata "was (is?)", Dan khususnya istilah "lebih lambat". Tidak pernah saya katakan bahwa Ruby itu sendiri lambat.
Arafangion
2

Python dapat menginterpretasikan kode tanpa mengkompilasinya ke bytecode. Java tidak bisa .

Python adalah bahasa yang ditafsirkan, sebagai lawan dari bahasa yang dikompilasi, meskipun perbedaannya bisa kabur karena adanya kompiler bytecode. Ini berarti bahwa file sumber dapat dijalankan secara langsung tanpa secara eksplisit membuat executable yang kemudian dijalankan.

(dari dokumentasi).

Dalam java, setiap file harus dikompilasi ke .classfile, yang kemudian berjalan pada JVM. Sebaliknya, python melakukan itu yang diimpor oleh skrip utama Anda, untuk membantu mempercepat penggunaan selanjutnya dari file-file itu.

Namun, dalam kasus tipikal, sebagian besar kode python (setidaknya, CPython) berjalan di mesin stack yang ditiru, yang memiliki instruksi yang hampir sama dengan JVM, jadi tidak ada perbedaan besar.

Namun alasan sebenarnya untuk perbedaan ini adalah karena, sejak awal, java mencap dirinya sebagai "portable, executable bytecode" dan python mencap dirinya sebagai bahasa yang dinamis dan ditafsirkan dengan REPL. Nama menempel!

blue_note
sumber
0

Pertama-tama Anda harus memahami bahwa pemrograman atau ilmu komputer pada umumnya bukan matematika dan kami tidak memiliki definisi yang ketat untuk sebagian besar istilah yang sering kami gunakan.

sekarang untuk pertanyaan Anda:

apa itu Penerjemah (dalam ilmu komputer)

Ini menerjemahkan kode sumber oleh unit terkecil yang dapat dieksekusi dan kemudian mengeksekusi unit itu.

apa itu mesin virtual

dalam kasus JVM mesin virtual adalah perangkat lunak yang berisi juru bahasa, pemuat kelas, pengumpul sampah, penjadwal ulir, kompiler JIT dan banyak hal lainnya.

seperti yang Anda lihat interpreter adalah bagian atau JVM dan seluruh JVM tidak dapat disebut interpreter karena mengandung banyak komponen lain.

mengapa menggunakan kata "Interpreter" ketika berbicara tentang python

dengan java bagian kompilasi eksplisit. python di sisi lain tidak eksplisit sebagai java tentang kompilasi dan proses interpretasinya, dari interpretasi perspektif pengguna akhir adalah satu-satunya mekanisme yang digunakan untuk menjalankan program python

perkasaWOZ
sumber
0

Tidak, keduanya tidak mengartikan kode byte.

Python hanya menginterpretasikan bytecode jika Anda menjalankan dengan pypy. Kalau tidak, itu dikompilasi ke dalam C dan ditafsirkan pada tingkat itu.

Java mengkompilasi ke bytecode.

Michael Tamillow
sumber
Bisakah Anda memberikan sumber daya untuk jawaban Anda?
Isuru Dilshan
dan ini ada di Jawa: en.wikipedia.org/wiki/Java_virtual_machine
Michael Tamillow
Inilah yang salah dengan Stack Overflow. Seseorang memiliki kecocokan kencing karena mereka dipanggil keluar dan mengekspresikannya dengan downvotes.
Michael Tamillow
0

Saya pikir garis-garis di antara keduanya kabur, sebagian besar orang berdebat tentang arti kata "interpreter" dan seberapa dekat bahasa itu berdiri di setiap sisi spektrum "interpreter ... compiler". Namun tidak ada yang menghasilkan 100%. Saya pikir mudah untuk menulis implementasi Java atau Python yang bernilai dari spektrum apa pun.

Saat ini baik Java dan Python memiliki mesin virtual dan bytecode, meskipun satu beroperasi dengan ukuran nilai konkret (seperti integer 32-bit) sementara yang lain harus menentukan ukuran untuk setiap panggilan, yang menurut saya tidak menentukan batas antara persyaratan.

Argumen bahwa Python tidak secara resmi mendefinisikan bytecode dan hanya ada di memori juga tidak meyakinkan saya, hanya karena saya berencana untuk mengembangkan perangkat yang hanya akan mengenali bytecode Python dan bagian kompilasi akan dilakukan di mesin JS browser.

Kinerja hanya tentang implementasi konkret. Kita tidak perlu mengetahui ukuran objek untuk dapat bekerja dengannya, dan akhirnya, dalam banyak kasus, kita bekerja dengan struktur, bukan tipe dasar. Dimungkinkan untuk mengoptimalkan Python VM dengan cara yang akan menghilangkan kebutuhan membuat objek baru setiap kali selama perhitungan ekspresi, dengan menggunakan kembali yang sudah ada. Setelah selesai, tidak ada perbedaan kinerja global antara menghitung jumlah dua bilangan bulat, yang merupakan tempat Java bersinar.

Tidak ada perbedaan yang mematikan antara keduanya, hanya beberapa nuansa implementasi dan kurangnya optimasi yang tidak relevan bagi pengguna akhir, mungkin sampai pada titik di mana ia mulai melihat kelambatan kinerja, tetapi sekali lagi ini adalah implementasi dan bukan masalah arsitektur.

Oleg Gordeev
sumber
0

untuk posting yang menyebutkan bahwa python tidak perlu menghasilkan kode byte, saya tidak yakin itu benar. tampaknya semua callable di Python harus memiliki .__code__.co_codeatribut yang berisi kode byte. Saya tidak melihat alasan yang berarti untuk memanggil python "tidak dikompilasi" hanya karena artefak yang dikompilasi mungkin tidak disimpan; dan sering tidak disimpan oleh desain di Python, misalnya semua kompilasi bytecode baru untuk inputnya, ini adalah alasan variabel lingkup pemahaman tidak konsisten antara compile(mode='exec, ...)dan kompilasi compile(mode='single', ...)seperti antara menjalankan skrip python dan menggunakan pdb

ThorSummoner
sumber