Obsah
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
8. Čtvrtý demonstrační příklad – přístup k prvkům jednorozměrných polí
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ě createObjectArrays 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 createObjectArrays 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/String;“. 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:
# | 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 polí
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
- Java quick guide: JVM Instruction Set (tabulka všech instrukcí JVM)
http://www.mobilefish.com/tutorials/java/java_quickguide_jvm_instruction_set.html - The JVM Instruction Set
http://mpdeboer.home.xs4all.nl/scriptie/node14.html - Control Flow in the Java Virtual Machine
http://www.artima.com/underthehood/flowP.html - Root.cz: Využití komprimovaných ukazatelů na objekty v JVM
http://www.root.cz/clanky/vyuziti-komprimovanych-ukazatelu-na-objekty-v-nbsp-jvm/ - Root.cz: JamVM aneb alternativa k HotSpotu nejenom pro embedded zařízení a chytré telefony
http://www.root.cz/clanky/jamvm-aneb-alternativa-k-hotspotu-nejenom-pro-embedded-zarizeni-tablety-a-chytre-telefony/ - The JavaTM Virtual Machine Specification, Second Edition
http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html - The class File Format
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html - javap – The Java Class File Disassembler
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/javap.html - javap-java-1.6.0-openjdk(1) – Linux man page
http://linux.die.net/man/1/javap-java-1.6.0-openjdk - Using javap
http://www.idevelopment.info/data/Programming/java/miscellaneous_java/Using_javap.html - Examine class files with the javap command
http://www.techrepublic.com/article/examine-class-files-with-the-javap-command/5815354 - BCEL Home page
http://commons.apache.org/bcel/ - BCEL Manual
http://commons.apache.org/bcel/manual.html - Byte Code Engineering Library (Wikipedia)
http://en.wikipedia.org/wiki/BCEL - Java programming dynamics, Part 7: Bytecode engineering with BCEL
http://www.ibm.com/developerworks/java/library/j-dyn0414/ - Bytecode Engineering
http://book.chinaunix.net/special/ebook/Core_Java2_Volume2AF/0131118269/ch13lev1sec6.html - BCEL Tutorial
http://www.smfsupport.com/support/java/bcel-tutorial!/ - ASM Home page
http://asm.ow2.org/ - Seznam nástrojů využívajících projekt ASM
http://asm.ow2.org/users.html - ObjectWeb ASM (Wikipedia)
http://en.wikipedia.org/wiki/ObjectWeb_ASM - Java Bytecode BCEL vs ASM
http://james.onegoodcookie.com/2005/10/26/java-bytecode-bcel-vs-asm/ - Bytecode Outline plugin for Eclipse (screenshoty + info)
http://asm.ow2.org/eclipse/index.html - aspectj (Eclipse)
http://www.eclipse.org/aspectj/ - Aspect-oriented programming (Wikipedia)
http://en.wikipedia.org/wiki/Aspect_oriented_programming - AspectJ (Wikipedia)
http://en.wikipedia.org/wiki/AspectJ - EMMA: a free Java code coverage tool
http://emma.sourceforge.net/ - Cobertura
http://cobertura.sourceforge.net/ - FindBugs
http://findbugs.sourceforge.net/ - GNU Classpath
www.gnu.org/s/classpath/ - Java VMs Compared
http://bugblogger.com/java-vms-compared-160/ - JSRs: Java Specification Requests – JSR 223: Scripting for the Java Platform
http://www.jcp.org/en/jsr/detail?id=223 - Scripting for the Java Platform
http://java.sun.com/developer/technicalArticles/J2SE/Desktop/scripting/ - Scripting for the Java Platform (Wikipedia)
http://en.wikipedia.org/wiki/Scripting_for_the_Java_Platform - Java Community Process
http://en.wikipedia.org/wiki/Java_Specification_Request - Java HotSpot VM Options
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html - Great Computer Language Shootout
http://c2.com/cgi/wiki?GreatComputerLanguageShootout - Java performance
http://en.wikipedia.org/wiki/Java_performance - Trying the prototype
http://mail.openjdk.java.net/pipermail/lambda-dev/2010-August/002179.html - Better closures (for Java)
http://blogs.sun.com/jrose/entry/better_closures - Lambdas in Java: An In-Depth Analysis
http://www.infoq.com/articles/lambdas-java-analysis - Class ReflectiveOperationException
http://download.java.net/jdk7/docs/api/java/lang/ReflectiveOperationException.html - Proposal: Indexing access syntax for Lists and Maps
http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001108.html - Proposal: Elvis and Other Null-Safe Operators
http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000047.html - Java 7 : Oracle pushes a first version of closures
http://www.baptiste-wicht.com/2010/05/oracle-pushes-a-first-version-of-closures/ - Groovy: An agile dynamic language for the Java Platform
http://groovy.codehaus.org/Operators - Better Strategies for Null Handling in Java
http://www.slideshare.net/Stephan.Schmidt/better-strategies-for-null-handling-in-java - Control Flow in the Java Virtual Machine
http://www.artima.com/underthehood/flowP.html - Java Virtual Machine
http://en.wikipedia.org/wiki/Java_virtual_machine - ==, .equals(), compareTo(), and compare()
http://leepoint.net/notes-java/data/expressions/22compareobjects.html - New JDK7 features
http://openjdk.java.net/projects/jdk7/features/ - Project Coin: Bringing it to a Close(able)
http://blogs.sun.com/darcy/entry/project_coin_bring_close - CloseableFinder source code
http://blogs.sun.com/darcy/resource/ProjectCoin/CloseableFinder.java - Joe Darcy blog about JDK
http://blogs.sun.com/darcy - Java 7 – more dynamics
http://www.baptiste-wicht.com/2010/04/java-7-more-dynamics/ - New JDK 7 Feature: Support for Dynamically Typed Languages in the Java Virtual Machine
http://java.sun.com/developer/technicalArticles/DynTypeLang/index.html