Programiranje

Predmeti in nizi

Dobrodošli v drugi izdaji Pod pokrovom. Ta stolpec se osredotoča na osnovne tehnologije Jave. Njegov namen je razvijalcem omogočiti vpogled v mehanizme, ki omogočajo izvajanje njihovih programov Java. Ta mesec si oglejte bajtke, ki obravnavajo predmete in nize.

Predmetno usmerjen stroj

Navidezni stroj Java (JVM) deluje s podatki v treh oblikah: predmeti, sklici na objekte in primitivni tipi. Predmeti se nahajajo na kupu zbranih smeti. Sklici na objekte in primitivni tipi se nahajajo bodisi v kupu Java kot lokalne spremenljivke, na kupu kot spremenljivke primerka predmetov ali v območju metode kot spremenljivke razreda.

V navideznem računalniku Java je pomnilnik na kopici zbranih odpadkov dodeljen samo kot predmeti. Na kopici ni mogoče dodeliti pomnilnika za primitivni tip, razen kot del predmeta. Če želite uporabiti primitivni tip, kjer je Predmet sklic je potreben, lahko za tip dodelite ovojni predmet iz java.lang paket. Na primer, obstaja Celo število razred, ki zavije int vnesite s predmetom. Samo sklici na objekte in primitivni tipi se lahko nahajajo v skladu Java kot lokalne spremenljivke. Predmeti nikoli ne morejo biti v kupu Java.

Arhitekturno ločevanje predmetov in primitivnih tipov v JVM se odraža v programskem jeziku Java, v katerem objektov ni mogoče prijaviti kot lokalne spremenljivke. Kot take je mogoče razglasiti samo sklice na objekte. Ob izjavi se sklic na objekt ne nanaša na nič. Šele potem, ko je referenca izrecno inicializirana - bodisi s sklicevanjem na obstoječi objekt bodisi s klicem novo - ali se sklic nanaša na dejanski predmet.

V naboru ukazov JVM se vsi predmeti ustvarijo in do njih pride z istim naborom kod, razen z nizi. V Javi so nizi polnopravni predmeti in se, tako kot kateri koli drugi predmet v programu Java, ustvarjajo dinamično. Sklice na matriko je mogoče uporabiti kjer koli sklic na vrsto Predmet in katero koli metodo Predmet lahko prikličete na matriki. Kljub temu pa se v navideznem stroju Java nizi obravnavajo s posebnimi bajtkodami.

Tako kot pri katerem koli drugem objektu tudi matrike ni mogoče deklarirati kot lokalne spremenljivke; lahko samo sklici na matriko. Predmeti matrike vedno vsebujejo bodisi vrsto primitivnih tipov bodisi vrsto referenc na objekt. Če prijavite polje predmetov, dobite polje referenc na objekt. Predmeti sami morajo biti izrecno ustvarjeni z novo in dodeljena elementom polja.

Opcode za predmete

Instantacija novih predmetov se izvede prek

novo

opcode. Dva enobajtna operanda sledita

novo

opcode. Ta dva bajta združita, da tvorita 16-bitni indeks v konstantno področje. Element konstantnega področja v določenem zamiku daje informacije o razredu novega predmeta. JVM ustvari nov primerek predmeta na kopici in potisne sklic na novi predmet v sklad, kot je prikazano spodaj.

Ustvarjanje predmetov
OpcodeOperand (i)Opis
novoindexbyte1, indexbyte2ustvari nov predmet na kupu, potisne sklic

Naslednja tabela prikazuje kode opcij, ki dajo in dobijo polja predmetov. Ti optični kodi, putfield in getfield, delujejo samo na poljih, ki so spremenljivke primerka. Do statičnih spremenljivk dostopata putstatic in getstatic, ki sta opisani kasneje. Navodila putfield in getfield zajemata po dva enobajtna operanda. Operandi se kombinirajo, da tvorijo 16-bitni indeks v konstantno področje. Element konstantnega področja v tem indeksu vsebuje informacije o vrsti, velikosti in odmiku polja. Referenca predmeta je vzeta iz sklada v navodilih za potfield in getfield. Navodilo za potfield vzame vrednost spremenljivke primerka iz sklada, ukaz getfield pa potisne pridobljeno vrednost spremenljivke primerka v sklad.

Dostop do spremenljivk primerka
OpcodeOperand (i)Opis
putfieldindexbyte1, indexbyte2nastavi polje, označeno z indeksom, predmeta vrednosti (oba vzeta iz sklada)
getfieldindexbyte1, indexbyte2potisne polje, označeno z indeksom, predmeta (vzeto iz sklada)

Do spremenljivk razreda dostopate prek getstatične in putstatične opcode, kot je prikazano v spodnji tabeli. Tako getstatic kot tudi putstatic zavzameta dva enobajtna operanda, ki ju JVM kombinira in tvori 16-bitni nepodpisani odmik v konstantno področje. Element konstantnega bazena na tej lokaciji daje informacije o enem statičnem polju razreda. Ker s statičnim poljem ni nobenega predmeta, povezanega z getstatic ali putstatic, ni sklica na objekt. Putstatično navodilo vzame vrednost, ki jo dodeli iz sklada. Navodilo getstatic potisne pridobljeno vrednost na sklad.

Dostop do spremenljivk razreda
OpcodeOperand (i)Opis
putstatičenindexbyte1, indexbyte2nastavi polje, označeno z indeksom, predmeta vrednosti (oba vzeta iz sklada)
getstaticindexbyte1, indexbyte2potisne polje, označeno z indeksom, predmeta (vzeto iz sklada)

Naslednje kode opcij preverijo, ali se sklic na objekt na vrhu sklada nanaša na primerek razreda ali vmesnika, ki ga indeksirajo operandi po optični kodi. Navodilo za preverjanje vrže CheckCastException če objekt ni primerek določenega razreda ali vmesnika. V nasprotnem primeru checkcast ne naredi ničesar. Sklic na objekt ostane v skladišču in izvajanje se nadaljuje pri naslednjem navodilu. To navodilo zagotavlja, da so zasedbe varne med izvajanjem in je del varnostne odeje JVM.

Navodilo instanceof izstreli sklic na objekt z vrha sklada in potisne true ali false. Če je objekt dejansko primerek določenega razreda ali vmesnika, je true v sklad potisnjen, sicer pa v sklad. Navodilo instanceof se uporablja za izvajanje instanceof ključna beseda Java, ki programerjem omogoča, da preizkusijo, ali je objekt primerek določenega razreda ali vmesnika.

Preverjanje tipa
OpcodeOperand (i)Opis
checkcastindexbyte1, indexbyte2Vrže ClassCastException, če objectref na skladu ni mogoče oddati v razred v indeksu
instanceofindexbyte1, indexbyte2Potisne true, če je objectref na skladu primer razreda v indeksu, sicer potisne false

Opcode za polja

Instantiranje novih nizov se izvede s pomočjo optičnih kod newarray, anewarray in multianewarray. Opardska koda newarray se uporablja za ustvarjanje nizov primitivnih tipov, ki niso sklici na objekt. Določen primitivni tip je določen z enim enobajtnim operandom po optični kodi novega niza. Navodilo newarray lahko ustvari polja za byte, short, char, int, long, float, double ali boolean.

Navodilo anewarray ustvari niz referenc na objekt. Dva enobajtna operanda sledita anewarray opcode in se združita, da tvorita 16-bitni indeks v konstantno področje. Opis razreda predmeta, za katerega je treba ustvariti matriko, najdete v konstantnem področju v podanem indeksu. To navodilo dodeli prostor za nabor referenc na objekte in inicializira sklice na nič.

Navodilo multianewarray se uporablja za dodelitev večdimenzionalnih nizov - ki so preprosto nizi nizov - in bi jih bilo mogoče dodeliti z večkratno uporabo navodil anewarray in newarray. Navodilo multianewarray preprosto stisne bytecode, potrebne za ustvarjanje večdimenzionalnih nizov, v eno navodilo. Dva enobajtna operanda sledita multianewarray opcode in se združita, da tvorita 16-bitni indeks v konstantno področje. Opis razreda predmeta, za katerega je treba ustvariti matriko, najdete v področju konstant pri podanem indeksu. Takoj za dvema enobajtnima operandoma, ki tvorita indeks konstantnega področja, je enobajtni operand, ki določa število dimenzij v tej večdimenzionalni matriki. Velikosti za vsako dimenzijo se izpirajo iz sklada. To navodilo dodeljuje prostor za vse nize, ki so potrebni za izvedbo večdimenzionalnih nizov.

Ustvarjanje novih nizov
OpcodeOperand (i)Opis
newarrayatypepops dolžina, dodeli novo polje primitivnih tipov, označenih z atype, potisne objectref novega polja
anewarrayindexbyte1, indexbyte2pops dolžina, dodeli novo polje predmetov razreda, označenih z indexbyte1 in indexbyte2, potisne objectref novega polja
multianewarrayindexbyte1, indexbyte2, dimenzijepops dimenzije število dolžin polja, dodeli novo večdimenzionalno polje razreda, označeno z indexbyte1 in indexbyte2, potisne objectref novega polja

Naslednja tabela prikazuje navodila, ki sklicujejo sklic na matriko z vrha sklada in potisnejo dolžino tega polja.

Pridobivanje dolžine polja
OpcodeOperand (i)Opis
dolžina niza(nič)pops objectref polja, potisne dolžino tega polja

Naslednje opcode pridobijo element iz polja. Indeks matrike in sklic na matriko sta izpisana iz sklada in vrednost na podanem indeksu podane matrike potisnjena nazaj na sklad.

Pridobivanje elementa matrike
OpcodeOperand (i)Opis
baload(nič)pops indeks in arrayref polja bajtov, potisne arrayref [indeks]
caload(nič)pops indeks in arrayref polja chars, potisne arrayref [indeks]
saload(nič)pops indeks in arrayref polja kratkih hlač, potisne arrayref [indeks]
iaload(nič)pops indeks in arrayref polja ints, potisne arrayref [indeks]
laload(nič)pops indeks in arrayref polja dolžin, potisne arrayref [indeks]
nalaganje(nič)pops indeks in arrayref polja floats, potisne arrayref [indeks]
daload(nič)pops indeks in arrayref polja dvojic, potisne arrayref [indeks]
aaload(nič)pops indeks in arrayref polja objectrefs, potisne arrayref [indeks]

Naslednja tabela prikazuje kode opcij, ki shranijo vrednost v element matrike. Sklic na vrednost, indeks in matriko se prikaže na vrhu sklada.

Shranjevanje v element matrike
OpcodeOperand (i)Opis
bastore(nič)pops vrednost, indeks in arrayref polja bajtov, dodeli arrayref [indeks] = vrednost
castore(nič)pops vrednost, indeks in niz matrike znakov, dodeli arrayref [indeks] = vrednost
sestavre(nič)pops vrednost, indeks in arrayref polja kratkih hlač, dodeli arrayref [indeks] = vrednost
iastore(nič)pops vrednost, indeks in arrayref polja ints, dodeli arrayref [indeks] = vrednost
lastore(nič)pops vrednost, indeks in arrayref polja dolžin, dodeli arrayref [indeks] = vrednost
fastore(nič)pops vrednost, indeks in arrayref polja floats, dodeli arrayref [indeks] = vrednost
dastore(nič)pops vrednost, indeks in arrayref polja dvojic, dodeli arrayref [indeks] = vrednost
aastore(nič)pops vrednost, indeks in arrayref niza objectrefs, dodeli arrayref [indeks] = vrednost

Tridimenzionalno polje: simulacija navideznega stroja Java

Spodnji programček prikazuje navidezni stroj Java, ki izvaja zaporedje bajt kod. Zaporedje bajt kod v simulaciji je ustvaril javac za initAnArray () metoda spodaj prikazanega razreda:

class ArrayDemo {static void initAnArray () {int [] [] [] threeD = new int [5] [4] [3]; for (int i = 0; i <5; ++ i) {for (int j = 0; j <4; ++ j) {for (int k = 0; k <3; ++ k) {threeD [ i] [j] [k] = i + j + k; }}}}} 

Bytecode, ki jih generira javac za initAnArray () so prikazani spodaj:

$config[zx-auto] not found$config[zx-overlay] not found