Programavimas

Objektai ir masyvai

Sveiki atvykę į kitą Po gaubtu. Šiame stulpelyje daugiausia dėmesio skiriama pagrindinėms „Java“ technologijoms. Jo tikslas - suteikti kūrėjams galimybę pažvelgti į mechanizmus, kurie leidžia vykdyti jų „Java“ programas. Šio mėnesio straipsnyje apžvelgiami bytecodes, kuriuose nagrinėjami objektai ir masyvai.

Į objektą orientuota mašina

„Java“ virtuali mašina (JVM) dirba su trimis formomis: objektais, objektų nuorodomis ir primityviais tipais. Objektai gyvena ant šiukšlių surinkto krūvos. Objektų nuorodos ir primityvūs tipai yra „Java“ šūsnyje kaip vietiniai kintamieji, kaupe kaip objektų kintamieji arba metodo srityje kaip klasės kintamieji.

„Java“ virtualioje mašinoje šiukšlių surinktam kaupui atmintis skiriama tik kaip objektai. Negalima skirti atminties primityviam tipui ant krūvos, išskyrus objekto dalį. Jei norite naudoti primityvų tipą, kur Objektas reikalinga nuoroda, tipui galite skirti pakavimo objektą iš java.lang pakuotė. Pavyzdžiui, yra Sveikasis skaičius klasė, kuri suvynioja an tarpt įveskite su objektu. „Java“ šūsnyje kaip vietiniai kintamieji gali būti tik objektų nuorodos ir primityvūs tipai. Objektai niekada negali būti „Java“ šūsnyje.

JVM objektų ir primityvių tipų architektūrinis atskyrimas atsispindi Java programavimo kalboje, kurioje objektų negalima deklaruoti kaip vietinių kintamųjų. Tik objekto nuorodos gali būti deklaruojamos kaip tokios. Deklaruojant objekto nuoroda nieko nereiškia. Tik po to, kai nuoroda yra aiškiai inicializuota - arba nuoroda į esamą objektą, arba skambinant naujas - ar nuoroda nurodo faktinį objektą.

JVM komandų rinkinyje visi objektai yra eksponuojami ir pasiekiami naudojant tą patį opcodų rinkinį, išskyrus masyvus. „Java“ masyvai yra pilnaverčiai objektai ir, kaip ir bet kuris kitas „Java“ programos objektas, yra kuriami dinamiškai. Masyvo nuorodos gali būti naudojamos visur, kur yra nuoroda į tipą Objektas reikalingas ir bet koks metodas Objektas galima iškviesti masyve. Vis dėlto „Java“ virtualioje mašinoje masyvai tvarkomi naudojant specialius baitų kodus.

Kaip ir bet kurio kito objekto atveju, masyvų negalima deklaruoti kaip vietinių kintamųjų; gali tik masyvo nuorodos. Pačiuose masyvo objektuose visada yra arba primityvių tipų masyvas, arba objektų nuorodų masyvas. Jei deklaruojate objektų masyvą, gausite objektų nuorodų masyvą. Patys objektai turi būti aiškiai sukurti naujas ir priskirti masyvo elementams.

Objektų opkodai

Naujų objektų greitinimas atliekamas per

naujas

opcode. Du vieno baito operandai seka

naujas

opcode. Šie du baitai yra sujungti, sudarant 16 bitų indeksą pastoviame telkinyje. Pastovus baseino elementas nurodytame poslinkyje suteikia informacijos apie naujo objekto klasę. JVM sukuria naują objekto egzempliorių ant krūvos ir pastumia nuorodą į naują objektą ant rietuvės, kaip parodyta žemiau.

Objektų kūrimas
„Opcode“Operandas (-ai)apibūdinimas
naujasindexbyte1, indexbyte2ant krūvos sukuria naują objektą, stumia nuorodą

Kitoje lentelėje pateikiami opkodai, kurie įdeda ir gauna objektų laukus. Šie opcodai, putfield ir getfield, veikia tik laukuose, kurie yra egzempliorių kintamieji. Prie statinių kintamųjų pasiekiama putstatic ir getstatic, kurie aprašomi vėliau. „Putfield“ ir „getfield“ instrukcijose yra du vieno baito operandai. Operandai sujungiami, sudarant 16 bitų indeksą pastoviame telkinyje. Tame indekse esančiame pastoviame baseino elemente yra informacijos apie lauko tipą, dydį ir poslinkį. Objekto nuoroda yra paimama iš šūsnio tiek putfield, tiek getfield instrukcijose. Putfieldo instrukcija paima egzemplioriaus kintamojo vertę iš kamino, o getfield instrukcija nustumia gautą egzemplioriaus kintamojo vertę į kaminą.

Prieiga prie egzempliorių kintamųjų
„Opcode“Operandas (-ai)apibūdinimas
putfieldasindexbyte1, indexbyte2nustatyti lauką, nurodytą indeksu, objekto vertę (abu paimti iš kamino)
getfieldindexbyte1, indexbyte2stumia objekto (paimto iš kamino) lauką, nurodytą indeksu

Klasių kintamuosius galima pasiekti per getstatic ir putstatic opcodes, kaip parodyta toliau pateiktoje lentelėje. Tiek „getstatic“, tiek „putstatic“ atveju reikia dviejų vieno baito operandų, kuriuos JVM sujungia ir sudaro 16 bitų nepasirašytą poslinkį į pastovų telkinį. Nuolatinis baseino elementas toje vietoje pateikia informaciją apie vieną statinį klasės lauką. Kadangi nėra jokio konkretaus objekto, susieto su statiniu lauku, nėra objekto nuorodos, naudojamos nei getstatic, nei putstatic. Putstatinė instrukcija paima vertę, kurią reikia priskirti iš kamino. „Getstatic“ instrukcija išstumia gautą vertę į rietuvę.

Prieiga prie klasės kintamųjų
„Opcode“Operandas (-ai)apibūdinimas
putstatiškasindexbyte1, indexbyte2nustatyti lauką, nurodytą indeksu, objekto vertę (abu paimti iš kamino)
getstaticindexbyte1, indexbyte2stumia objekto (paimto iš kamino) lauką, nurodytą indeksu

Šie opcodes patikrina, ar kamino viršuje esanti objekto nuoroda nurodo klasės ar sąsajos egzempliorių, indeksuojamą operandų, sekančių po opcode. Checkcast instrukcija meta „CheckCastException“ jei objektas nėra nurodytos klasės ar sąsajos egzempliorius. Priešingu atveju „checkcast“ nieko nedaro. Objekto nuoroda lieka rietuvėje ir vykdymas tęsiamas kitoje instrukcijoje. Ši instrukcija užtikrina, kad stumdymai yra saugūs vykdymo metu ir yra JVM apsaugos antklodės dalis.

Instrukcijos egzempliorius iškelia objekto nuorodą iš rietuvės viršaus ir išstumia teisingą arba klaidingą. Jei objektas iš tikrųjų yra nurodytos klasės ar sąsajos egzempliorius, „true“ stumiama ant kamino, priešingu atveju „false“ - ant kamino. Instrukcija „instanceof“ naudojama diegti egzempliorius „Java“ raktinis žodis, leidžiantis programuotojams patikrinti, ar objektas yra tam tikros klasės ar sąsajos egzempliorius.

Tipo tikrinimas
„Opcode“Operandas (-ai)apibūdinimas
čekisindexbyte1, indexbyte2Išmeta „ClassCastException“, jei „stackre“ esančio objekto nuorodos negalima perduoti į klasę rodyklėje
egzemplioriusindexbyte1, indexbyte2Stumia tiesą, jei „stackre“ esantis objekto nuoroda yra indekso klasės egzempliorius, dar kitaip - klaidingas

Masyvų opkodai

Naujų masyvų kūrimas atliekamas naudojant naujus, ankstesnius ir daugiasluoksnius opkodus. Newarray opcode naudojamas kuriant primityvių tipų masyvus, išskyrus objektų nuorodas. Konkretų primityvų tipą nurodo vienas vieno baito operandas po newarray opcode. „Newarray“ instrukcija gali sukurti baitų, trumpųjų, char, int, long, float, double arba boolean masyvus.

Anewarray instrukcija sukuria masyvą objektų nuorodų. Du vieno baito operandai vadovaujasi išankstinio veiksmo kodu ir sujungiami taip, kad sudarytų 16 bitų indeksą į pastovų telkinį. Objekto, kuriam turi būti sukurtas masyvas, aprašymas yra nurodyto indekso pastoviame telkinyje. Ši instrukcija paskirsto vietą objektų nuorodų masyvui ir inicijuoja nuorodas į nulį.

Daugiapakartė instrukcija naudojama paskirstyti daugiamačius masyvus - kurie yra paprasčiausiai masyvų masyvai - ir gali būti paskirstyti pakartotinai naudojant išankstinio ir naujojo išdėstymo instrukcijas. Daugialypė instrukcija paprasčiausiai suglaudina baitekodus, reikalingus daugiamatėms masyvams sukurti, į vieną komandą. Du vieno baito operandai vadovaujasi daugiakrypčiu opkodu ir sujungiami taip, kad sudarytų 16 bitų indeksą į pastovų telkinį. Objekto klasės, kuriai reikia sukurti masyvą, aprašymas yra nurodyto indekso pastoviame telkinyje. Iškart po dviejų vieno baito operandų, sudarančių pastovų baseino indeksą, yra vieno baito operandas, nurodantis matmenų skaičių šioje daugiamatėje masyve. Kiekvieno aspekto dydžiai atsispindi nuo rietuvės. Ši instrukcija paskirsto vietą visiems masyvams, reikalingiems daugiamatėms masyvams įgyvendinti.

Naujų masyvų kūrimas
„Opcode“Operandas (-ai)apibūdinimas
newarrayatipaspasirodo ilgis, priskiria naują tipų masyvą primityvių tipų, nurodytų atype, stumia naujojo masyvo objectref
iš naujoindexbyte1, indexbyte2pasirodo ilgis, priskiria naują klasės objektų masyvą, nurodytą indexbyte1 ir indexbyte2, stumia new masyvo objectref
daugiapakopisindexbyte1, indexbyte2, matmenyspasirodo matmenų masyvo ilgių skaičius, priskiria naują daugiamatį klasės masyvą, nurodytą indexbyte1 ir indexbyte2, stumia new masyvo objectref

Kitoje lentelėje pateikiama instrukcija, kuri iššaukia masyvo nuorodą nuo kamino viršaus ir išstumia tos masyvo ilgį.

Masyvo ilgio gavimas
„Opcode“Operandas (-ai)apibūdinimas
masyvo ilgis(nė vienas)pasirodo masyvo objectref, pastumia to masyvo ilgį

Šie opcodes gauna elementą iš masyvo. Masyvo rodyklė ir masyvo nuoroda iššokama iš kamino, o reikšmė nurodytame masyvo nurodytame rodyklėje nustumiama atgal į rietuvę.

Gaunamas masyvo elementas
„Opcode“Operandas (-ai)apibūdinimas
baload(nė vienas)iššaukia baitų masyvo indeksą ir masyvą, pastumia masyvą [rodyklė]
caload(nė vienas)pasirodo simbolių masyvo rodyklė ir masyvas, stumia arrayref [rodyklė]
saload(nė vienas)iššaukia trumpikių masyvo rodyklę ir masyvą, pastumia „arrayref“ [rodyklė]
iaload(nė vienas)pasirodo intų masyvo indeksas ir masyvas, pastumia masyvą [rodyklė]
laload(nė vienas)pasirodo ilgių masyvo rodyklę ir masyvą, pastumia masyvą [rodyklė]
faload(nė vienas)pasirodo plūdurių masyvo indeksą ir masyvą, pastumia masyvą [rodyklė]
daload(nė vienas)pasirodo indeksas ir masyvo dvikovų masyvas, stumia arrayref [rodyklė]
aaload(nė vienas)iššaukia „objectrefs“ masyvo indeksą ir masyvą, stumia „arrayref“ [rodyklė]

Kitoje lentelėje pateikiami opkodai, kurie saugo vertę masyvo elemente. Vertė, indeksas ir masyvo nuoroda iššokama iš rietuvės viršaus.

Saugojimas prie masyvo elemento
„Opcode“Operandas (-ai)apibūdinimas
bastore(nė vienas)iššaukia baitų masyvo vertę, indeksą ir masyvą, priskiria arrayref [rodyklė] = reikšmė
kastoras(nė vienas)iššaukia simbolių masyvo vertę, indeksą ir masyvą, priskiria arrayref [rodyklė] = reikšmė
šastore(nė vienas)iššaukia šortų masyvo vertę, indeksą ir masyvą, priskiria arrayref [rodyklė] = reikšmė
iastore(nė vienas)pasirodo intų masyvo reikšmę, indeksą ir masyvą, priskiria masyvą ref [rodyklė] = reikšmė
lastore(nė vienas)pasirodo ilgių masyvo reikšmę, indeksą ir masyvo atsakymą, priskiria masyvą ref [rodyklė] = reikšmė
fastore(nė vienas)pasirodo plūdurių masyvo vertę, indeksą ir masyvą, priskiria masyvą ref [rodyklė] = reikšmė
dastore(nė vienas)pasirodo dvigubų masyvo vertė, rodyklė ir masyvas, priskiria masyvą ref [rodyklė] = reikšmė
aastore(nė vienas)iššaukia objectrefs masyvo vertę, indeksą ir masyvą, priskiria arrayref [index] = reikšmė

Trimatis masyvas: „Java“ virtualiosios mašinos modeliavimas

Žemiau esanti programėlė demonstruoja „Java“ virtualią mašiną, vykdančią baitų kodų seką. Modeliavimo baitų kodų seką sukūrė javacinitAnArray () toliau nurodytos klasės metodas:

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

Sukurtus baitų kodus javac dėl initAnArray () rodomi žemiau: