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.
„Opcode“ | Operandas (-ai) | apibūdinimas |
---|
naujas | indexbyte1, indexbyte2 | ant 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 |
---|
putfieldas | indexbyte1, indexbyte2 | nustatyti lauką, nurodytą indeksu, objekto vertę (abu paimti iš kamino) |
getfield | indexbyte1, indexbyte2 | stumia 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škas | indexbyte1, indexbyte2 | nustatyti lauką, nurodytą indeksu, objekto vertę (abu paimti iš kamino) |
getstatic | indexbyte1, indexbyte2 | stumia 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.
„Opcode“ | Operandas (-ai) | apibūdinimas |
---|
čekis | indexbyte1, indexbyte2 | Išmeta „ClassCastException“, jei „stackre“ esančio objekto nuorodos negalima perduoti į klasę rodyklėje |
egzempliorius | indexbyte1, indexbyte2 | Stumia 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.
„Opcode“ | Operandas (-ai) | apibūdinimas |
---|
newarray | atipas | pasirodo ilgis, priskiria naują tipų masyvą primityvių tipų, nurodytų atype, stumia naujojo masyvo objectref |
iš naujo | indexbyte1, indexbyte2 | pasirodo ilgis, priskiria naują klasės objektų masyvą, nurodytą indexbyte1 ir indexbyte2, stumia new masyvo objectref |
daugiapakopis | indexbyte1, indexbyte2, matmenys | pasirodo 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į.
„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ė javac
už initAnArray ()
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: