Obsah
1. Pohled pod kapotu JVM – složené datové typy a programová smyčka typu for-each v Python VM
2. Překlad programové smyčky typu „for-each“ v programovacím jazyku Python do bajtkódu Python VM
3. Demonstrační příklad Test25.py n-tice a programová smyčka typu „for-each“
4. Okomentovaný bajtkód funkce printTuple()
5. Okomentovaný bajtkód funkce sum()
6. Demonstrační příklad Test26.py seznamy a programová smyčka typu „for-each“
7. Okomentovaný bajtkód funkce printList()
8. Okomentovaný bajtkód funkce sum()
9. Demonstrační příklad Test27.py slovníky a programová smyčka typu „for-each“
10. Okomentovaný bajtkód funkce printDictionary() a sum()
11. Repositář se zdrojovými kódy všech tří dnešních demonstračních příkladů
1. Pohled pod kapotu JVM – složené datové typy a programová smyčka typu for-each v Python VM
V předchozích dvou částech [137][138] seriálu o programovacím jazyku Java i o virtuálním stroji tohoto jazyka byl vysvětlen způsob překladu programové smyčky typu „for-each“ z programovacího jazyka Java do bajtkódu JVM i z programovacího jazyka Lua do bajtkódu Lua VM. V případě Javy a JVM jsme si ukázali použití této smyčky při průchodu poli i při průchodu různými typy kolekcí (seznam, mapa). Programovací jazyk Lua namísto polí a kolekcí nabízí programátorům jediný univerzálnější datový typ tabulka, takže jsme si ukázali, jak je do bajtkódu přeložen průchod tabulkou, a to jak tabulkou, kde jsou jednotlivé prvky indexovány celými čísly (ve výchozím případě od jedničky!), popř. i libovolnými jinými klíči (typicky se jedná o řetězce).
Ve vývojářské praxi velmi užitečnou programovou smyčku typu „for-each“ samozřejmě najdeme i v programovacím jazyku Python, kde ji lze použít společně s n-ticemi, seznamy, slovníky a taktéž i ve všech případech, kdy programátor použije vlastní iterátor popř. iterátor získaný ze standardní knihovny Pythonu (mimochodem: typ iterátor byl přidán do Pythonu verze 2.2, což de facto znamená, že je již použitelný v prakticky všech systémech, i když i dnes lze v některých speciálních případech narazit na již patnáct let starou verzi 1.5.2, viz též https://www.python.org/download/releases/). V následujících kapitolách si ukážeme, jakým způsobem se do bajtkódu jazyka Python překládá programová smyčka typu „for-each“ aplikovaná na n-tice (třetí kapitola), seznamy (šestá kapitola) i slovníky (devátá kapitola).
2. Překlad programové smyčky typu „for-each“ v programovacím jazyku Python do bajtkódu Python VM
V následujících kapitolách si na trojici demonstračních příkladů ukážeme překlad programové smyčky typu „for-each“ do bajtkódu programovacího jazyka Python. V přeložených tělech funkcí či metod nalezneme i tři popř. čtyři instrukce bajtkódu, které jsou pro překládané smyčky „for-each“ typické. Následuje podrobnější popis těchto instrukcí bajtkódu:
- JUMP_ABSOLUTE: za instrukčním kódem je uložena adresa, na níž se provede skok. Adresa je v pojetí virtuálního stroje jazyka Pythonu absolutní, ovšem pouze v rámci bajtkódu jedné metody. Není tedy možné skočit do kódu jiné metody (ani by to nedávalo žádný smysl). Tato instrukce je vkládána na konec těla přeložených smyček typu „for-each“, aby bylo možné pokračovat v další iteraci.
- GET_ITER: tato instrukce očekává na vrcholu zásobníku operandů (TOS=Top Of Stack) nějaký objekt. Pro tento objekt se získá iterátor, který je uložen zpět na TOS. Předpokládá se samozřejmě, že pro objekt lze iterátor získat, což samozřejmě platí jak pro n-tice, tak i pro seznamy a slovníky. Tato instrukce je typicky použita těsně před tělem přeložené programové smyčky typu „for-each“.
- FOR_ITER: tato instrukce očekává na vrcholu zásobníku operandů iterátor. Následně zavolá metodu next() a pokud tato metoda vrátí/vytvoří novou hodnotu, uloží se tato hodnota na zásobník (konkrétně na TOS, iterátor se tedy posune na druhou pozici v zásobníku). Pokud naopak metoda next() žádnou další hodnotu nevrátí, je iterátor ze zásobníku odstraněn a následně se provede skok o relativní adresu delta uloženou za instrukčním slovem.
- UNPACK_SEQUENCE: na vrcholu zásobníku operandů je uložený objekt, který se rozdělí na n individuálních hodnot uložených postupně zpět na zásobník. Tato instrukce se používá při průchodu slovníky, aby se v každé iteraci získala dvojice samostatných hodnot klíč a hodnota.
Zejména instrukce GET_ITER a FOR_ITER byly do bajtkódu Pythonu přidány téměř výhradně pro implementaci programových smyček.
3. Demonstrační příklad Test25.py n-tice a programová smyčka typu „for-each“
V dnešním prvním demonstračním příkladu nazvaném Test25.py je programová smyčka typu „for-each“ aplikována na n-tice, tj. na neměnitelné (immutable) složené datové typy, v nichž lze jednoduše (samozřejmě i náhodně) přistupovat k prvkům s využitím celočíselných indexů. V příkladu je implementována funkce printTuple(), v níž se postupně vytisknou všechny prvky n-tice a taktéž funkce sum() se stejným významem, s jakým jsme se již setkali v demonstračních příkladech uvedených v předchozích dvou částech tohoto seriálu. Následuje okomentovaný výpis zdrojového kódu příkladu Test25.py:
# # Demonstracni priklad cislo 25. # # n-tice a programova smycka typu for-each. # # # Vypis vsech prvku n-tice. # def printTuple(tuple): for item in tuple: print item # # Vypocet sumy vsech prvku. # def sum(tuple): sum = 0 for item in tuple: sum = sum + item return sum # # Test. # def main(): tuple = (1, 2, 3, 4) printTuple(tuple) print("Sum = " + str(sum(tuple))) print # # Ukazka disasembleru. # def disassemble(): from dis import dis print("\nprintTuple:") dis(printTuple) print("\nsum:") dis(sum) main() disassemble()
Po spuštění tohoto příkladu se na standardní výstup vypíše následující text (předpokládejme, že se nevolá funkce disassemble():
1 2 3 4 Sum = 10
4. Okomentovaný bajtkód funkce printTuple()
Podívejme se nyní, jakým způsobem je přeložena funkce printTuple() do bajtkódu programovacího jazyka Python:
printTuple: 13 0 SETUP_LOOP 19 // příprava bloku pro programovou smyčku (až do adresy 22) 3 LOAD_FAST 0 // uložení prvního parametru funkce (kterým je parametr typu n-tice) // na vrchol zásobníku operandů 6 GET_ITER // získání iterátoru pro n-tici // začátek těla programové smyčky >> 7 FOR_ITER 11 // přečtení další hodnoty generované iterátorem // pokud iterátor další hodnotu již nevrátí, // provede se skok na instrukci s indexem 21 10 STORE_FAST 1 // uložení hodnoty vrácené iterátorem (lokální proměnná "item") 14 13 LOAD_FAST 1 // přečtení hodnoty lokální proměnné "item" 16 PRINT_ITEM // výpis této hodnoty 17 PRINT_NEWLINE // odřádkování 18 JUMP_ABSOLUTE 7 // skok na začátek programové smyčky (na instrukci FOR_ITER) >> 21 POP_BLOCK // konec těla programové smyčky, zrušení bloku >> 22 LOAD_CONST 0 // uložit na vrchol zásobníku operandů konstantu None // = návratovou hodnotu této funkce 25 RETURN_VALUE // provedení návratu z funkce
Na výpisu bajtkódu je vidět snaha o co nejbližší přiblížení se k původnímu zdrojovému textu s podporou debuggingu na úrovni zdrojového textu; ve skutečnosti by však nebylo nutné použít dvojici instrukcí STORE_FAST+LOAD_FAST.
5. Okomentovaný bajtkód funkce sum()
Druhou implementovanou funkcí je funkce nazvaná sum(). Opět se podívejme na to, jakým způsobem došlo k jejímu překladu do bajtkódu:
sum: 22 0 LOAD_CONST 0 // uložit na vrchol zásobníku operandů konstantu 0 3 STORE_FAST 1 // tato hodnota se použije pro inicializaci lokální proměnné "sum" 23 6 SETUP_LOOP 24 // příprava bloku pro programovou smyčku (až do adresy 33) 9 LOAD_FAST 0 // načtení prvního parametru funkce (n-tice) a uložení na TOS 12 GET_ITER // získání iterátoru pro n-tici // začátek těla programové smyčky >> 13 FOR_ITER 16 // přečti další hodnotu generovanou iterátorem // pokud iterátor další hodnotu již nevrátí, skok na instrukci s indexem 32 16 STORE_FAST 2 // přečtení hodnoty lokální proměnné "item" 24 19 LOAD_FAST 1 // uložit na TOS hodnotu lokální proměnné "sum" 22 LOAD_FAST 2 // uložit na TOS hodnotu lokální proměnné "item" (původní TOS se posune) 25 BINARY_ADD // součet sum+item 26 STORE_FAST 1 // výsledek součtu se uloží zpět do lokální proměnné "sum" 29 JUMP_ABSOLUTE 13 // skok na začátek programové smyčky (na instrukci FOR_ITER) >> 32 POP_BLOCK // konec těla programové smyčky, zrušení bloku 25 >> 33 LOAD_FAST 1 // uložit na vrchol zásobníku operandů hodnotu lokální proměnné "sum" 36 RETURN_VALUE // návrat z funkce
6. Demonstrační příklad Test26.py seznamy a programová smyčka typu „for-each“
V dnešním druhém demonstračním příkladu nazvaném Test26.py je programová smyčka typu „for-each“ aplikována na seznamy, což jsou – na rozdíl od n-tic – měnitelné (mutable) datové typy, v nichž lze, stejně jako v případě n-tic, jednoduše (a samozřejmě i náhodně) přistupovat k jednotlivým prvkům s využitím celočíselných indexů. V příkladu je implementována funkce printList(), v níž se postupně vytisknou všechny prvky seznamu a taktéž nám již dobře známá funkce sum() (ve skutečnosti je však implementace těchto funkcí shodná s předchozím příkladem a to díky dynamickému typování v Pythonu):
# # Demonstracni priklad cislo 26. # # Seznamy a programova smycka typu for-each. # # # Vypis vsech prvku seznamu. # def printList(list): for item in list: print item # # Vypocet sumy vsech prvku. # def sum(list): sum = 0 for item in list: sum = sum + item return sum # # Test. # def main(): list = (1, 2, 3, 4) printList(list) print("Sum = " + str(sum(list))) print # # Ukazka disasembleru. # def disassemble(): from dis import dis print("\nprintList:") dis(printList) print("\nsum:") dis(sum) main() disassemble()
Po spuštění tohoto příkladu se na standardní výstup vypíšou shodné řádky, jako tomu byl v předchozím příkladu Test25.py:
1 2 3 4 Sum = 10
7. Okomentovaný bajtkód funkce printList()
Vzhledem k již zmíněnému dynamickému typování je bajtkód funkce printList() prakticky totožný s bajtkódem funkce printTuple() z předchozího demonstračního příkladu. Ostatně se o tom můžeme velmi snadno přesvědčit:
printList: 13 0 SETUP_LOOP 19 // příprava bloku pro programovou smyčku (až do adresy 22) 3 LOAD_FAST 0 // uložení prvního parametru funkce (kterým je parametr typu seznam) // na vrchol zásobníku operandů 6 GET_ITER // získání iterátoru pro seznam // začátek těla programové smyčky >> 7 FOR_ITER 11 // přečtení další hodnoty generované iterátorem // pokud iterátor další hodnotu již nevrátí, // provede se skok na instrukci s indexem 21 10 STORE_FAST 1 // uložení hodnoty vrácené iterátorem (lokální proměnná "item") 14 13 LOAD_FAST 1 // přečtení hodnoty lokální proměnné "item" 16 PRINT_ITEM // výpis této hodnoty 17 PRINT_NEWLINE // odřádkování 18 JUMP_ABSOLUTE 7 // skok na začátek programové smyčky (na instrukci FOR_ITER) >> 21 POP_BLOCK // konec těla programové smyčky, zrušení bloku >> 22 LOAD_CONST 0 // uložit na vrchol zásobníku operandů konstantu None // = návratovou hodnotu této funkce 25 RETURN_VALUE // provedení návratu z funkce
8. Okomentovaný bajtkód funkce sum()
I bajtkód funkce sum() bude po prostudování páté kapitoly čtenářům pravděpodobně povědomý:
sum: 22 0 LOAD_CONST 0 // uložit na vrchol zásobníku operandů konstantu 0 3 STORE_FAST 1 // tato hodnota se použije pro inicializaci lokální proměnné "sum" 23 6 SETUP_LOOP 24 // příprava bloku pro programovou smyčku (až do adresy 33) 9 LOAD_FAST 0 // načtení prvního parametru funkce (list) a uložení na TOS 12 GET_ITER // získání iterátoru pro seznam >> 13 FOR_ITER 16 // přečti další hodnotu generovanou iterátorem // pokud iterátor další hodnotu již nevrátí, skok na instrukci s indexem 32 16 STORE_FAST 2 // přečtení hodnoty lokální proměnné "item" 24 19 LOAD_FAST 1 // uložit na TOS hodnotu lokální proměnné "sum" 22 LOAD_FAST 2 // uložit na TOS hodnotu lokální proměnné "item" (původní TOS se posune) 25 BINARY_ADD // součet sum+item 26 STORE_FAST 1 // výsledek součtu se uloží zpět do lokální proměnné "sum" 29 JUMP_ABSOLUTE 13 // skok na začátek programové smyčky (na instrukci FOR_ITER) >> 32 POP_BLOCK // konec těla programové smyčky, zrušení bloku 25 >> 33 LOAD_FAST 1 // uložit na vrchol zásobníku operandů hodnotu lokální proměnné "sum" 36 RETURN_VALUE // návrat z funkce
9. Demonstrační příklad Test27.py slovníky a programová smyčka typu „for-each“
Při použití programové smyčky typu „for-each“ společně se slovníky (tedy asociativními poli) je nutné použít nepatrně odlišnou konstrukci této smyčky. Jedna z možností spočívá v zavolání metody items(). Nejedná se sice o jedinou variantu, ovšem využití items() mi připadne nejčitelnější a výsledná smyčka sémanticky odpovídá stejnému typu smyčky známé z programovacího jazyka Lua:
# # Demonstracni priklad cislo 27. # # Slovniky a programova smycka typu for-each. # # # Vypis vsech prvku slovniku. # def printDictionary(dictionary): for key, value in dictionary.items(): print key, value # # Vypocet sumy vsech prvku. # def sum(dictionary): sum = 0 for key, value in dictionary.items(): sum = sum + value return sum # # Test. # def main(): dictionary = {'first':1, 'second':2, 'third':3, 'fourth':4} printDictionary(dictionary) print("Sum = " + str(sum(dictionary))) print # # Ukazka disasembleru. # def disassemble(): from dis import dis print("\nprintDictionary:") dis(printDictionary) print("\nsum:") dis(sum) main() disassemble()
10. Okomentovaný bajtkód funkce printDictionary() a sum()
V bajtkódu funkce printDictionary() najdeme všechny čtyři instrukce popsané ve druhé kapitole, tj. konkrétně instrukce GET_ITER, FOR_ITER, UNPACK_SEQUENCE i JUMP_ABSOLUTE:
printDictionary: 13 0 SETUP_LOOP 35 // příprava bloku pro programovou smyčku (až do adresy 38) 3 LOAD_FAST 0 // uložení prvního parametru funkce (kterým je parametr typu slovník) 6 LOAD_ATTR 0 // příprava volání funkce items() nad slovníkem 9 CALL_FUNCTION 0 // zavolání funkce items() 12 GET_ITER // získání iterátoru pro slovník // začátek těla programové smyčky >> 13 FOR_ITER 21 // přečtení další hodnoty generované iterátorem // pokud iterátor další hodnotu již nevrátí, // provede se skok na instrukci s indexem 37 16 UNPACK_SEQUENCE 2 // iterátor uložil na zásobník dvojici klíč+hodnota // touto instrukcí se dvojice rozloží na dvě samostatné hodnoty 19 STORE_FAST 1 // uložení první části (klíče) z TOS do lokální proměnné 22 STORE_FAST 2 // uložení druhé části (hodnoty) z TOS do lokální proměnné 14 25 LOAD_FAST 1 // načtení klíče zpět na TOS 28 PRINT_ITEM // výpis této hodnoty 29 LOAD_FAST 2 // načtení hodnoty zpět na TOS 32 PRINT_ITEM // výpis této hodnoty 33 PRINT_NEWLINE // odřádkování 34 JUMP_ABSOLUTE 13 // skok na začátek programové smyčky (na instrukci FOR_ITER) >> 37 POP_BLOCK // odstranění bloku vytvořeného pro smyčku >> 38 LOAD_CONST 0 // uložit na vrchol zásobníku operandů konstantu None // = návratovou hodnotu této funkce 41 RETURN_VALUE // provedení návratu z funkce
Totéž ostatně platí i pro funkci sum(), jejíž bajtkód má následující podobu:
sum: 22 0 LOAD_CONST 0 // uložit na vrchol zásobníku operandů konstantu 0 3 STORE_FAST 1 // tato hodnota se použije pro inicializaci lokální proměnné "sum" 23 6 SETUP_LOOP 36 // příprava bloku pro programovou smyčku (až do adresy 15) 9 LOAD_FAST 0 // uložení prvního parametru funkce (kterým je parametr typu slovník) 12 LOAD_ATTR 0 // příprava volání funkce items() nad slovníkem 15 CALL_FUNCTION 0 // zavolání funkce items() // začátek těla programové smyčky 18 GET_ITER // získání iterátoru pro slovník >> 19 FOR_ITER 22 // přečtení další hodnoty generované iterátorem // pokud iterátor další hodnotu již nevrátí, // provede se skok na instrukci s indexem 44 22 UNPACK_SEQUENCE 2 // iterátor uložil na zásobník dvojici klíč+hodnota // touto instrukcí se dvojice rozloží na dvě samostatné hodnoty 25 STORE_FAST 2 // uložení první části (klíče) z TOS do lokální proměnné 28 STORE_FAST 3 // uložení druhé části (hodnoty) z TOS do lokální proměnné 24 31 LOAD_FAST 1 // uložit na TOS hodnotu lokální proměnné "sum" 34 LOAD_FAST 3 // uložit na TOS hodnotu lokální proměnné "value" (původní TOS se posune) 37 BINARY_ADD // součet sum+value 38 STORE_FAST 1 // výsledek součtu se uloží zpět do lokální proměnné "sum" 41 JUMP_ABSOLUTE 19 // skok na začátek programové smyčky (na instrukci FOR_ITER) >> 44 POP_BLOCK // konec těla programové smyčky, zrušení bloku 25 >> 45 LOAD_FAST 1 // uložit na vrchol zásobníku operandů hodnotu lokální proměnné "sum" 48 RETURN_VALUE // návrat z funkce
11. Repositář se zdrojovými kódy obou dnešních demonstračních příkladů
Všechny tři dnes popsané a použité demonstrační příklady byly uloženy do Mercurial repositáře umístěného na adrese http://icedtea.classpath.org/people/ptisnovs/jvm-tools/. Odkazy na prozatím poslední verze těchto příkladů naleznete v tabulce pod tímto odstavcem:
12. Odkazy na Internetu
- Python Byte Code Instructions
https://docs.python.org/release/2.5.2/lib/bytecodes.html - For-each Loop in Java
http://www.leepoint.net/notes-java/flow/loops/foreach.html - Programming in Lua (first edition)
http://www.lua.org/pil/contents.html - Programming in Lua: Numeric for
http://www.lua.org/pil/4.3.4.html - Programming in Lua: break and return
http://www.lua.org/pil/4.4.html - Programming in Lua: Tables
http://www.lua.org/pil/2.5.html - Programming in Lua: Table Constructors
http://www.lua.org/pil/3.6.html - Programovací jazyk Lua
http://palmknihy.cz/web/kniha/programovaci-jazyk-lua-12651.htm - Lua: Tables Tutorial
http://lua-users.org/wiki/TablesTutorial - Python 2.x: funkce range()
https://docs.python.org/2/library/functions.html#range - Python 2.x: typ iterátor
https://docs.python.org/2/library/stdtypes.html#iterator-types - Lua: Control Structure Tutorial
http://lua-users.org/wiki/ControlStructureTutorial - Lua Types Tutorial
http://lua-users.org/wiki/LuaTypesTutorial - Goto Statement in Lua
http://lua-users.org/wiki/GotoStatement - Python break, continue and pass Statements
http://www.tutorialspoint.com/python/python_loop_control.htm - For Loop (Wikipedia)
http://en.wikipedia.org/wiki/For_loop - Heinz Rutishauser
http://en.wikipedia.org/wiki/Heinz_Rutishauser - Parrot
http://www.parrot.org/ - Parrot languages
http://www.parrot.org/languages - Parrot Primer
http://docs.parrot.org/parrot/latest/html/docs/intro.pod.html - Parrot Opcodes
http://docs.parrot.org/parrot/latest/html/ops.html - Parrot VM
http://en.wikibooks.org/wiki/Parrot_Virtual_Machine - Parrot Assembly Language
http://www.perl6.org/archive/pdd/pdd06_pasm.html - Parrot Reference: Chapter 11 – Perl 6 and Parrot Essentials
http://oreilly.com/perl/excerpts/perl-6-and-parrot-essentials/parrot-reference.html - Python Bytecode: Fun With Dis
http://akaptur.github.io/blog/2013/08/14/python-bytecode-fun-with-dis/ - Python's Innards: Hello, ceval.c!
http://tech.blog.aknin.name/category/my-projects/pythons-innards/ - Byterun
https://github.com/nedbat/byterun - Python Byte Code Instructions
http://document.ihg.uni-duisburg.de/Documentation/Python/lib/node56.html - Python Byte Code Instructions
https://docs.python.org/3.2/library/dis.html#python-bytecode-instructions - Lua 5.2 sources
http://www.lua.org/source/5.2/ - Lua 5.2 sources – lopcodes.h
http://www.lua.org/source/5.2/lopcodes.h.html - Lua 5.2 sources – lopcodes.c
http://www.lua.org/source/5.2/lopcodes.c.html - dis – Python module
https://docs.python.org/2/library/dis.html - Comparison of Python virtual machines
http://polishlinux.org/apps/cli/comparison-of-python-virtual-machines/ - O-code
http://en.wikipedia.org/wiki/O-code_machine - 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 - GC safe-point (or safepoint) and safe-region
http://xiao-feng.blogspot.cz/2008/01/gc-safe-point-and-safe-region.html - Safepoints in HotSpot JVM
http://blog.ragozin.info/2012/10/safepoints-in-hotspot-jvm.html - Java theory and practice: Synchronization optimizations in Mustang
http://www.ibm.com/developerworks/java/library/j-jtp10185/ - How to build hsdis
http://hg.openjdk.java.net/jdk7/hotspot/hotspot/file/tip/src/share/tools/hsdis/README - Java SE 6 Performance White Paper
http://www.oracle.com/technetwork/java/6-performance-137236.html - Lukas Stadler's Blog
http://classparser.blogspot.cz/2010/03/hsdis-i386dll.html - How to build hsdis-amd64.dll and hsdis-i386.dll on Windows
http://dropzone.nfshost.com/hsdis.htm - PrintAssembly
https://wikis.oracle.com/display/HotSpotInternals/PrintAssembly - The Java Virtual Machine Specification: 3.14. Synchronization
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.14 - The Java Virtual Machine Specification: 8.3.1.4. volatile Fields
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.4 - The Java Virtual Machine Specification: 17.4. Memory Model
http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4 - The Java Virtual Machine Specification: 17.7. Non-atomic Treatment of double and long
http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7 - Open Source ByteCode Libraries in Java
http://java-source.net/open-source/bytecode-libraries - 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/ - BCEL Home page
http://commons.apache.org/bcel/ - Byte Code Engineering Library (před verzí 5.0)
http://bcel.sourceforge.net/ - Byte Code Engineering Library (verze >= 5.0)
http://commons.apache.org/proper/commons-bcel/ - BCEL Manual
http://commons.apache.org/bcel/manual.html - Byte Code Engineering Library (Wikipedia)
http://en.wikipedia.org/wiki/BCEL - BCEL Tutorial
http://www.smfsupport.com/support/java/bcel-tutorial!/ - Bytecode Engineering
http://book.chinaunix.net/special/ebook/Core_Java2_Volume2AF/0131118269/ch13lev1sec6.html - Bytecode Outline plugin for Eclipse (screenshoty + info)
http://asm.ow2.org/eclipse/index.html - Javassist
http://www.jboss.org/javassist/ - Byteman
http://www.jboss.org/byteman - Java programming dynamics, Part 7: Bytecode engineering with BCEL
http://www.ibm.com/developerworks/java/library/j-dyn0414/ - 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 - 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/ - jclasslib bytecode viewer
http://www.ej-technologies.com/products/jclasslib/overview.html