Hlavní navigace

Pohled pod kapotu JVM (1.část - prohlížení a modifikace bajtkódu)

13. 12. 2011
Doba čtení: 17 minut

Sdílet

V osmnácté části poněkud nepravidelně vycházejícího seriálu o programovacím jazyce Java i o vlastnostech JVM se budeme zabývat prohlížením a modifikací bajtkódu, do něhož jsou překládány zdrojové texty psané (nejenom) v Javě. Modifikace bajtkódu je často používána nástroji typu Cobertura, EMMA či AspectJ.

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

5. Soubory .class

6. Struktura souborů .class

7. Hlavička souborů .class

8. Constant pool – nedílná součást souborů .class

9. Odkazy na Internetu

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:

  1. aspectj (podpora AOP pro Eclipse IDE)
    http://www.eclip­se.org/aspectj/
  2. Aspect-oriented programming (Wikipedia)
    http://en.wiki­pedia.org/wiki/As­pect_oriented_pro­gramming
  3. AspectJ (Wikipedia)
    http://en.wiki­pedia.org/wiki/As­pectJ
  4. EMMA: a free Java code coverage tool
    http://emma.sou­rceforge.net/
  5. Cobertura
    http://cobertu­ra.sourceforge­.net/
  6. FindBugs (home page)
    http://findbug­s.sourceforge­.net/
  7. FindBugs (Wikipedia)
    http://en.wiki­pedia.org/wiki/Fin­dBugs

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:

  1. javap – The Java Class File Disassembler
    http://docs.o­racle.com/java­se/1.4.2/docs/to­oldocs/window­s/javap.html
  2. javap-java-1.6.0-openjdk(1) – Linux man page
    http://linux.di­e.net/man/1/j­avap-java-1.6.0-openjdk
  3. Using javap
    http://www.ide­velopment.info/da­ta/Programmin­g/java/miscella­neous_java/Usin­g_javap.html
  4. Examine class files with the javap command
    http://www.techre­public.com/ar­ticle/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:

  1. BCEL Home page
    http://common­s.apache.org/bcel/
  2. BCEL Manual
    http://common­s.apache.org/bcel/ma­nual.html
  3. Byte Code Engineering Library (Wikipedia)
    http://en.wiki­pedia.org/wiki/BCEL
  4. Java programming dynamics, Part 7: Bytecode engineering with BCEL
    http://www.ib­m.com/developer­works/java/li­brary/j-dyn0414/
  5. Bytecode Engineering
    http://book.chi­naunix.net/spe­cial/ebook/Co­re_Java2_Volu­me2AF/0131118269/ch13lev­1sec6.html
  6. BCEL Tutorial
    http://www.smfsup­port.com/suppor­t/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:

  1. ASM Home page
    http://asm.ow2­.org/
  2. Seznam nástrojů využívajících projekt ASM
    http://asm.ow2­.org/users.html
  3. ObjectWeb ASM (Wikipedia)
    http://en.wiki­pedia.org/wiki/Ob­jectWeb_ASM
  4. Java Bytecode BCEL vs ASM
    http://james.o­negoodcookie.com/2005/10­/26/java-bytecode-bcel-vs-asm/
  5. Bytecode Outline plugin for Eclipse (screenshoty + info)
    http://asm.ow2­.org/eclipse/in­dex.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:

  1. The JavaTM Virtual Machine Specification, Second Edition
    http://java.sun­.com/docs/book­s/jvms/second_e­dition/html/VMSp­ecTOC.doc.html
  2. The class File Format
    http://java.sun­.com/docs/book­s/jvms/second_e­dition/html/Clas­sFile.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):

root_podpora

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

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

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