Instruksi mesin virtual Java terdiri dari kode operasi panjang byte (Opcode) yang mewakili arti tertentu, diikuti oleh nol atau lebih operan yang mewakili parameter operasi. Banyak instruksi di mesin virtual tidak mengandung operan, hanya opcode. Jika pengecualian diabaikan, juru bahasa JVM dapat bekerja secara efektif hanya dengan satu kode.
Copy kode kodenya sebagai berikut:
Mengerjakan{
Secara otomatis menghitung register PC dan mengambil opcode dari lokasi register PC
if(operan ada) keluarkan operannya;
Lakukan operasi yang ditentukan oleh opcode;
} while (memproses perulangan berikutnya)
Jumlah dan panjang operan bergantung pada opcode. Jika panjang operan melebihi satu byte, operan akan disimpan dalam urutan Big-Endian (bytecode pertama kelas atas), dan nilainya harus (byte1<<8) | byte2.
Aliran instruksi bytecode disejajarkan dengan byte tunggal, dengan pengecualian instruksi "tableswitch" dan "lookupwitch". Operannya khusus dan dibagi 4 byte.
Membatasi panjang opcode mesin virtual Java menjadi satu byte dan melepaskan penyelarasan panjang parameter dari kode yang dikompilasi adalah untuk mendapatkan kode yang dikompilasi pendek dan ramping, meskipun implementasi JVM mungkin memerlukan biaya kinerja tertentu. Karena opcode hanya dapat memiliki panjang satu byte, ini membatasi jumlah set instruksi, dan tidak mengasumsikan bahwa data telah diselaraskan dengan baik, yang berarti bahwa ketika data melebihi satu byte, struktur data spesifik harus direkonstruksi dari byte. Beberapa kinerja akan hilang.
Tipe Data dan Mesin Virtual Java
Dalam set instruksi di JVM, sebagian besar instruksi berisi informasi tipe data yang sesuai dengan operasinya. Misalnya, instruksi iload memuat data tipe int dari tabel variabel lokal ke dalam tumpukan operan, sementara fload memuat data tipe float.
Untuk sebagian besar instruksi bytecode yang terkait dengan tipe data, mnemonik opcodenya memiliki karakter khusus untuk ditunjukkan: i mewakili tipe int, l mewakili tipe panjang, s mewakili pendek, b mewakili byte, c mewakili char, f singkatan dari float, d singkatan double, dan a singkatan dari referensi. Ada arahan terpisah yang dapat digunakan untuk mengonversi tipe yang tidak didukung ke tipe yang didukung bila diperlukan.
memuat dan menyimpan instruksi
Instruksi memuat dan menyimpan digunakan untuk mentransfer data ke dan dari tabel variabel lokal frame tumpukan dan tumpukan operan.
1) Instruksi untuk memuat variabel lokal ke dalam tumpukan operan meliputi: iload, iload_<n>, lload, lload_<n>, float, fload_<n>, dload, dload_<n>, aload, aload_<n>.
2) Instruksi untuk menyimpan nilai dari tumpukan operan ke variabel lokal: istore,istore_<n>,lstore,lstore_<n>,fstore,fstore_<n>,dstore,dstore_<n>,astore,astore_<n>
3) Instruksi untuk memuat konstanta ke dalam tumpukan operan: bipush, sipush, ldc, ldc_w, ldc2_w, aconst_null, icont_ml, icont_<i>, lconst_<l>, fconst_<f>, dconst_<d>
4) Akses instruksi indeks tabel variabel lokal: lebar
Beberapa instruksi yang diakhiri dengan tanda kurung sudut mewakili sekelompok instruksi, seperti iload_<i>, yang mewakili iload_0, iload_1, dll. Kelompok instruksi ini adalah instruksi umum dengan satu operan.
Instruksi pengoperasian
Instruksi aritmatika digunakan untuk melakukan operasi tertentu pada nilai pada dua tumpukan operan dan menyimpan hasilnya kembali di bagian atas tumpukan operasi.
1) Instruksi tambahan: iadd,ladd,fadd,dadd
2) Instruksi pengurangan: isub, lsub, fsub, dsub
3) Petunjuk perkalian: imul, lmul, fmul, dmul
4) Instruksi pembagian: idiv, ldiv, fdiv, ddiv
5) Petunjuk selebihnya: irem, lrem, frem, drem
6) Instruksi negatif: ineg, length, fneg, dneg
7) Petunjuk perpindahan: ishl,ishr,iushr,lshl,lshr,lusr
8) Instruksi Bitwise ATAU: ior, lor
9) Bitwise DAN instruksi: iand, tanah
10) Instruksi XOR Bitwise: ixor, lxor
11) Instruksi kenaikan variabel lokal: iinc
12) Petunjuk perbandingan: dcmpg, dcmpl, fcmpg, fcmpl, lcmp
Mesin virtual Java tidak secara jelas menetapkan luapan data bilangan bulat, tetapi menetapkan bahwa saat memproses data bilangan bulat, hanya instruksi pembagian dan sisa yang akan menyebabkan mesin virtual mengeluarkan pengecualian ketika pembaginya adalah 0.
memuat dan menyimpan instruksi
Instruksi memuat dan menyimpan digunakan untuk mentransfer data ke dan dari tabel variabel lokal dari frame tumpukan dan tumpukan operan.
1) Instruksi untuk memuat variabel lokal ke dalam tumpukan operan meliputi: iload, iload_<n>, lload, lload_<n>, float, fload_<n>, dload, dload_<n>, aload, aload_<n>.
2) Instruksi untuk menyimpan nilai dari tumpukan operan ke variabel lokal: istore,istore_<n>,lstore,lstore_<n>,fstore,fstore_<n>,dstore,dstore_<n>,astore,astore_<n>
3) Instruksi untuk memuat konstanta ke dalam tumpukan operan: bipush, sipush, ldc, ldc_w, ldc2_w, aconst_null, icont_ml, icont_<i>, lconst_<l>, fconst_<f>, dconst_<d>
4) Akses instruksi indeks tabel variabel lokal: lebar
Beberapa instruksi yang diakhiri dengan tanda kurung sudut mewakili sekelompok instruksi, seperti iload_<i>, yang mewakili iload_0, iload_1, dll. Kelompok instruksi ini adalah instruksi umum dengan satu operan.
Instruksi pengoperasian
Instruksi aritmatika digunakan untuk melakukan operasi tertentu pada nilai pada dua tumpukan operan dan menyimpan hasilnya kembali di bagian atas tumpukan operasi.
1) Instruksi tambahan: iadd,ladd,fadd,dadd
2) Instruksi pengurangan: isub, lsub, fsub, dsub
3) Petunjuk perkalian: imul, lmul, fmul, dmul
4) Instruksi pembagian: idiv, ldiv, fdiv, ddiv
5) Petunjuk selebihnya: irem, lrem, frem, drem
6) Instruksi negatif: ineg, length, fneg, dneg
7) Petunjuk perpindahan: ishl,ishr,iushr,lshl,lshr,lusr
8) Instruksi Bitwise ATAU: ior, lor
9) Bitwise DAN instruksi: iand, tanah
10) Instruksi XOR Bitwise: ixor, lxor
11) Instruksi kenaikan variabel lokal: iinc
12) Petunjuk perbandingan: dcmpg, dcmpl, fcmpg, fcmpl, lcmp
Mesin virtual Java tidak secara jelas menetapkan luapan data bilangan bulat, tetapi menetapkan bahwa saat memproses data bilangan bulat, hanya instruksi pembagian dan sisa yang akan menyebabkan mesin virtual mengeluarkan pengecualian ketika pembaginya adalah 0.
ketik instruksi konversi
Instruksi konversi tipe mengonversi dua tipe numerik mesin virtual Java satu sama lain. Operasi ini umumnya digunakan untuk mengimplementasikan operasi konversi tipe eksplisit dalam kode pengguna.
JVM mendukung konversi tipe yang diperluas (konversi tipe rentang kecil ke konversi tipe rentang besar):
1) Tipe int ke tipe panjang, mengambang, ganda
2) tipe panjang untuk mengapung, tipe ganda
3) mengapung ke tipe ganda
Petunjuk konversi tipe sempit: i2b, i2c, i2s, l2i, f2i, f2l, d2l dan d2f. Konversi tipe sempit dapat menyebabkan hasil konversi menghasilkan tanda dan orde besaran yang berbeda. Proses konversi dapat menyebabkan nilai numerik kehilangan presisi. Misalnya, ketika tipe int atau long diubah menjadi tipe integer T, proses konversi hanya membuang konten yang tidak diharapkan dari N byte terendah (N adalah panjang tipe data tipe T)
Pembuatan dan manipulasi objek
Meskipun instance kelas dan array keduanya merupakan objek, mesin virtual Java menggunakan instruksi bytecode yang berbeda untuk pembuatan dan pengoperasian instance dan array kelas.
1) Instruksi untuk membuat sebuah instance: baru
2) Petunjuk membuat array: newarray, anewarray, multianewarray
3) Akses instruksi lapangan: getfield, putfield, getstatic, putstatic
4) Muat elemen array ke dalam instruksi tumpukan operan: baload, caload, saload, iaload, laload, faload, daload, aaload
5) Simpan nilai tumpukan operan ke dalam elemen array dan jalankan: bastore,castore,castore,sastore,iastore,fastore,dastore,aastore
6) Dapatkan instruksi panjang array: panjang array
7) Periksa instruksi jenis instans: instanceof, checkcast
Instruksi manajemen tumpukan operan
Instruksi yang langsung mengoperasikan tumpukan operan: pop, pop2, dup, dup2, dup_x1, dup2_x1, dup_x2, dup2_x2 dan swap
instruksi transfer kontrol
Memungkinkan JVM melanjutkan eksekusi program secara kondisional atau tanpa syarat dari instruksi yang mengikuti instruksi yang ditentukan, bukan instruksi transfer kontrol. Instruksi transfer kontrol meliputi:
1) Cabang bersyarat: ifeq, iflt, ifle, ifne, ifgt, ifge, ifnull, ifnotnull, if_cmpeq, if_icmpne, if_icmlt, if_icmpgt, dll.
2) Cabang bersyarat gabungan: tablewitch, lookupwitch
3) Cabang tanpa syarat: goto,goto_w,jsr,jsr_w,ret
Ada set instruksi khusus di JVM untuk menangani operasi perbandingan cabang bersyarat dari tipe int dan referensi. Untuk menunjukkan dengan jelas apakah suatu nilai entitas adalah null, ada instruksi khusus untuk mendeteksi nilai null. Operasi perbandingan cabang bersyarat tipe boolean dan tipe byte, tipe char dan tipe pendek semuanya diselesaikan menggunakan instruksi perbandingan tipe int, sedangkan operasi perbandingan cabang bersyarat panjang, float, dan ganda dilakukan dengan instruksi operasi perbandingan dari tipe yang sesuai, dan operasi instruksi akan mengembalikan Nilai integer ditambahkan ke tumpukan operan, dan kemudian operasi perbandingan bersyarat tipe int dilakukan untuk menyelesaikan seluruh lompatan cabang. Semua jenis perbandingan pada akhirnya akan diubah menjadi operasi perbandingan tipe int.
Panggilan metode dan instruksi pengembalian
instruksi invokevirtual: Memanggil metode instance objek dan mengirimkannya sesuai dengan tipe objek sebenarnya (pengiriman mesin virtual).
instruksi invokeinterface: Panggil metode antarmuka, cari objek yang mengimplementasikan metode antarmuka ini saat runtime, dan temukan metode yang sesuai untuk dipanggil.
invokespecial: Memanggil metode instance yang memerlukan pemrosesan khusus, termasuk metode inisialisasi instance, metode privat, dan metode kelas induk
invokestatic: memanggil metode kelas (statis)
Instruksi pengembalian metode dibedakan menurut jenis nilai pengembalian, termasuk ireturn (nilai pengembalian adalah boolean, byte, char, short dan int), lreturn, freturn, drturn dan areturn. Pengembalian lainnya adalah untuk metode void, metode inisialisasi instance , kelas dan Inisialisasi kelas i metode antarmuka digunakan.
sinkronis
JVM mendukung sinkronisasi tingkat metode dan sinkronisasi urutan instruksi dalam suatu metode, keduanya diimplementasikan melalui monitor.
Sinkronisasi tingkat metode bersifat implisit dan tidak perlu dikontrol melalui instruksi bytecode. Sinkronisasi ini diterapkan dalam pemanggilan metode dan operasi pengembalian. Mesin virtual membedakan apakah itu metode sinkron dari tanda ACC_SYNCHRONIZED dalam struktur standar metode di kumpulan konstan metode. Ketika metode dipanggil, instruksi pemanggil akan memeriksa apakah flag telah disetel. Jika sudah disetel, thread eksekusi akan menahan monitor, kemudian mengeksekusi metode tersebut, dan akhirnya melepaskan monitor ketika metode tersebut selesai.
Sinkronkan urutan set instruksi, biasanya ditandai dengan blok tersinkronisasi. Set instruksi JVM memiliki monitorenter dan monitorexit untuk mendukung semantik yang disinkronkan.
Penguncian terstruktur adalah ketika setiap monitor keluar selama pemanggilan metode cocok dengan entri monitor sebelumnya. JVM memastikan bahwa kunci terstruktur dibuat melalui dua aturan berikut (T mewakili thread, M mewakili monitor):
1) Berapa kali T menahan M selama eksekusi metode harus sama dengan berapa kali T melepaskan M ketika metode tersebut selesai.
2) Kapan pun, tidak akan pernah ada situasi di mana T melepaskan M lebih banyak daripada T menahan M.