Hlavní navigace

Pohled pod kapotu JVM (11.část - instrukce pro tvorbu polí a přístup k prvkům polí)

21. 2. 2012
Doba čtení: 18 minut

Sdílet

Počet již popsaných instrukcí virtuálního stroje Javy se nám utěšeně zvětšuje. V dnešní části seriálu o programovacím jazyce Java i o JVM se zaměříme na popis dalších dvaceti instrukcí. Bude se jednat o instrukce používané pro vytváření polí různých typů a pro přístup k prvkům těchto polí.

Obsah

1. Instrukce newarray

2. První demonstrační příklad – vytvoření jednorozměrných polí s využitím instrukce newarray

3. Vytvoření pole objektů pomocí instrukce anewarray

4. První demonstrační příklad – vytvoření jednorozměrných polí s využitím instrukce anewarray

5. Pole s více dimenzemi a instrukce multianewarray

6. Třetí demonstrační příklad – vytvoření polí o více dimenzích

7. Přístup k prvkům pole

8. Čtvrtý demonstrační příklad – přístup k prvkům jednorozměrných po­lí

9. Odkazy na Internetu

1. Instrukce newarray

V předchozí části seriálu o programovacím jazyce Java i o vlastnostech virtuálního stroje Javy jsme se zabývali instrukcemi využívanými pro vytváření objektů, přístup ke statickým i nestatickým atributům a taktéž k instrukcím, pomocí nichž se volají statické metody, virtuální metody i metody speciální (zejména konstruktory). Ještě nám však zbývá popis instrukcí používaných při práci se druhým v Javě existujícím referenčním datovým typem – jedná se o pole. Připomeňme si, že objekty jsou společně s poli považovány za takzvané referenční datové typy, z toho důvodu, že se v Javě předávají ve formě referencí a nikoli přímo hodnoty. Zatímco objekty se vytváří pomocí instrukce new a pro přístup k jejich atributům se používají instrukce getfield a putfield, je situace v případě polí odlišná, protože se pro pole používá dvacet specializovaných instrukcí sloužících jak pro vytvoření pole, tak i pro přístup k jeho prvkům, popř. pro zjištění délky pole.

První instrukcí, se kterou se dnes seznámíme, je instrukce nazvaná newarray. Pravděpodobně uhodnete, k čemu tato instrukce slouží – lze ji použít pro vytvoření pole dané délky, ovšem pouze v tom případě, pokud má pole obsahovat prvky některého z primitivních datových typů, tj. pravdivostní hodnoty, znaky, celá čísla či čísla s plovoucí řádovou čárkou. Jinými slovy to znamená, že tuto instrukci nelze použít například pro vytvoření pole objektů. Formát instrukce newarray je vypsán v následující tabulce:

# Instrukce Opkód Operandy Prováděná operace
1 newarray 0×BC arraytype Vytvoří nové pole s prvky primitivního datového typu

Instrukce newarray očekává, že na vrcholu zásobníku operandů (TOS) bude uložena hodnota typu int udávající velikost pole. Tato hodnota je ze zásobníku v průběhu vytváření pole odstraněna a namísto ní se na vrchol zásobníku operandů uloží reference na právě vytvořené pole. Ještě nám zbývá popsat operand instrukce newarray nazvaný arraytype. Jde o jednobajtový operand, jehož hodnota určuje typ prvků vytvářeného pole. Jak jsme si již řekli v předchozím odstavci, může se pomocí instrukce newarray vytvořit pole složené z pravdivostních hodnot, znaků, celých čísel či čísel s plovoucí řádovou čárkou (ve všech případech se jedná o primitivní datové typy):

Arraytype Typ prvků pole
4 boolean
5 char
6 float
7 double
8 byte
9 short
10 int
11 long

2. První demonstrační příklad – vytvoření jednorozměrných polí s využitím instrukce newarray

Způsob použití instrukce newarray si ukážeme na jednoduchém demonstračním příkladu, v jehož třídě je deklarována jediná (statická) metoda, po jejímž zavolání se vytvoří osm lokálních proměnných, přičemž každá proměnná je referencí na pole zadané délky. Zdrojový kód tohoto demonstračního příkladu je velmi jednoduchý:

class CreateArrayTest {
 
    static void createArrays(int size) {
        boolean[] booleanArray    = new boolean[size];
        char[]    charArray       = new char[size];
        byte[]    byteArray       = new byte[size];
        short[]   shortArray      = new short[size];
        int[]     intArray        = new int[size];
        long[]    longArray       = new long[size];
        float[]   floatArray      = new float[size];
        double[]  doubleegerArray = new double[size];
    }
 
}

Překladač javac vygeneruje bajtkód, v němž jsou použity instrukce pro vytvoření všech osmi lokálních proměnných, i když ve skutečnosti nejsou tyto proměnné nikde použity. Z výpisu je patrné, že každé pole je vytvořeno s využitím pouze třech instrukcí – uložení počtu prvků vytvářeného pole na zásobník, vlastní vytvoření (konstrukce) pole a nakonec uložení reference do lokální proměnné:

static void createArrays(int);
  Code:
   0:     iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   1:     newarray boolean   // vytvoření pole s prvky typu boolean
   3:     astore_1           // reference na pole se uloží do lokální proměnné
 
   4:     iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   5:     newarray char      // vytvoření pole s prvky typu char
   7:     astore_2           // reference na pole se uloží do lokální proměnné
 
   8:     iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   9:     newarray byte      // vytvoření pole s prvky typu byte
   11:    astore_3           // reference na pole se uloží do lokální proměnné
 
   12:    iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   13:    newarray short     // vytvoření pole s prvky typu short
   15:    astore    4        // reference na pole se uloží do lokální proměnné
 
   17:    iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   18:    newarray int       // vytvoření pole s prvky typu int
   20:    astore    5        // reference na pole se uloží do lokální proměnné
 
   22:    iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   23:    newarray long      // vytvoření pole s prvky typu long
   25:    astore    6        // reference na pole se uloží do lokální proměnné
 
   27:    iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   28:    newarray float     // vytvoření pole s prvky typu float
   30:    astore    7        // reference na pole se uloží do lokální proměnné
 
   32:    iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   33:    newarray double    // vytvoření pole s prvky typu double
   35:    astore    8        // reference na pole se uloží do lokální proměnné
 
   37:    return             // návrat z metody

3. Vytvoření pole objektů pomocí instrukce anewarray

Další instrukcí používanou při vytváření polí je instrukce nazvaná anewarray (na začátku jména této instrukce se nachází znak „a“). Tato instrukce se používá pro vytvoření pole, jehož prvky jsou objekty, a to objekty libovolného (specifikovaného) typu. Zatímco se u instrukce newarray popsané v první kapitole specifikoval typ prvků pole pomocí hodnoty bajtu uloženého ihned za operačním kódem instrukce, je nutné u instrukce anewarray použít celé jméno třídy, rozhraní či výčtového typu (udávající typ prvků pole). Toto jméno třídy je, jak pravděpodobně již tušíte, uložené v constant poolu, takže se za operačním kódem instrukce anewarray nachází dvojice bajtů představujících index záznamu v constant poolu. Chování obou zmíněných instrukcí však zůstává stejné – z vrcholu zásobníku operandů se vyzvedne hodnota typu int představující velikost pole, pole daného typu se vytvoří a následně se na zásobník operandů uloží reference na vytvořený objekt (v případě polí objektů samozřejmě nejsou tyto objekty vytvořeny a pole obsahuje hodnoty null):

# Instrukce Opkód Operandy Prováděná operace
1 anewarray 0×BD highbyte, lowbyte Vytvoří nové pole objektů

Operandy highbyte a lowbyte tvoří dohromady šestnáctibitový index do constant poolu. Záznam uložený na tomto indexu musí být typu ClassName a může se jednat buď o název běžné třídy nebo o název rozhraní či dokonce o název výčtového typu.

4. První demonstrační příklad – vytvoření jednorozměrných polí s využitím instrukce anewarray

Způsob využití instrukce anewarray si opět ukážeme na jednoduchém demonstračním příkladu. V tomto příkladu je v metodě createObjectA­rrays vytvořeno celkem pět polí. První tři pole mohou obsahovat prvky typu Object, String a Color, popř. potomky těchto tříd. Zajímavé je čtvrté pole, které může obsahovat jakýkoli typ objektu, jehož třída implementuje rozhraní Comparable, tj. může se například jednat o řetězce, obalové objekty primitivních datových typů (Integer, Double…), data (Data), objekty typu BigInteger a BigDecimal atd. Páté pole může obsahovat prvky výčtového typu WeekDay:

import java.awt.Color;
 
enum WeekDay {
    MON, TUE, WED, THU, FRI, SAT, SUN
}
 
class CreateObjectArrayTest {
 
    static void createObjectArrays(int size) {
        Object[]     objects  = new Object[size];
        String[]     strings  = new String[size];
        Color[]      colors   = new Color[size];
        Comparable[] xyzzy    = new Comparable[size];
        WeekDay[]    weekDays = new WeekDay[size];
    }
 
}

Podívejme se nejdříve na obsah constant poolu. Položky, které nás budou zajímat, jsou označeny hvězdičkami:

const #1 = Method       #2.#16; //  java/lang/Object."<init>":()V
***************************************************************
const #2 = class        #17;    //  java/lang/Object
const #3 = class        #18;    //  java/lang/String
const #4 = class        #19;    //  java/awt/Color
const #5 = class        #20;    //  java/lang/Comparable
const #6 = class        #21;    //  WeekDay
***************************************************************
const #7 = class        #22;    //  CreateObjectArrayTest
const #8 = Asciz        <init>;
const #9 = Asciz        ()V;
const #10 = Asciz       Code;
const #11 = Asciz       LineNumberTable;
const #12 = Asciz       createObjectArrays;
const #13 = Asciz       (I)V;
const #14 = Asciz       SourceFile;
const #15 = Asciz       Test1.java;
const #16 = NameAndType #8:#9;//  "<init>":()V
const #17 = Asciz       java/lang/Object;
const #18 = Asciz       java/lang/String;
const #19 = Asciz       java/awt/Color;
const #20 = Asciz       java/lang/Comparable;
const #21 = Asciz       WeekDay;
const #22 = Asciz       CreateObjectArrayTest;

Nyní se již můžeme podívat na bajtkód metody createObjectA­rrays vygenerovaný překladačem javac:

static void createObjectArrays(int);
  Code:
   0:     iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   1:     anewarray #2;      // vytvoření pole s prvky typu java/lang/Object
   4:     astore_1           // reference na pole se uloží do lokální proměnné
 
   5:     iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   6:     anewarray #3;      // vytvoření pole s prvky typu java/lang/String
   9:     astore_2           // reference na pole se uloží do lokální proměnné
 
   10:    iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   11:    anewarray #4;      // vytvoření pole s prvky typu java/awt/Color
   14:    astore_3           // reference na pole se uloží do lokální proměnné
 
   15:    iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   16:    anewarray #5;      // vytvoření pole s prvky typu java/lang/Comparable
   19:    astore    4        // reference na pole se uloží do lokální proměnné
 
   21:    iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   22:    anewarray #6;      // vytvoření pole s prvky typu WeekDay
   25:    astore    5        // reference na pole se uloží do lokální proměnné
 
   27:    return             // návrat z metody

5. Pole s více dimenzemi a instrukce multianewarray

Obě dnes popsané instrukce newarray a anewarray mají jedno poměrně zásadní omezení – jsou totiž využitelné pouze pro vytvoření jednorozměrných polí. Pokud se však ve zdrojovém kódu vyskytuje programová konstrukce pro vytvoření polí o více dimenzích, vygeneruje překladač jinou instrukci nazvanou multianewarray. Jedná se, společně s již popsanými instrukcemi tableswitch a lookupswich o jednu z nejsložitějších instrukcí, kterou můžeme v bajtkódu najít, protože se za jejím operačním kódem nachází hned tři doplňkové bajty. První dva bajty tvoří společně index do constant poolu, v němž se nachází záznam o typu prvků uložených v poli (většinou se jedná o typ odpovídající poli, jehož počet dimenzí odpovídá počtu dimenzí pole vytvářeného). Třetí bajt uložený za operačním kódem instrukce multianewarray obsahuje počet dimenzí vytvářeného pole, z čehož mimochodem vyplývá, že pole může mít „pouze“ 256 dimenzí ;-). Před zavoláním této instrukce se musí na zásobník operandů uložit rozměry vytvářeného pole, přičemž počet rozměrů uložených na zásobníku musí odpovídat (vcelku logicky) počtu dimenzí, tj. hodnotě uložené ve třetím bajtu za operačním kódem instrukce multianewarray.

# Instrukce Opkód Operandy Prováděná operace
1 multianewarray 0×C5 highbyte, lowbyte, dimensions Vytvoří vícedimenzionální pole o dimensions dimenzích

Operandy highbyte a lowbyte opět společně tvoří šestnáctibitový index do constant poolu. Pokud se například vytváří dvourozměrné pole s prvky typu String, bude v constant poolu uložen záznam typu ClassName obsahující hodnotu „[[Ljava/lang/Strin­g;“. Podobné to bude i v případě vícerozměrného pole s prvky typu celé číslo či pravdivostní hodnota.

6. Třetí demonstrační příklad – vytvoření polí o více dimenzích

Dnešní třetí demonstrační příklad je poněkud složitější než předchozí dva příklady. V příkladu jsou deklarovány dvě statické metody, přičemž v první metodě se vytvoří lokální proměnná obsahující dvourozměrné pole s prvky typu int, zatímco druhá metoda vytvoří a vrátí trojrozměrné pole, do něhož se mohou ukládat instance třídy Color (toto trojrozměrné pole je možné například použít při volume renderingu). Následuje výpis zdrojového kódu třetího demonstračního příkladu:

import java.awt.Color;
 
class MultidimensionalArraysTest {
 
    static void createMatrix(int dim1, int dim2) {
        int[][] matrix = new int[dim1][dim2];
    }
 
    static Color[][][] createVolume(int dim1, int dim2, int dim3) {
        return new Color[dim1][dim2][dim3];
    }
 
}

Podobně jako u předchozího demonstračního příkladu, kde jsme si vysvětlovali způsob použití instrukce anewarray, i nyní bude vhodné se nejdříve podívat na obsah constant poolu uloženého v bajtkódu. Záznamy, které nás zajímají, jsou zvýrazněny pomocí hvězdiček:

const #1 = Method       #5.#16; //  java/lang/Object."<init>":()V
***************************************************************
const #2 = class        #17;    //  "[[I"
const #3 = class        #18;    //  "[[[Ljava/awt/Color;"
***************************************************************
const #4 = class        #19;    //  MultidimensionalArraysTest
const #5 = class        #20;    //  java/lang/Object
const #6 = Asciz        <init>;
const #7 = Asciz        ()V;
const #8 = Asciz        Code;
const #9 = Asciz        LineNumberTable;
const #10 = Asciz       createMatrix;
const #11 = Asciz       (II)V;
const #12 = Asciz       createVolume;
const #13 = Asciz       (III)[[[Ljava/awt/Color;;
const #14 = Asciz       SourceFile;
const #15 = Asciz       Test1.java;
const #16 = NameAndType #6:#7;//  "<init>":()V
const #17 = Asciz       [[I;
const #18 = Asciz       [[[Ljava/awt/Color;;
const #19 = Asciz       MultidimensionalArraysTest;
const #20 = Asciz       java/lang/Object;

Následuje dissasemblovaný kód metody createMatrix. Povšimněte si, že nejdříve jsou na zásobník operandů uloženy dvě hodnoty typu int představující rozměry pole a následně je zavolána instrukce multianewarray s dvojicí parametrů: první parametr (dvoubajtový) odkazuje na záznam v constant poolu s indexem 2 a druhý parametr obsahuje počet dimenzí vytvářeného pole. Typ pole uložený na constant poolu přitom odpovídá zadanému počtu dimenzí, což lze v tomto případě jednoduše zjistit z počtu levých hranatých závorek [, jejichž význam jsme si již v minulosti vysvětlili:

static void createMatrix(int, int);
  Code:
   0:   iload_0                 // na zásobník operandů uložit první dimenzi pole
   1:   iload_1                 // na zásobník operandů uložit druhou dimenzi pole
   2:   multianewarray  #2,  2; // class "[[I" - pole polí prvků typu int
                                // první dvojka je index do constant poolu
                                // druhá dvojka je počet dimenzí vytvářeného pole
   6:   astore_2                // uložit referenci na vytvořené pole do lokální proměnné
   7:   return                  // návrat z metody

Metoda createVolume používá taktéž instrukci multianewarray, ovšem nyní je tato instrukce použita pro vytvoření pole, v němž mají být uloženy reference na objekty typu Color. Výsledné pole je použito jako návratová hodnota metody:

static java.awt.Color[][][] createVolume(int, int, int);
  Code:
   0:   iload_0                 // na zásobník operandů uložit první dimenzi pole
   1:   iload_1                 // na zásobník operandů uložit druhou dimenzi pole
   2:   iload_2                 // na zásobník operandů uložit třetí dimenzi pole
   3:   multianewarray  #3,  3; // class "[[[Ljava/awt/Color;"
                                // první trojka je index do constant poolu
                                // druhá trojka je počet dimenzí vytvářeného pole
   7:   areturn                 // reference vytvořeného pole je návratovou hodnotou metody

7. Přístup k prvkům pole

Nyní již umíme vytvořit jednorozměrná i vícerozměrná pole, která mohou obsahovat prvky různých datových typů. Mezi další operace týkající se polí 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:

root_podpora

# 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[]

8. Čtvrtý demonstrační příklad – přístup k prvkům jednorozměrných po­lí

Ještě se musíme zmínit o poslední instrukci používané při práci s poli. Tato instrukce se jmenuje arraylength (operační kód 0×BE) a slouží pro zjištění délky pole, jehož reference je uložena na zásobníku operandů. Se znalostí této instrukce si již můžeme ukázat složitější příklad, v jehož metodě se do pole celých čísel uloží prvních třicet prvků Fibonacciho posloupnosti:

class FibSeq {
 
    static void calcFibSeq() {
        int[] sequence = new int[30];
        sequence[0] = 1;
        sequence[1] = 1;
 
        for (int i = 2; i < sequence.length; i++) {
            sequence[i] = sequence[i-2] + sequence[i-1];
        }
    }
 
}

Vzhledem k tomu, že se již jedná o netriviální příklad, tak nás asi nepřekvapí, že i vygenerovaný bajtkód je poměrně složitý a má délku celých 42 bajtů:

static void calcFibSeq();
  Code:
   0:   bipush  30              // počet prvků vytvářeného pole
   2:   newarray int            // vytvoření pole o třiceti prvcích typu int
   4:   astore_0                // uložení reference pole do první lokální proměnné
 
   5:   aload_0                 // \
   6:   iconst_0                //  \ sequence[0] = 1;
   7:   iconst_1                //  /
   8:   iastore                 // /
 
   9:   aload_0                 // \
   10:  iconst_1                //  \ sequence[1] = 1;
   11:  iconst_1                //  /
   12:  iastore                 // /
 
   13:  iconst_2                // \ int i = 2;
   14:  istore_1                // /
 
   15:  iload_1                 // hodnota čítače i na zásobník
   16:  aload_0                 // \ sequence.length;
   17:  arraylength             // /
   18:  if_icmpge   41          // if (i > sequence.length) konec smyčky
 
   21:  aload_0                 // \ příprava pro příkaz sequence[i] = něco
   22:  iload_1                 // /
 
   23:  aload_0                 // \
   24:  iload_1                 //  \
   25:  iconst_2                //   > prvek sequence[i-2] uložit na zásobník
   26:  isub                    //  /
   27:  iaload                  // /
 
   28:  aload_0                 // \
   29:  iload_1                 //  \
   30:  iconst_1                //   > prvek sequence[i-1] uložit na zásobník
   31:  isub                    //  /
   32:  iaload                  // /
 
   33:  iadd                    // sečíst oba prvky
   34:  iastore                 // dokončení příkazu začínajícího na adrese 21
 
   35:  iinc    1, 1            // i++
   38:  goto    15              // opakování smyčky
 
   41:  return                  // návrat z metody

9. Odkazy na Internetu

  1. Java quick guide: JVM Instruction Set (tabulka všech instrukcí JVM)
    http://www.mo­bilefish.com/tu­torials/java/ja­va_quickguide_jvm_in­struction_set­.html
  2. The JVM Instruction Set
    http://mpdebo­er.home.xs4all­.nl/scriptie/no­de14.html
  3. Control Flow in the Java Virtual Machine
    http://www.ar­tima.com/under­thehood/flowP­.html
  4. Root.cz: Využití komprimovaných ukazatelů na objekty v JVM
    http://www.ro­ot.cz/clanky/vy­uziti-komprimovanych-ukazatelu-na-objekty-v-nbsp-jvm/
  5. Root.cz: JamVM aneb alternativa k HotSpotu nejenom pro embedded zařízení a chytré telefony
    http://www.ro­ot.cz/clanky/jam­vm-aneb-alternativa-k-hotspotu-nejenom-pro-embedded-zarizeni-tablety-a-chytre-telefony/
  6. The JavaTM Virtual Machine Specification, Second Edition
    http://java.sun­.com/docs/book­s/jvms/second_e­dition/html/VMSp­ecTOC.doc.html
  7. The class File Format
    http://java.sun­.com/docs/book­s/jvms/second_e­dition/html/Clas­sFile.doc.html
  8. javap – The Java Class File Disassembler
    http://docs.o­racle.com/java­se/1.4.2/docs/to­oldocs/window­s/javap.html
  9. javap-java-1.6.0-openjdk(1) – Linux man page
    http://linux.di­e.net/man/1/j­avap-java-1.6.0-openjdk
  10. Using javap
    http://www.ide­velopment.info/da­ta/Programmin­g/java/miscella­neous_java/Usin­g_javap.html
  11. Examine class files with the javap command
    http://www.techre­public.com/ar­ticle/examine-class-files-with-the-javap-command/5815354
  12. BCEL Home page
    http://common­s.apache.org/bcel/
  13. BCEL Manual
    http://common­s.apache.org/bcel/ma­nual.html
  14. Byte Code Engineering Library (Wikipedia)
    http://en.wiki­pedia.org/wiki/BCEL
  15. Java programming dynamics, Part 7: Bytecode engineering with BCEL
    http://www.ib­m.com/developer­works/java/li­brary/j-dyn0414/
  16. Bytecode Engineering
    http://book.chi­naunix.net/spe­cial/ebook/Co­re_Java2_Volu­me2AF/0131118269/ch13lev­1sec6.html
  17. BCEL Tutorial
    http://www.smfsup­port.com/suppor­t/java/bcel-tutorial!/
  18. ASM Home page
    http://asm.ow2­.org/
  19. Seznam nástrojů využívajících projekt ASM
    http://asm.ow2­.org/users.html
  20. ObjectWeb ASM (Wikipedia)
    http://en.wiki­pedia.org/wiki/Ob­jectWeb_ASM
  21. Java Bytecode BCEL vs ASM
    http://james.o­negoodcookie.com/2005/10­/26/java-bytecode-bcel-vs-asm/
  22. Bytecode Outline plugin for Eclipse (screenshoty + info)
    http://asm.ow2­.org/eclipse/in­dex.html
  23. aspectj (Eclipse)
    http://www.eclip­se.org/aspectj/
  24. Aspect-oriented programming (Wikipedia)
    http://en.wiki­pedia.org/wiki/As­pect_oriented_pro­gramming
  25. AspectJ (Wikipedia)
    http://en.wiki­pedia.org/wiki/As­pectJ
  26. EMMA: a free Java code coverage tool
    http://emma.sou­rceforge.net/
  27. Cobertura
    http://cobertu­ra.sourceforge­.net/
  28. FindBugs
    http://findbug­s.sourceforge­.net/
  29. GNU Classpath
    www.gnu.org/s/clas­spath/
  30. Java VMs Compared
    http://bugblog­ger.com/java-vms-compared-160/
  31. JSRs: Java Specification Requests – JSR 223: Scripting for the Java Platform
    http://www.jcp­.org/en/jsr/de­tail?id=223
  32. Scripting for the Java Platform
    http://java.sun­.com/developer/techni­calArticles/J2SE/Des­ktop/scriptin­g/
  33. Scripting for the Java Platform (Wikipedia)
    http://en.wiki­pedia.org/wiki/Scrip­ting_for_the_Ja­va_Platform
  34. Java Community Process
    http://en.wiki­pedia.org/wiki/Ja­va_Specificati­on_Request
  35. Java HotSpot VM Options
    http://www.ora­cle.com/technet­work/java/java­se/tech/vmopti­ons-jsp-140102.html
  36. Great Computer Language Shootout
    http://c2.com/cgi/wi­ki?GreatCompu­terLanguageSho­otout
  37. Java performance
    http://en.wiki­pedia.org/wiki/Ja­va_performance
  38. Trying the prototype
    http://mail.o­penjdk.java.net/pi­permail/lambda-dev/2010-August/002179.html
  39. Better closures (for Java)
    http://blogs.sun­.com/jrose/en­try/better_clo­sures
  40. Lambdas in Java: An In-Depth Analysis
    http://www.in­foq.com/articles/lam­bdas-java-analysis
  41. Class ReflectiveOpe­rationExcepti­on
    http://downlo­ad.java.net/jdk7/doc­s/api/java/lan­g/ReflectiveO­perationExcep­tion.html
  42. Proposal: Indexing access syntax for Lists and Maps
    http://mail.o­penjdk.java.net/pi­permail/coin-dev/2009-March/001108.html
  43. Proposal: Elvis and Other Null-Safe Operators
    http://mail.o­penjdk.java.net/pi­permail/coin-dev/2009-March/000047.html
  44. Java 7 : Oracle pushes a first version of closures
    http://www.bap­tiste-wicht.com/2010/05­/oracle-pushes-a-first-version-of-closures/
  45. Groovy: An agile dynamic language for the Java Platform
    http://groovy­.codehaus.org/O­perators
  46. Better Strategies for Null Handling in Java
    http://www.sli­deshare.net/Step­han.Schmidt/bet­ter-strategies-for-null-handling-in-java
  47. Control Flow in the Java Virtual Machine
    http://www.ar­tima.com/under­thehood/flowP­.html
  48. Java Virtual Machine
    http://en.wiki­pedia.org/wiki/Ja­va_virtual_machi­ne
  49. ==, .equals(), compareTo(), and compare()
    http://leepoin­t.net/notes-java/data/expres­sions/22compa­reobjects.html
  50. New JDK7 features
    http://openjdk­.java.net/pro­jects/jdk7/fe­atures/
  51. Project Coin: Bringing it to a Close(able)
    http://blogs.sun­.com/darcy/en­try/project_co­in_bring_close
  52. CloseableFinder source code
    http://blogs.sun­.com/darcy/re­source/Projec­tCoin/Closeable­Finder.java
  53. Joe Darcy blog about JDK
    http://blogs.sun­.com/darcy
  54. Java 7 – more dynamics
    http://www.bap­tiste-wicht.com/2010/04­/java-7-more-dynamics/
  55. New JDK 7 Feature: Support for Dynamically Typed Languages in the Java Virtual Machine
    http://java.sun­.com/developer/techni­calArticles/Dyn­TypeLang/index­.html

Byl pro vás článek přínosný?