Objek dan tatasusunan

Selamat datang ke edisi Under The Hood yang lain . Lajur ini memfokuskan pada teknologi asas Java. Ini bertujuan untuk memberi gambaran kepada para pengembang mengenai mekanisme yang menjadikan program Java mereka berjalan. Artikel bulan ini melihat kod byt yang berkaitan dengan objek dan tatasusunan.

Mesin berorientasikan objek

Mesin maya Java (JVM) berfungsi dengan data dalam tiga bentuk: objek, rujukan objek, dan jenis primitif. Objek terletak di timbunan sampah. Rujukan objek dan jenis primitif berada di tumpukan Java sebagai pemboleh ubah tempatan, di timbunan sebagai pemboleh ubah contoh objek, atau di kawasan metode sebagai pemboleh ubah kelas.

Di mesin maya Java, memori dialokasikan di timbunan sampah hanya sebagai objek. Tidak ada cara untuk mengalokasikan memori untuk jenis primitif di timbunan, kecuali sebagai bagian dari objek. Sekiranya anda ingin menggunakan jenis primitif di mana Objectrujukan diperlukan, anda boleh memperuntukkan objek pembungkus untuk jenis dari java.langpaket. Sebagai contoh, ada Integerkelas yang membungkus intjenis dengan objek. Hanya rujukan objek dan jenis primitif yang dapat berada di tumpukan Java sebagai pemboleh ubah tempatan. Objek tidak boleh berada di tumpukan Java.

Pemisahan seni bina objek dan jenis primitif dalam JVM tercermin dalam bahasa pengaturcaraan Java, di mana objek tidak dapat dinyatakan sebagai pemboleh ubah tempatan. Hanya rujukan objek yang dapat dinyatakan seperti itu. Setelah menyatakan, rujukan objek tidak merujuk kepada apa-apa. Hanya setelah rujukan diinisialisasi secara eksplisit - baik dengan rujukan ke objek yang ada atau dengan panggilan ke new- apakah rujukan tersebut merujuk pada objek yang sebenarnya.

Dalam set arahan JVM, semua objek disusun dan diakses dengan set opkod yang sama, kecuali array. Di Java, array adalah objek penuh, dan, seperti objek lain dalam program Java, dibuat secara dinamis. Rujukan array boleh digunakan di mana sahaja rujukan untuk jenis diperlukan Object, dan kaedah apa pun Objectboleh dipanggil pada array. Namun, dalam mesin maya Java, tatasusunan ditangani dengan kod bytek khas.

Seperti objek lain, tatasusunan tidak dapat dinyatakan sebagai pemboleh ubah tempatan; hanya rujukan array yang boleh. Objek array sendiri selalu mengandungi susunan jenis primitif atau susunan rujukan objek. Sekiranya anda menyatakan pelbagai objek, anda akan mendapat pelbagai rujukan objek. Objek-objek itu sendiri mesti dibuat secara eksplisit dengan newdan diberikan kepada unsur-unsur larik.

Opkod untuk objek

Instantiasi objek baru dicapai melalui

new

kod op. Dua operan satu-byte mengikuti

new

kod op. Kedua-dua bait ini digabungkan untuk membentuk indeks 16-bit ke kumpulan tetap. Elemen kumpulan tetap pada ofset yang ditentukan memberikan maklumat mengenai kelas objek baru. JVM membuat contoh baru objek di timbunan dan mendorong rujukan ke objek baru ke tumpukan, seperti yang ditunjukkan di bawah.

Penciptaan objek
Kod Op Operan Penerangan
new indexbyte1, indexbyte2 membuat objek baru di timbunan, menolak rujukan

Jadual seterusnya menunjukkan opcode yang meletakkan dan mendapatkan medan objek. Opkod ini, putfield dan getfield, hanya beroperasi pada bidang yang merupakan pemboleh ubah contoh. Pemboleh ubah statik diakses oleh putstatic dan getstatic, yang dijelaskan kemudian. Arahan putfield dan getfield masing-masing mengambil dua operan satu-byte. Operan digabungkan untuk membentuk indeks 16-bit ke dalam kumpulan tetap. Item kumpulan tetap pada indeks itu mengandungi maklumat mengenai jenis, ukuran, dan ofset medan. Rujukan objek diambil dari timbunan di kedua-dua arahan putfield dan getfield. Arahan putfield mengambil nilai pemboleh ubah contoh dari timbunan, dan arahan getfield mendorong nilai pemboleh ubah contoh yang diambil ke tumpukan.

Mengakses pemboleh ubah contoh
Kod Op Operan Penerangan
putfield indexbyte1, indexbyte2 set field, ditunjukkan oleh indeks, objek ke nilai (keduanya diambil dari tumpukan)
getfield indexbyte1, indexbyte2 tolak medan, ditunjukkan oleh indeks, objek (diambil dari tumpukan)

Pemboleh ubah kelas diakses melalui opstode getstatic dan putstatic, seperti yang ditunjukkan dalam jadual di bawah. Kedua-dua getstatic dan putstatic mengambil dua operan satu-byte, yang digabungkan oleh JVM untuk membentuk offset tanpa tanda 16-bit ke kumpulan tetap. Item kumpulan tetap di lokasi tersebut memberikan maklumat mengenai satu medan statik kelas. Oleh kerana tidak ada objek tertentu yang terkait dengan medan statis, tidak ada rujukan objek yang digunakan oleh getstatic atau putstatic. Arahan putstatik mengambil nilai untuk diberikan dari timbunan. Arahan getstatik mendorong nilai yang diambil ke timbunan.

Mengakses pemboleh ubah kelas
Kod Op Operan Penerangan
putstatic indexbyte1, indexbyte2 set field, ditunjukkan oleh indeks, objek ke nilai (keduanya diambil dari tumpukan)
getstatic indexbyte1, indexbyte2 tolak medan, ditunjukkan oleh indeks, objek (diambil dari tumpukan)

Opkod berikut memeriksa untuk melihat sama ada rujukan objek di bahagian atas timbunan merujuk kepada contoh kelas atau antara muka yang diindeks oleh operan yang mengikuti opcode. Arahan checkcast melemparkan CheckCastExceptionjika objek itu bukan contoh kelas atau antara muka yang ditentukan. Jika tidak, checkcast tidak melakukan apa-apa. Rujukan objek tetap ada di tumpukan dan pelaksanaan dilanjutkan pada arahan berikutnya. Arahan ini memastikan bahawa pelakon selamat pada waktu berjalan dan menjadi sebahagian daripada selimut keselamatan JVM.

Arahan instanceof memunculkan rujukan objek dari bahagian atas timbunan dan menolak betul atau salah. Sekiranya objek itu adalah contoh dari kelas atau antara muka yang ditentukan, maka true didorong ke tumpukan, jika tidak, false didorong ke tumpukan. Instruksi instanceof digunakan untuk menerapkan instanceofkata kunci Java, yang memungkinkan pengaturcara untuk menguji apakah objek adalah contoh kelas atau antarmuka tertentu.

Pemeriksaan jenis
Kod Op Operan Penerangan
checkcast indexbyte1, indexbyte2 Lemparkan ClassCastException jika objekref pada timbunan tidak dapat dilemparkan ke kelas pada indeks
instanceof indexbyte1, indexbyte2 Tolak benar jika objekref pada timbunan adalah contoh kelas pada indeks, sebaliknya menolak palsu

Opkod untuk tatasusunan

Instantiasi tatasusunan baru dapat dicapai melalui opcode newarray, anewarray, dan multianewarray. Opcode newarray digunakan untuk membuat susunan jenis primitif selain rujukan objek. Jenis primitif tertentu ditentukan oleh satu operasi byte tunggal mengikuti kod opsyen baru. Arahan newarray boleh membuat tatasusunan untuk byte, pendek, char, int, long, float, double, atau boolean.

Arahan anewarray membuat pelbagai rujukan objek. Dua operan satu-byte mengikuti opcode anewarray dan digabungkan untuk membentuk indeks 16-bit ke kumpulan tetap. Keterangan mengenai kelas objek yang hendak dibuat array dijumpai di kumpulan tetap pada indeks yang ditentukan. Arahan ini memperuntukkan ruang untuk susunan rujukan objek dan menginisialisasi rujukan ke nol.

The multianewarray instruction is used to allocate multidimensional arrays -- which are simply arrays of arrays -- and could be allocated with repeated use of the anewarray and newarray instructions. The multianewarray instruction simply compresses the bytecodes needed to create multidimensional arrays into one instruction. Two one-byte operands follow the multianewarray opcode and are combined to form a 16-bit index into the constant pool. A description of the class of object for which the array is to be created is found in the constant pool at the specified index. Immediately following the two one-byte operands that form the constant pool index is a one-byte operand that specifies the number of dimensions in this multidimensional array. The sizes for each dimension are popped off the stack. This instruction allocates space for all arrays that are needed to implement the multidimensional arrays.

Creating new arrays
Opcode Operand(s) Description
newarray atype pops length, allocates new array of primitive types of type indicated by atype, pushes objectref of new array
anewarray indexbyte1, indexbyte2 pops length, allocates a new array of objects of class indicated by indexbyte1 and indexbyte2, pushes objectref of new array
multianewarray indexbyte1, indexbyte2, dimensions pops dimensions number of array lengths, allocates a new multidimensional array of class indicated by indexbyte1 and indexbyte2, pushes objectref of new array

The next table shows the instruction that pops an array reference off the top of the stack and pushes the length of that array.

Getting the array length
Opcode Operand(s) Description
arraylength (none) pops objectref of an array, pushes length of that array

The following opcodes retrieve an element from an array. The array index and array reference are popped from the stack, and the value at the specified index of the specified array is pushed back onto the stack.

Retrieving an array element
Opcode Operand(s) Description
baload (none) pops index and arrayref of an array of bytes, pushes arrayref[index]
caload (none) pops index and arrayref of an array of chars, pushes arrayref[index]
saload (none) pops index and arrayref of an array of shorts, pushes arrayref[index]
iaload (none) pops index and arrayref of an array of ints, pushes arrayref[index]
laload (none) pops index and arrayref of an array of longs, pushes arrayref[index]
faload (none) pops index and arrayref of an array of floats, pushes arrayref[index]
daload (none) pops index and arrayref of an array of doubles, pushes arrayref[index]
aaload (none) pops index and arrayref of an array of objectrefs, pushes arrayref[index]

The next table shows the opcodes that store a value into an array element. The value, index, and array reference are popped from the top of the stack.

Storing to an array element
Opcode Operand(s) Description
bastore (none) pops value, index, and arrayref of an array of bytes, assigns arrayref[index] = value
castore (none) pops value, index, and arrayref of an array of chars, assigns arrayref[index] = value
sastore (none) pops value, index, and arrayref of an array of shorts, assigns arrayref[index] = value
iastore (none) pops value, index, and arrayref of an array of ints, assigns arrayref[index] = value
lastore (none) pops value, index, and arrayref of an array of longs, assigns arrayref[index] = value
fastore (none) pops value, index, and arrayref of an array of floats, assigns arrayref[index] = value
dastore (none) pops value, index, and arrayref of an array of doubles, assigns arrayref[index] = value
aastore (none) muncul nilai, indeks, dan arrayref dari array objekrefs, menetapkan arrayref [index] = nilai

Susunan tiga dimensi: simulasi mesin maya Java

Applet di bawah menunjukkan mesin maya Java yang menjalankan urutan kod bytek. Urutan bytecode dalam penyelakuan telah dijanakan oleh javacuntuk initAnArray()kaedah kelas yang ditunjukkan di bawah:

kelas ArrayDemo {static void initAnArray () {int [] [] [] threeD = int baru [5] [4] [3]; untuk (int i = 0; i <5; ++ i) {untuk (int j = 0; j <4; ++ j) {untuk (int k = 0; k <3; ++ k) {threeD [ i] [j] [k] = i + j + k; }}}}}

Kod byt yang dihasilkan oleh javacuntuk initAnArray()ditunjukkan di bawah: