Obsah
1. Pohled pod kapotu JVM (1.část – prohlížení a modifikace bajtkódu)
2. Nástroj javap – základ pro hrátky s bajtkódem
3. Nástroj BCEL (Byte Code Engineering Library)
4. Nástroj ASM aneb alternativa k BCEL
8. Constant pool – nedílná součást souborů .class
1. Pohled pod kapotu JVM (1.část – prohlížení a modifikace bajtkódu)
V předchozích sedmnácti částech seriálu o programovacím jazyce Java i o vlastnostech virtuálního stroje Javy jsme se již několikrát zmínili o bajtkódu, tj. (poněkud zjednodušeně řečeno) o souborech s koncovkou .class. Tyto soubory většinou vznikají překladem zdrojových textů napsaných v Javě, ovšem není to pravidlem, protože bajtkód může být generován i překladači jiných programovacích jazyků, popř. se může jednat o bajtkód přeložený assemblerem typu Jasmin či některým generátorem kódu. My se v dalším textu zaměříme především na popis struktury bajtkódu a na to, jak lze tuto strukturu zobrazit. Teprve poté si ukážeme některé možnosti, které nám nabízí modifikace bajtkódu. Prohlížení či dokonce modifikace bajtkódu generovaného překladačem javac (popř. další nízkoúrovňové operace) sice nepatří mezi každodenní činnosti programátorů používajících Javu, ovšem v některých situacích se s bajtkódem skutečně manipuluje, ať již přímo, či (mnohem častěji) nepřímo s využitím různých specializovaných nástrojů.
Příkladem mohou být například nástroje typu Cobertura a EMMA, které slouží pro zjištění, které části zdrojového kódu aplikací jsou pokryty (jednotkovými) testy. Tyto nástroje musí umět dobře kooperovat s virtuálním strojem Javy, proto nejprve modifikují bajtkódy testovaných tříd, aby bylo možné při běhu testů dynamicky zjistit, které řádky kódu jsou skutečně z testů volány. Podobným způsobem je bajtkód modifikován nástroji podporujícími aspektově orientované programování (aspect oriented programming), které taktéž mohou zasahovat do bajtkódu vygenerovaného překladačem. Teoreticky je sice možné při použití aspektově orientovaného programování transformovat přímo zdrojové kódy programů (což je použito především v jiných programovacích jazycích), ale transformace bajtkódu je v případě Javy mnohem snazší. Ze stejného důvodu (analýza bajtkódu je jednodušší než analýza zdrojového textu) je bajtkód použit pro statickou analýzu a hledání potenciálních chyb nástrojem FindBugs.
Užitečné odkazy:
- aspectj (podpora AOP pro Eclipse IDE)
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 (home page)
http://findbugs.sourceforge.net/ - FindBugs (Wikipedia)
http://en.wikipedia.org/wiki/FindBugs
2. Nástroj javap – základ pro hrátky s bajtkódem
Jeden z nejjednodušších nástrojů určených pro prohlížení obsahu bajtkódu je součástí každé instalace JDK (Java Development Kit). Tento nástroj, jenž je sice na první pohled velmi jednoduchý, ovšem na druhou stranu v mnoha případech užitečný, se jmenuje javap a slouží pro výpis základní struktury přeložených tříd, popř. taktéž k zobrazení sekvence instrukcí tvořících těla metod (jedná se tedy o jednoduchý disassembler). S využitím tohoto nástroje je taktéž možné zobrazit hodnoty konstant uložených v bajtkódu v takzvaném constant poolu. V osmé kapitole si strukturu constant poolu vysvětlíme podrobněji. Při spuštění nástroje javap je nutné na příkazové řádce zadat minimálně jméno třídy (nikoli přímo jméno souboru s bajtkódem!), popř. lze využít i několik voleb, které určují, jaké informace se získají a následně zobrazí:
# | Volba (přepínač) | Význam volby |
---|---|---|
1 | -public | ve výpise budou uvedeny jen veřejné třídy, metody a atributy |
2 | -protected | ve výpise budou uvedeny i třídy, metody a atributy s příznakem „protected“ |
3 | -package | podobné předchozímu přepínači, ale navíc se vypíšou i třídy, metody a atributy s příznakem „package-protected“ |
4 | -private | vypíšou se třídy, metody a atributy se všemi příznaky (takto lze získat informaci o celé struktuře třídy) |
5 | -c | provede se navíc zpětný překlad těl metod (disassembler) |
6 | -l | pro každou metodu vypíše tabulku s korespondujícími řádky ve zdrojovém textu (ne vždy jsou tyto informace dostupné, záleží na použití volby -g:xxx při překladu třídy). |
7 | -verbose | nejpodrobnější režim výpisu, dojde zde i na výpis informací z×constant poolu |
K nástroji javap se ještě několikrát vrátíme v dalším textu.
Užitečné odkazy:
- 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
3. Nástroj BCEL (Byte Code Engineering Library)
I přes svoji nespornou užitečnost nemusí v mnoha případech výše popsaný nástroj javap pro všechny potřeby vývojářů dostačovat. Jedná se především o situace, v nichž je zapotřebí do bajtkódu nějakým způsobem aktivně zasahovat. V těchto případech lze využít programy BCEL či ASM, které umožňují s bajtkódem provádět mnoho i poměrně složitých operací, včetně změny těl metod. Historicky starší je program (či spíše knihovna) nazvaná BCEL (Byte Code Engineering Library) umožňující nejprve načíst celý bajtkód a posléze s tímto bajtkódem různým způsobem manipulovat. Vzhledem k tomu, že se bajtkód při načítání převádí na vnitřní reprezentaci (různé typy tříd), je manipulace s bajtkódem pomocí knihovny BCEL poměrně pomalá, což se však většinou negativně projeví až při práci s rozsáhlými projekty. Větší problém pro vývojáře představuje poněkud nepřehledné aplikační programové rozhraní knihovny BCEL a s tím související horší dokumentace.
Užitečné odkazy:
- 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!/
4. Nástroj ASM aneb alternativa k BCEL
Kromě knihovny BCEL lze v mnoha případech využít i knihovnu nazvanou ASM, která taktéž umožňuje manipulaci s bajtkódem (navíc má ASM snad nejlepší 3D logo, které jsem zatím viděl :-). Zatímco se v případě BCEL celý bajtkód nejprve načetl do paměti, knihovna ASM ve své základní konfiguraci pracuje odlišně – bajtkód je postupně načítán a pro každou informaci může být zaregistrován programový kód, který tuto informaci zpracovává. Samozřejmě je též možné použít opačný postup, při němž je bajtkód postupně generován. Transformace bajtkódu je tedy typicky provedena načítáním vstupního bajtkódu s postupným generováním bajtkódu výstupního (při přenosu informací ze vstupního bajtkódu do bajtkódu výstupního se aplikuje zvolená transformace či modifikace). Rozdíl mezi knihovnou BCEL a knihovnou ASM (opět připomínám, že v základní konfiguraci) se podobá rozdílu mezi způsobem zpracování XML souborů – buď lze použít DOM (Document Object Model) (analogie k BCEL) nebo SAX (Simple API for XML) (analogie k ASM). Knihovnu ASM je však taktéž možné využívat v „režimu DOM“, podobně jako BCEL, i když se API obou knihoven od sebe dosti liší.
Užitečné odkazy:
- 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
5. Soubory .class
Nyní se již (konečně :-) dostáváme k vlastnímu popisu souborů typu .class. Nejprve si řekněme, z čeho vlastně soubory .class vznikají. V některých učebnicích Javy se sice píše, že z každého zdrojového souboru .java vznikne překladem soubor .class pojmenovaný stejně, jako onen zdrojový soubor (liší se samozřejmě koncovka). Jak však již pravděpodobně vývojáři vědí, je situace poněkud složitější. V každém souboru .class se totiž může nacházet pouze bajtkód jediné třídy, což znamená, že se ve skutečnosti při překladu jednoho zdrojového textu může vygenerovat hned několik souborů .class, jejichž pojmenování se řídí striktními pravidly, které jsou dodržovány jak samotným překladačem, tak i JVM, který při inicializaci a spouštění programu musí najít a jednoznačně spárovat jména tříd se jmény souborů .class. Buďme konkrétnější – samostatný soubor .class se vygeneruje pro:
- každou běžnou třídu ve zdrojovém textu (v jednom zdrojovém souboru jich může být samozřejmě větší množství, ovšem pouze jedna třída může být veřejná a musí být pojmenována stejně, jako zdrojový soubor)
- každou vnitřní třídu. Název souboru .class je v tomto případě složen ze jména obalové třídy, znaku dolar a jména vnitřní třídy. Totéž pravidlo platí i pro statické vnitřní třídy.
- každou lokální třídu. V názvu souboru .class je použito jméno obalové třídy, znak dolar, generovaný index a jméno lokální třídy.
- každou anonymní třídu. Název souboru .class obsahuje pouze jméno obalové třídy, znak dolar a generovaný index.
- každý výčet (což je jen forma běžné třídy se stejnými pravidly pro pojmenování).
- každé rozhraní. Soubor se jmenuje stejně, jako jméno rozhraní.
Ukažme si způsob pojmenování souborů .class na jediném zdrojovém textu s různými typy tříd, rozhraní a výčtů, který má tvar:
// vycet enum E {} // vycet enum F {} // rozhrani interface I { } // rozhrani interface J { } // bezna trida (je verejna, tudiz pojmenovana stejne, jako zdrojovy soubor) public class A { // vnitrni trida class InnerClassA1 { } // vnitrni trida class InnerClassA2 { // vnitrni trida uvnitr vnitrni tridy :-) class InnerClassInA2 { } } // staticka vnitrni trida static class StaticInnerClassA { } // ctverice anonymnich trid I i1 = new I(){}; I i2 = new I(){}; J j1 = new J(){}; J j2 = new J(){}; void x() { // lokalni tridy class LocalClassX {}; class LocalClassY {}; class LocalClassZ {}; } void y() { // lokalni tridy class LocalClassX {}; class LocalClassY {}; class LocalClassZ {}; } } // bezna (neverejna) trida class B { // vnitrni trida class InnerClassA2 { } }
Po překladu výše vypsaného zdrojového textu získáme následující soubory. Můžete si sami zkusit spárovat jména těchto souborů s definicemi tříd, rozhraní a výčtů:
A.class A$InnerClassA1.class A$InnerClassA2.class A$InnerClassA2$InnerClassInA2.class A$StaticInnerClassA.class A$1.class A$1LocalClassX.class A$1LocalClassY.class A$1LocalClassZ.class A$2.class A$2LocalClassX.class A$2LocalClassY.class A$2LocalClassZ.class A$3.class A$4.class B.class B$InnerClassA2.class E.class F.class I.class J.class
6. Struktura souborů .class
Na jednu stranu jsou sice výše vypsaná pravidla určující způsob pojmenování souborů typu .class poněkud komplikovaná, na stranu druhou to však vede k tomu, že interní struktura těchto souborů může být poměrně jednoduchá, protože každý soubor .class může obsahovat, jak jsme si již řekli, pouze informace o jediné třídě, rozhraní či výčtovém typu. V souborech .class se nachází především velmi jednoduchá osmibajtová hlavička. Za ní je uložen takzvaný constant pool, který mnohdy tvoří více než 2/3 celkové velikosti souboru. Poté je v souboru v binární formě uložena informace o přístupových právech, jméno třídy i nadtřídy, seznam implementovaných rozhraní, seznam atributů třídy a konečně vlastní příkazy tvořící těla jednotlivých metod (JVM je založena na relativně jednoduchém zásobníkovém procesoru). Na konci souboru .class se mohou nacházet další informace, jejichž význam si popíšeme v následujících částech tohoto seriálu.
+------------------------------+ | Hlavička | +------------------------------+ | Constant pool | | ..... | | ..... | | ..... | +------------------------------+ | Definice přístupových práv | +------------------------------+ | Jméno třídy a nadtřídy | +------------------------------+ | Implementovaná rozhraní | | ..... | +------------------------------+ | Atributy třídy | | ..... | +------------------------------+ | Kódy jednotlivých metod | | ..... | | ..... | | ..... | +------------------------------+ | Další metadata třídy | +------------------------------+
Užitečné odkazy:
- 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
7. Hlavička souborů .class
Hlavička souborů .class je velmi jednoduchá, obsahuje totiž pouze trojici hodnot. Soubory tohoto typu začínají, podobně jako mnoho dalších typů binárních souborů, takzvanou magickou konstantou sloužící pro snadné (i když ne vždy zcela přesné) rozpoznání typu souboru. V případě souborů .class je tato konstanta čtyřbajtová a obsahuje hodnotu, která má v hexadecimálním vyjádření tvar 0× CAFE BABE (v minulosti se navíc používala podobná magická konstanta 0× CAFE DEAD pro označení souborů s perzistentními objekty). Tato konstanta je, podobně jako všechny další vícebajtové konstanty v souborech .class, uložena v pořadí big endian, tedy přesně naopak, než je zvykem u architektury i386 (Java ostatně původně vznikla na procesorech SPARC, nikoli na platformě i386). Za čtyřbajtovou magickou konstantou se nachází dvě dvoubajtové hodnoty, v nichž je uloženo minoritní a majoritní číslo verze bajtkódu. Tyto hodnoty jsou použity při načítání bajtkódu do virtuálního stroje pro základní kontrolu kompatibility. Následuje výpis struktury hlavičky bajtkódu:
+-------------------------+---------+ | Magická konstanta | 4 bajty | +-------------------------+---------+ | Minoritní verze formátu | 2 bajty | +-------------------------+---------+ | Majoritní verze formátu | 2 bajty | +-------------------------+---------+
Vraťme se na chvíli k číslu verze bajtkódu. V současnosti se můžete nejčastěji setkat s následujícími verzemi:
Verze JVM/JRE | Číslo verze bajtkódu |
---|---|
1.1 | 45 |
1.2 | 45 |
1.3 | 47 |
1.4 | 48 |
5.0 | 49 |
6.0 | 50 |
7 | 51 |
V některých případech se může stát, že je zapotřebí využít bajtkód přeložený pro vyšší verzi JVM/JRE a současně není k dispozici zdrojový kód tříd. V tomto případě je možné (ovšemže na vlastní riziko) ručně upravit majoritní číslo verze bajtkódu, protože samotná struktura bajtkódu neprošla většími změnami – pouze byly doplněny metainformace o třídě a taktéž došlo k doplnění nových instrukcí (asi nejznámější novinkou v této oblasti je instrukce invokedynamic, k níž se někdy ještě vrátíme). Změny v API základních knihoven jsou navíc testovány až za běhu JRE.
Poznámka: taktéž se lze setkat s opačným problémem, kdy je zapotřebí vygenerovat soubory .class, které budou využívané starší JVM/JRE (mnoho komerčních aplikací například stále používá Javu 1.4.2). Zde je řešení většinou jednoduché – postačuje použít při překladu přepínače -source 1.x a -target 1.x:
javac -source 1.4 -target 1.4 Hello.java
Verze Javy odpovídající zdrojovým kódům musí být menší nebo rovna verzi cílového JVM/JRE.
8. Constant pool – nedílná součást souborů .class
Za hlavičkou následuje obvykle objemově nejrozsáhlejší část souborů .class. Jedná se o takzvaný constant pool, v němž jsou uloženy některé číselné konstanty a taktéž všechny řetězcové konstanty (to je ostatně jeden z důvodů, proč lze s konstantními řetězci definovanými v rámci jedné třídy provádět operaci porovnání pomocí operátoru ==). Dále se zde nachází přesné typové informace o všech použitých třídách i o volaných metodách těchto tříd. Prvním údajem v constant poolu je informace o jeho délce, což je dvoubajtové číslo obsahující hodnotu o jedničku větší, než je skutečný počet záznamů v constant poolu. Každý prvek začíná jednobajtovým tagem, který určuje jeho typ a posléze již následují uložené údaje. Celkem se rozeznává jedenáct typů záznamů.
Nejjednodušší jsou záznamy o číselných konstantách typu int a float, protože hodnoty těchto konstant jsou uloženy přímo za tagem záznamu. Poněkud složitější je způsob uložení konstant typu long a double. Tyto konstanty jsou taktéž uloženy ihned za tagem, ale tvůrci bajtkódu se dosti nešťastně rozhodli, že za těmito konstantami bude následovat jeden nepoužitý záznam (ten samozřejmě není uložený v bajtkódu, ale při dekódování informací z constant poolu se musí korektně zvýšit hodnota indexu – ovšem to je již problém dekódovacích nástrojů a prozatím se jim nemusíme zaobírat).
Tag | Název tagu | Parametr 1 | Parametr 2 |
---|---|---|---|
3 | Integer | čtyřbajtová konstanta | × |
4 | Float | čtyřbajtová konstanta | × |
5 | Long | osmibajtová konstanta | × |
6 | Double | osmibajtová konstanta | × |
Důležitý je taktéž záznam obsahující řetězec (kódovaný s využitím UTF-8, navíc se zadanou délkou bez ukončující nuly), protože na tento typ záznamu se odkazují mnohé další záznamy. Týká se to i záznamu typu String, který se odkazuje právě na záznam typu Utf8 (odkaz není nic jiného, než index záznamu v constant poolu):
Tag | Název tagu | Parametr 1 | Parametr 2 |
---|---|---|---|
1 | Utf8 | délka řetězce v bajtech | sekvence bajtů (počet znaků je obecně menší než počet bajtů) |
8 | String | 2 bajty: odkaz na vlastní řetězec (záznam typu Utf8) | × |
Začíná přituhovat :-) Všechny další typy záznamů obsahují pouze reference (indexy) na další záznam či dokonce na dvojici záznamů. Týká se to například záznamu nesoucího informaci o referencované metodě (Methodref), který odkazuje na záznam s informací o třídě (Class) a dále na záznam s informací o jménu a typu metody. Jak záznam s informací o třídě, tak i záznam s informací o jménu a typu taktéž obsahují odkazy/reference na další záznamy; konkrétně odkazy na řetězce se jménem třídy, jménem metody, její návratové hodnoty a taktéž jejich parametrech (zní to poměrně složitě, ve skutečnosti je tento způsob někdy i velmi úsporný). Všechny odkazy/reference jsou uloženy ve formě dvoubajtových indexů záznamů, přičemž indexování začíná od jedničky. V následující tabulce jsou vypsány typy záznamů obsahující reference na jiné záznamy:
Tag | Název tagu | Parametr 1 | Parametr 2 |
---|---|---|---|
7 | Class | 2 bajty: odkaz na jméno třídy (záznam typu Utf8) | × |
9 | Fieldref | 2 bajty: odkaz na jméno třídy (záznam typu Utf8) | 2 bajty: odkaz na záznam typu NameAndType |
10 | Methodref | 2 bajty: odkaz na jméno třídy (záznam typu Utf8) | 2 bajty: odkaz na záznam typu NameAndType |
11 | InterfaceMethodref | 2 bajty: odkaz na jméno třídy (záznam typu Utf8) | 2 bajty: odkaz na záznam typu NameAndType |
12 | NameAndType | 2 bajty: odkaz na záznam typu Utf8 | 2 bajty: odkaz na záznam typu Utf8 |
Indexy těchto záznamů jsou intenzivně používány v instrukcích tvořících těla metod. Díky tomu jsou například instrukce pro volání metod velmi krátké, protože obsahují pouze krátký index do constant poolu, nikoli například 32 či 64bitovou adresu skoku. Vše si podrobně vysvětlíme v dalším pokračování tohoto seriálu, kde si taktéž ukážeme jednoduchý nástroj (naprogramovaný v céčku), který dokáže rychle zobrazit obsah celého constant poolu způsobem, který je podobný způsobu používanému mj. i nástrojem javap. Příště si taktéž popíšeme další součásti bajtkódu.
9. Odkazy na Internetu
- 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 - ClosableFinder 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/