Programovanie

Predmety a polia

Vitajte v ďalšom vydaní Pod kapotou. Tento stĺpec sa zameriava na základné technológie Java. Jeho cieľom je poskytnúť vývojárom pohľad na mechanizmy, ktoré zabezpečujú fungovanie ich programov Java. Článok tento mesiac pojednáva o bytových kódoch, ktoré sa zaoberajú objektmi a poľami.

Objektovo orientovaný stroj

Virtuálny stroj Java (JVM) pracuje s údajmi v troch formách: objekty, odkazy na objekty a primitívne typy. Objekty sa nachádzajú na hromade odpadu. Odkazy na objekty a primitívne typy sa nachádzajú buď v zásobníku Java ako lokálne premenné, na halde ako premenné inštancie objektov, alebo v oblasti metódy ako premenné triedy.

Vo virtuálnom stroji Java je pamäť vyhradená na halde zhromaždenej odpadkami iba ako objekty. Neexistuje spôsob, ako na halde prideliť pamäť primitívnemu typu, s výnimkou časti objektu. Ak chcete použiť primitívny typ, kde Objekt je potrebný odkaz, môžete prideliť obalový objekt pre typ z java.lang balíček. Napríklad existuje Celé číslo trieda, ktorá zalamuje int typ s predmetom. Ako lokálne premenné sa v zásobníku Java môžu nachádzať iba odkazy na objekty a primitívne typy. Objekty nikdy nemôžu byť umiestnené v zásobníku Java.

Architektonické oddelenie objektov a primitívnych typov v JVM sa odráža v programovacom jazyku Java, v ktorom objekty nemožno deklarovať ako lokálne premenné. Za také možno deklarovať iba referencie na objekty. Po vyhlásení odkaz na objekt nič nehovorí. Až po výslovnej inicializácii referencie - buď s odkazom na existujúci objekt, alebo s volaním na Nový - odkazuje sa odkaz na skutočný objekt.

V sade inštrukcií JVM sú všetky objekty inštancované a pristupuje sa k nim rovnaká sada operačných kódov, s výnimkou polí. V prostredí Java sú polia plnohodnotnými objektmi a ako každý iný objekt v programe Java sa vytvárajú dynamicky. Odkazy na pole možno použiť kdekoľvek ako odkaz na typ Objekt je požadovaná a akákoľvek metóda Objekt je možné vyvolať na poli. Vo virtuálnom stroji Java sú však polia spracovávané so špeciálnymi bajtkódmi.

Rovnako ako v prípade iných objektov, ani v tomto prípade nemožno pole deklarovať ako lokálne premenné; môžu iba odkazy na pole. Samotné objekty poľa vždy obsahujú buď pole primitívnych typov, alebo pole odkazov na objekty. Ak deklarujete pole objektov, získate pole odkazov na objekty. Samotné objekty musia byť explicitne vytvorené pomocou Nový a priradené k prvkom poľa.

Protokoly pre objekty

Vytvorenie nového objektu sa uskutoční prostredníctvom servera

Nový

operačný kód. Nasledujú dva jednobajtové operandy

Nový

operačný kód. Tieto dva bajty sa skombinujú do 16-bitového indexu do konštantnej oblasti. Element konštantnej skupiny v zadanom posunutí poskytuje informácie o triede nového objektu. Spoločný podnik JVM vytvorí na halde novú inštanciu objektu a presunie odkaz na nový objekt do zásobníka, ako je uvedené nižšie.

Tvorba objektov
Operačný kódOperand (y)Popis
Novýindexbyte1, indexbyte2vytvorí na halde nový objekt, posunie referenciu

Nasledujúca tabuľka zobrazuje operačné kódy, ktoré umiestňujú a získavajú polia objektov. Tieto operačné kódy, putfield a getfield, fungujú iba na poliach, ktoré sú inštančnými premennými. K statickým premenným sa dostane pomocou putstatických a getstatických, ktoré sú opísané neskôr. Každá z inštrukcií putfield a getfield trvá dva jednobajtové operandy. Operandy sú skombinované tak, aby vytvorili 16-bitový index do konštantnej oblasti. Položka konštantnej skupiny v tomto indexe obsahuje informácie o type, veľkosti a posunutí poľa. Odkaz na objekt je prevzatý zo zásobníka v pokynoch putfield aj getfield. Inštrukcia putfield vezme hodnotu premennej inštancie zo zásobníka a inštrukcia getfield natlačí načítanú hodnotu premennej inštancie do zásobníka.

Prístup k premenným inštancie
Operačný kódOperand (y)Popis
Putfieldindexbyte1, indexbyte2nastavenie poľa označeného indexom hodnoty objektu (obe prevzaté zo zásobníka)
getfieldindexbyte1, indexbyte2tlačí pole (označené indexom) objektu (prevzaté zo zásobníka)

K premenným triedy sa pristupuje prostredníctvom getstatických a putstatických kódov, ako je uvedené v nasledujúcej tabuľke. Getstatic aj putstatic majú dva jednobajtové operandy, ktoré JVM skombinuje a vytvorí 16-bitový nepodpísaný offset do konštantnej oblasti. Položka konštantnej skupiny na danom mieste poskytuje informácie o jednom statickom poli triedy. Pretože so statickým poľom nie je spojený žiadny konkrétny objekt, neexistuje žiadny odkaz na objekt, ktorý používa getstatic alebo putstatic. Putstatická inštrukcia nadobúda hodnotu, ktorá sa má priradiť zo zásobníka. Getstatická inštrukcia posúva načítanú hodnotu do zásobníka.

Prístup k premenným triedy
Operačný kódOperand (y)Popis
putstatickýindexbyte1, indexbyte2nastavenie poľa označeného indexom hodnoty objektu (obe prevzaté zo zásobníka)
getstatickýindexbyte1, indexbyte2tlačí pole (označené indexom) objektu (prevzaté zo zásobníka)

Nasledujúce operačné kódy kontrolujú, či odkaz na objekt v hornej časti zásobníka odkazuje na inštanciu triedy alebo rozhrania indexovaného operandmi nasledujúcimi po operačnom kóde. Inštrukcia checkcast hodí CheckCastException ak objekt nie je inštanciou zadanej triedy alebo rozhrania. Inak checkcast nerobí nič. Odkaz na objekt zostáva v zásobníku a vykonávanie pokračuje v ďalšej inštrukcii. Táto inštrukcia zaisťuje, že vrhače sú bezpečné za behu a tvoria súčasť bezpečnostnej prikrývky JVM.

Inštrukcia instanceof vysunie odkaz na objekt z hornej časti zásobníka a stlačí true alebo false. Ak je objekt skutočne inštanciou zadanej triedy alebo rozhrania, potom sa do zásobníka vloží hodnota true, inak sa do zásobníka vloží hodnota false. Inštrukcia instanceof sa používa na implementáciu inštancia kľúčové slovo Java, ktoré umožňuje programátorom testovať, či je objekt inštanciou konkrétnej triedy alebo rozhrania.

Kontrola typu
Operačný kódOperand (y)Popis
checkcastindexbyte1, indexbyte2Vyvolá ClassCastException, ak objectref na zásobníku nemožno vrhnúť do triedy na indexe
inštanciaindexbyte1, indexbyte2Stlačí true, ak je objectref na zásobníku instanceof triedy v indexe, inak tlačí false

Protokoly pre polia

Vytvorenie inštancie nových polí sa dosahuje pomocou oparodov newarray, anewarray a multianewarray. Operačný kód newarray sa používa na vytváranie polí primitívnych typov iných ako odkazy na objekty. Konkrétny primitívny typ je určený jedným jednobajtovým operandom nasledujúcim za operačným kódom newarray. Inštrukcia newarray môže vytvárať polia pre byte, short, char, int, long, float, double alebo boolean.

Inštrukcia anewarray vytvára pole odkazov na objekty. Dva jednobajtové operandy sledujú operačný kód anewarray a sú skombinované tak, aby vytvorili 16-bitový index do konštantnej oblasti. Popis triedy objektu, pre ktorý sa má pole vytvoriť, sa nachádza v oblasti konštánt pri uvedenom indexe. Táto inštrukcia vyhradzuje priestor pre pole odkazov na objekty a inicializuje odkazy na hodnotu null.

Inštrukcia viacnásobné pole sa používa na pridelenie viacrozmerných polí - čo sú jednoducho polia polí - a je možné ich prideliť pri opakovanom použití pokynov anewarray a newarray. Multianewarray inštrukcia jednoducho komprimuje bajtkódy potrebné na vytvorenie multidimenzionálnych polí do jednej inštrukcie. Dva jednobajtové operandy sledujú operačný kód multianewarray a sú skombinované tak, aby vytvorili 16-bitový index do konštantnej oblasti. Popis triedy objektu, pre ktorý sa má pole vytvoriť, sa nachádza v oblasti konštánt pri uvedenom indexe. Okamžite po dvoch jednobajtových operandoch, ktoré tvoria index konštantnej oblasti, je jednobajtový operand, ktorý určuje počet dimenzií v tomto multidimenzionálnom poli. Veľkosti pre každú dimenziu sa vysunú zo zásobníka. Táto inštrukcia vyhradzuje priestor pre všetky polia, ktoré sú potrebné na implementáciu viacrozmerných polí.

Vytvára sa nové pole
Operačný kódOperand (y)Popis
newarraytypobjaví dĺžku, pridelí nové pole primitívnych typov typu označeného atype, zatlačí objectref nového poľa
anewarrayindexbyte1, indexbyte2objaví dĺžku, pridelí nové pole objektov triedy označenej indexbyte1 a indexbyte2, zatlačí objectref nového poľa
multianewarrayindexbyte1, indexbyte2, rozmeryobjaví rozmery počet dĺžok poľa, pridelí nové viacrozmerné pole triedy označené indexbyte1 a indexbyte2, zatlačí objectref nového poľa

Nasledujúca tabuľka zobrazuje inštrukciu, ktorá zobrazí odkaz na pole z hornej časti zásobníka a posúva dĺžku tohto poľa.

Získava sa dĺžka poľa
Operačný kódOperand (y)Popis
dĺžka poľa(žiadny)objaví objectref poľa, posunie dĺžku tohto poľa

Nasledujúce operačné kódy načítajú prvok z poľa. Index poľa a referencia poľa sú vyradené zo zásobníka a hodnota v zadanom indexe zadaného poľa sa vráti späť do zásobníka.

Načítava sa prvok poľa
Operačný kódOperand (y)Popis
balón(žiadny)objaví index a arrayref z radu bajtov, zatlačí arrayref [index]
caload(žiadny)objaví index a arrayref z radu znakov, zatlačí arrayref [index]
vrecovina(žiadny)objaví index a arrayref z radu šortiek, zatlačí arrayref [index]
iaload(žiadny)objaví index a arrayref z radu ints, zatlačí arrayref [index]
zaťaženie(žiadny)objaví index a arrayref z radu dĺžok, zatlačí arrayref [index]
faload(žiadny)objaví index a arrayref z radu plavákov, zatlačí arrayref [index]
daload(žiadny)objaví index a arrayref z radu štvorhier, zatlačí arrayref [index]
aaload(žiadny)objaví index a arrayref z radu objectrefs, zatlačí arrayref [index]

Nasledujúca tabuľka zobrazuje operačné kódy, ktoré ukladajú hodnotu do prvku poľa. Hodnota, index a referencia poľa sú vysunuté z hornej časti zásobníka.

Ukladá sa do prvku poľa
Operačný kódOperand (y)Popis
bastore(žiadny)objaví hodnotu, index a arrayref poľa bajtov, priradí arrayref [index] = hodnota
castore(žiadny)objaví hodnotu, index a arrayref z radu znakov, priradí arrayref [index] = hodnota
sklad(žiadny)objaví hodnotu, index a arrayref radu šortiek, priradí arrayref [index] = hodnota
iastore(žiadny)objaví hodnotu, index a arrayref z radu ints, priradí arrayref [index] = hodnota
vydržať(žiadny)objaví hodnotu, index a arrayref z radu dĺžok, priradí arrayref [index] = hodnota
fastore(žiadny)objaví hodnotu, index a arrayref z radu plavákov, priradí arrayref [index] = hodnota
dastore(žiadny)objaví hodnotu, index a arrayref poľa štvorhry, priradí arrayref [index] = hodnota
aastore(žiadny)objaví hodnotu, index a arrayref z radu objectrefs, priradí arrayref [index] = hodnota

Trojrozmerné pole: simulácia virtuálneho stroja Java

Nižšie uvedený applet demonštruje virtuálny stroj Java vykonávajúci sekvenciu bajtových kódov. Sekvencia bytecode v simulácii bola vygenerovaná používateľom javac pre initAnArray () metóda triedy uvedená nižšie:

trieda ArrayDemo {static void initAnArray () {int [] [] [] threeD = new int [5] [4] [3]; pre (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; }}}}} 

Bajtové kódy vygenerované javac pre initAnArray () sú zobrazené nižšie:

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