Pohled pod kapotu JVM – přístup k prvkům složených datových typů v JVM, Lua VM a Python VM

Pavel Tišnovský 24. 6. 2014

V dnešní části seriálu o Javě i o virtuálním stroji tohoto jazyka si řekneme, jakým způsobem je v bajtkódech JVM, Lua VM a Python VM realizován přístup k prvkům složených datových typů. V případě Javy se samozřejmě jedná o pole, v případě jazyka Lua o tabulky a Python obsahuje podporu pro seznamy a n-tice.

Obsah

1. Pohled pod kapotu JVM – přístup k prvkům složených datových typů v JVM, Lua VM a Python VM

2. Přístup k prvkům polí v JVM

3. Demonstrační příklad Test21.java: přístup k prvkům jednorozměrného pole

4. Demonstrační příklad Test22.java: přístup k prvkům dvourozměrného pole

5. Přístup k prvkům tabulek v Lua VM

6. Demonstrační příklad Test21.lua: přístup k prvkům jednorozměrného pole (tabulky)

7. Demonstrační příklad Test22.lua: přístup k prvkům dvourozměrného pole (tabulky)

8. Přístup k prvkům seznamů a n-tic v Python VM

9. Repositář se zdrojovými kódy všech dnešních demonstračních příkladů

10. Odkazy na Internetu

1. Pohled pod kapotu JVM – přístup k prvkům složených datových typů v JVM, Lua VM a Python VM

V předchozí části tohoto seriálu jsme si kromě dalších informací řekli a současně i na několika demonstračních příkladech ukázali, jakým způsobem lze v JVM, Lua VM i Python VM vytvářet složené datové typy, tj. pole, tabulky, seznamy či n-tice. Dnes budeme v tomto tématu pokračovat, protože si ukážeme způsob přístupu k prvkům těchto typů. Řekneme si, jak lze prvky přečíst (a to například pro jednorozměrnou i vícerozměrnou variantu složeného datového typu), i jak je lze zapsat, samozřejmě ovšem jen v těch případech, kdy je to dovoleno (u n-tic v Pythonu není zápis z pochopitelných důvodů povolen). Manipulace s prvky složených datových typů je již poněkud komplikovanější, než tomu bylo v případě jednoduchých datových typů (čísel, pravdivostních hodnot, znaků), a to z toho důvodu, že příslušné instrukce bajtkódu musí zpracovat jak referenci na příslušné pole/tabulku/seznam, tak i index čteného či zapisovaného prvku. Způsob implementace těchto operací bude vysvětlen na několika příkladech.

2. Přístup k prvkům polí v JVM

Mezi další operace týkající se polí podporovaných programovacím jazykem Java patří čtení obsahu jednotlivých prvků, popř. změna hodnoty jednotlivých prvků pole. Pro tyto účely je v instrukční sadě JVM vyhrazeno šestnáct instrukcí rozdělených do dvou sad. V první sadě je osm instrukcí určených pro přečtení prvku pole a uložení přečtené hodnoty na vrchol zásobníku operandů. Před zavoláním těchto instrukcí musí být na zásobníku operandů uložena reference na pole (tj. výsledek instrukce newarray, anewarray) a taktéž index prvku, který se má přečíst. Povšimněte si, že pole s prvky typu boolean je ve skutečnosti obsluhováno takovým způsobem, jako by obsahovalo prvky typu byte:

# Instrukce Opkód Operandy Prováděná operace
1 iaload 0×2E × přečtení prvku z pole typu int[]
2 laload 0×2F × přečtení prvku z pole typu long[]
3 faload 0×30 × přečtení prvku z pole typu float[]
4 daload 0×31 × přečtení prvku z pole typu double[]
5 aaload 0×32 × přečtení prvku z pole typu reference[]
6 baload 0×33 × přečtení prvku z pole typu byte[] nebo boolean[]
7 caload 0×34 × přečtení prvku z pole typu char[]
8 saload 0×35 × přečtení prvku z pole typu short[]

Ve druhé skupině se nachází taktéž osm instrukcí. Tyto instrukce slouží pro změnu hodnoty vybraného prvku pole. Před spuštěním těchto instrukcí musí být na zásobníku operandů uložena jak reference na pole, tak i index měněného prvku a samozřejmě i jeho nová hodnota:

# Instrukce Opkód Operandy Prováděná operace
1 iastore 0×4F × zápis nové hodnoty prvku do pole typu int[]
2 lastore 0×50 × zápis nové hodnoty prvku do pole typu long[]
3 fastore 0×51 × zápis nové hodnoty prvku do pole typu float[]
4 dastore 0×52 × zápis nové hodnoty prvku do pole typu double[]
5 aastore 0×53 × zápis nové hodnoty prvku do pole typu reference[]
6 bastore 0×54 × zápis nové hodnoty prvku do pole typu byte[] nebo boolean[]
7 castore 0×55 × zápis nové hodnoty prvku do pole typu char[]
8 sastore 0×56 × zápis nové hodnoty prvku do pole typu short[]

3. Demonstrační příklad Test21.java: přístup k prvkům jednorozměrného pole

Podívejme se nyní na demonstrační příklad (pojmenovaný Test21.java), v němž se provádí přístup k prvkům jednorozměrných polí. V příkladu je implementována přetížená metoda readItem() pro čtení prvku s daným indexem z pole, dále pak přetížená metoda writeItem() pro zápis prvku do pole a konečně již poněkud složitější metoda modify(), v níž se hodnota všech prvků pole zvýší o jedničku. Všechny metody jsou přetížené z toho důvodu, protože je zapotřebí ukázat, jak se pracuje s poli různých datových typů, a to jak primitivních datových typů (byte, short, int, long, floatdouble), tak i s poli referenčních typů (tj. objektů, přesněji řečeno pole referencí na objekty):

/**
 * Pristup k prvkum jednorozmerneho pole.
 */
public class Test21 {
 
    /* ---------------------------------------------------------------- */
    /* Pole typu byte[]                                                 */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z pole.
     */
    static byte readItem(byte[] array, int index) {
        return array[index];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(byte[] array, int index, byte value) {
        array[index] = value;
    }
 
    /**
     * Zvyseni hodnoty vsech prvku pole o jednicku.
     */
    static void modify(byte[] array) {
        for (int i=0; i < array.length; i++) {
            array[i]++;
        }
    }
 
    /* ---------------------------------------------------------------- */
    /* Pole typu short[]                                                */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z pole.
     */
    static short readItem(short[] array, short index) {
        return array[index];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(short[] array, short index, short value) {
        array[index] = value;
    }
 
    /**
     * Zvyseni hodnoty vsech prvku pole o jednicku.
     */
    static void modify(short[] array) {
        for (int i=0; i < array.length; i++) {
            array[i]++;
        }
    }
 
    /* ---------------------------------------------------------------- */
    /* Pole typu int[]                                                  */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z pole.
     */
    static int readItem(int[] array, int index) {
        return array[index];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(int[] array, int index, int value) {
        array[index] = value;
    }
 
    /**
     * Zvyseni hodnoty vsech prvku pole o jednicku.
     */
    static void modify(int[] array) {
        for (int i=0; i < array.length; i++) {
            array[i]++;
        }
    }
 
    /* ---------------------------------------------------------------- */
    /* Pole typu long[]                                                 */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z pole.
     */
    static long readItem(long[] array, int index) {
        return array[index];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(long[] array, int index, long value) {
        array[index] = value;
    }
 
    /**
     * Zvyseni hodnoty vsech prvku pole o jednicku.
     */
    static void modify(long[] array) {
        for (int i=0; i < array.length; i++) {
            array[i]++;
        }
    }
 
    /* ---------------------------------------------------------------- */
    /* Pole typu float[]                                                */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z pole.
     */
    static float readItem(float[] array, int index) {
        return array[index];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(float[] array, int index, float value) {
        array[index] = value;
    }
 
    /**
     * Zvyseni hodnoty vsech prvku pole o jednicku.
     */
    static void modify(float[] array) {
        for (int i=0; i < array.length; i++) {
            array[i]++;
        }
    }
 
    /* ---------------------------------------------------------------- */
    /* Pole typu double[]                                               */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z pole.
     */
    static double readItem(double[] array, int index) {
        return array[index];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(double[] array, int index, double value) {
        array[index] = value;
    }
 
    /**
     * Zvyseni hodnoty vsech prvku pole o jednicku.
     */
    static void modify(double[] array) {
        for (int i=0; i < array.length; i++) {
            array[i]++;
        }
    }
 
    /* ---------------------------------------------------------------- */
    /* Pole typu Object[]                                               */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z pole.
     */
    static Object readItem(Object[] array, int index) {
        return array[index];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(Object[] array, int index, Object value) {
        array[index] = value;
    }
 
}

Nejprve si ukažme, jak je přeložena přetížená metoda readItem(). Vidíme zde použití instrukcí typu *aload pro přečtení prvku z pole:

Precteni prvku z pole typu byte[]
 
static byte readItem(byte[], int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index cteneho prvku na zasobnik operandu
   2:   baload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   3:   ireturn              // vratit prislusny prvek precteny z pole
 
 
 
Precteni prvku z pole typu short[]
 
static short readItem(short[], short);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index cteneho prvku na zasobnik operandu
   2:   saload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   3:   ireturn              // vratit prislusny prvek precteny z pole
 
 
 
Precteni prvku z pole typu int[]
 
static int readItem(int[], int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index cteneho prvku na zasobnik operandu
   2:   iaload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   3:   ireturn              // vratit prislusny prvek precteny z pole
 
 
 
Precteni prvku z pole typu long[]
 
static long readItem(long[], int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index cteneho prvku na zasobnik operandu
   2:   laload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   3:   lreturn              // vratit prislusny prvek precteny z pole
 
 
 
Precteni prvku z pole typu float[]
 
static float readItem(float[], int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index cteneho prvku na zasobnik operandu
   2:   faload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   3:   freturn              // vratit prislusny prvek precteny z pole
 
 
 
Precteni prvku z pole typu double[]
 
static double readItem(double[], int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index cteneho prvku na zasobnik operandu
   2:   daload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   3:   dreturn              // vratit prislusny prvek precteny z pole
 
 
 
Precteni prvku z pole typu Object[]
 
static java.lang.Object readItem(java.lang.Object[], int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   3:   areturn              // vratit prislusny prvek precteny z pole

V přetížené metodě writeItem() se po překladu používají instrukce *astore:

Zapis prvku do pole typu byte[]
 
static void writeItem(byte[], int, byte);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index zapisovaneho prvku na zasobnik operandu
   2:   iload_2              // ulozit novou (zapisovanou) hodnotu prvku na zasobnik operandu
   3:   bastore              // zapsat prvek do pole a soucasne odstranit tri polozky ze zasobniku
   4:   return               // navrat z metody
 
 
 
Zapis prvku do pole typu short[]
 
static void writeItem(short[], short, short);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index zapisovaneho prvku na zasobnik operandu
   2:   iload_2              // ulozit novou (zapisovanou) hodnotu prvku na zasobnik operandu
   3:   sastore              // zapsat prvek do pole a soucasne odstranit tri polozky ze zasobniku
   4:   return               // vratit prislusny prvek precteny z pole
 
 
 
Zapis prvku do pole typu int[]
 
static void writeItem(int[], int, int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index zapisovaneho prvku na zasobnik operandu
   2:   iload_2              // ulozit novou (zapisovanou) hodnotu prvku na zasobnik operandu
   3:   iastore              // zapsat prvek do pole a soucasne odstranit tri polozky ze zasobniku
   4:   return               // vratit prislusny prvek precteny z pole
 
 
 
Zapis prvku do pole typu long[]
 
static void writeItem(long[], int, long);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index zapisovaneho prvku na zasobnik operandu
   2:   lload_2              // ulozit novou (zapisovanou) hodnotu prvku na zasobnik operandu
   3:   lastore              // zapsat prvek do pole a soucasne odstranit tri polozky ze zasobniku
   4:   return               // vratit prislusny prvek precteny z pole
 
 
 
Zapis prvku do pole typu float[]
 
static void writeItem(float[], int, float);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index zapisovaneho prvku na zasobnik operandu
   2:   fload_2              // ulozit novou (zapisovanou) hodnotu prvku na zasobnik operandu
   3:   fastore              // zapsat prvek do pole a soucasne odstranit tri polozky ze zasobniku
   4:   return               // vratit prislusny prvek precteny z pole
 
 
 
Zapis prvku do pole typu double[]
 
static void writeItem(double[], int, double);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index zapisovaneho prvku na zasobnik operandu
   2:   dload_2              // ulozit novou (zapisovanou) hodnotu prvku na zasobnik operandu
   3:   dastore              // zapsat prvek do pole a soucasne odstranit tri polozky ze zasobniku
   4:   return               // vratit prislusny prvek precteny z pole
 
 
 
Zapis prvku do pole typu Object[]
 
static void writeItem(java.lang.Object[], int, java.lang.Object);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit index zapisovaneho prvku na zasobnik operandu
   2:   aload_2              // ulozit novou (zapisovanou) hodnotu prvku na zasobnik operandu
   3:   aastore              // zapsat prvek do pole a soucasne odstranit tri polozky ze zasobniku
   4:   return               // vratit prislusny prvek precteny z pole

V metodě modify() můžeme vidět kombinaci čtení i zápisu hodnot prvků do polí:

Operace s prvky typu byte[]
 
static void modify(byte[]);
  Code:
   0:   iconst_0
   1:   istore_1             // lokalni promenna pouzita ve funkci pocitadla smycky
   2:   iload_1              // hodnota pocitadla na zasobnik
   3:   aload_0              // ulozit referenci na pole na zasobnik operandu
   4:   arraylength          // vypocitat delku pole (pocet prvku)
   5:   if_icmpge    22      // podminka na zacatku iterace
   8:   aload_0              // ulozit referenci na pole na zasobnik operandu
   9:   iload_1              // hodnota pocitadla na zasobnik
   10:  dup2                 // pocitadlo bude pouzito 2x - i pro zapis
   11:  baload               // nacist aktualni hodnotu prvku a ulozit ji na zasobnik operandu
   12:  iconst_1
   13:  iadd                 // pricist jednicku k puvodni hodnote prvku
   14:  i2b                  // konverze vysledku
   15:  bastore              // ulozit novou hodnotu prvku do pole
   16:  iinc    1, 1         // zvysit hodnotu pocitadla o jednicku
   19:  goto    2            // skok na zacatek programove smycky
   22:  return               // vratit prislusny prvek precteny z pole
 
 
 
Operace s prvky typu short[]
 
static void modify(short[]);
  Code:
   0:   iconst_0
   1:   istore_1             // lokalni promenna pouzita ve funkci pocitadla smycky
   2:   iload_1              // hodnota pocitadla na zasobnik
   3:   aload_0              // ulozit referenci na pole na zasobnik operandu
   4:   arraylength          // vypocitat delku pole (pocet prvku)
   5:   if_icmpge    22      // podminka na zacatku iterace
   8:   aload_0              // ulozit referenci na pole na zasobnik operandu
   9:   iload_1              // hodnota pocitadla na zasobnik
   10:  dup2                 // pocitadlo bude pouzito 2x - i pro zapis
   11:  saload               // nacist aktualni hodnotu prvku a ulozit ji na zasobnik operandu
   12:  iconst_1
   13:  iadd                 // pricist jednicku k puvodni hodnote prvku
   14:  i2s                  // konverze vysledku
   15:  sastore              // ulozit novou hodnotu prvku do pole
   16:  iinc    1, 1         // zvysit hodnotu pocitadla o jednicku
   19:  goto    2            // skok na zacatek programove smycky
   22:  return               // vratit prislusny prvek precteny z pole
 
 
 
Operace s prvky typu int[]
 
static void modify(int[]);
  Code:
   0:   iconst_0
   1:   istore_1             // lokalni promenna pouzita ve funkci pocitadla smycky
   2:   iload_1              // hodnota pocitadla na zasobnik
   3:   aload_0              // ulozit referenci na pole na zasobnik operandu
   4:   arraylength          // vypocitat delku pole (pocet prvku)
   5:   if_icmpge    21      // podminka na zacatku iterace
   8:   aload_0              // ulozit referenci na pole na zasobnik operandu
   9:   iload_1              // hodnota pocitadla na zasobnik
   10:  dup2                 // pocitadlo bude pouzito 2x - i pro zapis
   11:  iaload               // nacist aktualni hodnotu prvku a ulozit ji na zasobnik operandu
   12:  iconst_1
   13:  iadd                 // pricist jednicku k puvodni hodnote prvku
   14:  iastore              // ulozit novou hodnotu prvku do pole
   15:  iinc    1, 1         // zvysit hodnotu pocitadla o jednicku
   18:  goto    2            // skok na zacatek programove smycky
   21:  return               // vratit prislusny prvek precteny z pole
 
 
 
Operace s prvky typu long[]
 
static void modify(long[]);
  Code:
   0:   iconst_0
   1:   istore_1             // lokalni promenna pouzita ve funkci pocitadla smycky
   2:   iload_1              // hodnota pocitadla na zasobnik
   3:   aload_0              // ulozit referenci na pole na zasobnik operandu
   4:   arraylength          // vypocitat delku pole (pocet prvku)
   5:   if_icmpge    21      // podminka na zacatku iterace
   8:   aload_0              // ulozit referenci na pole na zasobnik operandu
   9:   iload_1              // hodnota pocitadla na zasobnik
   10:  dup2                 // pocitadlo bude pouzito 2x - i pro zapis
   11:  laload               // nacist aktualni hodnotu prvku a ulozit ji na zasobnik operandu
   12:  lconst_1
   13:  ladd                 // pricist jednicku k puvodni hodnote prvku
   14:  lastore              // ulozit novou hodnotu prvku do pole
   15:  iinc    1, 1         // zvysit hodnotu pocitadla o jednicku
   18:  goto    2            // skok na zacatek programove smycky
   21:  return               // vratit prislusny prvek precteny z pole
 
 
 
Operace s prvky typu float[]
 
static void modify(float[]);
  Code:
   0:   iconst_0
   1:   istore_1             // lokalni promenna pouzita ve funkci pocitadla smycky
   2:   iload_1              // hodnota pocitadla na zasobnik
   3:   aload_0              // ulozit referenci na pole na zasobnik operandu
   4:   arraylength          // vypocitat delku pole (pocet prvku)
   5:   if_icmpge    21      // podminka na zacatku iterace
   8:   aload_0              // ulozit referenci na pole na zasobnik operandu
   9:   iload_1              // hodnota pocitadla na zasobnik
   10:  dup2                 // pocitadlo bude pouzito 2x - i pro zapis
   11:  faload               // nacist aktualni hodnotu prvku a ulozit ji na zasobnik operandu
   12:  fconst_1
   13:  fadd                 // pricist jednicku k puvodni hodnote prvku
   14:  fastore              // ulozit novou hodnotu prvku do pole
   15:  iinc    1, 1         // zvysit hodnotu pocitadla o jednicku
   18:  goto    2            // skok na zacatek programove smycky
   21:  return               // vratit prislusny prvek precteny z pole
 
 
 
Operace s prvky typu double[]
static void modify(double[]);
  Code:
   0:   iconst_0
   1:   istore_1             // lokalni promenna pouzita ve funkci pocitadla smycky
   2:   iload_1              // hodnota pocitadla na zasobnik
   3:   aload_0              // ulozit referenci na pole na zasobnik operandu
   4:   arraylength          // vypocitat delku pole (pocet prvku)
   5:   if_icmpge    21      // podminka na zacatku iterace
   8:   aload_0              // ulozit referenci na pole na zasobnik operandu
   9:   iload_1              // hodnota pocitadla na zasobnik
   10:  dup2                 // pocitadlo bude pouzito 2x - i pro zapis
   11:  daload               // nacist aktualni hodnotu prvku a ulozit ji na zasobnik operandu
   12:  dconst_1
   13:  dadd                 // pricist jednicku k puvodni hodnote prvku
   14:  dastore              // ulozit novou hodnotu prvku do pole
   15:  iinc    1, 1         // zvysit hodnotu pocitadla o jednicku
   18:  goto    2            // skok na zacatek programove smycky
   21:  return               // vratit prislusny prvek precteny z pole

4. Demonstrační příklad Test22.java: přístup k prvkům dvourozměrného pole

Zatímco přístup k jednorozměrným polím byl vcelku přímočarý, u dvourozměrných (a samozřejmě taktéž i vícerozměrných) polí již nastává problém s přístupem k jednotlivým prvkům, a to z toho důvodu, že vícerozměrné pole je v Javě chápáno jako pole referencí na další pole o jednu dimenzi menšího. Nejprve se nicméně podívejme na zdrojový kód dalšího demonstračního příkladu, v němž se opět provádí čtení i zápis:

/**
 * Pristup k prvkum dvourozmerneho pole.
 */
public class Test22 {
 
    /* ---------------------------------------------------------------- */
    /* Pole typu byte[]                                                 */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z dvourozmerneho pole.
     */
    static byte readItem(byte[][] array, int index1, int index2) {
        return array[index1][index2];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(byte[][] array, int index1, int index2, byte value) {
        array[index1][index2] = value;
    }
 
    /**
     * Vypocet sumy vsech prvku
     */
    static byte sum(byte[][] array) {
        byte sum = 0;
        for (int j = 0; j < array.length; j++) {
            for (int i = 0; i < array[j].length; i++) {
                sum += array[j][i];
            }
        }
        return sum;
    }
 
    /* ---------------------------------------------------------------- */
    /* Pole typu short[]                                                */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z dvourozmerneho pole.
     */
    static short readItem(short[][] array, int index1, int index2) {
        return array[index1][index2];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(short[][] array, int index1, int index2, short value) {
        array[index1][index2] = value;
    }
 
    /**
     * Vypocet sumy vsech prvku
     */
    static short sum(short[][] array) {
        short sum = 0;
        for (int j = 0; j < array.length; j++) {
            for (int i = 0; i < array[j].length; i++) {
                sum += array[j][i];
            }
        }
        return sum;
    }
 
    /* ---------------------------------------------------------------- */
    /* Pole typu int[]                                                  */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z dvourozmerneho pole.
     */
    static int readItem(int[][] array, int index1, int index2) {
        return array[index1][index2];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(int[][] array, int index1, int index2, int value) {
        array[index1][index2] = value;
    }
 
    /**
     * Vypocet sumy vsech prvku
     */
    static int sum(int[][] array) {
        int sum = 0;
        for (int j = 0; j < array.length; j++) {
            for (int i = 0; i < array[j].length; i++) {
                sum += array[j][i];
            }
        }
        return sum;
    }
 
    /* ---------------------------------------------------------------- */
    /* Pole typu long[]                                                 */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z dvourozmerneho pole.
     */
    static long readItem(long[][] array, int index1, int index2) {
        return array[index1][index2];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(long[][] array, int index1, int index2, long value) {
        array[index1][index2] = value;
    }
 
    /**
     * Vypocet sumy vsech prvku
     */
    static long sum(long[][] array) {
        long sum = 0;
        for (int j = 0; j < array.length; j++) {
            for (int i = 0; i < array[j].length; i++) {
                sum += array[j][i];
            }
        }
        return sum;
    }
 
    /* ---------------------------------------------------------------- */
    /* Pole typu float[]                                                */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z dvourozmerneho pole.
     */
    static float readItem(float[][] array, int index1, int index2) {
        return array[index1][index2];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(float[][] array, int index1, int index2, float value) {
        array[index1][index2] = value;
    }
 
    /**
     * Vypocet sumy vsech prvku
     */
    static float sum(float[][] array) {
        float sum = 0;
        for (int j = 0; j < array.length; j++) {
            for (int i = 0; i < array[j].length; i++) {
                sum += array[j][i];
            }
        }
        return sum;
    }
 
    /* ---------------------------------------------------------------- */
    /* Pole typu double[]                                               */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z dvourozmerneho pole.
     */
    static double readItem(double[][] array, int index1, int index2) {
        return array[index1][index2];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(double[][] array, int index1, int index2, double value) {
        array[index1][index2] = value;
    }
 
    /**
     * Vypocet sumy vsech prvku
     */
    static double sum(double[][] array) {
        double sum = 0;
        for (int j = 0; j < array.length; j++) {
            for (int i = 0; i < array[j].length; i++) {
                sum += array[j][i];
            }
        }
        return sum;
    }
 
    /* ---------------------------------------------------------------- */
    /* Pole typu Object[]                                               */
    /* ---------------------------------------------------------------- */
 
    /**
     * Nejjednodussi operace - precteni hodnoty prvku z dvourozmerneho pole.
     */
    static Object readItem(Object[][] array, int index1, int index2) {
        return array[index1][index2];
    }
 
    /**
     * Dalsi jednoducha operace - zapis hodnoty prvku do pole.
     */
    static void writeItem(Object[][] array, int index1, int index2, Object value) {
        array[index1][index2] = value;
    }
 
    /**
     * Vypocet sumy hash kodu vsech prvku pole.
     */
    static int sum(Object[][] array) {
        int sum = 0;
        for (int j = 0; j < array.length; j++) {
            for (int i = 0; i < array[j].length; i++) {
                sum += array[j][i].hashCode();
            }
        }
        return sum;
    }
 
}

Při čtení prvků z dvourozměrného pole můžeme v bajtkódu vidět použití dvojice instrukcí aaload+*aload, kde první instrukce slouží k přečtení „pole polí“ a teprve druhá instrukce přečte vlastní prvek:

Precteni prvku z pole typu byte[][]
 
static byte readItem(byte[][], int, int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   baload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   5:   ireturn              // vratit prislusny prvek precteny z pole
 
 
 
Precteni prvku z pole typu short[][]
 
static short readItem(short[][], int, int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   saload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   5:   ireturn              // vratit prislusny prvek precteny z pole
 
 
 
Precteni prvku z pole typu int[][]
 
static int readItem(int[][], int, int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   iaload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   5:   ireturn              // vratit prislusny prvek precteny z pole
 
 
 
Precteni prvku z pole typu long[][]
 
static long readItem(long[][], int, int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   laload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   5:   lreturn              // vratit prislusny prvek precteny z pole
 
 
 
Precteni prvku z pole typu float[][]
 
static float readItem(float[][], int, int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   faload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   5:   freturn              // vratit prislusny prvek precteny z pole
 
 
 
Precteni prvku z pole typu double[][]
 
static double readItem(double[][], int, int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   daload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   5:   dreturn              // vratit prislusny prvek precteny z pole
 
 
 
Precteni prvku z pole typu Object[][]
 
static java.lang.Object readItem(java.lang.Object[][], int, int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   aaload               // nacist prislusny prvek a ulozit ho na zasobik operandu
   5:   areturn              // vratit prislusny prvek precteny z pole

Při zápisu prvku do pole se používá dvojice instrukcí aaload+*astore:

Zapis prvku do pole typu byte[][]
 
static void writeItem(byte[][], int, int, byte);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   iload_3              // ulozit zapisovanou hodnotu na zasobnik
   5:   bastore              // zmena prvku v poli
   6:   return               // navrat z metody
 
 
 
Zapis prvku do pole typu short[][]
 
static void writeItem(short[][], int, int, short);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   iload_3              // ulozit zapisovanou hodnotu na zasobnik
   5:   sastore              // zmena prvku v poli
   6:   return               // navrat z metody
 
 
 
Zapis prvku do pole typu int[][]
 
static void writeItem(int[][], int, int, int);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   iload_3              // ulozit zapisovanou hodnotu na zasobnik
   5:   iastore              // zmena prvku v poli
   6:   return               // navrat z metody
 
 
 
Zapis prvku do pole typu long[][]
 
static void writeItem(long[][], int, int, long);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   lload_3              // ulozit zapisovanou hodnotu na zasobnik
   5:   lastore              // zmena prvku v poli
   6:   return               // navrat z metody
 
 
 
Zapis prvku do pole typu float[][]
 
static void writeItem(float[][], int, int, float);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   fload_3              // ulozit zapisovanou hodnotu na zasobnik
   5:   fastore              // zmena prvku v poli
   6:   return               // navrat z metody
 
 
 
Zapis prvku do pole typu double[][]
 
static void writeItem(double[][], int, int, double);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   dload_3              // ulozit zapisovanou hodnotu na zasobnik
   5:   dastore              // zmena prvku v poli
   6:   return               // navrat z metody
 
 
 
Zapis prvku do pole typu Object[][]
 
static void writeItem(java.lang.Object[][], int, int, java.lang.Object);
  Code:
   0:   aload_0              // ulozit referenci na pole na zasobnik operandu
   1:   iload_1              // ulozit prvni index cteneho prvku na zasobnik operandu
   2:   aaload               // nacist n-te pole poli
   3:   iload_2              // ulozit druhy index cteneho prvku na zasobnik operandu
   4:   aload_3              // ulozit zapisovanou hodnotu na zasobnik
   5:   aastore              // zmena prvku v poli
   6:   return               // navrat z metody

Podívejme se i na složitější algoritmus, v němž se prochází všemi prvky dvourozměrného pole:

Operace s prvky pole typu byte[][]
 
static byte sum(byte[][]);
  Code:
   0:   iconst_0             // konstanta 0 na vrchol zasobniku operandu
   1:   istore_1             // lokalni promenna pouzita ve funkci sumy
   2:   iconst_0             // konstanta 0 na vrchol zasobniku operandu
   3:   istore_2             // lokalni promenna pouzita ve funkci pocitadla vnejsi smycky
   4:   iload_2              // hodnota pocitadla na zasobnik
   5:   aload_0              // ulozit referenci na pole na zasobnik operandu
   6:   arraylength          // vypocitat delku pole (pocet prvku)
   7:   if_icmpge       41   // podminka na zacatku iterace (vnejsi smycka)
   10:  iconst_0             // konstanta 0 na vrchol zasobniku operandu
   11:  istore_3             // lokalni promenna pouzita ve funkci pocitadla vnitrni smycky
   12:  iload_3              // hodnota pocitadla na zasobnik
   13:  aload_0              // ulozit referenci na pole na zasobnik operandu
   14:  iload_2              // pocitadlo vnejsi smycky ve funkci indexu
   15:  aaload               // nacist i-ty prvek "vnejsiho" pole
   16:  arraylength          // spocitat delku sub-pole
   17:  if_icmpge       35   // podminka na zacatku iterace (vnitrni smycka)
   20:  iload_1              // hodnota sumy na zasobnik
   21:  aload_0              // ulozit referenci na pole na zasobnik operandu
   22:  iload_2
   23:  aaload               // nacist sub-pole
   24:  iload_3
   25:  baload               // nacist jiz konkretni prvek pole
   26:  iadd                 // pricist k sume
   27:  i2b                  // konverze mezivysledku
   28:  istore_1             // ulozit mezivysledek
   29:  iinc    3, 1         // zvysit hodnotu pocitadla vnitrni smycky o jednicku
   32:  goto    12           // skok na zacatek vnitrni programove smycky
   35:  iinc    2, 1         // zvysit hodnotu pocitadla vnejsi smycky o jednicku
   38:  goto    4            // skok na zacatek vnejsi programove smycky
   41:  iload_1              // suma
   42:  ireturn              // vratit hodnotu sumy
 
 
 
Operace s prvky pole typu short[][]
 
static short sum(short[][]);
  Code:
   0:   iconst_0             // konstanta 0 na vrchol zasobniku operandu
   1:   istore_1             // lokalni promenna pouzita ve funkci sumy
   2:   iconst_0             // konstanta 0 na vrchol zasobniku operandu
   3:   istore_2             // lokalni promenna pouzita ve funkci pocitadla vnejsi smycky
   4:   iload_2              // hodnota pocitadla na zasobnik
   5:   aload_0              // ulozit referenci na pole na zasobnik operandu
   6:   arraylength          // vypocitat delku pole (pocet prvku)
   7:   if_icmpge       41   // podminka na zacatku iterace (vnejsi smycka)
   10:  iconst_0             // konstanta 0 na vrchol zasobniku operandu
   11:  istore_3             // lokalni promenna pouzita ve funkci pocitadla vnitrni smycky
   12:  iload_3              // hodnota pocitadla na zasobnik
   13:  aload_0              // ulozit referenci na pole na zasobnik operandu
   14:  iload_2              // pocitadlo vnejsi smycky ve funkci indexu
   15:  aaload               // nacist i-ty prvek "vnejsiho" pole
   16:  arraylength          // spocitat delku sub-pole
   17:  if_icmpge       35   // podminka na zacatku iterace (vnitrni smycka)
   20:  iload_1              // hodnota sumy na zasobnik
   21:  aload_0              // ulozit referenci na pole na zasobnik operandu
   22:  iload_2
   23:  aaload               // nacist sub-pole
   24:  iload_3
   25:  saload               // nacist jiz konkretni prvek pole
   26:  iadd                 // pricist k sume
   27:  i2s                  // konverze mezivysledku
   28:  istore_1             // ulozit mezivysledek
   29:  iinc    3, 1         // zvysit hodnotu pocitadla vnitrni smycky o jednicku
   32:  goto    12           // skok na zacatek vnitrni programove smycky
   35:  iinc    2, 1         // zvysit hodnotu pocitadla vnejsi smycky o jednicku
   38:  goto    4            // skok na zacatek vnejsi programove smycky
   41:  iload_1              // suma
   42:  ireturn              // vratit hodnotu sumy
 
 
 
Operace s prvky pole typu int[][]
 
static int sum(int[][]);
  Code:
   0:   iconst_0             // konstanta 0 na vrchol zasobniku operandu
   1:   istore_1             // lokalni promenna pouzita ve funkci sumy
   2:   iconst_0             // konstanta 0 na vrchol zasobniku operandu
   3:   istore_2             // lokalni promenna pouzita ve funkci pocitadla vnejsi smycky
   4:   iload_2              // hodnota pocitadla na zasobnik
   5:   aload_0              // ulozit referenci na pole na zasobnik operandu
   6:   arraylength          // vypocitat delku pole (pocet prvku)
   7:   if_icmpge       40   // podminka na zacatku iterace (vnejsi smycka)
   10:  iconst_0             // konstanta 0 na vrchol zasobniku operandu
   11:  istore_3             // lokalni promenna pouzita ve funkci pocitadla vnitrni smycky
   12:  iload_3              // hodnota pocitadla na zasobnik
   13:  aload_0              // ulozit referenci na pole na zasobnik operandu
   14:  iload_2              // pocitadlo vnejsi smycky ve funkci indexu
   15:  aaload               // nacist i-ty prvek "vnejsiho" pole
   16:  arraylength          // spocitat delku sub-pole
   17:  if_icmpge       34   // podminka na zacatku iterace (vnitrni smycka)
   20:  iload_1              // hodnota sumy na zasobnik
   21:  aload_0              // ulozit referenci na pole na zasobnik operandu
   22:  iload_2
   23:  aaload               // nacist sub-pole
   24:  iload_3
   25:  iaload               // nacist jiz konkretni prvek pole
   26:  iadd
   27:  istore_1             // ulozit mezivysledek
   28:  iinc    3, 1         // zvysit hodnotu pocitadla vnitrni smycky o jednicku
   31:  goto    12           // skok na zacatek vnitrni programove smycky
   34:  iinc    2, 1         // zvysit hodnotu pocitadla vnejsi smycky o jednicku
   37:  goto    4            // skok na zacatek vnejsi programove smycky
   40:  iload_1              // suma
   41:  ireturn              // vratit hodnotu sumy
 
 
 
Operace s prvky pole typu long[][]
 
static long sum(long[][]);
  Code:
   0:   lconst_0             // konstanta 0 na vrchol zasobniku operandu
   1:   lstore_1             // lokalni promenna pouzita ve funkci sumy
   2:   iconst_0             // konstanta 0 na vrchol zasobniku operandu
   3:   istore_3             // lokalni promenna pouzita ve funkci pocitadla vnejsi smycky
   4:   iload_3              // hodnota pocitadla na zasobnik
   5:   aload_0              // ulozit referenci na pole na zasobnik operandu
   6:   arraylength          // vypocitat delku pole (pocet prvku)
   7:   if_icmpge       43   // podminka na zacatku iterace (vnejsi smycka)
   10:  iconst_0             // konstanta 0 na vrchol zasobniku operandu
   11:  istore  4            // lokalni promenna pouzita ve funkci pocitadla vnitrni smycky
   13:  iload   4            // hodnota pocitadla na zasobnik
   15:  aload_0              // ulozit referenci na pole na zasobnik operandu
   16:  iload_3              // pocitadlo vnejsi smycky ve funkci indexu
   17:  aaload               // nacist i-ty prvek "vnejsiho" pole
   18:  arraylength          // spocitat delku sub-pole
   19:  if_icmpge       37   // podminka na zacatku iterace (vnitrni smycka)
   22:  lload_1              // hodnota sumy na zasobnik
   23:  aload_0
   24:  iload_3
   25:  aaload               // nacist i-ty prvek "vnejsiho" pole
   26:  iload   4
   28:  laload               // nacist jiz konkretni prvek pole
   29:  ladd
   30:  lstore_1             // ulozit mezivysledek
   31:  iinc    4, 1         // zvysit hodnotu pocitadla vnitrni smycky o jednicku
   34:  goto    13           // skok na zacatek vnitrni programove smycky
   37:  iinc    3, 1         // zvysit hodnotu pocitadla vnejsi smycky o jednicku
   40:  goto    4            // skok na zacatek vnejsi programove smycky
   43:  lload_1              // suma
   44:  lreturn              // vratit hodnotu sumy
 
 
 
Operace s prvky pole typu float[][]
 
static float sum(float[][]);
  Code:
   0:   fconst_0             // konstanta 0 na vrchol zasobniku operandu
   1:   fstore_1             // lokalni promenna pouzita ve funkci sumy
   2:   iconst_0             // konstanta 0 na vrchol zasobniku operandu
   3:   istore_2             // lokalni promenna pouzita ve funkci pocitadla vnejsi smycky
   4:   iload_2              // hodnota pocitadla na zasobnik
   5:   aload_0              // ulozit referenci na pole na zasobnik operandu
   6:   arraylength          // vypocitat delku pole (pocet prvku)
   7:   if_icmpge       40   // podminka na zacatku iterace (vnejsi smycka)
   10:  iconst_0             // konstanta 0 na vrchol zasobniku operandu
   11:  istore_3             // lokalni promenna pouzita ve funkci pocitadla vnitrni smycky
   12:  iload_3              // hodnota pocitadla na zasobnik
   13:  aload_0              // ulozit referenci na pole na zasobnik operandu
   14:  iload_2              // pocitadlo vnejsi smycky ve funkci indexu
   15:  aaload               // nacist i-ty prvek "vnejsiho" pole
   16:  arraylength          // spocitat delku sub-pole
   17:  if_icmpge       34   // podminka na zacatku iterace (vnitrni smycka)
   20:  fload_1              // hodnota sumy na zasobnik
   21:  aload_0
   22:  iload_2
   23:  aaload               // nacist i-ty prvek "vnejsiho" pole
   24:  iload_3
   25:  faload               // nacist jiz konkretni prvek pole
   26:  fadd
   27:  fstore_1             // ulozit mezivysledek
   28:  iinc    3, 1         // zvysit hodnotu pocitadla vnitrni smycky o jednicku
   31:  goto    12           // skok na zacatek vnitrni programove smycky
   34:  iinc    2, 1         // zvysit hodnotu pocitadla vnejsi smycky o jednicku
   37:  goto    4            // skok na zacatek vnejsi programove smycky
   40:  fload_1              // suma
   41:  freturn              // vratit hodnotu sumy
 
 
 
Operace s prvky pole typu double[][]
 
static double sum(double[][]);
  Code:
   0:   dconst_0             // konstanta 0 na vrchol zasobniku operandu
   1:   dstore_1             // lokalni promenna pouzita ve funkci sumy
   2:   iconst_0             // konstanta 0 na vrchol zasobniku operandu
   3:   istore_3             // lokalni promenna pouzita ve funkci pocitadla vnejsi smycky
   4:   iload_3              // hodnota pocitadla na zasobnik
   5:   aload_0              // ulozit referenci na pole na zasobnik operandu
   6:   arraylength          // vypocitat delku pole (pocet prvku)
   7:   if_icmpge       43   // podminka na zacatku iterace (vnejsi smycka)
   10:  iconst_0             // konstanta 0 na vrchol zasobniku operandu
   11:  istore  4            // lokalni promenna pouzita ve funkci pocitadla vnitrni smycky
   13:  iload   4            // hodnota pocitadla na zasobnik
   15:  aload_0              // ulozit referenci na pole na zasobnik operandu
   16:  iload_3              // pocitadlo vnejsi smycky ve funkci indexu
   17:  aaload               // nacist i-ty prvek "vnejsiho" pole
   18:  arraylength          // spocitat delku sub-pole
   19:  if_icmpge       37   // podminka na zacatku iterace (vnitrni smycka)
   22:  dload_1              // hodnota sumy na zasobnik
   23:  aload_0
   24:  iload_3
   25:  aaload               // nacist i-ty prvek "vnejsiho" pole
   26:  iload   4
   28:  daload               // nacist jiz konkretni prvek pole
   29:  dadd
   30:  dstore_1             // ulozit mezivysledek
   31:  iinc    4, 1         // zvysit hodnotu pocitadla vnitrni smycky o jednicku
   34:  goto    13           // skok na zacatek vnitrni programove smycky
   37:  iinc    3, 1         // zvysit hodnotu pocitadla vnejsi smycky o jednicku
   40:  goto    4            // skok na zacatek vnejsi programove smycky
   43:  dload_1              // suma
   44:  dreturn              // vratit hodnotu sumy
 
 
 
Operace s prvky pole typu Object[][]
 
static int sum(java.lang.Object[][]);
  Code:
   0:   iconst_0             // konstanta 0 na vrchol zasobniku operandu
   1:   istore_1             // lokalni promenna pouzita ve funkci sumy
   2:   iconst_0             // konstanta 0 na vrchol zasobniku operandu
   3:   istore_2             // lokalni promenna pouzita ve funkci pocitadla vnejsi smycky
   4:   iload_2              // hodnota pocitadla na zasobnik
   5:   aload_0              // ulozit referenci na pole na zasobnik operandu
   6:   arraylength          // vypocitat delku pole (pocet prvku)
   7:   if_icmpge       43   // podminka na zacatku iterace (vnejsi smycka)
   10:  iconst_0             // konstanta 0 na vrchol zasobniku operandu
   11:  istore_3             // lokalni promenna pouzita ve funkci pocitadla vnitrni smycky
   12:  iload_3              // hodnota pocitadla na zasobnik
   13:  aload_0              // ulozit referenci na pole na zasobnik operandu
   14:  iload_2              // pocitadlo vnejsi smycky ve funkci indexu
   15:  aaload               // nacist i-ty prvek "vnejsiho" pole
   16:  arraylength          // spocitat delku sub-pole
   17:  if_icmpge       37   // podminka na zacatku iterace (vnitrni smycka)
   20:  iload_1              // hodnota sumy na zasobnik
   21:  aload_0
   22:  iload_2
   23:  aaload               // nacist i-ty prvek "vnejsiho" pole
   24:  iload_3
   25:  aaload               // nacist jiz konkretni prvek pole
   26:  invokevirtual   #2;  // Method java/lang/Object.hashCode:()I
   29:  iadd
   30:  istore_1             // ulozit mezivysledek
   31:  iinc    3, 1         // zvysit hodnotu pocitadla vnitrni smycky o jednicku
   34:  goto    12           // skok na zacatek vnitrni programove smycky
   37:  iinc    2, 1         // zvysit hodnotu pocitadla vnejsi smycky o jednicku
   40:  goto    4            // skok na zacatek vnejsi programove smycky
   43:  iload_1              // suma
   44:  ireturn              // vratit hodnotu sumy

5. Přístup k prvkům tabulek v Lua VM

Bajtkód využívaný virtuálním strojem programovacího jazyka Lua je založen, jak jsme se již dozvěděli v předcházejících částech tohoto seriálu, na registrech, do nichž jsou ukládány jak parametry funkcí, tak i lokální proměnné. Navíc se u většiny instrukcí bajtkódu používají parametry, které jsou součástí instrukčního slova. Nejinak je tomu i u instrukcí určených pro čtení a zápis hodnot do polí, přesněji řečeno do tabulek. Jedná se o instrukce nazvané GETTABLESETTABLE. Instrukce GETTABLE má v instrukčním slovu uloženy indexy tří registrů – index registru pro uložení výsledku, index registru s referencí na tabulku a index registru s uloženým pořadím čteného prvku. U instrukce SETTABLE je taktéž použita trojice indexů, které obsahují registr s referencí na pole, registr s indexem zapisovaného prvku a konečně registr s novou hodnotou prvku:

# Instrukce Operandy Prováděná operace
1 GETTABLE registr pole index přečtení prvku z tabulky
2 SETTABLE pole index hodnota zápis prvku do tabulky
3 LEN registr pole vrací délku pole

6. Demonstrační příklad Test21.lua: přístup k prvkům jednorozměrného pole (tabulky)

Opět se, podobně jako v případě programovacího jazyka Java, podívejme na jednoduchý demonstrační příklad, v němž se provádí čtení i zápis do tabulek. Na rozdíl od Javy nemusíme v případě programovacího jazyka Lua přetěžovat funkce/metody, protože bajtkód Lua VM používá dynamické typování. Z tohoto důvodu je demonstrační příklad mnohem kratší:

--
-- Pristup k prvkum (jednorozmerne) tabulky.
--
 
 
 
--
-- Nejjednodussi operace - precteni hodnoty prvku z pole/tabulky.
--
function readItem(array, index)
    return array[index]
end
 
 
 
--
-- Dalsi jednoducha operace - zapis hodnoty prvku do pole/tabulky.
--
function writeItem(array, index, value)
    array[index] = value
end
 
 
 
--
-- Zvyseni hodnoty vsech prvku pole/tabulky o jednicku.
--
function modify(array)
    for i = 1, #array do
        array[i] = array[i] + 1
    end
end
 
 
 
--
-- Tisk vsech prvku pole/tabulky.
--
function printArray(array)
    for i = 1, #array do
        print(readItem(array, i))
    end
end
 
 
 
--
-- Test.
--
function main()
    local array = {1, 2, 3}
 
    print("Original array:")
    printArray(array)
    print()
 
    writeItem(array, 2, 42)
    print("2nd item have been changed:")
    printArray(array)
    print()
 
    modify(array)
    print("Modified array:")
    printArray(array)
    print()
end
 
 
 
main()

Bajtkód funkce readItem() je velmi jednoduchý, protože obsahuje pouze trojici instrukcí, kde je navíc poslední instrukce ve skutečnosti nadbytečná. Přečtení prvku na daném indexu je provedeno jedinou instrukcí GETTABLE:

function <Test21.lua:10,12> (3 instructions at 0x9da4c88)
2 params, 3 slots, 0 upvalues, 2 locals, 0 constants, 0 functions
        1       [11]    GETTABLE        2 0 1            // prime precteni prvku z tabulky (parametr 0) s indexem (parametr 1)
        2       [11]    RETURN          2 2              // vraceni prectene hodnoty prvku
        3       [12]    RETURN          0 1              // automaticky vkladany navrat z funkce

Funkce writeItem() určená pro změnu hodnoty vybraného prvku tabulky je dokonce ještě jednodušší, protože všechnu funkcionalitu vykonává jediná instrukce SETTABLE:

function <Test21.lua:19,21> (2 instructions at 0x9da4f08)
3 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions
        1       [20]    SETTABLE        0 1 2            // primy zapis prvku do tabulky (parametr 0) s indexem (parametr 1)
        2       [21]    RETURN          0 1              // automaticky vkladany navrat z funkce

Poněkud složitější je bajtkód funkce, v níž se zvyšují hodnoty všech prvků tabulky o jedničku. Nejprve se zjistí délka tabulky instrukcí LEN a posléze je s využitím FORPREPFORLOOP realizována počítaná programová smyčka:

function <Test21.lua:28,32> (9 instructions at 0x9da50f8)
1 param, 6 slots, 0 upvalues, 5 locals, 1 constant, 0 functions
        1       [29]    LOADK           1 -1    ; 1      // pocatecni hodnota pocitadla pro for
        2       [29]    LEN             2 0              // vraci se delka tabulky
        3       [29]    LOADK           3 -1    ; 1      // priprava smycky for
        4       [29]    FORPREP         1 3     ; to 8   // zacatek smycky for
        5       [30]    GETTABLE        5 0 4            // cteni puvodni hodnoty prvku
        6       [30]    ADD             5 5 -1  ; - 1    // pricteni jednicky (-1 je index konstanty)
        7       [30]    SETTABLE        0 4 5            // zapis nove hodnoty prvku
        8       [29]    FORLOOP         1 -4    ; to 5   // iterace na konci smycky
        9       [32]    RETURN          0 1              // automaticky vkladany navrat z funkce

Na této trojici přeložených funkcí můžeme vidět, že bajtkód Lua VM je na jedné straně velmi flexibilní (dynamické typování) a na straně druhé i do značné míry kompaktní, zejména v porovnání s JVM.

7. Demonstrační příklad Test22.lua: přístup k prvkům dvourozměrného pole (tabulky)

Další demonstrační příklad nazvaný Test22.lua obsahuje trojici funkcí, které přistupují k prvkům dvourozměrné tabulky, která je chápána jako běžná jednorozměrná tabulka obsahující jako své prvky další tabulky:

--
-- Pristup k prvkum tabulky.
--
 
 
 
--
-- Nejjednodussi operace - precteni hodnoty prvku z dvourozmerne tabulky/pole.
--
function readItem(array, index1, index2)
    return array[index1][index2]
end
 
 
 
--
-- Dalsi jednoducha operace - zapis hodnoty prvku do dvourozmerne tabulky.
--
function writeItem(array, index1, index2, value)
    array[index1][index2] = value
end
 
 
 
--
-- Vypocet sumy vsech prvku dvourozmerneho pole.
--
function sum(array)
    local sum = 0
    for i = 1, #array do
        for j = 1, #array[i] do
            sum = sum + array[i][j]
        end
    end
    return sum
end
 
 
 
--
-- Tisk vsech prvku dvourozmerneho pole.
--
function printArray(array)
    for i = 1, #array do
        for j = 1, #array[i] do
            io.write(readItem(array, i, j))
            io.write(' ')
        end
        print()
    end
end
 
 
 
--
-- Test.
--
function main()
    local array = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
 
    printArray(array)
    print("Sum = " .. sum(array))
    print()
 
    writeItem(array, 2, 2, 0)
    printArray(array)
 
    print("Sum = " .. sum(array))
end
 
 
 
main()

V bajtkódu funkce readItem() vidíme dvojici instrukcí GETTABLE použitých pro přečtení i-té podtabulky a j-tého prvku z této podtabulky:

function <Test22.lua:10,12> (4 instructions at 0x970cc88)
3 params, 4 slots, 0 upvalues, 3 locals, 0 constants, 0 functions
        1       [11]    GETTABLE        3 0 1            // precteni tabulky (parametr 0) s indexem (parametr 1)
        2       [11]    GETTABLE        3 3 2            // cteni hodnoty prvku z podtabulky
        3       [11]    RETURN          3 2              // vraceni prectene hodnoty prvku
        4       [12]    RETURN          0 1              // automaticky vkladany navrat z funkce

Bajtkód funkce writeItem() nejprve získá pomocí instrukce GETTABLE i-tou podtabulku a posléze do ní zapíše j-tý prvek instrukcí SETTABLE:

function <Test22.lua:19,21> (3 instructions at 0x970cf28)
4 params, 5 slots, 0 upvalues, 4 locals, 0 constants, 0 functions
        1       [20]    GETTABLE        4 0 1            // precteni tabulky (parametr 0) s indexem (parametr 1)
        2       [20]    SETTABLE        4 2 3            // primy zapis prvku do tabulky
        3       [21]    RETURN          0 1              // automaticky vkladany navrat z funkce

Získání sumy všech prvků dvourozměrné tabulky (tj. tabulky s podtabulkami) opět vyžaduje použití vnořených programových smyček typu for, což je ostatně patrné i z následujícího výpisu:

function <Test22.lua:28,36> (17 instructions at 0x970d148)
1 param, 11 slots, 0 upvalues, 10 locals, 2 constants, 0 functions
        1       [29]    LOADK           1 -1    ; 0      // registr cislo 1 obsahuje pocitanou sumu
        2       [30]    LOADK           2 -2    ; 1
        3       [30]    LEN             3 0              // delka tabulky (pocet podtabulek)
        4       [30]    LOADK           4 -2    ; 1      // vsechny parametry vnejsi smycky jsou nastaveny
        5       [30]    FORPREP         2 9     ; to 15  // zacatek vnejsi smycky for
        6       [31]    LOADK           6 -2    ; 1
        7       [31]    GETTABLE        7 0 5            // cteni podtabulky
        8       [31]    LEN             7 7              // a vypocet jeji delky
        9       [31]    LOADK           8 -2    ; 1      // vsechny parametry vnitrni smycky jsou nastaveny
        10      [31]    FORPREP         6 3     ; to 14  // zacatek vnitrni smycky for
        11      [32]    GETTABLE        10 0 5           // cteni podtabulky
        12      [32]    GETTABLE        10 10 9          // cteni prvku z podtabulky do registru 10
        13      [32]    ADD             1 1 10           // pricteni hodnoty k sume
        14      [31]    FORLOOP         6 -4    ; to 11  // iterace na konci vnitrni smycky
        15      [30]    FORLOOP         2 -10   ; to 6   // iterace na konci vnejsi smycky
        16      [35]    RETURN          1 2
        17      [36]    RETURN          0 1              // automaticky vkladany navrat z funkce

Opět je patrná kompaktnost bajtkódu Lua VM.

widgety

8. Přístup k prvkům seznamů a n-tic v Python VM

V programovacím jazyce Python se namísto polí či tabulek využívá dvojice složených datových typů. Jedná se o seznamy (list), které jsou modifikovatelné, tj. lze do nich vkládat nové prvky, měnit hodnoty prvků či prvky vyjímat. Seznamy jsou v tomto pojetí velmi flexibilním datovým typem, jenž může plnohodnotně nahradit další složené datové typy, jakými jsou zásobník (stack) či fronta (queue). Kromě seznamů lze v Pythonu používat i n-tice (tuple), které jsou na rozdíl od seznamů neměnitelné, tj. immutable. Díky této vlastnosti lze n-tice použít například ve funkci klíčů v asociativních polích atd. Jakým způsobem je realizován přístup k prvkům seznamů i n-tic si podrobněji řekneme v navazující části tohoto seriálu. Kromě toho si příště popíšeme i další „vychytávky“ Lua VM a Python VM, včetně využití již zmíněných asociativních polí, která jsou velmi flexibilním složeným datovým typem.

09. Repositář se zdrojovými kódy všech dnešních demonstračních příkladů

Všechny dnes popsané a využité demonstrační příklady (naprogramované v Javě, Lue i Pythonu) byly uloženy do Mercurial repositáře umístěného na adrese http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/. Odkazy na prozatím poslední verze těchto příkladů naleznete v tabulce pod tímto odstavcem:

10. Odkazy na Internetu

  1. Programming in Lua (first edition)
    http://www.lua.org/pil/contents.html
  2. Programming in Lua: Numeric for
    http://www.lua.org/pil/4.3.4.html
  3. Programming in Lua: break and return
    http://www.lua.org/pil/4.4.html
  4. Programming in Lua: Tables
    http://www.lua.org/pil/2.5.html
  5. Programming in Lua: Table Constructors
    http://www.lua.org/pil/3.6.html
  6. Programovací jazyk Lua
    http://palmknihy.cz/web/kni­ha/programovaci-jazyk-lua-12651.htm
  7. Lua: Tables Tutorial
    http://lua-users.org/wiki/TablesTutorial
  8. Lua: Control Structure Tutorial
    http://lua-users.org/wiki/ControlStruc­tureTutorial
  9. Lua Types Tutorial
    http://lua-users.org/wiki/LuaTypesTutorial
  10. Goto Statement in Lua
    http://lua-users.org/wiki/GotoStatement
  11. Python break, continue and pass Statements
    http://www.tutorialspoint­.com/python/python_loop_con­trol.htm
  12. For Loop (Wikipedia)
    http://en.wikipedia.org/wiki/For_loop
  13. Heinz Rutishauser
    http://en.wikipedia.org/wi­ki/Heinz_Rutishauser
  14. Parrot
    http://www.parrot.org/
  15. Parrot languages
    http://www.parrot.org/languages
  16. Parrot Primer
    http://docs.parrot.org/pa­rrot/latest/html/docs/intro­.pod.html
  17. Parrot Opcodes
    http://docs.parrot.org/pa­rrot/latest/html/ops.html
  18. Parrot VM
    http://en.wikibooks.org/wi­ki/Parrot_Virtual_Machine
  19. Parrot Assembly Language
    http://www.perl6.org/archi­ve/pdd/pdd06_pasm.html
  20. Parrot Reference: Chapter 11 – Perl 6 and Parrot Essentials
    http://oreilly.com/perl/excerpts/perl-6-and-parrot-essentials/parrot-reference.html
  21. Python Bytecode: Fun With Dis
    http://akaptur.github.io/blog/2013/08/14/pyt­hon-bytecode-fun-with-dis/
  22. Python's Innards: Hello, ceval.c!
    http://tech.blog.aknin.na­me/category/my-projects/pythons-innards/
  23. Byterun
    https://github.com/nedbat/byterun
  24. Python Byte Code Instructions
    http://document.ihg.uni-duisburg.de/Documentation/Pyt­hon/lib/node56.html
  25. Python Byte Code Instructions
    https://docs.python.org/3­.2/library/dis.html#python-bytecode-instructions
  26. Lua 5.2 sources
    http://www.lua.org/source/5.2/
  27. Lua 5.2 sources – lopcodes.h
    http://www.lua.org/source/5­.2/lopcodes.h.html
  28. Lua 5.2 sources – lopcodes.c
    http://www.lua.org/source/5­.2/lopcodes.c.html
  29. dis – Python module
    https://docs.python.org/2/li­brary/dis.html
  30. Comparison of Python virtual machines
    http://polishlinux.org/ap­ps/cli/comparison-of-python-virtual-machines/
  31. O-code
    http://en.wikipedia.org/wiki/O-code_machine
  32. BCPL
    http://en.wikipedia.org/wiki/BCPL
  33. The BCPL Cintcode System and Cintpos User Guide by Martin Richards
    http://www.cl.cam.ac.uk/u­sers/mr/bcplman.pdf
  34. Bootstrapping the BCPL Compiler using INTCODE
    http://www.gtoal.com/langu­ages/bcpl/amiga/bcpl/bootin­g.txt
  35. p-code machine
    http://en.wikipedia.org/wiki/P-code_machine
  36. ucsd-psystem-vm 0.11 (a portable virtual machine for the UCSD p-System)
    http://ucsd-psystem-vm.sourceforge.net/
  37. Introduction to Smalltalk bytecodes
    http://marianopeck.wordpres­s.com/2011/05/21/introduc­tion-to-smalltalk-bytecodes/
  38. Audio File Formats.
    http://sox.sourceforge.net/Au­dioFormats-11.html
  39. TestSounds.com: pure digital sounds to test your audio
    http://www.testsounds.com/
  40. Test Tones (20hz – 20khz)
    http://mdf1.tripod.com/test-tones.html
  41. WAV (Wikipedia)
    http://en.wikipedia.org/wiki/WAV
  42. WAVE PCM soundfile format
    https://ccrma.stanford.edu/cou­rses/422/projects/WaveFor­mat/
  43. Audio Interchange File Format
    http://en.wikipedia.org/wiki/Aiff
  44. Musical Instrument Digital Interface,
    http://en.wikipedia.org/wi­ki/Musical_Instrument_Digi­tal_Interface
  45. A MIDI Pedalboard Encode,
    http://www.pykett.org.uk/a_mi­di_pedalboard_encoder.htm
  46. MIDI Note Number, Frequency Table,
    http://tonalsoft.com/pub/news/pitch-bend.aspx
  47. Note names, MIDI numbers and frequencies,
    http://www.phys.unsw.edu.au­/jw/notes.html
  48. The MIDI Specification,
    http://www.gweep.net/~pre­fect/eng/reference/protocol/mi­dispec.html
  49. Essentials of the MIDI protocol,
    http://ccrma.stanford.edu/~cra­ig/articles/linuxmidi/mis­c/essenmidi.html
  50. General MIDI,
    http://en.wikipedia.org/wi­ki/General_MIDI
  51. Obecné MIDI (General MIDI),
    http://www-kiv.zcu.cz/~herout/html_sbo/mi­di/5.html
  52. Custom Chips: Paula
    http://www.amiga-hardware.com/showhardware­.cgi?HARDID=1460
  53. Big Book of Amiga Hardware
    http://www.amiga-resistance.info/bboahfaq/
  54. Amiga Hardware Database
    http://amiga.resource.cx/
  55. ExoticA
    http://www.exotica.org.uk/wi­ki/Main_Page
  56. The absolute basics of Amiga audio
    http://www.sufo.estates.co­.uk/amiga/amimus.html
  57. Wikipedia: Tracker
    http://en.wikipedia.org/wiki/Tracker
  58. Wikipedia: Trackers
    http://en.wikipedia.org/wiki/Trackers
  59. Ultimate Soundtracker
    http://en.wikipedia.org/wi­ki/Ultimate_Soundtracker
  60. Protracker
    http://en.wikipedia.org/wi­ki/ProTracker
  61. Impulse Tracker
    http://en.wikipedia.org/wi­ki/Impulse_Tracker
  62. Scream Tracker
    http://en.wikipedia.org/wi­ki/ScreamTracker
  63. MikMod for Java
    http://jmikmod.berlios.de/
  64. List of audio trackers
    http://en.wikipedia.org/wi­ki/List_of_audio_trackers
  65. Wikipedia: Module File
    http://en.wikipedia.org/wi­ki/Module_file
  66. Wikipedia: Chiptune
    http://en.wikipedia.org/wiki/Chiptune
  67. SDL_mixer 2.0
    http://www.libsdl.org/pro­jects/SDL_mixer/
  68. SDLJava: package sdljava.ttf
    http://sdljava.sourceforge­.net/docs/api/sdljava/ttf/pac­kage-summary.html#package_description
  69. SDLJava: class sdljava.ttf.SDLTTF
    http://sdljava.sourceforge­.net/docs/api/sdljava/ttf/SDLTTF­.html
  70. SDLJava: class sdljava.ttf.SDLTrueTypeFont
    http://sdljava.sourceforge­.net/docs/api/sdljava/ttf/SDLTru­eTypeFont.html
  71. SDL_ttf Documentation
    http://www.libsdl.org/pro­jects/SDL_ttf/docs/
  72. SDL_ttf 2.0 (není prozatím součástí SDLJava)
    http://www.libsdl.org/pro­jects/SDL_ttf/
  73. SDL_ttf doc
    http://www.libsdl.org/pro­jects/SDL_ttf/docs/SDL_ttf_fra­me.html
  74. SDL 1.2 Documentation: SDL_Surface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsurface.html
  75. SDL 1.2 Documentation: SDL_PixelFormat
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlpixelformat.html
  76. SDL 1.2 Documentation: SDL_LockSurface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdllocksurface.html
  77. SDL 1.2 Documentation: SDL_UnlockSurface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlunlocksurface.html
  78. SDL 1.2 Documentation: SDL_LoadBMP
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlloadbmp.html
  79. SDL 1.2 Documentation: SDL_SaveBMP
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsavebmp.html
  80. SDL 1.2 Documentation: SDL_BlitSurface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlblitsurface.html
  81. SDL 1.2 Documentation: SDL_VideoInfo
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlvideoinfo.html
  82. SDL 1.2 Documentation: SDL_GetVideoInfo
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlgetvideoinfo.html
  83. glDrawArrays
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawArrays­.xml
  84. glDrawElements
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawElemen­ts.xml
  85. glDrawArraysInstanced
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawArraysIn­stanced.xml
  86. glDrawElementsInstanced
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawElemen­tsInstanced.xml
  87. Root.cz: Seriál Grafická knihovna OpenGL
    http://www.root.cz/serialy/graficka-knihovna-opengl/
  88. Root.cz: Seriál Tvorba přenositelných grafických aplikací využívajících knihovnu GLUT
    http://www.root.cz/serialy/tvorba-prenositelnych-grafickych-aplikaci-vyuzivajicich-knihovnu-glut/
  89. Best Practices for Working with Vertex Data
    https://developer.apple.com/li­brary/ios/documentation/3ddra­wing/conceptual/opengles_pro­grammingguide/Techniquesfor­WorkingwithVertexData/Techni­quesforWorkingwithVertexDa­ta.html
  90. Class BufferStrategy
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/i­mage/BufferStrategy.html
  91. Class Graphics
    http://docs.oracle.com/ja­vase/1.5.0/docs/api/java/aw­t/Graphics.html
  92. Double Buffering and Page Flipping
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/doublebuf.html
  93. BufferStrategy and BufferCapabilities
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/bufferstrategy.html
  94. Java:Tutorials:Double Buffering
    http://content.gpwiki.org/in­dex.php/Java:Tutorials:Dou­ble_Buffering
  95. Double buffer in standard Java AWT
    http://www.codeproject.com/Ar­ticles/2136/Double-buffer-in-standard-Java-AWT
  96. Java 2D: Hardware Accelerating – Part 1 – Volatile Images
    http://www.javalobby.org/fo­rums/thread.jspa?threadID=16840&tstar­t=0
  97. Java 2D: Hardware Accelerating – Part 2 – Buffer Strategies
    http://www.javalobby.org/ja­va/forums/t16867.html
  98. How does paintComponent work?
    http://stackoverflow.com/qu­estions/15544549/how-does-paintcomponent-work
  99. A Swing Architecture Overview
    http://www.oracle.com/technet­work/java/architecture-142923.html
  100. Class javax.swing.JComponent
    http://docs.oracle.com/ja­vase/6/docs/api/javax/swin­g/JComponent.html
  101. Class java.awt.Component
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.html
  102. Class java.awt.Component.BltBufferStrategy
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.BltBufferStrategy.html
  103. Class java.awt.Component.FlipBufferStrategy
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.FlipBufferStrategy­.html
  104. Metoda java.awt.Component.isDoubleBuffered()
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.html#isDoubleBuffe­red()
  105. Metoda javax.swing.JComponent.is­DoubleBuffered()
    http://docs.oracle.com/ja­vase/6/docs/api/javax/swin­g/JComponent.html#isDouble­Buffered()
  106. Metoda javax.swing.JComponent.set­DoubleBuffered()
    http://docs.oracle.com/ja­vase/6/docs/api/javax/swin­g/JComponent.html#setDouble­Buffered(boolean)
  107. Javadoc – třída GraphicsDevice
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Grap­hicsDevice.html
  108. Javadoc – třída GraphicsEnvironment
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Grap­hicsEnvironment.html
  109. Javadoc – třída GraphicsConfiguration
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Grap­hicsConfiguration.html
  110. Javadoc – třída DisplayMode
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Dis­playMode.html
  111. Lesson: Full-Screen Exclusive Mode API
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/
  112. Full-Screen Exclusive Mode
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/exclusivemode.html
  113. Display Mode
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/displaymode.html
  114. Using the Full-Screen Exclusive Mode API in Java
    http://www.developer.com/ja­va/other/article.php/3609776/U­sing-the-Full-Screen-Exclusive-Mode-API-in-Java.htm
  115. Java quick guide: JVM Instruction Set (tabulka všech instrukcí JVM)
    http://www.mobilefish.com/tu­torials/java/java_quickgu­ide_jvm_instruction_set.html
  116. The JVM Instruction Set
    http://mpdeboer.home.xs4a­ll.nl/scriptie/node14.html
  117. MultiMedia eXtensions
    http://softpixel.com/~cwrig­ht/programming/simd/mmx.phpi
  118. SSE (Streaming SIMD Extentions)
    http://www.songho.ca/misc/sse/sse­.html
  119. Timothy A. Chagnon: SSE and SSE2
    http://www.cs.drexel.edu/~tc365/mpi-wht/sse.pdf
  120. Intel corporation: Extending the Worldr's Most Popular Processor Architecture
    http://download.intel.com/techno­logy/architecture/new-instructions-paper.pdf
  121. SIMD architectures:
    http://arstechnica.com/ol­d/content/2000/03/simd.ar­s/
  122. GC safe-point (or safepoint) and safe-region
    http://xiao-feng.blogspot.cz/2008/01/gc-safe-point-and-safe-region.html
  123. Safepoints in HotSpot JVM
    http://blog.ragozin.info/2012/10/sa­fepoints-in-hotspot-jvm.html
  124. Java theory and practice: Synchronization optimizations in Mustang
    http://www.ibm.com/develo­perworks/java/library/j-jtp10185/
  125. How to build hsdis
    http://hg.openjdk.java.net/jdk7/hot­spot/hotspot/file/tip/src/sha­re/tools/hsdis/README
  126. Java SE 6 Performance White Paper
    http://www.oracle.com/technet­work/java/6-performance-137236.html
  127. Lukas Stadler's Blog
    http://classparser.blogspot­.cz/2010/03/hsdis-i386dll.html
  128. How to build hsdis-amd64.dll and hsdis-i386.dll on Windows
    http://dropzone.nfshost.com/hsdis.htm
  129. PrintAssembly
    https://wikis.oracle.com/dis­play/HotSpotInternals/Prin­tAssembly
  130. The Java Virtual Machine Specification: 3.14. Synchronization
    http://docs.oracle.com/ja­vase/specs/jvms/se7/html/jvms-3.html#jvms-3.14
  131. The Java Virtual Machine Specification: 8.3.1.4. volatile Fields
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-8.html#jls-8.3.1.4
  132. The Java Virtual Machine Specification: 17.4. Memory Model
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-17.html#jls-17.4
  133. The Java Virtual Machine Specification: 17.7. Non-atomic Treatment of double and long
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-17.html#jls-17.7
  134. Open Source ByteCode Libraries in Java
    http://java-source.net/open-source/bytecode-libraries
  135. ASM Home page
    http://asm.ow2.org/
  136. Seznam nástrojů využívajících projekt ASM
    http://asm.ow2.org/users.html
  137. ObjectWeb ASM (Wikipedia)
    http://en.wikipedia.org/wi­ki/ObjectWeb_ASM
  138. Java Bytecode BCEL vs ASM
    http://james.onegoodcooki­e.com/2005/10/26/java-bytecode-bcel-vs-asm/
  139. BCEL Home page
    http://commons.apache.org/bcel/
  140. Byte Code Engineering Library (před verzí 5.0)
    http://bcel.sourceforge.net/
  141. Byte Code Engineering Library (verze >= 5.0)
    http://commons.apache.org/pro­per/commons-bcel/
  142. BCEL Manual
    http://commons.apache.org/bcel/ma­nual.html
  143. Byte Code Engineering Library (Wikipedia)
    http://en.wikipedia.org/wiki/BCEL
  144. BCEL Tutorial
    http://www.smfsupport.com/sup­port/java/bcel-tutorial!/
  145. Bytecode Engineering
    http://book.chinaunix.net/spe­cial/ebook/Core_Java2_Volu­me2AF/0131118269/ch13lev1sec6­.html
  146. Bytecode Outline plugin for Eclipse (screenshoty + info)
    http://asm.ow2.org/eclipse/index.html
  147. Javassist
    http://www.jboss.org/javassist/
  148. Byteman
    http://www.jboss.org/byteman
  149. Java programming dynamics, Part 7: Bytecode engineering with BCEL
    http://www.ibm.com/develo­perworks/java/library/j-dyn0414/
  150. The JavaTM Virtual Machine Specification, Second Edition
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/VMSpec­TOC.doc.html
  151. The class File Format
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/Clas­sFile.doc.html
  152. javap – The Java Class File Disassembler
    http://docs.oracle.com/ja­vase/1.4.2/docs/tooldocs/win­dows/javap.html
  153. javap-java-1.6.0-openjdk(1) – Linux man page
    http://linux.die.net/man/1/javap-java-1.6.0-openjdk
  154. Using javap
    http://www.idevelopment.in­fo/data/Programming/java/mis­cellaneous_java/Using_javap­.html
  155. Examine class files with the javap command
    http://www.techrepublic.com/ar­ticle/examine-class-files-with-the-javap-command/5815354
  156. aspectj (Eclipse)
    http://www.eclipse.org/aspectj/
  157. Aspect-oriented programming (Wikipedia)
    http://en.wikipedia.org/wi­ki/Aspect_oriented_program­ming
  158. AspectJ (Wikipedia)
    http://en.wikipedia.org/wiki/AspectJ
  159. EMMA: a free Java code coverage tool
    http://emma.sourceforge.net/
  160. Cobertura
    http://cobertura.sourceforge.net/
  161. jclasslib bytecode viewer
    http://www.ej-technologies.com/products/jclas­slib/overview.html
Našli jste v článku chybu?
120na80.cz: Pálení žáhy: která jídla ne a co nás uzdraví?

Pálení žáhy: která jídla ne a co nás uzdraví?

Root.cz: Hořící telefon Samsung Note 7 zapálil auto

Hořící telefon Samsung Note 7 zapálil auto

Lupa.cz: Cimrman má hry na YouTube i vlastní doodle

Cimrman má hry na YouTube i vlastní doodle

Vitalia.cz: Tradiční čínská medicína a rakovina

Tradiční čínská medicína a rakovina

Měšec.cz: TEST: Vyzkoušeli jsme pražské taxikáře

TEST: Vyzkoušeli jsme pražské taxikáře

Lupa.cz: Jak se prodává firma za miliardu?

Jak se prodává firma za miliardu?

DigiZone.cz: Ginx TV: pořad o počítačových hráčích

Ginx TV: pořad o počítačových hráčích

DigiZone.cz: DVB-T2 ověřeno: seznam TV zveřejněn

DVB-T2 ověřeno: seznam TV zveřejněn

DigiZone.cz: Samsung EVO-S: novinka pro Skylink

Samsung EVO-S: novinka pro Skylink

Vitalia.cz: Tahák, jak vyzrát nad zápachem z úst

Tahák, jak vyzrát nad zápachem z úst

Lupa.cz: Patička e-mailu závazná jako vlastnoruční podpis?

Patička e-mailu závazná jako vlastnoruční podpis?

Vitalia.cz: dTest odhalil ten nejlepší kečup

dTest odhalil ten nejlepší kečup

Vitalia.cz: Tohle jsou nejlepší česká piva podle odborníků

Tohle jsou nejlepší česká piva podle odborníků

Podnikatel.cz: Letáky? Lidi zuří, ale ony stále fungují

Letáky? Lidi zuří, ale ony stále fungují

Podnikatel.cz: Udělali jsme velkou chybu, napsal Čupr

Udělali jsme velkou chybu, napsal Čupr

Vitalia.cz: Pryč se zastaralým stravováním ve školách

Pryč se zastaralým stravováním ve školách

DigiZone.cz: Digi Slovakia zařazuje stanice SPI

Digi Slovakia zařazuje stanice SPI

Vitalia.cz: Muž, který miluje příliš. Ženám neimponuje

Muž, který miluje příliš. Ženám neimponuje

DigiZone.cz: Technisat připravuje trojici DAB

Technisat připravuje trojici DAB

Podnikatel.cz: Instalatér, malíř a elektrikář. "Vymřou"?

Instalatér, malíř a elektrikář. "Vymřou"?